Skip to content

🤖 fix: store post-compaction context on the compaction boundary row - #7693

Open
ethanndickson wants to merge 28 commits into
mainfrom
durable-post-compaction-attachments
Open

ethanndickson wants to merge 28 commits into
mainfrom
durable-post-compaction-attachments

Conversation

@ethanndickson

@ethanndickson ethanndickson commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

I looked at why we keep losing thinking blocks mid-session, and 22 of the 43 drops came from post-compaction attachments (plan file, edited file diffs, todo list, path skills). We only injected them into the provider request, at a position and with content that changed between turns, so the prefix changed under the model and Anthropic dropped the replayed thinking.

My first attempt wrote the attachments as a separate synthetic row in chat.jsonl, but five review rounds showed that a separate row touches every history consumer (the rolling cut, edits, forks, the timeline, retries).

Instead, compaction now renders the attachments once and stores the text on the boundary row itself, as postCompactionContext metadata. Every request inserts that text as a synthetic user row right after the boundary, so every turn, step and compaction request in the window builds the same bytes. Forks, edits and truncation already keep the boundary row as is, so they keep the context for free. The field isn't in MuxMessageSchema, so the frontend never receives it.

Continuous compaction builds the header when it prepares the swap and journals it on the boundary, so the persisted row matches the prefix that was already sent. The builder fits the summary and adds the header once, and finalize persists that row as is, even when a later pending follow-up makes it oversized (the history scanner recovers oversized boundaries). If the header would push the row over the history line limit, we drop it together with its plan baseline rather than cut the summary. The build is time-boxed at 30s, and a failure just publishes the boundary without a header. The context-exceeded retry from #1932 still exists for normal requests; it now marks the boundary row so later requests leave the header out, also after a restart. Compaction requests skip it, since their input trim can already drop the header and they have their own retry. The header also stores the plan as it read it, and turn start tracks the plan from there, so an external plan edit after the snapshot still gets a notice, even one made before the next turn or after a restart. We only track the plan when the header carries it, so a sidebar exclusion change after compaction doesn't change what gets tracked. Replay envelopes no longer store postCompactionAttachmentsHash, as the header is in chat.jsonl now. The retry's mark records the first request without the header, so replay-verify rebuilds the earlier requests with it.

The header is a snapshot from compaction time, so it no longer refreshes every 5 turns, and a change to the sidebar exclusions applies from the next compaction. Tracking the plan from the header can report a plan edit twice, when the agent made it after the snapshot (continuous compaction runs mid-stream) or we already reported it before a restart, but it never misses one. Boundaries written before this change have no header, so the first window after an upgrade runs without the context until the next compaction. That includes a continuous-compaction journal an older build left behind for recovery. Remote runtimes still don't re-track the plan file, as the file tracker reads the host filesystem; that's the same on main, and a runtime-backed tracker can be a follow-up.

Two more follow-ups. The header's skill names list every skill in the snapshot, even one the 80k budget cut, so path activation won't point the model at a cut skill; main derives the names the same way. A fork copies the header as is, so it names the source workspace's plan path. On main a fork after compaction got no post-compaction context at all, and the copied summary already names that path; remapping it without breaking the replayed thinking can come later.


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: xhigh

Post-compaction attachments (plan file, edited-file diffs, todo list, path skills) were injected only into the provider request. The next turn rebuilt the request without them, so the model saw its context change between turns. This caused many thinking-block drops.

Now the first non-compaction turn after a compaction appends the attachments as a hidden synthetic row in chat.jsonl, after the user message, like the file-change notice rows. Later turns read the same row from history, so the request prefix stays stable.

