🤖 feat: share workspace memory notes across a sub-agent task tree - #4139
🤖 feat: share workspace memory notes across a sub-agent task tree#4139ThomasK33 wants to merge 101 commits into
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7f235f92df
ℹ️ 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".
|
Security 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. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3164b699f9
ℹ️ 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".
|
Security 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. |
|
@codex review |
|
Security 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: 3ab8207bc2
ℹ️ 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".
|
@codex review |
|
Security 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: f6e044dc0b
ℹ️ 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".
|
@codex review |
|
Security 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: a684564bcf
ℹ️ 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".
|
@codex review |
|
Security 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: 6b926d3116
ℹ️ 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".
|
@codex review |
|
Security 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: 00145748fa
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6bce3639e8
ℹ️ 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".
|
Security 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. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 11debce4f2
ℹ️ 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".
|
Security 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. |
|
@codex review |
1 similar comment
|
@codex review |
# Conflicts: # src/node/services/historyService.ts # src/node/services/workspaceService.ts
Placeholder discard denies the epoch when the row cannot be removed; fork snapshots carry history-segment.json; segment starts must be safe integers and a malformed segment file is quarantined and reseeded instead of failing every append; source rollback rows are gated by isUsableRollbackRow and a live row with a malformed action aborts the handover; duplicated user row ids fail every id-keyed policy accounting closed. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high -->
There was a problem hiding this comment.
💡 Codex Review
xum/src/node/services/workspaceRemoval.ts
Line 521 in 8383b85
With multiple backends, startup healing can race a user retrying an old failed removal: this backend may read and stat the stale tombstone, the live retry can atomically replace the same path with its fresh attemptId, and this unconditional removal then deletes the new attempt's marker. Writers can subsequently pass the durable removal gate after the retry's final handover or session deletion, recreating an orphan or losing a late journal row. Acquire the removal's session target lock and revalidate the same attempt and age immediately before deleting.
AGENTS.md reference: AGENTS.md:L212-L212
ℹ️ 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".
A placeholder that can be neither removed nor denied surfaces the policy persist error instead of the turn's own outcome; a corrupt segment file in an emptied workspace reseeds above the wall clock so no earlier identity recurs; migration liveness counts only memory-kind rollback rows. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high -->
There was a problem hiding this comment.
💡 Codex Review
xum/src/node/services/workspaceRemoval.ts
Line 508 in a22b8fe
When a retained removal tombstone for a still-registered workspace is truncated or otherwise malformed, this parse throws and the catch skips it on every startup. Since isWorkspaceRemovalTombstoned() gates writes solely on the file's existence, that workspace remains permanently unable to append history or mutate memory even after restarting. After the age guard, identify tombstones by the registered workspace's derived filename and quarantine malformed entries instead of requiring their payload to parse before they can be healed.
AGENTS.md reference: AGENTS.md:L109-L114
ℹ️ 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".
Next history sequences must be safe integers everywhere they are derived (a segment start at the boundary is malformed and reseeds; a persisted row at the boundary refuses the append), and a corrupt policy-record container is healed by the next write instead of pinning every epoch to its blanket deny. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high -->
There was a problem hiding this comment.
💡 Codex Review
xum/src/node/services/workspaceRemoval.ts
Lines 508 to 512 in e5cb003
When an old removal tombstone for a still-registered workspace contains a valid workspaceId but has a missing or nonnumeric removedAt, this check skips it forever even though the recovery logic ages the file exclusively through stat.mtimeMs and never consumes removedAt. Because mere tombstone presence makes history and memory writers refuse the workspace, this recoverable field corruption permanently bricks it across restarts; once the payload identifies a registered workspace and the file is old enough by mtime, heal it without requiring the unused timestamp.
AGENTS.md reference: AGENTS.md:L109-L114
ℹ️ 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".
…sume fixture The builder's MAX_SAFE_INTEGER placeholder is replaced in production before the card is appended; HistoryService now refuses a counter it could not advance past that value, so the fixture assigns sequences the way WorkspaceService does. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high -->
A memory owner pin is honored only once the recorded parent is gone (a live parent chain takes precedence and removal re-pins from it); the probe token fingerprints a redirected child's legacy notebook through the same throttled scan as the owner's; the workspace memory clock refuses to advance past the safe-integer range; and a tombstoned adoption record counts as absent only when the stat proves it. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high -->
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 48735ddca7
ℹ️ 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".
A requestPreludeMessageIds entry accounts for a row only when that row has prelude shape (synthetic), in the harvest gate, the prior-turn check and the tail-copy stamps, so a listing naming an ordinary user turn cannot make it read as covered. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high -->
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1f2453fafa
ℹ️ 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".
Prelude shape now means a synthetic assistant row or a synthetic user row carrying an @mention/skill/MCP snapshot, so synthetic user turns (auto-resume, goal continuations) stay turns of their own. History sequences without a safe successor are skipped like fractions, so appends continue and /clear removes them instead of every append and clear refusing. The session's workspace-memory writable mirror is keyed by policy epoch and re-binds to the summary sequence on a preserved tail, so another backend's epoch change cannot carry a stale value. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high -->
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0099ff0561
ℹ️ 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".
One predicate decides which history segment starts are persisted and read back, so a clear can no longer write a start the next read rejects. A persisted row floors the counter only when the segment that retires it is such a start, appends assign only sequences that remain usable floors, and a reseed that cannot be persisted refuses before quarantining the malformed file instead of leaving the segment to restart at 0. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high -->
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 42e3e3695f
ℹ️ 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".
A downgraded child's legacy edit replaces its adopted copy in place only while that copy is still this adoption's generation (settled records by stamp, a pending fresh adoption by its pending write); a copy the owner deleted and recreated with the same bytes is the owner's, so the edit is imported beside it instead. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high -->
There was a problem hiding this comment.
💡 Codex Review
xum/src/node/services/historyService.ts
Lines 2967 to 2970 in 1061c45
When a commit-worthy persisted partial.json carries historySequence: Number.MAX_SAFE_INTEGER, this check accepts it, appends the row, and sets the cached counter to an unsafe integer. The persisted-max refresh deliberately ignores the exhausted row but is advance-only, so it cannot lower that cache; subsequent appends repeatedly receive the same rounded unsafe sequence, and finalization can update an unrelated row sharing it. Fresh evidence beyond the exhausted-history repairs is that this pre-sequenced append path still uses the weaker nonnegative-integer guard instead of isUsableHistorySequence.
AGENTS.md reference: AGENTS.md:L111-L113
When two backend instances receive the same compaction completion, the second can read the first instance's freshly persisted pending record here. Because every non-completed record below the attempt cap enters this branch, it immediately launches another model harvest instead of recognizing that the first is still active; the process-local harvestInFlight map cannot coalesce the other backend. This duplicates model cost and lets concurrent harvests race their memory mutations, so only failed or stale-pending records should start a retry.
ℹ️ 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".
A prelude listing exempts a synthetic user row only when its snapshot has the shape the backend writes. A retargeted pre-sharing row is order-unknown against every row not proven to share its origin, whatever the persisted workspace ids say. Legacy adoption stages a copy's bytes in a hidden owner store entry, takes their identity there and records it in the pending manifest before installing them by rename, so a retry recognizes the copy by stamp on either side of an interrupted install and a byte match alone — another backend's identical note at the planned target — never counts as provenance. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high -->
There was a problem hiding this comment.
💡 Codex Review
xum/src/node/services/workspaceRemoval.ts
Lines 526 to 528 in 5ba3627
When an aged removal tombstone for a still-registered workspace is truncated or otherwise malformed, this catch skips it on every startup, while isWorkspaceRemovalTombstoned() continues treating the file's existence as authoritative. The workspace is therefore permanently unable to append history or mutate memory without manual filesystem repair. Use the deterministic hashed filename to match aged malformed markers against registered workspace IDs and quarantine or remove the matching residue instead of requiring the payload to parse.
AGENTS.md reference: AGENTS.md:L109-L112
xum/src/node/services/workspaceRemoval.ts
Lines 518 to 521 in 5ba3627
With XUM_ALLOW_MULTIPLE_INSTANCES, the age check and deletion are not serialized with publishRemovalTombstone(): this sweep can stat an old failed-removal marker, then another backend can acquire the removal locks, replace it with a fresh marker and delete the session, and this backend can still remove that fresh marker while the workspace remains registered before deregistration. During that window foreign history or memory writers are readmitted and can recreate the deleted session or mutate the owner's notebook after the final handover. Acquire the same session target lock and re-read/re-stat the marker immediately before deleting it.
ℹ️ 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".
When a renamed legacy note lands on its own conflict copy, the successor record inherits the generation observed on disk — the receipt that proved the copy unchanged — rather than the predecessor's targetStamp, which on the far side of an interrupted in-place replacement names the overwritten generation and would make the copy read as replaced by the owner at once. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high -->
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ba9ebc70b3
ℹ️ 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".
The harvest gate, the tail-copy stamps and the segment start share one predicate for a persisted history sequence (a nonnegative safe integer), so an unsafe request bound stamps nothing the gate would refuse. Adoption staging moves out of the memory namespace to a directory beside the owner's memory root: a legacy note under any in-namespace path, however named, is adopted and kept, and the install rename is fenced so a failure fails the note rather than the pass. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high -->
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 15ea436ca0
ℹ️ 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".
| for (const message of messages) { | ||
| if (!isDurableContextBoundaryMarker(message)) continue; | ||
| const sequence = message.metadata?.historySequence; | ||
| if (typeof sequence !== "number" || !Number.isInteger(sequence) || sequence < 0) continue; |
There was a problem hiding this comment.
Reject unsafe boundary sequences when deriving policy epochs
When a persisted boundary carries an unsafe integer such as 9007199254740992, this accepts it as the current policy epoch even though the history counter ignores such unadvanceable values. The next compaction can therefore have a normal summary sequence below this previousBoundaryHistorySequence; getMessagesForCompactionEpoch() then filters every intervening turn as older than the boundary, producing a successful but empty harvest and silently losing that epoch's memories. Use isPersistedHistorySequence() here as well.
AGENTS.md reference: AGENTS.md:L109-L113
Useful? React with 👍 / 👎.
| return ( | ||
| typeof snapshot.serverName === "string" && | ||
| typeof snapshot.promptName === "string" && | ||
| typeof snapshot.commandKey === "string" |
There was a problem hiding this comment.
Match MCP prelude snapshots to their invoking turn
When a crash leaves an MCP snapshot before its invoking user row is appended, and corrupted requestPreludeMessageIds later names that orphan, this predicate accepts it without checking invokingMessageId. Both prior-turn admission and harvest accounting can then treat the orphan's user content as part of the later batch, allowing an assistant that never consumed it to mark it covered and expose it to memory harvesting. Require a string invokingMessageId that matches the anchor user row, consistent with the orphan filtering already used for provider requests.
AGENTS.md reference: AGENTS.md:L109-L113
Useful? React with 👍 / 👎.
| const rollbackByTarget = new Map( | ||
| rows.filter(isMigratableRollbackRow).map((row) => [row.data.rollbackOf!, row] as const) | ||
| ); |
There was a problem hiding this comment.
Reject branched rollback lineages before migration
When a raw child journal contains multiple usable rollback rows for the same rollbackOf, this Map silently keeps only the last branch. For example, if A → R1 → R3 has re-applied A and a later stray R2 also targets A, isLive(A) follows only R2 and classifies A as dead; migration skips A, cannot copy the dependent rollback rows without its owner-side ID, and removal deletes the only inverse even though A remains applied. Detect duplicate outgoing rollback edges and abort removal rather than choosing one.
AGENTS.md reference: AGENTS.md:L111-L111
Useful? React with 👍 / 👎.
| const segmentStart = await this.readHistorySegmentStart(workspaceId); | ||
| if (segmentStart !== null) this.historySegmentStarts.set(workspaceId, segmentStart); | ||
| let maxSequence = (segmentStart ?? this.historySegmentStarts.get(workspaceId) ?? 0) - 1; |
There was a problem hiding this comment.
Advance stale segment files after a downgraded clear
When a user downgrades to a build that does not know history-segment.json, runs a full clear, and then upgrades again, the old clear removes the history and restarts sequences at zero but leaves this sidecar and the new policy records intact. This floor then resumes at the stale segment start and stamps new rows with the same segment identity used before the downgrade, so workspaceMemoryPolicyEpochOf() consults a policy record from the discarded conversation; in particular, a stale deny suppresses harvesting until another boundary. Detect legacy post-clear history below the recorded start and open a fresh segment instead of reusing the sidecar generation.
AGENTS.md reference: AGENTS.md:L10-L11
Useful? React with 👍 / 👎.
| (bucketId === workspaceId || | ||
| self.memoryService.resolveWorkspaceMemoryOwnerId(bucketId, () => cfg) === workspaceId) | ||
| ) | ||
| .flatMap(([, bucket]) => Object.values(bucket)); |
There was a problem hiding this comment.
Keep recovered harvests bound to their persisted bucket
With the new owner-wide recovery, a parseable but corrupted child bucket can contain a retryable record whose completionMetadata.workspaceId names an unrelated workspace. This flattening discards both the checked bucket ID and boundary key, then calls maybeHarvestThenSweep() using the unverified payload; when its stored writable bit is true, even a failed harvest proceeds to a Dream sweep of that unrelated workspace, so merely consolidating the owner can spend provider tokens and mutate another task tree. Preserve the keys and require metadata.workspaceId === bucketId and metadata.summaryMessageId === boundaryKey before retrying.
AGENTS.md reference: AGENTS.md:L111-L111
Useful? React with 👍 / 👎.
## Summary The PR Workflow section of `AGENTS.md` now bounds the Codex review loop by scope instead of by "iterate until clean". It adds two early-stop cases (the loop does not converge, or the next fix grows the scope) and a classification for review fixes that keeps a PR recognizable as the change it started as. ## Background PR coder#4139 grew from +447/-64 to +15.8k/-506 over 91 Codex rounds because every finding was fixed in place, including findings that needed new modules, on-disk artifacts, persisted fields, and second-backend races. The existing guidance had one early-stop case (reviewer misunderstands the change) and no scope rule. ThomasK33 asked for guidance that describes the shape of scope growth without hard numeric thresholds, written in plain English (short sentences, condition before command, numbered steps). ## Implementation Doc-only change to `docs/AGENTS.md` (the root `AGENTS.md` is a symlink): 1. The single early-stop sentence becomes a three-item list: reviewer misunderstanding, non-converging loop, scope growth. 2. New `### Review fixes and scope` subsection: fix in place when small and inside the original change, otherwise reply on the thread, resolve, and deliver as a stacked PR (`gh stack`) or tracked follow-up. Findings that need corrupted persisted state, narrow crash windows, or a second racing backend are deferrable unless the PR introduced that surface. A reasoned rejection is a valid resolution. 3. The mandatory-readiness block now points at the early-stop cases so the two paragraphs do not contradict each other. ## Risks None at runtime. Agent behavior changes: agents will pause and report a split proposal instead of growing a PR under review. --- _Generated with `xum` • Model: `anthropic:claude-fable-5-1` • Thinking: `high` • Cost: `$940.64`_ <!-- mux-attribution: model=anthropic:claude-fable-5-1 thinking=high costs=940.64 -->
Summary
Sub-agent child workspaces now share their parent/owner's
/memories/workspace/...notes. The workspace scope resolves to the task-tree root's<sessionDir>/memory, so an owner and all of its (nested) sub-agents read and write one notebook, while transcripts and other session artifacts stay per-workspace.Background
Workspace memory was strictly per-workspace: a sub-agent spawned via
taskgot an empty/memories/workspace/and any notes it wrote died with its child workspace, invisible to the parent that delegated the work. Since the parent owns the task, the tree should share one notebook (context-notes.mdincluded). Fullkind: "workspace"tasks and forks carry noparentWorkspaceIdand keep their own notes.Implementation
MemoryService.resolveWorkspaceMemoryOwnerId(workspaceId)walksparentWorkspaceIdto the root (cycle/depth guarded; unknown ids resolve to themselves; positive results memoized since parent links are immutable). It backs the workspace store root, sidecar pin/usage keys (one ranking per shared file),changeevents (carry the owner id), and the removal-tombstone commit check (acting and owner: a removed child cannot keep writing into its parent, a lingering child cannot recreate a removed owner's session dir).<sessionDir>/memory; global/project rows stay attributed to the acting workspace.AgentSessionin the same tree (WorkspaceService.invalidateMemoryContextWhere, wired incore.ts).Validation
New tests cover owner resolution (root / parentless / unknown), the shared physical store with owner-keyed events and sidecar stats (and isolation from unrelated workspaces), journal placement (owner vs acting), the subscription filter, child Dream refusal + launch-sweep skip, and external memory-context invalidation.
Risks
Medium, scoped to the Memory experiment. Workspaces without
parentWorkspaceIdbehave exactly as before (owner == self). For sub-agents the notebook location moves from the child's session dir to the owner's; existing child-local notes from earlier sessions are not migrated (children are ephemeral). Known limitation: the launch sweep does not fold child activity into the owner's idle recency, mirroring the existing owner-agent vs. Dream concurrency.Generated with
xum• Model:anthropic:claude-fable-5-1• Thinking:high• Cost:$1.63