diff --git a/.changeset/patient-voles-chatter.md b/.changeset/patient-voles-chatter.md new file mode 100644 index 000000000..f26c07e8e --- /dev/null +++ b/.changeset/patient-voles-chatter.md @@ -0,0 +1,5 @@ +--- +type: Changed +pr: 2010 +--- +**MemPalace `memory_mode` `kg_backend` and `replace` are now functional** — selecting either mode now routes recall through the palace instead of silently behaving like `augment`: `kg_backend` treats the palace temporal KG as the primary knowledge-graph source (native `.planning/graphs/` as fallback), and `replace` resolves recall through the palace as the source of truth. Every mode stays default-resilient — an unreachable palace falls back to native memory and no memory is lost. (#2010) diff --git a/CONTEXT.md b/CONTEXT.md index 5b48787ce..0b191c568 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -265,7 +265,7 @@ A cross-Wing knowledge connection created by `mempalace_create_tunnel`. GSD prop A per-agent narrative entry written by `mempalace_diary_write`. GSD's `gsd-mempalace-curator` writes a diary entry at `ship:post` when `mempalace.diary_journal: true`, recording a session summary scoped to the project and agent role. MemPalace vocabulary — see Connected Capability. ### memory_mode -The `mempalace.memory_mode` config key controlling how tightly MemPalace couples to GSD's native memory. Three declared values: `augment` (default — **implemented**; palace is an additional write-mostly recall layer; lowest coupling), `kg_backend` (**declared; routing seam not yet implemented** — intended to route graphify KG queries through MemPalace's temporal graph; selecting today behaves as `augment`), `replace` (**declared; not yet functional** — intended to make the palace the durable store; selecting today behaves as `augment`). Only `augment` has effect in the current release; `kg_backend` and `replace` are forward-declared for a future release. Read at hook-render time; switching is a config change, not a reinstall. See MemPalace Settings in `docs/CONFIGURATION.md`. +The `mempalace.memory_mode` config key controlling how authoritative MemPalace is during recall/capture relative to GSD's native memory. Three wired values: `augment` (default — palace is an additive recall layer; native memory stays authoritative; lowest coupling), `kg_backend` (knowledge-graph queries resolve against MemPalace's temporal graph as the primary source, `.planning/graphs/` as fallback; non-KG drawer recall stays additive), `replace` (recall resolves through the palace as the source of truth, native artifacts as fallback). Every mode is `onError:skip` and default-resilient — an unreachable palace degrades to native memory and GSD keeps writing `.planning/graphs/`, so no mode loses memory. Read at hook-render time; switching is a config change, not a reinstall. Cross-mode migration of existing `.planning/graphs/` into the palace is a separate, not-yet-implemented concern (PRD/ADR §17 open question). See MemPalace Settings in `docs/CONFIGURATION.md`. ### Runtime Hooks Surface Module Standalone hook-surface writer module extracted from `bin/install.js` as ADR-857 phase 5f-1 (behavior-preserving relocation, no logic change). Owns: Cline rules-body/agents-md/pre-tool-use hook generation (`buildClineRulesBody`, `buildClineAgentsMdBody`, `buildClinePreToolUseHook`, `mergeGsdAgentsMd`, `writeClineArtifacts`); Cursor `hooks.json` lifecycle (`buildCursorHookEntry`, `isManagedCursorHookEntry`, `reconcileCursorHooksJson`, `writeCursorHooksJson`, `removeCursorHooksJson`); Copilot session-hook config (`buildCopilotHookConfig`, `writeCopilotHookConfig`); Codex hook-block and event management (`buildCodexHookBlock`, `rewriteLegacyCodexHookBlock`, `reconcileCodexHooksJsonEvent`, `reconcileCodexHooksJsonSessionStart`, `ensureCodexHooksJsonSessionStart`, `ensureCodexHooksJsonEvent`, `removeCodexHooksJsonEvent`, `removeCodexHooksJsonSessionStart`, `buildCodexHookWindowsShimIR`); and shared hook command helpers (`buildHookCommand`, `rewriteLegacyManagedNodeHookCommands`, `normalizeNodePath`, `resolveNodeRunner`). `bin/install.js` delegates to this module via thin wrappers and re-exports its functions unchanged so existing tests require no modification. Source: `src/runtime-hooks-surface.cts`. Built output: `gsd-core/bin/lib/runtime-hooks-surface.cjs`. diff --git a/agents/gsd-mempalace-curator.md b/agents/gsd-mempalace-curator.md index 3bd7c1fba..b6e43a46d 100644 --- a/agents/gsd-mempalace-curator.md +++ b/agents/gsd-mempalace-curator.md @@ -22,7 +22,7 @@ If `mempalace.enabled !== true`, do nothing and report `MemPalace disabled — c ## Wing / mode / transport - **Wing:** `mempalace.wing` if non-empty, else `project_code`, else the repo directory name. Every call you make is scoped to this one wing. -- **Mode:** only `augment` is currently wired — KG writes are an additive mirror of `.planning/graphs/`. `kg_backend`/`replace` are forward-declared and behave as `augment` today. +- **Mode** (`mempalace.memory_mode`): under `augment`, KG writes are an additive mirror of `.planning/graphs/`. Under `kg_backend`/`replace`, the palace KG is the authoritative fact store — still mirror every fact here as the primary target; GSD's normal graphify keeps `.planning/graphs/` current, so an unreachable palace never loses history. - **Transport:** prefer the `mempalace_*` MCP tools interactively; fall back to the `mempalace` CLI in headless/cron runs. If neither is reachable, report unavailability and stop — do not error. ## Tasks (each independently best-effort) diff --git a/capabilities/mempalace/capability.json b/capabilities/mempalace/capability.json index 0ff3ee460..f4bce2459 100644 --- a/capabilities/mempalace/capability.json +++ b/capabilities/mempalace/capability.json @@ -37,7 +37,7 @@ "replace" ], "default": "augment", - "description": "How MemPalace relates to GSD native memory. Only 'augment' (additive) is implemented today; 'kg_backend' and 'replace' are forward-declared (routing seam not yet built) and currently behave as 'augment'." + "description": "How MemPalace relates to GSD native memory during recall/capture. 'augment' (default): the palace is an additive layer alongside .planning/graphs/ — native memory stays authoritative. 'kg_backend': knowledge-graph queries resolve against the palace's temporal KG as the primary source, with .planning/graphs/ as fallback. 'replace': recall resolves through the palace as the source of truth, native memory as fallback. Every mode stays onError:skip and default-resilient — an unreachable palace degrades to native memory, and GSD keeps writing .planning/graphs/ so no memory is lost. Cross-mode migration of existing .planning/graphs/ into the palace is a separate, not-yet-implemented concern." }, "mempalace.wing": { "type": "string", diff --git a/capabilities/mempalace/fragments/capture-problems.md b/capabilities/mempalace/fragments/capture-problems.md index 9b273c23a..122ee37d3 100644 --- a/capabilities/mempalace/fragments/capture-problems.md +++ b/capabilities/mempalace/fragments/capture-problems.md @@ -15,6 +15,6 @@ For each confirmed bug/issue resolved in this wave: 2. **Dedupe first.** Call `mempalace_check_duplicate` (interactive) before filing so re-runs don't create duplicate drawers. 3. **File the drawer verbatim.** Store the problem statement and its fix as a drawer in `room: problems` — interactive: `mempalace_add_drawer`; headless: `mempalace mine` / `mempalace hook run`. Include provenance (`source_file`, phase id). 4. **Mirror the KG fact** when `mempalace.mirror_kg` is on: add `(, fixed_by, )` with `valid_from` = the phase date via `mempalace_kg_add`. -5. **Mode awareness.** Only `augment` is currently wired: the fact is an *additive* mirror alongside `.planning/graphs/` (never a replacement). `kg_backend`/`replace` are forward-declared and behave as `augment` today. +5. **Mode awareness** (`mempalace.memory_mode`). Under `augment` the fact is an *additive* mirror alongside `.planning/graphs/`. Under `kg_backend`/`replace` the palace is the *authoritative* store for the fact; GSD still writes `.planning/graphs/` through its normal graphify, so an unreachable palace never loses it. Captures are idempotent: deterministic drawer IDs + `check_duplicate` mean re-running the wave re-files the same content without duplication. On any error, skip and let the wave complete normally. diff --git a/capabilities/mempalace/fragments/recall-discuss.md b/capabilities/mempalace/fragments/recall-discuss.md index 774287cfe..f40b2e0b2 100644 --- a/capabilities/mempalace/fragments/recall-discuss.md +++ b/capabilities/mempalace/fragments/recall-discuss.md @@ -16,7 +16,7 @@ Otherwise — before gathering new context, surface what you already know. This 3. **Targeted recall.** Search the palace for prior work on this phase's topic: - Interactive → `mempalace_search(query=, wing=)` and, when `mempalace.mirror_kg` is on, `mempalace_kg_query` / `mempalace_kg_timeline` for decision facts and their validity windows. - Headless → `mempalace search "" --wing `. -4. **Mode awareness.** Only `augment` is currently wired: always treat the palace as an *additional* recall layer on top of GSD's native memory — never skip `.planning/graphs/` or STATE. `kg_backend`/`replace` are forward-declared and behave as `augment` today. +4. **Mode awareness** (`mempalace.memory_mode`). `augment` (default): the palace is an *additional* layer — never skip `.planning/graphs/` or STATE. `kg_backend`: query the palace's temporal KG as the *primary* graph source, with `.planning/graphs/` as fallback. `replace`: resolve recall *through the palace as the source of truth*, native memory as fallback. In every mode an unreachable palace falls back to native memory — recall never blocks. 5. **Surface, don't dump.** Fold the top relevant drawers, decisions, patterns, and *surprises* into the discussion as prior context — cite drawer/fact provenance. Do not paste raw search output. If any MemPalace call errors or times out, skip the rest of recall and proceed with discussion as normal. diff --git a/commands/gsd/mempalace-capture.md b/commands/gsd/mempalace-capture.md index 271920886..6f106ef91 100644 --- a/commands/gsd/mempalace-capture.md +++ b/commands/gsd/mempalace-capture.md @@ -56,7 +56,7 @@ On any error or timeout, stop and let the phase continue -- capture is best-effo 1. **Dedup first.** Interactive: `mempalace_check_duplicate` on the artifact's deterministic drawer id. Headless: rely on `mempalace mine`'s content-hash idempotency. 2. **Add the drawer (verbatim).** File the exact artifact text into `room: ` of `wing: ` with provenance (`source_file`, phase id). Interactive: `mempalace_add_drawer`. Headless: `mempalace mine --wing --room `. -3. **Mirror KG facts** when `config.mempalace.mirror_kg` is true: extract decision/delivery facts and `mempalace_kg_add` them with `valid_from` = the phase date (e.g. `(, decided, )` from CONTEXT; `(, delivered, )` from SUMMARY). Only `augment` is currently wired, so these are an *additive* mirror of `.planning/graphs/`. (`kg_backend`/`replace` are forward-declared and behave as `augment` today.) +3. **Mirror KG facts** when `config.mempalace.mirror_kg` is true: extract decision/delivery facts and `mempalace_kg_add` them with `valid_from` = the phase date (e.g. `(, decided, )` from CONTEXT; `(, delivered, )` from SUMMARY). Under `augment` these are an *additive* mirror of GSD's native `.planning/graphs/`. Under `kg_backend`/`replace` the palace KG is the *authoritative* fact store — GSD still produces `.planning/graphs/` through its normal graphify, so an unreachable palace never loses a fact. 4. Re-running a phase MUST NOT create duplicate drawers (deterministic ids + `check_duplicate`). ## Step 4 -- Report diff --git a/commands/gsd/mempalace-recall.md b/commands/gsd/mempalace-recall.md index 14bd9df72..fc3bd367a 100644 --- a/commands/gsd/mempalace-recall.md +++ b/commands/gsd/mempalace-recall.md @@ -48,13 +48,17 @@ This step is `onError: skip` at `plan:pre` -- recall never blocks planning. ## Step 2 -- Resolve wing, mode, and transport 1. **Wing.** Use `config.mempalace.wing` if non-empty; otherwise derive from `config.project_code`; otherwise fall back to the repository directory name. -2. **Mode.** Read `config.mempalace.memory_mode` (`augment` | `kg_backend` | `replace`, default `augment`). Only `augment` is wired today, so recall always treats the palace as additive; `kg_backend`/`replace` are forward-declared and behave as `augment`. +2. **Mode.** Read `config.mempalace.memory_mode` (`augment` | `kg_backend` | `replace`, default `augment`). It sets how authoritative the palace is during recall: + - `augment` — the palace is an *additional* layer; read native memory (`.planning/graphs/`, STATE) too and treat the palace as supplementary. + - `kg_backend` — for knowledge-graph facts, query the palace's temporal KG *first, as the primary source*; fall back to `.planning/graphs/` when the palace is unreachable. Non-KG drawer recall stays additive. + - `replace` — resolve recall *through the palace as the source of truth*; consult native artifacts only as a fallback when the palace is unreachable. + In every mode an unreachable palace degrades to native memory — recall never blocks (`onError: skip`). 3. **Transport.** Prefer the **MCP tools** (`mempalace_*`) in interactive runs *when your MemPalace MCP server is registered and your runtime permits those tools*. Otherwise — headless/cron/autonomous runs, or runtimes that don't grant the MemPalace MCP tools — use the **CLI** (`mempalace wake-up`, `mempalace search`), which this skill's `Bash` allow-tool always covers. If neither is reachable, go to Step 4. 4. **Topic.** Read the phase `CONTEXT.md` (the consumed artifact). Derive a short search query from its title, goal, and key decisions. ## Step 3 -- Retrieve (read-only) -All calls in this step are side-effect-free. On any error or timeout, stop retrieving and write whatever was gathered (or the stub) -- never raise. +All calls in this step are side-effect-free. On any error or timeout, stop retrieving and write whatever was gathered (or the stub) -- never raise. This skill reads only the palace; GSD's planner reads native memory (`.planning/graphs/`, STATE) regardless. So under `kg_backend`/`replace` an unreachable palace falls back to that native memory automatically — reflect that in the stub (Step 4) rather than implying memory is gone. 1. **Wake up** (cheap, ~600--900 tokens): - Interactive: read the wing identity/summary, then `mempalace_search`. @@ -62,7 +66,7 @@ All calls in this step are side-effect-free. On any error or timeout, stop retri 2. **Targeted search:** - Interactive: `mempalace_search(query=, wing=)`. - Headless: `mempalace search "" --wing `. -3. **Knowledge-graph facts** (when `config.mempalace.mirror_kg` is true): `mempalace_kg_query` / `mempalace_kg_timeline` for decisions relevant to the topic and their validity windows. Only `augment` is currently wired, so the palace KG *supplements* GSD's native `.planning/graphs/` — do not treat it as the sole source. (`kg_backend`/`replace` are forward-declared and behave as `augment` today.) +3. **Knowledge-graph facts** (when `config.mempalace.mirror_kg` is true): `mempalace_kg_query` / `mempalace_kg_timeline` for decisions relevant to the topic and their validity windows. Under `augment` the palace KG *supplements* GSD's native `.planning/graphs/` — combine both, do not treat the palace as the sole source. Under `kg_backend` or `replace` the palace KG is the *primary* graph source — query it first and use `.planning/graphs/` only as a fallback when the palace is unreachable. 4. **Dedup** the returned drawers/facts; keep the top results. ## Step 4 -- Write MEMORY-RECALL.md @@ -86,12 +90,12 @@ _Wing: · Mode: · Transport: _ - — ``` -When MemPalace is unreachable, write the stub and continue: +When MemPalace is unreachable, write the stub and continue. Under `kg_backend`/`replace`, name the native fallback so the planner knows memory is not gone — only un-augmented by the palace this run: ```markdown # Memory Recall (MemPalace) -_MemPalace unavailable at recall time — proceeding without recalled memory._ +_MemPalace unavailable at recall time — falling back to GSD native memory (`.planning/graphs/`, STATE). No palace recall this run._ ``` ## Anti-Patterns diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 28c6d2b21..4e1a09b4b 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -667,7 +667,7 @@ MemPalace is an opt-in, default-resilient memory capability. Every hook is `onEr | Setting | Type | Default | Description | |---------|------|---------|-------------| | `mempalace.enabled` | boolean | `false` | Master gate for the MemPalace memory capability. When `false` (the default) every recall/capture hook is inactive and the loop is unchanged. All other `mempalace.*` keys are inert while this is `false`. | -| `mempalace.memory_mode` | enum: `augment`, `kg_backend`, `replace` | `augment` | How MemPalace relates to GSD native memory. `augment` (**implemented** — MemPalace is an additional write-mostly recall layer alongside GSD's native graphs/learnings; lowest coupling). `kg_backend` (**declared; routing seam not yet implemented** — intended to route graphify KG queries through MemPalace's temporal graph instead of `.planning/graphs/`; selecting this today behaves the same as `augment`). `replace` (**declared; not yet functional** — intended to make the palace the durable store for GSD memory reads; selecting this today behaves the same as `augment`). | +| `mempalace.memory_mode` | enum: `augment`, `kg_backend`, `replace` | `augment` | How authoritative MemPalace is during recall/capture. `augment` (default — an additive recall layer alongside GSD's native graphs/learnings; native memory stays authoritative; lowest coupling). `kg_backend` (knowledge-graph queries resolve against MemPalace's temporal graph as the primary source, with `.planning/graphs/` as fallback; non-KG drawer recall stays additive). `replace` (recall resolves through the palace as the source of truth, native artifacts as fallback). Every mode is `onError:skip` and default-resilient: an unreachable palace degrades to native memory and GSD keeps writing `.planning/graphs/`, so no memory is lost. Cross-mode migration of existing `.planning/graphs/` into the palace is a separate, not-yet-implemented concern. | | `mempalace.wing` | string | `""` | Palace wing name for this project. Empty (the default) derives the wing from `project_code` or the project directory name. | | `mempalace.recall_on_discuss` | boolean | `true` | When `mempalace.enabled` is `true`: inject a wake-up + semantic-search recall fragment into the orchestrator at `discuss:pre`. Surfaces prior decisions, patterns, and surprises before the discussion starts. | | `mempalace.recall_on_plan` | boolean | `true` | When `mempalace.enabled` is `true`: run the `mempalace-recall` skill at `plan:pre` to produce `MEMORY-RECALL.md` from prior decisions, patterns, and surprises relevant to the plan. | @@ -679,21 +679,21 @@ MemPalace is an opt-in, default-resilient memory capability. Every hook is `onEr #### Memory modes in detail -| Mode | `.planning/graphs` KG | Recall source | Coupling | Status | -|------|-----------------------|---------------|---------|--------| -| `augment` (default) | stays native | GSD native + palace search | lowest | **Implemented** | -| `kg_backend` | intended: routed to MemPalace temporal graph | intended: KG queries hit MemPalace | medium | **Declared — routing seam not yet implemented; behaves as `augment`** | -| `replace` | intended: backed by palace | intended: palace is the durable store | highest | **Declared — not yet functional; behaves as `augment`** | +| Mode | KG-query source | Recall source | Coupling | +|------|-----------------|---------------|---------| +| `augment` (default) | GSD native + palace (additive) | GSD native + palace search | lowest | +| `kg_backend` | palace temporal KG primary, `.planning/graphs/` fallback | GSD native + palace search | medium | +| `replace` | palace primary, native fallback | palace as source of truth, native fallback | highest | -Mode is read at hook-render time; switching modes is a config change, not a reinstall. Only `augment` has effect today — `kg_backend` and `replace` are forward-declared for a future release. +Mode is read at hook-render time; switching modes is a config change, not a reinstall. In every mode the palace is `onError:skip` and default-resilient — an unreachable palace degrades to native memory, and GSD keeps writing `.planning/graphs/` so no memory is lost. Switching an established project to `kg_backend`/`replace` changes how new recall/capture resolve but does not backfill existing `.planning/graphs/` into the palace (a separate, not-yet-implemented concern). #### Example ```bash -# Enable MemPalace (augment mode — the only implemented mode today) +# Enable MemPalace (augment is the default mode) gsd-tools query config-set mempalace.enabled true -# Forward-declared: kg_backend/replace are not yet functional (declared for future release) +# Optional: route knowledge-graph recall through the palace's temporal KG (native as fallback) # gsd-tools query config-set mempalace.memory_mode kg_backend # Enable cross-project tunnel proposals at ship:post diff --git a/docs/FEATURES.md b/docs/FEATURES.md index 637776808..0019ee7dd 100644 --- a/docs/FEATURES.md +++ b/docs/FEATURES.md @@ -3149,7 +3149,7 @@ The load-bearing wire is the `plan-phase` lift: `covered` and `backstop` edges b - REQ-MP-02: At `plan:pre`, skill `mempalace-recall` produces `MEMORY-RECALL.md` from prior decisions, patterns, and surprises retrieved via wake-up + semantic search + KG timeline. When MemPalace is unreachable, writes an "unavailable" stub and continues. - REQ-MP-03: At `discuss:post`, `plan:post`, and `verify:post`, skill `mempalace-capture` files the phase artifact verbatim into the appropriate MemPalace room (`decisions`, `planning`, `milestones`). Capture is idempotent via `mempalace_check_duplicate`. - REQ-MP-04: At `ship:post`, agent `gsd-mempalace-curator` writes a diary entry, proposes cross-project tunnels (when `mempalace.cross_project_tunnels: true`), and runs wing-scoped sync pruning. -- REQ-MP-05: `mempalace.memory_mode` declares three values: `augment` (default, **implemented** — palace is an additional recall layer alongside GSD native memory), `kg_backend` (**forward-declared; routing seam not yet implemented** — selecting this today behaves identically to `augment`), `replace` (**forward-declared; not yet functional** — selecting this today behaves identically to `augment`). Only `augment` has effect in the current release. +- REQ-MP-05: `mempalace.memory_mode` has three wired values: `augment` (default — palace is an additive recall layer alongside GSD native memory, which stays authoritative), `kg_backend` (knowledge-graph queries resolve against the palace's temporal KG as the primary source, `.planning/graphs/` as fallback; non-KG drawer recall stays additive), `replace` (recall resolves through the palace as the source of truth, native memory as fallback). Every mode is `onError:skip` and default-resilient — an unreachable palace degrades to native memory and GSD keeps writing `.planning/graphs/`, so no mode loses memory. Cross-mode migration of existing `.planning/graphs/` into the palace is out of scope (not yet implemented). - REQ-MP-06: Every hook is `onError: skip`. No hook carries `blocking: true`. Memory never halts or fails a phase. - REQ-MP-07: Interactive runs prefer MCP tools; headless/cron runs prefer the MemPalace CLI (`mempalace wake-up`, `mempalace search`, `mempalace mine`, `mempalace sync`). - REQ-MP-08: `mempalace.auto_capture_hooks` is **forward-declared and not yet functional**. No native Claude Code hooks (`stop`, `precompact`, `session-start`) are installed by this key; the capability's hooks array is empty. This key is reserved for the future "Connected Capability" phase. Default `false`. diff --git a/docs/how-to/enable-cross-session-memory-with-mempalace.md b/docs/how-to/enable-cross-session-memory-with-mempalace.md index fc01a33a5..abc0f5f6b 100644 --- a/docs/how-to/enable-cross-session-memory-with-mempalace.md +++ b/docs/how-to/enable-cross-session-memory-with-mempalace.md @@ -34,21 +34,23 @@ That is the only required step — `mempalace.enabled` is the master switch that ## Step 3 — Choose a memory mode -The `mempalace.memory_mode` key controls how tightly MemPalace couples to GSD's native memory. **Only `augment` is implemented today.** The other modes are declared for future use — selecting them today has no additional effect beyond `augment`. +The `mempalace.memory_mode` key controls how authoritative MemPalace is during recall and capture — how tightly it couples to GSD's native memory (`.planning/graphs/`, STATE, learnings). All three modes are wired. Every mode is `onError: skip` and default-resilient: an unreachable palace degrades to native memory, and GSD keeps writing `.planning/graphs/`, so no mode risks memory loss. -| Mode | What it does | When to use it | Status | -|------|-------------|----------------|--------| -| `augment` (default) | MemPalace is an additional recall layer alongside `.planning/graphs/` and learnings. Lowest coupling — palace is write-mostly and never required. | Most users. Safe to enable immediately. | **Implemented** | -| `kg_backend` | Intended to route knowledge-graph queries through MemPalace's temporal graph instead of `.planning/graphs/`. | Future use — not yet functional today. | **Declared; routing seam not yet implemented** | -| `replace` | Intended to make the palace the durable store; GSD memory reads would resolve through it. | Future use — not yet functional today. | **Declared; not yet functional** | +| Mode | What it does | When to use it | +|------|-------------|----------------| +| `augment` (default) | The palace is an *additional* recall layer alongside `.planning/graphs/` and learnings. Lowest coupling — native memory stays authoritative and the palace supplements it. | Most users. Safe to enable immediately. | +| `kg_backend` | Knowledge-graph queries resolve against the palace's temporal KG as the *primary* source; `.planning/graphs/` becomes the fallback. Non-KG drawer recall stays additive. | You want the palace's temporal KG to drive decision recall while keeping native graphs as a safety net. | +| `replace` | Recall resolves *through the palace as the source of truth*; native artifacts are consulted only as a fallback when the palace is unreachable. | You want the palace to be the authoritative memory store for this project. | -Until `kg_backend` and `replace` are implemented, changing `memory_mode` away from `augment` has no effect. Use the default and revisit when these modes ship. +Set the mode with: ```bash -# memory_mode defaults to augment (the only functional mode today) -# no change needed for most users +# augment is the default; most users need no change. +gsd-tools query config-set mempalace.memory_mode kg_backend # or: replace ``` +> **Note — cross-mode migration.** Switching an established project to `kg_backend` or `replace` changes how *new* recall and capture resolve; it does **not** retro-migrate memory already written to `.planning/graphs/` into the palace. Backfilling existing native memory into the palace is a separate, not-yet-implemented concern — choose the mode you want at the start of a project for the cleanest result. + --- ## Step 4 — Run a phase and observe recall and capture diff --git a/gsd-core/bin/lib/capability-registry.cjs b/gsd-core/bin/lib/capability-registry.cjs index 54888b319..9d2d40442 100644 --- a/gsd-core/bin/lib/capability-registry.cjs +++ b/gsd-core/bin/lib/capability-registry.cjs @@ -1450,7 +1450,7 @@ const capabilities = { "replace" ], "default": "augment", - "description": "How MemPalace relates to GSD native memory. Only 'augment' (additive) is implemented today; 'kg_backend' and 'replace' are forward-declared (routing seam not yet built) and currently behave as 'augment'." + "description": "How MemPalace relates to GSD native memory during recall/capture. 'augment' (default): the palace is an additive layer alongside .planning/graphs/ — native memory stays authoritative. 'kg_backend': knowledge-graph queries resolve against the palace's temporal KG as the primary source, with .planning/graphs/ as fallback. 'replace': recall resolves through the palace as the source of truth, native memory as fallback. Every mode stays onError:skip and default-resilient — an unreachable palace degrades to native memory, and GSD keeps writing .planning/graphs/ so no memory is lost. Cross-mode migration of existing .planning/graphs/ into the palace is a separate, not-yet-implemented concern." }, "mempalace.wing": { "type": "string", @@ -1563,7 +1563,7 @@ const capabilities = { "into": "orchestrator", "fragment": { "path": "fragments/recall-discuss.md", - "inline": "\n### Memory recall (MemPalace)\n\n**Gate first.** Read `.planning/config.json`. If `mempalace.enabled` is not `true`, or `mempalace.recall_on_discuss` is `false`, **skip this entire section** and continue the discussion unchanged. (This contribution is only injected when the capability is enabled; the `recall_on_discuss` check lets you turn discuss-time recall off without disabling the rest of the capability.)\n\nOtherwise — before gathering new context, surface what you already know. This is read-only and side-effect-free; if MemPalace is unreachable, note \"memory unavailable\" and continue — recall never blocks discussion.\n\n1. **Resolve the wing.** Use `mempalace.wing` if set; otherwise derive it from `project_code` (fall back to the project directory name).\n2. **Wake up (cheap, ~600–900 tokens).**\n - Interactive run → call `mempalace_search` after a wake-up read of the wing.\n - Headless/cron run (no MCP server) → run `mempalace wake-up --wing ` via the CLI.\n3. **Targeted recall.** Search the palace for prior work on this phase's topic:\n - Interactive → `mempalace_search(query=, wing=)` and, when `mempalace.mirror_kg` is on, `mempalace_kg_query` / `mempalace_kg_timeline` for decision facts and their validity windows.\n - Headless → `mempalace search \"\" --wing `.\n4. **Mode awareness.** Only `augment` is currently wired: always treat the palace as an *additional* recall layer on top of GSD's native memory — never skip `.planning/graphs/` or STATE. `kg_backend`/`replace` are forward-declared and behave as `augment` today.\n5. **Surface, don't dump.** Fold the top relevant drawers, decisions, patterns, and *surprises* into the discussion as prior context — cite drawer/fact provenance. Do not paste raw search output.\n\nIf any MemPalace call errors or times out, skip the rest of recall and proceed with discussion as normal.\n" + "inline": "\n### Memory recall (MemPalace)\n\n**Gate first.** Read `.planning/config.json`. If `mempalace.enabled` is not `true`, or `mempalace.recall_on_discuss` is `false`, **skip this entire section** and continue the discussion unchanged. (This contribution is only injected when the capability is enabled; the `recall_on_discuss` check lets you turn discuss-time recall off without disabling the rest of the capability.)\n\nOtherwise — before gathering new context, surface what you already know. This is read-only and side-effect-free; if MemPalace is unreachable, note \"memory unavailable\" and continue — recall never blocks discussion.\n\n1. **Resolve the wing.** Use `mempalace.wing` if set; otherwise derive it from `project_code` (fall back to the project directory name).\n2. **Wake up (cheap, ~600–900 tokens).**\n - Interactive run → call `mempalace_search` after a wake-up read of the wing.\n - Headless/cron run (no MCP server) → run `mempalace wake-up --wing ` via the CLI.\n3. **Targeted recall.** Search the palace for prior work on this phase's topic:\n - Interactive → `mempalace_search(query=, wing=)` and, when `mempalace.mirror_kg` is on, `mempalace_kg_query` / `mempalace_kg_timeline` for decision facts and their validity windows.\n - Headless → `mempalace search \"\" --wing `.\n4. **Mode awareness** (`mempalace.memory_mode`). `augment` (default): the palace is an *additional* layer — never skip `.planning/graphs/` or STATE. `kg_backend`: query the palace's temporal KG as the *primary* graph source, with `.planning/graphs/` as fallback. `replace`: resolve recall *through the palace as the source of truth*, native memory as fallback. In every mode an unreachable palace falls back to native memory — recall never blocks.\n5. **Surface, don't dump.** Fold the top relevant drawers, decisions, patterns, and *surprises* into the discussion as prior context — cite drawer/fact provenance. Do not paste raw search output.\n\nIf any MemPalace call errors or times out, skip the rest of recall and proceed with discussion as normal.\n" }, "produces": [], "consumes": [], @@ -1575,7 +1575,7 @@ const capabilities = { "into": "verifier", "fragment": { "path": "fragments/capture-problems.md", - "inline": "\n### Capture problems → fixes (MemPalace)\n\n**Gate first.** Read `.planning/config.json`. If `mempalace.enabled` is not `true`, or `mempalace.capture_artifacts` is `false`, **skip this entire section** and let the wave complete unchanged. (This contribution is only injected when the capability is enabled; the `capture_artifacts` check lets you turn capture off without disabling the rest of the capability.)\n\nOtherwise — after verifying this wave, persist any *confirmed* problem→fix pairs into the palace so they are recalled in future phases. This is best-effort; if MemPalace is unreachable, skip silently — capture never fails a wave.\n\nFor each confirmed bug/issue resolved in this wave:\n\n1. **Resolve the wing** (`mempalace.wing`, else `project_code`, else project dir) and target `room: problems`.\n2. **Dedupe first.** Call `mempalace_check_duplicate` (interactive) before filing so re-runs don't create duplicate drawers.\n3. **File the drawer verbatim.** Store the problem statement and its fix as a drawer in `room: problems` — interactive: `mempalace_add_drawer`; headless: `mempalace mine` / `mempalace hook run`. Include provenance (`source_file`, phase id).\n4. **Mirror the KG fact** when `mempalace.mirror_kg` is on: add `(, fixed_by, )` with `valid_from` = the phase date via `mempalace_kg_add`.\n5. **Mode awareness.** Only `augment` is currently wired: the fact is an *additive* mirror alongside `.planning/graphs/` (never a replacement). `kg_backend`/`replace` are forward-declared and behave as `augment` today.\n\nCaptures are idempotent: deterministic drawer IDs + `check_duplicate` mean re-running the wave re-files the same content without duplication. On any error, skip and let the wave complete normally.\n" + "inline": "\n### Capture problems → fixes (MemPalace)\n\n**Gate first.** Read `.planning/config.json`. If `mempalace.enabled` is not `true`, or `mempalace.capture_artifacts` is `false`, **skip this entire section** and let the wave complete unchanged. (This contribution is only injected when the capability is enabled; the `capture_artifacts` check lets you turn capture off without disabling the rest of the capability.)\n\nOtherwise — after verifying this wave, persist any *confirmed* problem→fix pairs into the palace so they are recalled in future phases. This is best-effort; if MemPalace is unreachable, skip silently — capture never fails a wave.\n\nFor each confirmed bug/issue resolved in this wave:\n\n1. **Resolve the wing** (`mempalace.wing`, else `project_code`, else project dir) and target `room: problems`.\n2. **Dedupe first.** Call `mempalace_check_duplicate` (interactive) before filing so re-runs don't create duplicate drawers.\n3. **File the drawer verbatim.** Store the problem statement and its fix as a drawer in `room: problems` — interactive: `mempalace_add_drawer`; headless: `mempalace mine` / `mempalace hook run`. Include provenance (`source_file`, phase id).\n4. **Mirror the KG fact** when `mempalace.mirror_kg` is on: add `(, fixed_by, )` with `valid_from` = the phase date via `mempalace_kg_add`.\n5. **Mode awareness** (`mempalace.memory_mode`). Under `augment` the fact is an *additive* mirror alongside `.planning/graphs/`. Under `kg_backend`/`replace` the palace is the *authoritative* store for the fact; GSD still writes `.planning/graphs/` through its normal graphify, so an unreachable palace never loses it.\n\nCaptures are idempotent: deterministic drawer IDs + `check_duplicate` mean re-running the wave re-files the same content without duplication. On any error, skip and let the wave complete normally.\n" }, "produces": [], "consumes": [], @@ -2482,7 +2482,7 @@ const byLoopPoint = { "into": "orchestrator", "fragment": { "path": "fragments/recall-discuss.md", - "inline": "\n### Memory recall (MemPalace)\n\n**Gate first.** Read `.planning/config.json`. If `mempalace.enabled` is not `true`, or `mempalace.recall_on_discuss` is `false`, **skip this entire section** and continue the discussion unchanged. (This contribution is only injected when the capability is enabled; the `recall_on_discuss` check lets you turn discuss-time recall off without disabling the rest of the capability.)\n\nOtherwise — before gathering new context, surface what you already know. This is read-only and side-effect-free; if MemPalace is unreachable, note \"memory unavailable\" and continue — recall never blocks discussion.\n\n1. **Resolve the wing.** Use `mempalace.wing` if set; otherwise derive it from `project_code` (fall back to the project directory name).\n2. **Wake up (cheap, ~600–900 tokens).**\n - Interactive run → call `mempalace_search` after a wake-up read of the wing.\n - Headless/cron run (no MCP server) → run `mempalace wake-up --wing ` via the CLI.\n3. **Targeted recall.** Search the palace for prior work on this phase's topic:\n - Interactive → `mempalace_search(query=, wing=)` and, when `mempalace.mirror_kg` is on, `mempalace_kg_query` / `mempalace_kg_timeline` for decision facts and their validity windows.\n - Headless → `mempalace search \"\" --wing `.\n4. **Mode awareness.** Only `augment` is currently wired: always treat the palace as an *additional* recall layer on top of GSD's native memory — never skip `.planning/graphs/` or STATE. `kg_backend`/`replace` are forward-declared and behave as `augment` today.\n5. **Surface, don't dump.** Fold the top relevant drawers, decisions, patterns, and *surprises* into the discussion as prior context — cite drawer/fact provenance. Do not paste raw search output.\n\nIf any MemPalace call errors or times out, skip the rest of recall and proceed with discussion as normal.\n" + "inline": "\n### Memory recall (MemPalace)\n\n**Gate first.** Read `.planning/config.json`. If `mempalace.enabled` is not `true`, or `mempalace.recall_on_discuss` is `false`, **skip this entire section** and continue the discussion unchanged. (This contribution is only injected when the capability is enabled; the `recall_on_discuss` check lets you turn discuss-time recall off without disabling the rest of the capability.)\n\nOtherwise — before gathering new context, surface what you already know. This is read-only and side-effect-free; if MemPalace is unreachable, note \"memory unavailable\" and continue — recall never blocks discussion.\n\n1. **Resolve the wing.** Use `mempalace.wing` if set; otherwise derive it from `project_code` (fall back to the project directory name).\n2. **Wake up (cheap, ~600–900 tokens).**\n - Interactive run → call `mempalace_search` after a wake-up read of the wing.\n - Headless/cron run (no MCP server) → run `mempalace wake-up --wing ` via the CLI.\n3. **Targeted recall.** Search the palace for prior work on this phase's topic:\n - Interactive → `mempalace_search(query=, wing=)` and, when `mempalace.mirror_kg` is on, `mempalace_kg_query` / `mempalace_kg_timeline` for decision facts and their validity windows.\n - Headless → `mempalace search \"\" --wing `.\n4. **Mode awareness** (`mempalace.memory_mode`). `augment` (default): the palace is an *additional* layer — never skip `.planning/graphs/` or STATE. `kg_backend`: query the palace's temporal KG as the *primary* graph source, with `.planning/graphs/` as fallback. `replace`: resolve recall *through the palace as the source of truth*, native memory as fallback. In every mode an unreachable palace falls back to native memory — recall never blocks.\n5. **Surface, don't dump.** Fold the top relevant drawers, decisions, patterns, and *surprises* into the discussion as prior context — cite drawer/fact provenance. Do not paste raw search output.\n\nIf any MemPalace call errors or times out, skip the rest of recall and proceed with discussion as normal.\n" }, "produces": [], "consumes": [], @@ -2774,7 +2774,7 @@ const byLoopPoint = { "into": "verifier", "fragment": { "path": "fragments/capture-problems.md", - "inline": "\n### Capture problems → fixes (MemPalace)\n\n**Gate first.** Read `.planning/config.json`. If `mempalace.enabled` is not `true`, or `mempalace.capture_artifacts` is `false`, **skip this entire section** and let the wave complete unchanged. (This contribution is only injected when the capability is enabled; the `capture_artifacts` check lets you turn capture off without disabling the rest of the capability.)\n\nOtherwise — after verifying this wave, persist any *confirmed* problem→fix pairs into the palace so they are recalled in future phases. This is best-effort; if MemPalace is unreachable, skip silently — capture never fails a wave.\n\nFor each confirmed bug/issue resolved in this wave:\n\n1. **Resolve the wing** (`mempalace.wing`, else `project_code`, else project dir) and target `room: problems`.\n2. **Dedupe first.** Call `mempalace_check_duplicate` (interactive) before filing so re-runs don't create duplicate drawers.\n3. **File the drawer verbatim.** Store the problem statement and its fix as a drawer in `room: problems` — interactive: `mempalace_add_drawer`; headless: `mempalace mine` / `mempalace hook run`. Include provenance (`source_file`, phase id).\n4. **Mirror the KG fact** when `mempalace.mirror_kg` is on: add `(, fixed_by, )` with `valid_from` = the phase date via `mempalace_kg_add`.\n5. **Mode awareness.** Only `augment` is currently wired: the fact is an *additive* mirror alongside `.planning/graphs/` (never a replacement). `kg_backend`/`replace` are forward-declared and behave as `augment` today.\n\nCaptures are idempotent: deterministic drawer IDs + `check_duplicate` mean re-running the wave re-files the same content without duplication. On any error, skip and let the wave complete normally.\n" + "inline": "\n### Capture problems → fixes (MemPalace)\n\n**Gate first.** Read `.planning/config.json`. If `mempalace.enabled` is not `true`, or `mempalace.capture_artifacts` is `false`, **skip this entire section** and let the wave complete unchanged. (This contribution is only injected when the capability is enabled; the `capture_artifacts` check lets you turn capture off without disabling the rest of the capability.)\n\nOtherwise — after verifying this wave, persist any *confirmed* problem→fix pairs into the palace so they are recalled in future phases. This is best-effort; if MemPalace is unreachable, skip silently — capture never fails a wave.\n\nFor each confirmed bug/issue resolved in this wave:\n\n1. **Resolve the wing** (`mempalace.wing`, else `project_code`, else project dir) and target `room: problems`.\n2. **Dedupe first.** Call `mempalace_check_duplicate` (interactive) before filing so re-runs don't create duplicate drawers.\n3. **File the drawer verbatim.** Store the problem statement and its fix as a drawer in `room: problems` — interactive: `mempalace_add_drawer`; headless: `mempalace mine` / `mempalace hook run`. Include provenance (`source_file`, phase id).\n4. **Mirror the KG fact** when `mempalace.mirror_kg` is on: add `(, fixed_by, )` with `valid_from` = the phase date via `mempalace_kg_add`.\n5. **Mode awareness** (`mempalace.memory_mode`). Under `augment` the fact is an *additive* mirror alongside `.planning/graphs/`. Under `kg_backend`/`replace` the palace is the *authoritative* store for the fact; GSD still writes `.planning/graphs/` through its normal graphify, so an unreachable palace never loses it.\n\nCaptures are idempotent: deterministic drawer IDs + `check_duplicate` mean re-running the wave re-files the same content without duplication. On any error, skip and let the wave complete normally.\n" }, "produces": [], "consumes": [], @@ -3118,7 +3118,7 @@ const configSchema = { "owner": "mempalace", "type": "enum", "default": "augment", - "description": "How MemPalace relates to GSD native memory. Only 'augment' (additive) is implemented today; 'kg_backend' and 'replace' are forward-declared (routing seam not yet built) and currently behave as 'augment'.", + "description": "How MemPalace relates to GSD native memory during recall/capture. 'augment' (default): the palace is an additive layer alongside .planning/graphs/ — native memory stays authoritative. 'kg_backend': knowledge-graph queries resolve against the palace's temporal KG as the primary source, with .planning/graphs/ as fallback. 'replace': recall resolves through the palace as the source of truth, native memory as fallback. Every mode stays onError:skip and default-resilient — an unreachable palace degrades to native memory, and GSD keeps writing .planning/graphs/ so no memory is lost. Cross-mode migration of existing .planning/graphs/ into the palace is a separate, not-yet-implemented concern.", "values": [ "augment", "kg_backend", diff --git a/skills/gsd-mempalace-capture/SKILL.md b/skills/gsd-mempalace-capture/SKILL.md index 5841295ab..9baa41e6c 100644 --- a/skills/gsd-mempalace-capture/SKILL.md +++ b/skills/gsd-mempalace-capture/SKILL.md @@ -56,7 +56,7 @@ On any error or timeout, stop and let the phase continue -- capture is best-effo 1. **Dedup first.** Interactive: `mempalace_check_duplicate` on the artifact's deterministic drawer id. Headless: rely on `mempalace mine`'s content-hash idempotency. 2. **Add the drawer (verbatim).** File the exact artifact text into `room: ` of `wing: ` with provenance (`source_file`, phase id). Interactive: `mempalace_add_drawer`. Headless: `mempalace mine --wing --room `. -3. **Mirror KG facts** when `config.mempalace.mirror_kg` is true: extract decision/delivery facts and `mempalace_kg_add` them with `valid_from` = the phase date (e.g. `(, decided, )` from CONTEXT; `(, delivered, )` from SUMMARY). Only `augment` is currently wired, so these are an *additive* mirror of `.planning/graphs/`. (`kg_backend`/`replace` are forward-declared and behave as `augment` today.) +3. **Mirror KG facts** when `config.mempalace.mirror_kg` is true: extract decision/delivery facts and `mempalace_kg_add` them with `valid_from` = the phase date (e.g. `(, decided, )` from CONTEXT; `(, delivered, )` from SUMMARY). Under `augment` these are an *additive* mirror of GSD's native `.planning/graphs/`. Under `kg_backend`/`replace` the palace KG is the *authoritative* fact store — GSD still produces `.planning/graphs/` through its normal graphify, so an unreachable palace never loses a fact. 4. Re-running a phase MUST NOT create duplicate drawers (deterministic ids + `check_duplicate`). ## Step 4 -- Report diff --git a/skills/gsd-mempalace-recall/SKILL.md b/skills/gsd-mempalace-recall/SKILL.md index e427164b3..a62169980 100644 --- a/skills/gsd-mempalace-recall/SKILL.md +++ b/skills/gsd-mempalace-recall/SKILL.md @@ -48,13 +48,17 @@ This step is `onError: skip` at `plan:pre` -- recall never blocks planning. ## Step 2 -- Resolve wing, mode, and transport 1. **Wing.** Use `config.mempalace.wing` if non-empty; otherwise derive from `config.project_code`; otherwise fall back to the repository directory name. -2. **Mode.** Read `config.mempalace.memory_mode` (`augment` | `kg_backend` | `replace`, default `augment`). Only `augment` is wired today, so recall always treats the palace as additive; `kg_backend`/`replace` are forward-declared and behave as `augment`. +2. **Mode.** Read `config.mempalace.memory_mode` (`augment` | `kg_backend` | `replace`, default `augment`). It sets how authoritative the palace is during recall: + - `augment` — the palace is an *additional* layer; read native memory (`.planning/graphs/`, STATE) too and treat the palace as supplementary. + - `kg_backend` — for knowledge-graph facts, query the palace's temporal KG *first, as the primary source*; fall back to `.planning/graphs/` when the palace is unreachable. Non-KG drawer recall stays additive. + - `replace` — resolve recall *through the palace as the source of truth*; consult native artifacts only as a fallback when the palace is unreachable. + In every mode an unreachable palace degrades to native memory — recall never blocks (`onError: skip`). 3. **Transport.** Prefer the **MCP tools** (`mempalace_*`) in interactive runs *when your MemPalace MCP server is registered and your runtime permits those tools*. Otherwise — headless/cron/autonomous runs, or runtimes that don't grant the MemPalace MCP tools — use the **CLI** (`mempalace wake-up`, `mempalace search`), which this skill's `Bash` allow-tool always covers. If neither is reachable, go to Step 4. 4. **Topic.** Read the phase `CONTEXT.md` (the consumed artifact). Derive a short search query from its title, goal, and key decisions. ## Step 3 -- Retrieve (read-only) -All calls in this step are side-effect-free. On any error or timeout, stop retrieving and write whatever was gathered (or the stub) -- never raise. +All calls in this step are side-effect-free. On any error or timeout, stop retrieving and write whatever was gathered (or the stub) -- never raise. This skill reads only the palace; GSD's planner reads native memory (`.planning/graphs/`, STATE) regardless. So under `kg_backend`/`replace` an unreachable palace falls back to that native memory automatically — reflect that in the stub (Step 4) rather than implying memory is gone. 1. **Wake up** (cheap, ~600--900 tokens): - Interactive: read the wing identity/summary, then `mempalace_search`. @@ -62,7 +66,7 @@ All calls in this step are side-effect-free. On any error or timeout, stop retri 2. **Targeted search:** - Interactive: `mempalace_search(query=, wing=)`. - Headless: `mempalace search "" --wing `. -3. **Knowledge-graph facts** (when `config.mempalace.mirror_kg` is true): `mempalace_kg_query` / `mempalace_kg_timeline` for decisions relevant to the topic and their validity windows. Only `augment` is currently wired, so the palace KG *supplements* GSD's native `.planning/graphs/` — do not treat it as the sole source. (`kg_backend`/`replace` are forward-declared and behave as `augment` today.) +3. **Knowledge-graph facts** (when `config.mempalace.mirror_kg` is true): `mempalace_kg_query` / `mempalace_kg_timeline` for decisions relevant to the topic and their validity windows. Under `augment` the palace KG *supplements* GSD's native `.planning/graphs/` — combine both, do not treat the palace as the sole source. Under `kg_backend` or `replace` the palace KG is the *primary* graph source — query it first and use `.planning/graphs/` only as a fallback when the palace is unreachable. 4. **Dedup** the returned drawers/facts; keep the top results. ## Step 4 -- Write MEMORY-RECALL.md @@ -86,12 +90,12 @@ _Wing: · Mode: · Transport: _ - — ``` -When MemPalace is unreachable, write the stub and continue: +When MemPalace is unreachable, write the stub and continue. Under `kg_backend`/`replace`, name the native fallback so the planner knows memory is not gone — only un-augmented by the palace this run: ```markdown # Memory Recall (MemPalace) -_MemPalace unavailable at recall time — proceeding without recalled memory._ +_MemPalace unavailable at recall time — falling back to GSD native memory (`.planning/graphs/`, STATE). No palace recall this run._ ``` ## Anti-Patterns diff --git a/tests/agent-size-baseline.json b/tests/agent-size-baseline.json index 3f94f8657..5374cf811 100644 --- a/tests/agent-size-baseline.json +++ b/tests/agent-size-baseline.json @@ -18,7 +18,7 @@ "gsd-framework-selector.md": 6778, "gsd-integration-checker.md": 15238, "gsd-intel-updater.md": 18166, - "gsd-mempalace-curator.md": 4160, + "gsd-mempalace-curator.md": 4325, "gsd-nyquist-auditor.md": 7345, "gsd-pattern-mapper.md": 12487, "gsd-phase-researcher.md": 40832, diff --git a/tests/capability-registry.test.cjs b/tests/capability-registry.test.cjs index 082a78751..c4b902f1f 100644 --- a/tests/capability-registry.test.cjs +++ b/tests/capability-registry.test.cjs @@ -15,8 +15,6 @@ const fs = require('node:fs'); const os = require('node:os'); const path = require('node:path'); -const { spawnSync } = require('node:child_process'); - const { cleanup } = require('./helpers.cjs'); const { @@ -6012,6 +6010,118 @@ describe('fix-1628 capability validation: mempalace.memory_mode (enum)', () => { }); }); +// ─── ROUTING CONTRACT: mempalace.memory_mode wired behavior (#2007) ─────────── +// +// memory_mode is an instruction-only contract: `augment`/`kg_backend`/`replace` +// change how the mempalace recall/capture/curator markdown tells the agent to +// treat the palace vs. GSD native memory. There is no code branch to unit-test, +// so the governed surface IS the instruction text across five parallel surfaces +// plus the capability schema. This block asserts (a) every mode is named with +// distinct, non-forward-declared routing, and (b) the parallel surfaces stay in +// parity so a future edit can't silently revert one to the inert state +// (CLAUDE.md Generative Fix Divergence). Reads .md/.json only — the no-source-grep +// rule targets .cjs/.js/.ts source reads, so no allow-test-rule exemption applies. + +describe('#2007 mempalace.memory_mode routing contract (instruction surfaces)', () => { + const MODES = ['augment', 'kg_backend', 'replace']; + + // The five parallel instruction surfaces that must express per-mode routing. + const SURFACES = [ + 'capabilities/mempalace/fragments/recall-discuss.md', + 'capabilities/mempalace/fragments/capture-problems.md', + 'commands/gsd/mempalace-recall.md', + 'commands/gsd/mempalace-capture.md', + 'agents/gsd-mempalace-curator.md', + ]; + + // Retired forward-declaration hedges — the presence of any one means a surface + // reverted to the pre-#2007 inert state where the modes did nothing. + const RETIRED_HEDGES = [ + 'forward-declared', + 'behave as `augment`', + 'behaves as `augment`', + 'not yet functional', + 'routing seam not yet', + 'Only `augment` is currently wired', + 'Only `augment` is wired', + ]; + + for (const rel of SURFACES) { + const body = fs.readFileSync(path.join(ROOT, rel), 'utf8'); + + test(`${rel} names all three memory modes`, () => { + for (const m of MODES) { + assert.ok( + body.includes('`' + m + '`'), + `${rel} must reference mode \`${m}\`` + ); + } + }); + + test(`${rel} carries no retired forward-declaration hedge`, () => { + for (const hedge of RETIRED_HEDGES) { + assert.ok( + !body.includes(hedge), + `${rel} still contains retired hedge "${hedge}" — memory_mode must describe wired per-mode routing, not a forward-declaration` + ); + } + }); + + test(`${rel} expresses both halves of the routing contract (palace-primary + native-fallback)`, () => { + // The wired contract is a duality: kg_backend/replace make the palace + // primary/authoritative, AND every mode keeps native memory as a + // fallback/mirror so the capability stays default-resilient (an unreachable + // palace never loses memory). A surface that expresses only one half is a + // defect — this guards the exact contradiction the #2007 review surfaced. + assert.match( + body, + /primary|authoritative|source of truth/i, + `${rel} must describe kg_backend/replace treating the palace as primary/authoritative` + ); + assert.match( + body, + /fallback|mirror|additive|supplement/i, + `${rel} must describe the native-memory fallback/mirror relationship (default-resilience)` + ); + assert.ok( + body.includes('.planning/graphs'), + `${rel} must anchor the native memory surface (.planning/graphs/) that the palace augments/falls back to` + ); + }); + } + + test('capability.json memory_mode schema declares the three modes and drops the not-implemented claim', () => { + const cap = JSON.parse( + fs.readFileSync( + path.join(ROOT, 'capabilities/mempalace/capability.json'), + 'utf8' + ) + ); + const mode = cap.config['mempalace.memory_mode']; + assert.deepEqual( + mode.values, + MODES, + 'enum values must be exactly [augment, kg_backend, replace]' + ); + assert.equal( + mode.default, + 'augment', + 'default stays augment (default-resilient)' + ); + for (const hedge of [ + 'forward-declared', + 'not yet built', + 'behave as', + 'behaves the same as', + ]) { + assert.ok( + !mode.description.includes(hedge), + `schema description must not claim the modes are unimplemented (found "${hedge}")` + ); + } + }); +}); + // ─── BOOLEAN: workflow.tdd_mode ────────────────────────────────────────────── describe('fix-1628 capability validation: workflow.tdd_mode (boolean)', () => { diff --git a/tests/fixtures/golden-install-parity/antigravity.json b/tests/fixtures/golden-install-parity/antigravity.json index d4c0ab94c..e884fbf03 100644 --- a/tests/fixtures/golden-install-parity/antigravity.json +++ b/tests/fixtures/golden-install-parity/antigravity.json @@ -20,7 +20,7 @@ "agents/gsd-framework-selector.md": "daa62c79619c76bf", "agents/gsd-integration-checker.md": "0643cd2d779b131c", "agents/gsd-intel-updater.md": "26c1f1e028c6346a", - "agents/gsd-mempalace-curator.md": "a7269018acb973ce", + "agents/gsd-mempalace-curator.md": "dafdc4394d514a93", "agents/gsd-nyquist-auditor.md": "805a1404d03629f1", "agents/gsd-pattern-mapper.md": "e62ee90d39084802", "agents/gsd-phase-researcher.md": "cff1196c8e8bb4fa", @@ -367,8 +367,8 @@ "skills/gsd-ingest-docs/SKILL.md": "f4e43968af317ed8", "skills/gsd-manager/SKILL.md": "6e51785860784d8c", "skills/gsd-map-codebase/SKILL.md": "e10431a9386c6aec", - "skills/gsd-mempalace-capture/SKILL.md": "5647f915e5c85482", - "skills/gsd-mempalace-recall/SKILL.md": "d41523e659d1920f", + "skills/gsd-mempalace-capture/SKILL.md": "588ddf4fbf3ebe65", + "skills/gsd-mempalace-recall/SKILL.md": "2d95e385fee26dee", "skills/gsd-milestone-summary/SKILL.md": "2955ab3e3a444ca3", "skills/gsd-mvp-phase/SKILL.md": "1cf7622d655840ac", "skills/gsd-new-milestone/SKILL.md": "f97a28dd1e2b9317", diff --git a/tests/fixtures/golden-install-parity/augment.json b/tests/fixtures/golden-install-parity/augment.json index e68a5edae..e3557f981 100644 --- a/tests/fixtures/golden-install-parity/augment.json +++ b/tests/fixtures/golden-install-parity/augment.json @@ -20,7 +20,7 @@ "agents/gsd-framework-selector.md": "4b77eebbe9288d80", "agents/gsd-integration-checker.md": "fa53e2d78be1de74", "agents/gsd-intel-updater.md": "fa40e685d7441ace", - "agents/gsd-mempalace-curator.md": "63676937f8970bf3", + "agents/gsd-mempalace-curator.md": "78f4894a9d5f44b1", "agents/gsd-nyquist-auditor.md": "230e6667411ccf2f", "agents/gsd-pattern-mapper.md": "43c6021cf7caabfa", "agents/gsd-phase-researcher.md": "f1f6fd6a3e67c7a8", @@ -63,8 +63,8 @@ "commands/gsd-ingest-docs.md": "6718b04c597a5428", "commands/gsd-manager.md": "8f4ae79774902293", "commands/gsd-map-codebase.md": "f3a06c4c7503f243", - "commands/gsd-mempalace-capture.md": "016a90f0eb7493ac", - "commands/gsd-mempalace-recall.md": "babb21998c7e6a6f", + "commands/gsd-mempalace-capture.md": "2e610f3ebe2eb5b4", + "commands/gsd-mempalace-recall.md": "38716c0983a3ef9c", "commands/gsd-milestone-summary.md": "ff5e11e6b33d4b5e", "commands/gsd-mvp-phase.md": "ffc5905aed8f450a", "commands/gsd-new-milestone.md": "e9ddaec1dd29d023", @@ -414,8 +414,8 @@ "skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "48846bf26ccaf0e7", "skills/gsd-ns-context/skills/graphify/SKILL.md": "3d6341614add6ccd", "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "51d6b970dca3c28e", - "skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "c585b152e9d9d6d3", - "skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "1a3267902234c607", + "skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "a7261b5ead71cc58", + "skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "646e59e76acd548f", "skills/gsd-ns-ideate/SKILL.md": "d70360a5f7e8ac90", "skills/gsd-ns-ideate/skills/capture/SKILL.md": "74651f6959cfbbd3", "skills/gsd-ns-ideate/skills/explore/SKILL.md": "bb8413dc283a5bb1", diff --git a/tests/fixtures/golden-install-parity/claude.json b/tests/fixtures/golden-install-parity/claude.json index cc89fc1d4..7a285ad10 100644 --- a/tests/fixtures/golden-install-parity/claude.json +++ b/tests/fixtures/golden-install-parity/claude.json @@ -19,7 +19,7 @@ "agents/gsd-framework-selector.md": "c350ee693cb1aa4e", "agents/gsd-integration-checker.md": "c8b4e65dee89c8ea", "agents/gsd-intel-updater.md": "5b41e05f90ce89d9", - "agents/gsd-mempalace-curator.md": "61c387c3fd9bae78", + "agents/gsd-mempalace-curator.md": "77b53f1b155242b4", "agents/gsd-nyquist-auditor.md": "0bc0cdad7b3a0013", "agents/gsd-pattern-mapper.md": "b45b5e106775bec1", "agents/gsd-phase-researcher.md": "529a4573230b104e", @@ -366,8 +366,8 @@ "skills/gsd-ingest-docs/SKILL.md": "eb85e654917a503a", "skills/gsd-manager/SKILL.md": "1370d93741e47828", "skills/gsd-map-codebase/SKILL.md": "5009595dbde69739", - "skills/gsd-mempalace-capture/SKILL.md": "e9b66db79fce0a2f", - "skills/gsd-mempalace-recall/SKILL.md": "9bfa9e76c7a10e26", + "skills/gsd-mempalace-capture/SKILL.md": "40a31ad049374297", + "skills/gsd-mempalace-recall/SKILL.md": "c3f412d5a64f3921", "skills/gsd-milestone-summary/SKILL.md": "33d51a325d314f3a", "skills/gsd-mvp-phase/SKILL.md": "f9a1348c6c297579", "skills/gsd-new-milestone/SKILL.md": "ac99ffb8a966fe9d", diff --git a/tests/fixtures/golden-install-parity/cline.json b/tests/fixtures/golden-install-parity/cline.json index 12e67ac45..734dc44ab 100644 --- a/tests/fixtures/golden-install-parity/cline.json +++ b/tests/fixtures/golden-install-parity/cline.json @@ -23,7 +23,7 @@ "agents/gsd-framework-selector.md": "564669d479433f15", "agents/gsd-integration-checker.md": "1bbbdd3d420b994e", "agents/gsd-intel-updater.md": "42c40fffbc720d0b", - "agents/gsd-mempalace-curator.md": "63676937f8970bf3", + "agents/gsd-mempalace-curator.md": "78f4894a9d5f44b1", "agents/gsd-nyquist-auditor.md": "4f9bba7b9762835d", "agents/gsd-pattern-mapper.md": "b526065fd2efa19c", "agents/gsd-phase-researcher.md": "c507db2ba66038f4", @@ -325,8 +325,8 @@ "skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "d39269bea995fabc", "skills/gsd-ns-context/skills/graphify/SKILL.md": "030050fcd08d129d", "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "19aec854da15f77b", - "skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "5647f915e5c85482", - "skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "d41523e659d1920f", + "skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "588ddf4fbf3ebe65", + "skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "2d95e385fee26dee", "skills/gsd-ns-ideate/SKILL.md": "c10342345c01c91f", "skills/gsd-ns-ideate/skills/capture/SKILL.md": "fb53053848bb6695", "skills/gsd-ns-ideate/skills/explore/SKILL.md": "d8e26a5ed95a4ecc", diff --git a/tests/fixtures/golden-install-parity/codebuddy.json b/tests/fixtures/golden-install-parity/codebuddy.json index 160dc8aba..09416cee7 100644 --- a/tests/fixtures/golden-install-parity/codebuddy.json +++ b/tests/fixtures/golden-install-parity/codebuddy.json @@ -20,7 +20,7 @@ "agents/gsd-framework-selector.md": "7726fccc86bfeb50", "agents/gsd-integration-checker.md": "2d8339790bbb2dc3", "agents/gsd-intel-updater.md": "c51339956197cbd3", - "agents/gsd-mempalace-curator.md": "63676937f8970bf3", + "agents/gsd-mempalace-curator.md": "78f4894a9d5f44b1", "agents/gsd-nyquist-auditor.md": "42676eea063d2ec5", "agents/gsd-pattern-mapper.md": "92cfa2e6c2a06bf3", "agents/gsd-phase-researcher.md": "6338474da1a5d65e", @@ -63,8 +63,8 @@ "commands/gsd-ingest-docs.md": "ab3e58239c23d61d", "commands/gsd-manager.md": "bfe9e261fa918876", "commands/gsd-map-codebase.md": "9ed09a9a9ce48ffd", - "commands/gsd-mempalace-capture.md": "6fa6ca7a1ecd562d", - "commands/gsd-mempalace-recall.md": "146d97ab543d8df2", + "commands/gsd-mempalace-capture.md": "e9e00b0602e1d8b8", + "commands/gsd-mempalace-recall.md": "6efef238d8c62569", "commands/gsd-milestone-summary.md": "e3a36fbd695a1833", "commands/gsd-mvp-phase.md": "671791ba61c4654a", "commands/gsd-new-milestone.md": "00b5d757991941c7", @@ -437,8 +437,8 @@ "skills/gsd-ingest-docs/SKILL.md": "2df55e0ec95d57d9", "skills/gsd-manager/SKILL.md": "816db4d4ed618537", "skills/gsd-map-codebase/SKILL.md": "00622b489483ba69", - "skills/gsd-mempalace-capture/SKILL.md": "12a57bef275e2961", - "skills/gsd-mempalace-recall/SKILL.md": "69275abbee414350", + "skills/gsd-mempalace-capture/SKILL.md": "5f10d368835e062c", + "skills/gsd-mempalace-recall/SKILL.md": "70c8491f53f4161b", "skills/gsd-milestone-summary/SKILL.md": "9eb030a1ac307fa1", "skills/gsd-mvp-phase/SKILL.md": "236fcdd69f47d101", "skills/gsd-new-milestone/SKILL.md": "be371ad30631385e", diff --git a/tests/fixtures/golden-install-parity/codex.json b/tests/fixtures/golden-install-parity/codex.json index 71546779d..f150fac04 100644 --- a/tests/fixtures/golden-install-parity/codex.json +++ b/tests/fixtures/golden-install-parity/codex.json @@ -39,8 +39,8 @@ "agents/gsd-integration-checker.toml": "53f3cfac6fbd6447", "agents/gsd-intel-updater.md": "8e5453421c92c0fd", "agents/gsd-intel-updater.toml": "94888d7182fd2fb5", - "agents/gsd-mempalace-curator.md": "159f24243bf3acfb", - "agents/gsd-mempalace-curator.toml": "30bcaf1ca0b926db", + "agents/gsd-mempalace-curator.md": "60a8ec0e990ba777", + "agents/gsd-mempalace-curator.toml": "015f156ad7d2dd0f", "agents/gsd-nyquist-auditor.md": "554dbb4a01760a9d", "agents/gsd-nyquist-auditor.toml": "b3d7214b42fb67fa", "agents/gsd-pattern-mapper.md": "efbcfa7c5de4027f", @@ -382,8 +382,8 @@ "skills/gsd-ingest-docs/SKILL.md": "5bd2838bf0b6dc1b", "skills/gsd-manager/SKILL.md": "cb1cf56f5d3f66d6", "skills/gsd-map-codebase/SKILL.md": "25d0b3adfc8b75dc", - "skills/gsd-mempalace-capture/SKILL.md": "65164de8f661d217", - "skills/gsd-mempalace-recall/SKILL.md": "4fd21539559aed6c", + "skills/gsd-mempalace-capture/SKILL.md": "1a7fac4d53f607ab", + "skills/gsd-mempalace-recall/SKILL.md": "7205b02250e89f25", "skills/gsd-milestone-summary/SKILL.md": "af84ecb400f23556", "skills/gsd-mvp-phase/SKILL.md": "72b65ae927b280fe", "skills/gsd-new-milestone/SKILL.md": "587574d2d475bb10", diff --git a/tests/fixtures/golden-install-parity/copilot.json b/tests/fixtures/golden-install-parity/copilot.json index ee76933b3..c375753f6 100644 --- a/tests/fixtures/golden-install-parity/copilot.json +++ b/tests/fixtures/golden-install-parity/copilot.json @@ -20,7 +20,7 @@ "agents/gsd-framework-selector.agent.md": "cafeec0b3489be45", "agents/gsd-integration-checker.agent.md": "30439b804927acc7", "agents/gsd-intel-updater.agent.md": "238c1a886f35a25c", - "agents/gsd-mempalace-curator.agent.md": "bbb2c654e8fbf8fb", + "agents/gsd-mempalace-curator.agent.md": "9e5290ea4c4ac211", "agents/gsd-nyquist-auditor.agent.md": "6463a50d90ada125", "agents/gsd-pattern-mapper.agent.md": "b1f488b0fa6a2395", "agents/gsd-phase-researcher.agent.md": "fc6062a07152951b", @@ -347,8 +347,8 @@ "skills/gsd-ingest-docs/SKILL.md": "10500de29525f6cf", "skills/gsd-manager/SKILL.md": "9946975bec15e737", "skills/gsd-map-codebase/SKILL.md": "75806f8189d8af49", - "skills/gsd-mempalace-capture/SKILL.md": "d7e72629ec3772e2", - "skills/gsd-mempalace-recall/SKILL.md": "5f397524acf592d1", + "skills/gsd-mempalace-capture/SKILL.md": "f4511f69c14befb7", + "skills/gsd-mempalace-recall/SKILL.md": "89523db66f834b2f", "skills/gsd-milestone-summary/SKILL.md": "5ca1dabfe0cd85f0", "skills/gsd-mvp-phase/SKILL.md": "60ac3c3fa6a6a19b", "skills/gsd-new-milestone/SKILL.md": "e5eafe44e271bb92", diff --git a/tests/fixtures/golden-install-parity/cursor.json b/tests/fixtures/golden-install-parity/cursor.json index c73beb88e..dc2e7f08f 100644 --- a/tests/fixtures/golden-install-parity/cursor.json +++ b/tests/fixtures/golden-install-parity/cursor.json @@ -20,7 +20,7 @@ "agents/gsd-framework-selector.md": "4b77eebbe9288d80", "agents/gsd-integration-checker.md": "5da30584d06b878c", "agents/gsd-intel-updater.md": "b8971c5d96e63b38", - "agents/gsd-mempalace-curator.md": "63676937f8970bf3", + "agents/gsd-mempalace-curator.md": "78f4894a9d5f44b1", "agents/gsd-nyquist-auditor.md": "e18b0209cea56a2e", "agents/gsd-pattern-mapper.md": "1229c215677f740d", "agents/gsd-phase-researcher.md": "982d59921bed463d", @@ -63,8 +63,8 @@ "commands/gsd-ingest-docs.md": "9e7f8757b9408c01", "commands/gsd-manager.md": "f300b708a5487c76", "commands/gsd-map-codebase.md": "cf50f4a600119c8a", - "commands/gsd-mempalace-capture.md": "eab7aa94d6e71138", - "commands/gsd-mempalace-recall.md": "7da498f89250cb0f", + "commands/gsd-mempalace-capture.md": "b30bce634ac3136c", + "commands/gsd-mempalace-recall.md": "08c910285469a394", "commands/gsd-milestone-summary.md": "adfad2cf43fc5aad", "commands/gsd-mvp-phase.md": "e8debeee627a0bf2", "commands/gsd-new-milestone.md": "64b997f99b1e6293", @@ -417,8 +417,8 @@ "skills/gsd-ingest-docs/SKILL.md": "01ed9183a00252ee", "skills/gsd-manager/SKILL.md": "62cd9f671a39e8a4", "skills/gsd-map-codebase/SKILL.md": "f529da27d3a30b09", - "skills/gsd-mempalace-capture/SKILL.md": "c6e93f22453145e8", - "skills/gsd-mempalace-recall/SKILL.md": "62c697606d67eddc", + "skills/gsd-mempalace-capture/SKILL.md": "b308823dee547c65", + "skills/gsd-mempalace-recall/SKILL.md": "56f3037091a8bd9a", "skills/gsd-milestone-summary/SKILL.md": "c5dbbc8edb97a7f7", "skills/gsd-mvp-phase/SKILL.md": "9d8e2999fa9f7830", "skills/gsd-new-milestone/SKILL.md": "642d0741c89b911a", diff --git a/tests/fixtures/golden-install-parity/hermes.json b/tests/fixtures/golden-install-parity/hermes.json index 305d3a9eb..2bb6ec260 100644 --- a/tests/fixtures/golden-install-parity/hermes.json +++ b/tests/fixtures/golden-install-parity/hermes.json @@ -20,7 +20,7 @@ "agents/gsd-framework-selector.md": "ea9981d65d6b3429", "agents/gsd-integration-checker.md": "35b4f2969d279871", "agents/gsd-intel-updater.md": "5fe5edfae2719cb8", - "agents/gsd-mempalace-curator.md": "576b8d0db51bc462", + "agents/gsd-mempalace-curator.md": "399e90e473b33814", "agents/gsd-nyquist-auditor.md": "8bfde4a9a36318aa", "agents/gsd-pattern-mapper.md": "cea092600aeb3978", "agents/gsd-phase-researcher.md": "1c73b638d891363e", @@ -345,8 +345,8 @@ "skills/gsd/gsd-ns-context/skills/extract-learnings/SKILL.md": "36e59d6e514dcaf0", "skills/gsd/gsd-ns-context/skills/graphify/SKILL.md": "169eefd42c444cde", "skills/gsd/gsd-ns-context/skills/map-codebase/SKILL.md": "6062ccca1a14b827", - "skills/gsd/gsd-ns-context/skills/mempalace-capture/SKILL.md": "1565901c4833a49e", - "skills/gsd/gsd-ns-context/skills/mempalace-recall/SKILL.md": "eba3ad69c0e7b157", + "skills/gsd/gsd-ns-context/skills/mempalace-capture/SKILL.md": "3fa619f73834c436", + "skills/gsd/gsd-ns-context/skills/mempalace-recall/SKILL.md": "5d06922e0d7ab7d9", "skills/gsd/gsd-ns-ideate/SKILL.md": "b36bb4700ed6723a", "skills/gsd/gsd-ns-ideate/skills/capture/SKILL.md": "76fc7c1200124ece", "skills/gsd/gsd-ns-ideate/skills/explore/SKILL.md": "bb39acf6117cb9ca", diff --git a/tests/fixtures/golden-install-parity/kilo.json b/tests/fixtures/golden-install-parity/kilo.json index 490b8b7ec..4818d444d 100644 --- a/tests/fixtures/golden-install-parity/kilo.json +++ b/tests/fixtures/golden-install-parity/kilo.json @@ -20,7 +20,7 @@ "agents/gsd-framework-selector.md": "ad5f2c6b9bec6270", "agents/gsd-integration-checker.md": "c503e2f4a3d8ec05", "agents/gsd-intel-updater.md": "231393da62a45b2e", - "agents/gsd-mempalace-curator.md": "6461da48ed937556", + "agents/gsd-mempalace-curator.md": "c6a7fe754b6ca5e1", "agents/gsd-nyquist-auditor.md": "7bc3cc159c7be987", "agents/gsd-pattern-mapper.md": "6a5408fd11d70391", "agents/gsd-phase-researcher.md": "94818f28c498bb26", @@ -63,8 +63,8 @@ "command/gsd-ingest-docs.md": "e655ecf1d4433ba9", "command/gsd-manager.md": "1cdc133079833552", "command/gsd-map-codebase.md": "186c8f79319abc1c", - "command/gsd-mempalace-capture.md": "08b9750f1b1d1ba6", - "command/gsd-mempalace-recall.md": "2316f1a950490845", + "command/gsd-mempalace-capture.md": "a94ca275cbe7134c", + "command/gsd-mempalace-recall.md": "d358cdd89c935877", "command/gsd-milestone-summary.md": "4ab29b777f62f0bb", "command/gsd-mvp-phase.md": "273a1c26ca13274b", "command/gsd-new-milestone.md": "a315b3205c5d3470", @@ -438,8 +438,8 @@ "skills/gsd-ingest-docs/SKILL.md": "f049f06a6ec7da43", "skills/gsd-manager/SKILL.md": "a37ecdbe32952262", "skills/gsd-map-codebase/SKILL.md": "e8c01704e8ada1d2", - "skills/gsd-mempalace-capture/SKILL.md": "260e1dabc7014ba2", - "skills/gsd-mempalace-recall/SKILL.md": "045d85c8cab1afcc", + "skills/gsd-mempalace-capture/SKILL.md": "f960b7b1a8fdf89b", + "skills/gsd-mempalace-recall/SKILL.md": "2091c48e6e986e28", "skills/gsd-milestone-summary/SKILL.md": "da645171ca2299d8", "skills/gsd-mvp-phase/SKILL.md": "eeb0ac0f88647475", "skills/gsd-new-milestone/SKILL.md": "bc8989d97f3161ad", diff --git a/tests/fixtures/golden-install-parity/kimi.json b/tests/fixtures/golden-install-parity/kimi.json index 64f7812a0..fce5a3af1 100644 --- a/tests/fixtures/golden-install-parity/kimi.json +++ b/tests/fixtures/golden-install-parity/kimi.json @@ -41,7 +41,7 @@ "agents/subagents/gsd-integration-checker.yaml": "3500c65ccbbe432d", "agents/subagents/gsd-intel-updater.md": "1964fb57cf27be8d", "agents/subagents/gsd-intel-updater.yaml": "01445ee99bec4b31", - "agents/subagents/gsd-mempalace-curator.md": "34b7476d313bfda4", + "agents/subagents/gsd-mempalace-curator.md": "62b7c34d6c33ed0b", "agents/subagents/gsd-mempalace-curator.yaml": "28dd095c371ada3b", "agents/subagents/gsd-nyquist-auditor.md": "d9dbd1e92e2598c2", "agents/subagents/gsd-nyquist-auditor.yaml": "48ad300fa775dd5d", @@ -381,8 +381,8 @@ "skills/gsd-ingest-docs/SKILL.md": "6366644e623ae9e4", "skills/gsd-manager/SKILL.md": "8a11a1beb8e35a9c", "skills/gsd-map-codebase/SKILL.md": "55dade835b0f4954", - "skills/gsd-mempalace-capture/SKILL.md": "3746fa9b34e20e71", - "skills/gsd-mempalace-recall/SKILL.md": "07b1b0e767da162c", + "skills/gsd-mempalace-capture/SKILL.md": "64a2ec493092d26e", + "skills/gsd-mempalace-recall/SKILL.md": "c6e0195e55cd934c", "skills/gsd-milestone-summary/SKILL.md": "3ea93ccaa0d4d967", "skills/gsd-mvp-phase/SKILL.md": "d2f98f1e955797b6", "skills/gsd-new-milestone/SKILL.md": "52c3cbe5b931985b", diff --git a/tests/fixtures/golden-install-parity/opencode.json b/tests/fixtures/golden-install-parity/opencode.json index afb72a7b4..dacda292c 100644 --- a/tests/fixtures/golden-install-parity/opencode.json +++ b/tests/fixtures/golden-install-parity/opencode.json @@ -20,7 +20,7 @@ "agents/gsd-framework-selector.md": "1c0a10355e787675", "agents/gsd-integration-checker.md": "a9de5928e5a5c649", "agents/gsd-intel-updater.md": "493e07482fa6198a", - "agents/gsd-mempalace-curator.md": "aa7cf2c611057735", + "agents/gsd-mempalace-curator.md": "197308371baa53ad", "agents/gsd-nyquist-auditor.md": "7a7e0d1cbafd6b63", "agents/gsd-pattern-mapper.md": "7c6d1d9817a9c1e7", "agents/gsd-phase-researcher.md": "9874110700b41f48", @@ -63,8 +63,8 @@ "command/gsd-ingest-docs.md": "b47c812c247e58a4", "command/gsd-manager.md": "86ece154b34b6d1b", "command/gsd-map-codebase.md": "1fb678f8a17a380e", - "command/gsd-mempalace-capture.md": "08b9750f1b1d1ba6", - "command/gsd-mempalace-recall.md": "2316f1a950490845", + "command/gsd-mempalace-capture.md": "a94ca275cbe7134c", + "command/gsd-mempalace-recall.md": "d358cdd89c935877", "command/gsd-milestone-summary.md": "86a827271bc647c5", "command/gsd-mvp-phase.md": "d45fd76cb9cff3ef", "command/gsd-new-milestone.md": "64c9dc73425a66a2", @@ -439,8 +439,8 @@ "skills/gsd-ingest-docs/SKILL.md": "8f294b4894f782a5", "skills/gsd-manager/SKILL.md": "cf40f237b4f20aa7", "skills/gsd-map-codebase/SKILL.md": "6d74ea41e29ff035", - "skills/gsd-mempalace-capture/SKILL.md": "260e1dabc7014ba2", - "skills/gsd-mempalace-recall/SKILL.md": "045d85c8cab1afcc", + "skills/gsd-mempalace-capture/SKILL.md": "f960b7b1a8fdf89b", + "skills/gsd-mempalace-recall/SKILL.md": "2091c48e6e986e28", "skills/gsd-milestone-summary/SKILL.md": "175366bb500b5e64", "skills/gsd-mvp-phase/SKILL.md": "0531d0e907af41ce", "skills/gsd-new-milestone/SKILL.md": "45688741cc4bab41", diff --git a/tests/fixtures/golden-install-parity/qwen.json b/tests/fixtures/golden-install-parity/qwen.json index 8917f288e..bec6afbe0 100644 --- a/tests/fixtures/golden-install-parity/qwen.json +++ b/tests/fixtures/golden-install-parity/qwen.json @@ -20,7 +20,7 @@ "agents/gsd-framework-selector.md": "ea9981d65d6b3429", "agents/gsd-integration-checker.md": "33fd537b862eb944", "agents/gsd-intel-updater.md": "699dacdc0a1f2478", - "agents/gsd-mempalace-curator.md": "576b8d0db51bc462", + "agents/gsd-mempalace-curator.md": "399e90e473b33814", "agents/gsd-nyquist-auditor.md": "7fb0ecf639c1cdfe", "agents/gsd-pattern-mapper.md": "9ab071c3ffc1cf46", "agents/gsd-phase-researcher.md": "b064bc7bb4881443", @@ -344,8 +344,8 @@ "skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "8d38e55e5f8b774b", "skills/gsd-ns-context/skills/graphify/SKILL.md": "ac3661e6e576188b", "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "5009595dbde69739", - "skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "e9b66db79fce0a2f", - "skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "9bfa9e76c7a10e26", + "skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "40a31ad049374297", + "skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "c3f412d5a64f3921", "skills/gsd-ns-ideate/SKILL.md": "4a0d2691054b23e5", "skills/gsd-ns-ideate/skills/capture/SKILL.md": "05fa421c95fbad2d", "skills/gsd-ns-ideate/skills/explore/SKILL.md": "7ee5c455f37093be", diff --git a/tests/fixtures/golden-install-parity/trae.json b/tests/fixtures/golden-install-parity/trae.json index a8c7fc401..a045862ef 100644 --- a/tests/fixtures/golden-install-parity/trae.json +++ b/tests/fixtures/golden-install-parity/trae.json @@ -20,7 +20,7 @@ "agents/gsd-framework-selector.md": "7726fccc86bfeb50", "agents/gsd-integration-checker.md": "7cd2072984411c7f", "agents/gsd-intel-updater.md": "83de6ba9172891c3", - "agents/gsd-mempalace-curator.md": "63676937f8970bf3", + "agents/gsd-mempalace-curator.md": "78f4894a9d5f44b1", "agents/gsd-nyquist-auditor.md": "58efbed3b81b5ede", "agents/gsd-pattern-mapper.md": "b5d7a4abb1baecb9", "agents/gsd-phase-researcher.md": "2256f1f82212c757", @@ -322,8 +322,8 @@ "skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "d39269bea995fabc", "skills/gsd-ns-context/skills/graphify/SKILL.md": "e0253aef14693a7e", "skills/gsd-ns-context/skills/map-codebase/SKILL.md": "0910348701b1fc65", - "skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "92740c97e0ce6942", - "skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "d41523e659d1920f", + "skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "36c486f14abe869a", + "skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "2d95e385fee26dee", "skills/gsd-ns-ideate/SKILL.md": "c10342345c01c91f", "skills/gsd-ns-ideate/skills/capture/SKILL.md": "90aee26970fa7639", "skills/gsd-ns-ideate/skills/explore/SKILL.md": "d8e26a5ed95a4ecc", diff --git a/tests/fixtures/golden-install-parity/windsurf.json b/tests/fixtures/golden-install-parity/windsurf.json index bb29666f9..ae20090c1 100644 --- a/tests/fixtures/golden-install-parity/windsurf.json +++ b/tests/fixtures/golden-install-parity/windsurf.json @@ -20,7 +20,7 @@ "agents/gsd-framework-selector.md": "4b77eebbe9288d80", "agents/gsd-integration-checker.md": "4ffb37fb230c2b90", "agents/gsd-intel-updater.md": "a81d77c143c02108", - "agents/gsd-mempalace-curator.md": "63676937f8970bf3", + "agents/gsd-mempalace-curator.md": "78f4894a9d5f44b1", "agents/gsd-nyquist-auditor.md": "0ef8609fd897e399", "agents/gsd-pattern-mapper.md": "ada0c169daa2f0ec", "agents/gsd-phase-researcher.md": "2a45ebde829555ec", diff --git a/tests/issue-498-package-identity.test.cjs b/tests/issue-498-package-identity.test.cjs index 12293df14..1e8fd0513 100644 --- a/tests/issue-498-package-identity.test.cjs +++ b/tests/issue-498-package-identity.test.cjs @@ -12,8 +12,6 @@ const { test, describe } = require('node:test'); const assert = require('node:assert/strict'); const path = require('node:path'); -const fs = require('node:fs'); - const ROOT = path.join(__dirname, '..'); const { deriveIdentity, formatManualInstall, slugifyPackageName } = require( path.join(ROOT, 'scripts', 'generate-package-identity.cjs'),