- Skip the row for compaction turns, prepared requests and when attachments are disabled. Reuse an existing row in the current window.
- Delete the row on a context-exceeded retry (new HistoryService.deleteMessageUnderAdmission).
- Never copy the row into a compaction's preserved tail.
- Hide the row in the transcript.
- Treat the row like the budget warning row for resume, task goal continuation, goal follower and revival scans.
- Remove the periodic refresh every 5 turns.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `xhigh` • Cost: `$94.02`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=xhigh costs=94.02 -->
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 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-10-30T06:01:54.980144Z 942e080 Manual request
🔒 Security Review ✅ Completed 2026-10-30T05:59:02.020979Z 942e080 Manual request

Security findings

Advisory findings (2)

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

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

🟢 e2e stories (Haiku): 14 passed

22 agent steps · 7 replayed from cache · 15 model calls · 46.3k tokens (24% cached)
Spend: $0.09 of the $1.00 cap (proxy ledger)

All 14 tests in 9 files
Test Agent Time
🟢 chatRestart.e2e.ts · 1 passed 1 step · 1 call 5.9s
🟢 a chat survives a restart of the server 1 step · 1 call 5.9s
🟢 compaction.e2e.ts · 1 passed 1 step · 1 call 4.2s
🟢 /compact replaces the old chat with a summary 1 step · 1 call 4.2s
🟢 pluginTrustRestart.e2e.ts · 1 passed 4 steps · 2 calls 9.7s
🟢 a trusted plugin hook stays trusted after the server restarts 4 steps · 2 calls 9.7s
🟢 settingsRoundTrip.e2e.ts · 1 passed 2 steps · 1 call 8.8s
🟢 a chat survives trips through Settings 2 steps · 1 call 8.8s
🟢 sidebarPerWorkspace.e2e.ts · 1 passed 4 steps · 1 call 4.2s
🟢 a new workspace starts with its right sidebar collapsed while another keeps it open 4 steps · 1 call 4.2s
🟢 smoke.e2e.ts · 1 passed 2 steps · 1 call 2.8s
🟢 the agent opens the playground workspace 2 steps · 1 call 2.8s
🟢 streamErrors.e2e.ts · 1 passed 1 step · 1 call 6.5s
🟢 stream errors show in the chat, and the chat recovers 1 step · 1 call 6.5s
🟢 todoNudge.e2e.ts · 1 passed 1 step · 1 call 2.7s
🟢 the agent finishes open TODO items after the turn-end nudge 1 step · 1 call 2.7s
🟢 touchAlignment.e2e.ts · 6 passed 6 steps · 6 calls 21.0s
🟢 the Settings close button is level with the title on a touch screen 390px wide 1 step · 1 call 3.8s
🟢 the Settings close button is level with the title on a touch screen 768px wide 1 step · 1 call 3.8s
🟢 Backup settings checkboxes are small and level with their labels on a touch phone 1 step · 1 call 4.5s
🟢 the heartbeat checkbox is small and level with its label on a touch phone 1 step · 1 call 3.1s
🟢 a reply's model and time stay on one line on a touch phone 1 step · 1 call 3.0s
🟢 the workspace actions menu stays on the title row on a touch phone 1 step · 1 call 2.8s

e2e 0.20.0 · 1m 9s · web · run artifacts

🟢 e2e Electron stories (Haiku): 3 passed

3 agent steps · 3 model calls · 8.0k tokens (22% cached)
Spend: $0.02 of the $1.00 cap (proxy ledger)

All 3 tests in 3 files
Test Agent Time
🟢 electron/deepLink.e2e.ts · 1 passed 1 step · 1 call 5.2s
🟢 a deep link of a second launch starts a chat in the running app 1 step · 1 call 5.2s
🟢 electron/menuBar.e2e.ts · 1 passed 1 step · 1 call 5.3s
🟢 the workspace menu bar is the desktop title bar 1 step · 1 call 5.3s
🟢 electron/smoke.e2e.ts · 1 passed 1 step · 1 call 5.4s
🟢 Xum Electron opens the playground workspace 1 step · 1 call 5.4s

e2e 0.20.0 · 18.2s · electron · run artifacts

🟢 e2e agent repros (Haiku): no tests selected

