Skip to content

🤖 feat: share the workspace memory notebook across a sub-agent task tree - #4210

Open
ThomasK33 wants to merge 6 commits into
mainfrom
memory-sharing-l1
Open

🤖 feat: share the workspace memory notebook across a sub-agent task tree#4210
ThomasK33 wants to merge 6 commits into
mainfrom
memory-sharing-l1

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Sep 11, 2026

Copy link
Copy Markdown
Member

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/workspace for 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

  1. memoryWorkspaceOwner.ts: resolveWorkspaceMemoryOwnerId walks the parentWorkspaceId chain 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.
  2. MemoryService: owner memo invalidated by a config file stamp (Config.configFileStamp) and by onConfigChanged; the owner resolved at the start of a command is pinned per command context, and assertMutationCommittable refuses to commit if ownership changed mid-command (for example config.json recovered 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. setPinned runs under the store mutation lock; Dream's delete/rename pass rejectPinned so the pin check happens inside the lock.
  3. Subscriptions and sessions: subscribeMemoryChanges matches workspace-scope events by resolved owner and re-roots on ownersInvalidated; di/layers/core.ts invalidates the cached memory context of every session in the tree on a write or ownership change.
  4. Consolidation: maybeRun redirects a child to its owner (teardown and archive gates checked first), runCore and the launch sweep skip children, harvest recovery iterates all tree members, and status reports the owner's records.

Known limitations (addressed in later layers)

  1. Removing a workspace whose store is shared is not yet coordinated with the owner lock, and grandchildren of a removed intermediate ancestor fall back to their private store (L1b).
  2. Notes a sub-agent wrote before this change stay in its private store and are not read (legacy adoption, L3).
  3. A second backend on the same ~/.xum is 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

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= -->
@ThomasK33 ThomasK33 changed the title memory sharing l1 🤖 feat: share the workspace memory notebook across a sub-agent task tree Sep 11, 2026
@ThomasK33
ThomasK33 marked this pull request as ready for review September 11, 2026 11:07
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 11, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-11T12:09:17.801844Z 6fa91ef Manual request
🔒 Security Review Completed 2026-09-11T12:09:58.500676Z 6fa91ef Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 05206d59b5

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/node/services/memoryService.ts
Comment thread src/node/services/memoryService.ts Outdated
Comment thread src/node/services/memoryWorkspaceOwner.ts
Comment thread src/node/services/memoryService.ts
Comment thread src/node/services/di/layers/core.ts
Comment thread src/node/services/memoryConsolidationService.ts Outdated
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 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 4d61dceb28

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/node/services/agentSession.ts
Comment thread src/node/services/memoryService.ts
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 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 6fa91ef217

ℹ️ 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".

@chatgpt-codex-connector

Copy link
Copy Markdown

🛡️ Codex Security Review · Automatically triggered

Security review completed. No security issues were found in this pull request.

Reviewed commit: 6fa91ef217

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant