PROBLEM. vault-merged-recall gave show and show-chunk a --parent flag so an agent can resolve a from_parent item where it lives. The write-side commands the recall/learn procedures need next — activate (Step 2.7), amend (Step 2.5C), learn (Step 2.5C absent-write handoff, Step 4, and the learn skill itself) — have no --parent (internal/cli/activate.go, learn.go, amend.go: zero references at 1c741828), even though all three are already in the served command set (vault-serve-api: query, query-chunks, show, show-chunk, activate, learn, amend).
Consequence on a child. Every one of those writes targets the local vault by default. On a child with no local vault (the /app/repo sandbox today: ~/.local/share/engram/ holds only chunks/), activate on a parent note cannot find it, and a learn would mint a brand-new local vault that diverges from the parent — the opposite of what a child should do. The recall skill's own contract ("used notes must stay warm or the recency-competition mechanism breaks") is unmeetable from a child as written.
Workaround, verified 2026-08-30. Per-invocation server routing works: ENGRAM_SERVER="$ENGRAM_PARENT" engram show 824 resolved the parent note; the same override on activate/learn/amend reaches the served endpoints, and a served learn/amend lands as a pending offer for curate — which is the right semantics for a child contributing upward. But it cannot be set globally: Decision 5 makes ENGRAM_PARENT inert whenever ENGRAM_SERVER is set, so a node that exports ENGRAM_SERVER loses merged recall. It has to be a per-command trick, and neither recall/SKILL.md nor learn/SKILL.md mentions it — both are written as if the vault is always local (SKILL.md:26 "Do not pass --vault or --chunks-dir"; :207-216 bare engram activate --note …).
Proposal.
- Add
--parent to activate, learn, and amend with the same semantics show/show-chunk already have (route that one call to ENGRAM_PARENT's served endpoint; error if ENGRAM_PARENT is unset; inert under ENGRAM_SERVER). Served-write identity/offer rules (vault-serve-api, vault-offer-curation) apply unchanged.
- Recall/learn skill text: on a merged node, items tagged
from_parent: true are read with show --parent / show-chunk --parent and written back with activate --parent / amend --parent; new notes derived from parent candidates are written with learn --parent (landing as offers). This is a rung-2 skill edit — writing-skills TDD with a merged-mode fixture.
Related. #729; sibling issues filed the same day (zeroed budget block; explore displacing direct matches under --limit; parent clusters dropped). Note the spec's own rationale for an explicit flag over silent fallback (design Decision 8: bare Luhmann ids collide across independently-minted vaults) applies with more force to writes than to reads — an activate that silently hit a colliding local id would bump the wrong note with no error.
Siblings (filed 2026-08-30 from the same recall run): #743 (zeroed budget block), #744 (explore displaces direct matches under --limit), #745 (parent clusters dropped)
Addendum (same session): served activate hides partial failures from the client. RunActivate (internal/cli/activate.go:54-72) logs each miss via deps.LogWarning and only errors when every path fails (errActivateAllFailed); over the wire those warnings stay on the server's stderr, so a child calling ENGRAM_SERVER=… engram activate --note a --note b gets exit 0 even if b was skipped. Verified: a single bogus name returns POST /activate: activate: all note paths failed; a 17-note batch returned exit 0 with no output. Whatever shape --parent takes, the served response should carry the per-note skip list.
PROBLEM.
vault-merged-recallgaveshowandshow-chunka--parentflag so an agent can resolve afrom_parentitem where it lives. The write-side commands the recall/learn procedures need next —activate(Step 2.7),amend(Step 2.5C),learn(Step 2.5C absent-write handoff, Step 4, and the learn skill itself) — have no--parent(internal/cli/activate.go,learn.go,amend.go: zero references at1c741828), even though all three are already in the served command set (vault-serve-api:query, query-chunks, show, show-chunk, activate, learn, amend).Consequence on a child. Every one of those writes targets the local vault by default. On a child with no local vault (the
/app/reposandbox today:~/.local/share/engram/holds onlychunks/),activateon a parent note cannot find it, and alearnwould mint a brand-new local vault that diverges from the parent — the opposite of what a child should do. The recall skill's own contract ("used notes must stay warm or the recency-competition mechanism breaks") is unmeetable from a child as written.Workaround, verified 2026-08-30. Per-invocation server routing works:
ENGRAM_SERVER="$ENGRAM_PARENT" engram show 824resolved the parent note; the same override onactivate/learn/amendreaches the served endpoints, and a servedlearn/amendlands as a pending offer for curate — which is the right semantics for a child contributing upward. But it cannot be set globally: Decision 5 makesENGRAM_PARENTinert wheneverENGRAM_SERVERis set, so a node that exportsENGRAM_SERVERloses merged recall. It has to be a per-command trick, and neitherrecall/SKILL.mdnorlearn/SKILL.mdmentions it — both are written as if the vault is always local (SKILL.md:26"Do not pass--vaultor--chunks-dir";:207-216bareengram activate --note …).Proposal.
--parenttoactivate,learn, andamendwith the same semanticsshow/show-chunkalready have (route that one call toENGRAM_PARENT's served endpoint; error ifENGRAM_PARENTis unset; inert underENGRAM_SERVER). Served-write identity/offer rules (vault-serve-api,vault-offer-curation) apply unchanged.from_parent: trueare read withshow --parent/show-chunk --parentand written back withactivate --parent/amend --parent; new notes derived from parent candidates are written withlearn --parent(landing as offers). This is a rung-2 skill edit —writing-skillsTDD with a merged-mode fixture.Related. #729; sibling issues filed the same day (zeroed
budgetblock; explore displacing direct matches under--limit; parent clusters dropped). Note the spec's own rationale for an explicit flag over silent fallback (design Decision 8: bare Luhmann ids collide across independently-minted vaults) applies with more force to writes than to reads — anactivatethat silently hit a colliding local id would bump the wrong note with no error.Siblings (filed 2026-08-30 from the same recall run): #743 (zeroed
budgetblock), #744 (explore displaces direct matches under--limit), #745 (parent clusters dropped)Addendum (same session): served
activatehides partial failures from the client.RunActivate(internal/cli/activate.go:54-72) logs each miss viadeps.LogWarningand only errors when every path fails (errActivateAllFailed); over the wire those warnings stay on the server's stderr, so a child callingENGRAM_SERVER=… engram activate --note a --note bgets exit 0 even ifbwas skipped. Verified: a single bogus name returnsPOST /activate: activate: all note paths failed; a 17-note batch returned exit 0 with no output. Whatever shape--parenttakes, the served response should carry the per-note skip list.