Spend: $0.00 of the $1.00 cap (proxy ledger)

e2e 0.20.0 · 5.3s · 2 targets (web, phone) · run artifacts

@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 Security Review · Automatically triggered

Here are some automated security review suggestions for this pull request.

Reviewed commit: a51fdcfed3

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

Comment thread src/node/services/agentSession.ts Resolved

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

ℹ️ 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 Resolved
Comment thread src/node/services/turnRequestBuilder.ts Resolved
Comment thread src/node/services/agentSession.ts Resolved
- Place the attachments row before the turn's prompt in every provider request.
- Append the row only while the history tail still matches the turn's read, so a compaction
  publication that lands meanwhile cannot leave a row from the older snapshot in the new window.
- Count skills that the row carries as surfaced, so path-scoped skills get no second pointer.
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Round 1 is addressed in b6d680e and 36832f5: the attachments row sits before the prompt in the provider payload, the row append and the row reuse both check that the history tail still matches the turn's read, and carried skills count as surfaced.

Declined: "Track durable attachment rows after acknowledgment". After the acknowledgment the row is ordinary history that the model already acted on. Deleting it on a later overflow would change that conversation. Before this PR, later turns had no retry without attachments either. Overflow from later history goes through the context strategy recovery (contextController.onSendFailure), like any other large row.

@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: 36832f51e7

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: 36832f51e7

ℹ️ 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 Resolved
Comment thread src/node/services/agentSession.ts Resolved
- Restore the post-compaction attachments row when an edit cuts it, unless the edit also cut
  the row's context boundary. The snapshot was acknowledged, so no later turn writes it again.
- Consume the pending snapshot and mark the context retry only after the row delete succeeds,
  so a failed delete leaves a row that the next turn can still reuse or delete.
- Stop reading carried skills from the row text: plan text or a skill body can contain a skill
  tag and hide a real path-skill pointer. A carried skill can now get one extra pointer.
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Round 2 is addressed in b8a5950:

  • A context-exceeded retry now deletes the attachments row before it retries. If the delete fails, the turn keeps the pending snapshot and skips the retry.
  • The skill-tag parsing of the row text is gone, so row text can no longer suppress a skill pointer. A carried path skill can get one extra pointer per window; the PR description lists the follow-up.
  • Editing an earlier message re-appends the last removed attachments row, unless the edit also removes a compaction boundary.

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

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: b8a5950bbc

ℹ️ 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 Resolved
Comment thread src/node/services/agentSession.ts Resolved
Comment thread src/node/services/compactionHandler.ts Resolved
The post-compaction attachments row is a user-role row stored after its
turn's prompt. Edits that cut a later boundary keep it, branch summaries
and /refine skip it, rolling cuts and title context do not start a turn on
it, request context goes before the prompt instead of before the row, and
the default Continue resume stays muted when the row follows it.
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Round 3 fixes are in cee66e8. Every history consumer now treats the post-compaction attachments row as carried context, not as a turn: edit restore, branch summaries and /refine, rolling cuts, the default Continue mute, request context placement, and title context.

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

ℹ️ 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 boundary drops the old window's post-compaction attachments row, and
the attachment budget already counts the fresh row that replaces it. Cut
selection and the staged-summary fit check now give that row zero weight,
so a large row no longer forces a smaller or empty retained tail.
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Round 4 fix is in 7484a75: rolling cut selection and the staged-summary fit check no longer count the old attachments row that the boundary drops. The security advisory about provider order was fixed in b6d680e (placePostCompactionAttachmentsBeforePrompt, covered by "sends the attachments before the operator's prompt on every turn" in messagePipeline.test.ts).

@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: 7484a7586a

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: 7484a7586a

ℹ️ 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 Resolved
Comment thread src/node/services/agentSession.ts Resolved
Comment thread src/node/services/agentSession.ts Resolved
@ethanndickson

Copy link
Copy Markdown
Member Author

