🤖 feat: share the workspace memory notebook across a sub-agent task tree - #4210
🤖 feat: share the workspace memory notebook across a sub-agent task tree#4210ThomasK33 wants to merge 6 commits into
Conversation
Sub-agent child workspaces (parentWorkspaceId set) now resolve /memories/workspace/... to the task-tree root's <sessionDir>/memory, so an owner and all of its (nested) sub-agents read and write one notebook while their transcripts and session artifacts stay separate. - MemoryService.resolveWorkspaceMemoryOwnerId walks parentWorkspaceId to the root (cycle/depth guarded, unknown ids resolve to themselves) and is used for the workspace store root, sidecar pin/usage keys, change events, the workspace-scope refinement journal (owner session, where rollback confinement holds), and the removal tombstone check (acting + owner). - Memory tab subscriptions/list/pin resolve the owner too. - Dream consolidation refuses sub-agent children and the launch sweep skips them; children still harvest into the shared inbox, the owner sweeps it. - A workspace-scope write invalidates the cached memory context of every live session in the same tree. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high` • Cost: `$1.38`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high costs=1.38 -->
Move the parentWorkspaceId walk into memoryWorkspaceOwner.ts (pure over one config snapshot, indexed once per snapshot) and make MemoryService's memo coherent while the tree changes: - Config.configFileStamp (one stat) invalidates the owner memo on rewrites by ANY backend; local edits notify through onConfigChanged. Unreadable config is never memoized as a self fallback, and memoized owners are retained while a changed file cannot be read. Owner changes emit ownersInvalidated. - Per-command owner cache (ownerWorkspaceIdFor) reset by runCommand; the commit check refuses when a fresh resolution disagrees with the owner the command's store was bound to. - Refinement rows stay in the acting workspace's journal; workspace-scope sidecar keys and change events follow the owner. - setPinned runs under the store lock with the same commit guard; rejectPinned enforces consolidation's pin protection in-lock. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high` • Cost: `$`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high costs= -->
… tabs - Memory subscriptions resolve the owner per event and synthesize a root-addressed refresh (plus a consolidation-status refresh) when the subscriber's ownership changes (ownersInvalidated). - core.ts invalidates the cached memory context of every live session in the tree on workspace-scope writes (one config snapshot per pass) and of the affected sessions on ownership changes; startup-recovery sessions count too. - memoryOperations keys list/pin sidecar entries by the same per-request owner the store resolved to and routes pins through MemoryService.setPinned so other tabs on the shared store refetch. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high` • Cost: `$`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high costs= -->
A sub-agent's Dream/compaction run consolidates the OWNER's notebook under the owner's in-flight lock (child archive is refused); the acting child's removal cancellation and tombstone still gate and abort the owner-keyed run. The owner's status view is what a child's Memory tab shows, the owner run's recovery retries every tree member's harvest bucket, the launch sweep folds tree recency onto the owner, and a removal-cancelled run skips recovery. Consolidation's pin protection is enforced in-lock via rejectPinned. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high` • Cost: `$`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high costs= -->
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 05206d59b5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Refuse a child's workspace-scope mutation once the owner's removal tombstone exists, publish read-side hot-set re-ranking to the tree's other sessions, and gate harvest recovery on the acting child's cancellation as well as the owner's. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high` • Cost: `$975.00`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high costs=975.00 -->
|
@codex review |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4d61dceb28
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Hold the owner's memory store lock while removing a sub-agent's session directory, and guard the session memory-context cache with an invalidation generation so a build or rollover candidate that overlapped a sibling's write does not repopulate the cache with a stale snapshot. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high` • Cost: `$990.00`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high costs=990.00 -->
|
@codex review |
|
Codex Review: Didn't find any major issues. Chef's kiss. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
🛡️ Codex Security Review · Automatically triggeredSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
Summary
Sub-agent workspaces (those spawned with a
parentWorkspaceId) now read and write the memory notebook of the root workspace of their task tree instead of a private one./memories/workspacefor a child resolves to<sessions>/<owner>/memory, the sidecar and refinement journal are keyed by the owner, the Memory tab and open sessions follow ownership changes, and Dream (consolidation) runs for a child are redirected to the owner. Transcripts and other session artifacts stay per workspace.Stack: layer 1 of the split of #4139. This layer is the "sharing works while every workspace is alive" slice. Removal and rollback safety, memory-policy epochs, legacy note adoption, and multi-backend coherence follow as stacked PRs.
Background
Sub-agents forked from a workspace could not see the parent's notebook, and their own notes were lost when the child was removed. #4139 implemented sharing but grew to +15.8k lines over 91 review rounds by fixing every finding in place. It is being re-delivered as a stack carved from that final tree, so each layer is reviewable on its own.
Implementation
memoryWorkspaceOwner.ts:resolveWorkspaceMemoryOwnerIdwalks theparentWorkspaceIdchain over one config snapshot (indexed once per snapshot via a WeakMap). Unknown IDs, dangling parents, cycles, and depth overflow resolve to the workspace itself so a misconfigured tree degrades to per-workspace behavior.MemoryService: owner memo invalidated by a config file stamp (Config.configFileStamp) and byonConfigChanged; the owner resolved at the start of a command is pinned per command context, andassertMutationCommittablerefuses to commit if ownership changed mid-command (for exampleconfig.jsonrecovered from unreadable and the workspace moved from its private fallback to the shared store). Store paths, sidecar logical keys, change events, and refinement journal rows are owner keyed.setPinnedruns under the store mutation lock; Dream's delete/rename passrejectPinnedso the pin check happens inside the lock.subscribeMemoryChangesmatches workspace-scope events by resolved owner and re-roots onownersInvalidated;di/layers/core.tsinvalidates the cached memory context of every session in the tree on a write or ownership change.maybeRunredirects a child to its owner (teardown and archive gates checked first),runCoreand the launch sweep skip children, harvest recovery iterates all tree members, and status reports the owner's records.Known limitations (addressed in later layers)
~/.xumis not detected (L4).Validation
Ported tests cover owner resolution edge cases, store redirection, journal placement, config-change re-resolution (local edit, external rewrite, unreadable then recovered), refusal to commit after an ownership change, subscription owner matching and invalidation, and Dream redirection/skip. Sibling suites (memory, consolidation, sessions, workspace service/removal, task service, refinement rollback, config): 1698 pass.
Risks
Medium, scoped to workspaces with a
parentWorkspaceId. Workspaces without one resolve to themselves and keep today's behavior. The main regression surface is the owner memo invalidation path (a stale owner would write to the wrong store); it is guarded by the in-lock ownership re-check.Generated with
xum• Model:anthropic:claude-fable-5-1• Thinking:high• Cost:$956.36