Skip to content

🤖 feat: share workspace memory notes across a sub-agent task tree - #4139

Open
ThomasK33 wants to merge 101 commits into
mainfrom
workspace-sharing-xcph
Open

🤖 feat: share workspace memory notes across a sub-agent task tree#4139
ThomasK33 wants to merge 101 commits into
mainfrom
workspace-sharing-xcph

Conversation

@ThomasK33

Copy link
Copy Markdown
Member

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 task got 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.md included). Full kind: "workspace" tasks and forks carry no parentWorkspaceId and keep their own notes.

Implementation

  • MemoryService.resolveWorkspaceMemoryOwnerId(workspaceId) walks parentWorkspaceId to 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), change events (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).
  • Workspace-scope refinement journal rows land in the owner's session journal, because rollback confinement only admits a journal's own <sessionDir>/memory; global/project rows stay attributed to the acting workspace.
  • Memory tab list/pin and the change subscription resolve the owner, so the parent's tab refreshes on child writes and a child's tab shows the shared notes.
  • Dream consolidation refuses sub-agent children (any trigger) and the launch sweep skips them; children still harvest into the shared inbox and the owner sweeps it (child writes are keyed under the owner).
  • A workspace-scope change invalidates the cached memory context of every live AgentSession in the same tree (WorkspaceService.invalidateMemoryContextWhere, wired in core.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 parentWorkspaceId behave 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

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 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-11T09:16:47.109735Z 15ea436 New commits
🔒 Security Review Completed 2026-09-11T09:06:36.997856Z 15ea436 New commits

Security findings

Advisory findings (33)

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

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@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: 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".

Comment thread src/node/services/memoryService.ts Outdated
Comment thread src/node/services/agentSession.ts
Comment thread src/node/services/memoryService.ts Outdated
Comment thread src/node/services/di/layers/core.ts Outdated
Comment thread src/node/services/memoryConsolidationService.ts Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

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

Reviewed commit: 7f235f92df

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.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@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: 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".

Comment thread src/node/services/memoryService.ts
Comment thread src/node/services/refinement/refinementRollback.ts
Comment thread src/node/services/tools/refinement_rollback.ts Outdated
Comment thread src/node/services/workspaceService.ts Outdated
Comment thread src/node/services/memoryConsolidationService.ts Outdated
Comment thread src/node/services/memoryConsolidationService.ts Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

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

Reviewed commit: 3164b699f9

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.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

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

Reviewed commit: 3ab8207bc2

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

Comment thread src/node/services/memoryService.ts Outdated
Comment thread src/node/orpc/routerSubscriptions.ts Outdated
Comment thread src/node/services/memoryOperations.ts Outdated
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

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

Reviewed commit: f6e044dc0b

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

Comment thread src/node/services/memoryService.ts Outdated
Comment thread src/node/services/memoryService.ts Outdated
Comment thread src/node/services/memoryConsolidationService.ts Outdated
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

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

Reviewed commit: a684564bcf

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

Comment thread src/node/services/refinement/refinementRollback.ts Outdated
Comment thread src/node/services/turnRequestBuilder.ts Outdated
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

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

Reviewed commit: 6b926d3116

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

Comment thread src/node/services/memoryConsolidationService.ts Outdated
Comment thread src/node/services/memoryService.ts Outdated
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

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

Reviewed commit: 00145748fa

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

Comment thread src/node/orpc/routerSubscriptions.ts
Comment thread src/node/services/workspaceRemoval.ts
Comment thread src/node/services/memoryConsolidationService.ts Outdated
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@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: 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".

Comment thread src/node/services/workspaceRemoval.ts Outdated
Comment thread src/node/services/memoryService.ts
@chatgpt-codex-connector

Copy link
Copy Markdown

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

Reviewed commit: 6bce3639e8

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.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@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: 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".

Comment thread src/node/services/memoryService.ts Outdated
Comment thread src/node/services/workspaceService.ts Outdated
Comment thread src/node/services/workspaceService.ts Outdated
Comment thread src/node/services/refinement/sharedMemoryRowMigration.ts Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

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

Reviewed commit: 11debce4f2

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.

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

1 similar comment
@ThomasK33

Copy link
Copy Markdown
Member Author

@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 -->

@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

await fsPromises.rm(filePath, { force: true });

P2 Badge Revalidate the tombstone before healing it

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

Comment thread src/node/services/turnRequestBuilder.ts Outdated
Comment thread src/node/services/historyService.ts
Comment thread src/node/services/refinement/sharedMemoryRowMigration.ts Outdated
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 -->

@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

const parsed = JSON.parse(await fsPromises.readFile(filePath, "utf-8")) as {

P2 Badge Quarantine malformed tombstones for registered workspaces

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

Comment thread src/node/services/historyService.ts Outdated
Comment thread src/node/services/workspaceService.ts Outdated
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 -->

@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

const parsed = JSON.parse(await fsPromises.readFile(filePath, "utf-8")) as {
workspaceId?: unknown;
removedAt?: unknown;
};
if (typeof parsed.workspaceId !== "string" || typeof parsed.removedAt !== "number") continue;

P2 Badge Heal tombstones with malformed unused timestamps

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

Comment thread src/node/services/memoryWorkspaceOwner.ts Outdated
Comment thread src/node/services/memoryService.ts Outdated
Comment thread src/node/services/refinement/workspaceMemoryRevision.ts
Comment thread src/node/services/memoryLegacyAdoption.ts Outdated
…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 -->

@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: 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".

Comment thread src/node/services/memoryConsolidationService.ts Outdated
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 -->

@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: 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".

Comment thread src/common/utils/messages/compactionBoundary.ts Outdated
Comment thread src/node/services/historyService.ts Outdated
Comment thread src/node/services/workspaceService.ts
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 -->

@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: 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".

Comment thread src/node/services/historyService.ts Outdated
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 -->

@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: 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".

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

@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

if (existingSeqNum !== undefined) {
assert(
isNonNegativeInteger(existingSeqNum),
"appendToHistory requires historySequence to be a non-negative integer when provided"

P2 Badge Reject pre-sequenced rows without a safe successor

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


if (existing?.status !== "completed" && existingAttemptCount < HARVEST_MAX_ATTEMPTS) {

P2 Badge Do not retry a fresh pending harvest

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

Comment thread src/common/utils/messages/compactionBoundary.ts Outdated
Comment thread src/node/services/memoryService.ts Outdated
Comment thread src/node/services/refinement/refinementRollback.ts Outdated
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 -->

@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

} catch (error) {
// Per-entry isolation: one unreadable marker must not stop the sweep.
log.debug("Skipping unreadable removal tombstone during self-heal", { entry, error });

P2 Badge Recover malformed tombstones for registered workspaces

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


const stat = await fsPromises.stat(filePath);
if (Date.now() - stat.mtimeMs < REMOVAL_TOMBSTONE_HEAL_MIN_AGE_MS) continue;
if (config.findWorkspace(parsed.workspaceId) == null) continue;
await fsPromises.rm(filePath, { force: true });

P2 Badge Serialize tombstone healing with active removal

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

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

@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: 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".

Comment thread src/node/services/compactionHandler.ts Outdated
Comment thread src/node/services/memoryService.ts Outdated
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 -->

@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: 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;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

Comment on lines +343 to +346
return (
typeof snapshot.serverName === "string" &&
typeof snapshot.promptName === "string" &&
typeof snapshot.commandKey === "string"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

Comment on lines +131 to +133
const rollbackByTarget = new Map(
rows.filter(isMigratableRollbackRow).map((row) => [row.data.rollbackOf!, row] as const)
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

Comment on lines +2065 to +2067
const segmentStart = await this.readHistorySegmentStart(workspaceId);
if (segmentStart !== null) this.historySegmentStarts.set(workspaceId, segmentStart);
let maxSequence = (segmentStart ?? this.historySegmentStarts.get(workspaceId) ?? 0) - 1;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

yermakoffivan pushed a commit to yermakoffivan/mux that referenced this pull request Sep 11, 2026
## 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 -->
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