Pausing the Codex review loop for a human decision (AGENTS.md early stop case 2: the loop does not converge).

Findings per round: 4, 3, 6, 1, 5. Round 5 grew again. Each round finds one more consumer of chat.jsonl that the new attachments row leaks into (rolling cut, edit, retry, timeline, fork). This pattern points at the design, not at single bugs: every history consumer must know about the row.

Open round 5 findings on 7484a75:

  1. Summary head counts the dropped attachments row (rollingCut.ts). Introduced by this PR. Small fix.
  2. Edit continues when restoring the row fails (agentSession.ts). Failure path in code this PR added.
  3. Retry continues when the pending-state discard fails (agentSession.ts). Failure path in code this PR added.
  4. The row reaches the timeline as a synthetic turn (agentSession.ts, timeline mapper). Introduced by this PR. Small fix.
  5. Fork from the prompt drops the row. Fork did not carry attachments before this PR either (post-compaction.json is not copied), so this existed before. Defer.

I left these threads open. Options: fix 1 to 4 and continue the loop, simplify the design so fewer consumers see the row, or stop here for human review.

Compaction renders the post-compaction context once and stores it on the
boundary row. Every request of the window inserts the same synthetic row
after the boundary, so the prefix stays stable and Anthropic keeps the
replayed thinking.

Keeps the context-exceeded retry without the header, the report cutoff at
wall-clock time, a 30s header build limit, the header fit for continuous
compaction, and plan-file re-tracking after the post-compaction clear.
@ethanndickson ethanndickson changed the title 🤖 fix: persist post-compaction attachments as a durable history row 🤖 fix: store post-compaction context on the compaction boundary row Oct 29, 2026
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

…ary row

The context-exceeded retry now marks the boundary row with the first request sequence that leaves the header out. Later requests leave it out too, also after a restart, and replay-verify rebuilds the earlier requests with it.

The header also stores the plan as it read. Turn start tracks the plan from it, so plan edits after the snapshot get a change notice, even before the next turn or after a restart.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `xhigh`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=xhigh -->
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

Resuming the loop. 9d8597d stores the header omission and the plan baseline on the boundary row, so both survive a restart. The security finding got a reasoned reply on its thread.

expect.any(Number) inside toEqual is an unsafe any assignment for the type-aware ESLint rule. Check the plan fields with toMatchObject and the modified time with typeof.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `xhigh`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=xhigh -->
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

2c3e21e fixes the type-aware ESLint error in the FIFO plan integration test (test-only).

@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: 2c3e21ee2f

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: 2c3e21ee2f

ℹ️ 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 Resolved
Comment thread src/node/services/agentSession.ts Resolved
…mal requests

The continuous compaction builder now fits the summary and adds the header once. The swap sends that row, and finalize persists it as built. A pending follow-up that makes the row too big leaves it oversized; the history scanner recovers oversized compaction boundaries.

The header keeps its plan baseline or is dropped with it. A plan in the header that nothing tracks would replay stale after the user edits the file.

The header-omission retry arms only for requests that are not compaction requests. A compaction request trims its input to its budget, and the trim can drop the header row, so its overflow does not show that the header caused it.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `xhigh`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=xhigh -->
@ethanndickson

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: 0f577a887c

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.

ℹ️ 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 Resolved
Comment thread src/node/services/agentSession.ts Resolved
A context-exceeded retry leaves the post-compaction header out of later
requests. The boundary row's contextUsage now drops the header's tokens at
the same time, so the context meter and the next compaction check stop
counting a header that requests no longer render.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `xhigh`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=xhigh -->
@ethanndickson

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: a6a78d7e9d

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: a6a78d7e9d

ℹ️ 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 Resolved
An edit or fork that removes every row a request without the header saw
also removes the reason to leave the header out: the retained turns ran with
it, and the request that overflowed is gone. Truncation now clears the
omission mark on the latest boundary in that case and counts the header in
the boundary's usage again.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `xhigh`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=xhigh -->
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

