feat(#956): add MemPalace memory capability (ADR-857 feature plug-in) (#1201)

* feat(#956): add MemPalace memory capability (ADR-857 feature plug-in)

Adds an opt-in, default-resilient ADR-857 feature capability that wires
MemPalace (local-first memory: MCP server + CLI) into the GSD loop:
deliberate recall before discuss/plan and verbatim + temporal-KG capture
at phase boundaries. Three memory modes (augment default; kg_backend and
replace forward-declared). Master gate mempalace.enabled (default off);
every hook onError:skip, zero gates; absent/disabled MemPalace => loop
unchanged. Transport is rendered-markdown only — MemPalace runs
out-of-process, no third-party code in gsd-core (ADR-857 §7).

Capability: capabilities/mempalace/ (manifest + 2 fragments), skills
commands/gsd/mempalace-{recall,capture}.md, agent
agents/gsd-mempalace-curator.md. Registration: ns-context router,
utility cluster, KNOWN_SKILLS, help full.md, model-catalog, copilot
install list, size baselines; regenerated capability-registry +
inventory manifest. ship:post wired into ship.md (wire-on-demand).

HELD on #1196: this capability also declares hooks at discuss:pre and
discuss:post, which are structurally un-wireable until the host-loop
conformance model covers the discuss phase (discuss-phase.md is not in
HOST_LOOP_FILES). The phase6-capstone-conformance gate therefore fails
on exactly those two orphaned points by design — see #1196. Once #1196
lands, rebase onto next and the gate goes green with no further change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs(#956): backfill changeset PR number (#1201)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-06-14 02:09:10 -04:00
committed by GitHub
parent b1e8a74708
commit a375c4b354
29 changed files with 1117 additions and 31 deletions

View File

@@ -0,0 +1,128 @@
{
"id": "mempalace",
"role": "feature",
"title": "MemPalace memory",
"description": "Cross-session, cross-project memory: deliberate recall before discuss/plan and verbatim capture + temporal-KG sync at phase boundaries, via the MemPalace MCP server and CLI.",
"tier": "full",
"requires": [],
"runtimeCompat": { "supported": ["*"], "unsupported": [] },
"skills": ["mempalace-recall", "mempalace-capture"],
"agents": ["gsd-mempalace-curator"],
"hooks": [],
"config": {
"mempalace.enabled": {
"type": "boolean",
"default": false,
"description": "Master toggle for the MemPalace memory capability."
},
"mempalace.memory_mode": {
"type": "enum",
"values": ["augment", "kg_backend", "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'."
},
"mempalace.wing": {
"type": "string",
"default": "",
"description": "Palace wing name; empty derives from project_code / project dir."
},
"mempalace.recall_on_discuss": {
"type": "boolean",
"default": true,
"description": "Inject wake-up + search recall at discuss:pre."
},
"mempalace.recall_on_plan": {
"type": "boolean",
"default": true,
"description": "Produce MEMORY-RECALL.md at plan:pre."
},
"mempalace.capture_artifacts": {
"type": "boolean",
"default": true,
"description": "File CONTEXT/PLAN/SUMMARY and learnings into the palace at phase boundaries."
},
"mempalace.mirror_kg": {
"type": "boolean",
"default": true,
"description": "Mirror decisions/learnings into MemPalace's temporal knowledge graph."
},
"mempalace.cross_project_tunnels": {
"type": "boolean",
"default": false,
"description": "Propose/create cross-wing tunnels at ship:post."
},
"mempalace.diary_journal": {
"type": "boolean",
"default": true,
"description": "Write a per-agent diary entry at ship:post."
},
"mempalace.auto_capture_hooks": {
"type": "boolean",
"default": false,
"description": "Reserved / not yet implemented: will install MemPalace's native stop/precompact Claude Code hooks for passive mid-session capture (the capability's hooks array is currently empty)."
}
},
"steps": [
{
"point": "discuss:post",
"ref": { "skill": "mempalace-capture" },
"produces": [],
"consumes": ["CONTEXT.md"],
"when": "mempalace.enabled",
"onError": "skip"
},
{
"point": "plan:pre",
"ref": { "skill": "mempalace-recall" },
"produces": ["MEMORY-RECALL.md"],
"consumes": ["CONTEXT.md"],
"when": "mempalace.enabled",
"onError": "skip"
},
{
"point": "plan:post",
"ref": { "skill": "mempalace-capture" },
"produces": [],
"consumes": ["PLAN.md"],
"when": "mempalace.enabled",
"onError": "skip"
},
{
"point": "verify:post",
"ref": { "skill": "mempalace-capture" },
"produces": [],
"consumes": ["SUMMARY.md"],
"when": "mempalace.enabled",
"onError": "skip"
},
{
"point": "ship:post",
"ref": { "agent": "gsd-mempalace-curator" },
"produces": [],
"consumes": ["UAT.md"],
"when": "mempalace.enabled",
"onError": "skip"
}
],
"contributions": [
{
"point": "discuss:pre",
"into": "orchestrator",
"fragment": { "path": "fragments/recall-discuss.md" },
"produces": [],
"consumes": [],
"when": "mempalace.enabled",
"onError": "skip"
},
{
"point": "execute:wave:post",
"into": "verifier",
"fragment": { "path": "fragments/capture-problems.md" },
"produces": [],
"consumes": [],
"when": "mempalace.enabled",
"onError": "skip"
}
],
"gates": []
}

View File

@@ -0,0 +1,20 @@
<!--
MemPalace capability — contribution fragment.
Rendered into the execute:wave:post verifier prompt when `mempalace.capture_artifacts` is true.
Contributes DATA (capture instructions), not control flow. onError: skip — never fails a wave.
-->
### Capture problems → fixes (MemPalace)
**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.)
Otherwise — 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.
For each confirmed bug/issue resolved in this wave:
1. **Resolve the wing** (`mempalace.wing`, else `project_code`, else project dir) and target `room: problems`.
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 `(<bug>, fixed_by, <fix>)` 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.
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.

View File

@@ -0,0 +1,22 @@
<!--
MemPalace capability — contribution fragment.
Rendered into the discuss:pre orchestrator prompt when `mempalace.recall_on_discuss` is true.
Contributes DATA (recall instructions), not control flow. onError: skip — never blocks discussion.
-->
### Memory recall (MemPalace)
**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.)
Otherwise — 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.
1. **Resolve the wing.** Use `mempalace.wing` if set; otherwise derive it from `project_code` (fall back to the project directory name).
2. **Wake up (cheap, ~600–900 tokens).**
- Interactive run → call `mempalace_search` after a wake-up read of the wing.
- Headless/cron run (no MCP server) → run `mempalace wake-up --wing <wing>` via the CLI.
3. **Targeted recall.** Search the palace for prior work on this phase's topic:
- Interactive → `mempalace_search(query=<phase topic>, wing=<wing>)` and, when `mempalace.mirror_kg` is on, `mempalace_kg_query` / `mempalace_kg_timeline` for decision facts and their validity windows.
- Headless → `mempalace search "<phase topic>" --wing <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.
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.