5675315 fixes the edit/fork finding: a cut before the header omission puts the header back.

Accepted known limitations (please do not raise these again):

  • The post-compaction header is best effort. When its build throws, times out, or does not fit the boundary row, that window has no header, and its diffs are not carried to a later compaction.
  • A context-exceeded retry cannot leave the header out of a boundary row over the 1 MiB history line limit (only a queued follow-up of about 1 MiB causes one). The retry is refused on purpose, and the turn ends with the normal context-exceeded error.
  • Builds before this PR ignore postCompactionContext, so a downgrade loses the header on every boundary this version wrote, pending continuous-compaction journals included. The journal keeps version 1 because a bump would not change that.

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

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: 5675315150

ℹ️ 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 Resolved
Comment thread src/node/services/compactionHandler.ts Resolved
This reverts commit 5675315. Rendering the header again after an edit or
fork cut did not restore the state that the headerless retry had already
changed: the plan-baseline cache keyed by the boundary ID and the discarded
carryover. An edit or fork back before a header omission now keeps the
header out, and the boundary state stays consistent.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `xhigh`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=xhigh -->
A continuous boundary drops a header that does not fit its row, but its
contextUsage still added the header estimate from before the build. The
boundary now counts the header on the row: the journaled header for a
prepared boundary, and the header that publication adds for the others.
The unused attachmentTokens argument of buildContinuousCompactionRows is
removed.

---

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `xhigh`_

<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=xhigh -->
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

42718e9 reverts 5675315: rendering a left-out header again after an edit or fork cut could not restore the plan-baseline cache or the discarded carryover. e53d3bf makes a continuous boundary count only the header that its row keeps.

Accepted known limitations (please do not raise these again):

  • The post-compaction header is best effort. When its build throws, times out, or does not fit the boundary row, that window has no header, and its diffs are not carried to a later compaction.
  • A context-exceeded retry cannot leave the header out of a boundary row over the 1 MiB history line limit (only a queued follow-up of about 1 MiB causes one). The retry is refused on purpose, and the turn ends with the normal context-exceeded error.
  • Builds before this PR ignore postCompactionContext, so a downgrade loses the header on every boundary this version wrote, pending continuous-compaction journals included. The journal keeps version 1 because a bump would not change that.
  • After a context-exceeded retry leaves the header out, an edit or fork back to before that retry keeps the header out. The carryover that the retry discarded stays discarded, and the plan baseline stays consistent with the requests.

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

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: e53d3bfec6

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

@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

No code change since e53d3bf. The discard-failure finding is declined with reasons in its thread.

Accepted known limitations (please do not raise these again):

  • The post-compaction header is best effort. When its build throws, times out, or does not fit the boundary row, that window has no header, and its diffs are not carried to a later compaction.
  • A context-exceeded retry cannot leave the header out of a boundary row over the 1 MiB history line limit (only a queued follow-up of about 1 MiB causes one). The retry is refused on purpose, and the turn ends with the normal context-exceeded error.
  • Builds before this PR ignore postCompactionContext, so a downgrade loses the header on every boundary this version wrote, pending continuous-compaction journals included. The journal keeps version 1 because a bump would not change that.
  • After a context-exceeded retry leaves the header out, an edit or fork back to before that retry keeps the header out. The carryover that the retry discarded stays discarded, and the plan baseline stays consistent with the requests.
  • The retry's carryover discard uses the existing consume(), which logs storage errors and does not throw. The snapshot is discarded in memory at once; only a failed delete followed by a restart can bring the file back, and the header stays best effort then.

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

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: e53d3bfec6

ℹ️ 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 Resolved
- A mid-stream prefix swap now checks the window again with the header it sends. The estimate that admitted the summary can lack that header when its build timed out. A swap that no longer fits falls back to the durable apply.
- Turn start seeds the plan baseline from the boundary header only when the tracker has no newer state for the plan. A tool in the retained tail of a swap can record a newer state that the model already saw.

_Generated with `xum` • Model: `anthropic:claude-opus-5-5` • Thinking: `xhigh`_
<!-- mux-attribution: model=anthropic:claude-opus-5-5 thinking=xhigh -->
@ethanndickson

Copy link
Copy Markdown
Member Author

@codex review

942e080 fixes the 2 findings on e53d3bf:

  • A mid-stream prefix swap now checks the window again with the header that its boundary keeps. If the swap no longer fits, the compactor uses the durable apply.
  • Turn start seeds the plan baseline from the boundary header only when the tracker has no newer state for the plan.

Accepted known limitations (please do not raise these again):

  • The post-compaction header is best effort. When its build throws, times out, or does not fit the boundary row, that window has no header, and its diffs are not carried to a later compaction.
  • A context-exceeded retry cannot leave the header out of a boundary row over the 1 MiB history line limit (only a queued follow-up of about 1 MiB causes one). The retry is refused on purpose, and the turn ends with the normal context-exceeded error.
  • Builds before this PR ignore postCompactionContext, so a downgrade loses the header on every boundary this version wrote, pending continuous-compaction journals included. The journal keeps version 1 because a bump would not change that.
  • After a context-exceeded retry leaves the header out, an edit or fork back to before that retry keeps the header out. The carryover that the retry discarded stays discarded, and the plan baseline stays consistent with the requests.
  • The retry's carryover discard uses the existing consume(), which logs storage errors and does not throw. The snapshot is discarded in memory at once; only a failed delete followed by a restart can bring the file back, and the header stays best effort then.

@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: 942e080f01

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: 942e080f01

ℹ️ 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 on lines +203 to +205
const withContext: MuxMessage = {
...boundary,
metadata: { ...boundary.metadata, postCompactionContext: context },

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 Preserve headers during late boundary rewrites

When compaction upgrades a streamed placeholder before a late finalizer rewrites the same row, this newly stored field is lost: getCompactionMetadataToPreserve() preserves the boundary markers and summary metadata but not postCompactionContext. The next turn can therefore acknowledge the pending snapshot against a headerless boundary, dropping a successfully built plan/skills/diffs header. Preserve the header in the existing late-rewrite protection.

AGENTS.md reference: AGENTS.md:L114-L117

Useful? React with 👍 / 👎.

Comment on lines +134 to +139
const omitted: MuxMessage = {
...boundary,
metadata: {
...boundary.metadata,
postCompactionContext: { ...context, omittedFromRequestSequence: requestHistorySequence },
},

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 Invalidate staged summaries when omitting the header

In continuous mode, an eager summary can be staged while this header is still present; if a later request hits context_exceeded, this rewrite removes the header without resetting the compactor. Because ContinuousCompactor.fingerprint() excludes postCompactionContext, the staged summary still passes isValid() and can later be applied even though it was generated from the carryover that the retry deliberately discarded. Include the header/omission state in the fingerprint or invalidate the staged summary when persisting this marker.

AGENTS.md reference: AGENTS.md:L114-L117

Useful? React with 👍 / 👎.

Comment on lines +13545 to +13549
if (
this.planBaselineBoundaryId !== undefined &&
(await this.contextController.compaction.peekPendingState()) === null
)
return;

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 Re-seed the plan after edits cross a boundary

When the user edits a message from before the latest compaction, truncation can remove that boundary and expose an older plan-bearing boundary, but planBaselineBoundaryId remains defined and this fast path skips the history read because no new pending state exists. The tracker consequently retains the discarded branch's newer plan baseline, so the model keeps seeing the older header without receiving a diff for the current plan. This is separate from the reverted omitted-header restoration case: a normal edit changes the latest boundary ID without invalidating this cache; reset the cache and incompatible tracked plan state when such an edit truncates across a boundary.

Useful? React with 👍 / 👎.

This branch has not been deployed

No deployments
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