feat(agent-core-v2): anchor compaction resumption on the latest user message - #3537
feat(agent-core-v2): anchor compaction resumption on the latest user message#35377Sageer wants to merge 5 commits into
Conversation
🦋 Changeset detectedLatest commit: 07c4d35 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9bb7136196
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| messages: [ | ||
| ...keptMessages, | ||
| createCompactionSummaryMessage(contextSummary), | ||
| createCompactionContinuationMessage(), |
There was a problem hiding this comment.
Include the continuation reminder in tokensAfter
For every non-legacy compaction, this adds another model-visible message, but the tokensAfter calculation above still includes only request overhead, the summary, and keptMessages. AgentContextMemoryService.applyCompaction then rebases token counting to that underestimated value, and the same value is used for compaction thresholds, telemetry, and PostCompact hooks; near the context limit, the next request can therefore be allowed despite exceeding the configured budget. Add the continuation message's estimated tokens to the calculation before rebasing.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 915d462 — the continuation message is now included in the tokensAfter estimate, and the token-ledger tests cover it.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2e35106bea
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| export function buildCompactionContinuationText(): string { | ||
| return wrapSystemReminder( | ||
| 'Context compaction is complete — continue the work for the latest user message from where it stopped.', | ||
| ); |
There was a problem hiding this comment.
Preserve the active non-user turn after compaction
When automatic compaction runs during a system_trigger, task, cron_job, or similar turn, this reminder redirects the model to an unrelated earlier user request. The full-compaction hook runs before every step in fullCompactionService.ts, while compactionUserMessageDisposition deliberately removes those non-user inputs from the rebuilt context, leaving their instructions only in the summary. The continuation should therefore refer to the in-flight task or summary rather than unconditionally selecting the latest user message.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 8d4968c — the continuation no longer unconditionally selects the latest user message; it now says to continue the work that was in progress when compaction began, which covers non-user turns (cron/system_trigger/task) whose prompts are dropped from the rebuilt context.
| @@ -1 +1 @@ | |||
| The conversation so far has been compacted to free up context. What follows is your own working summary of this task — use it to continue your train of thought rather than starting over. Treat it as notes, not proof: where it says a step was done, tests passed, or a fix worked, verify that yourself before relying on it. Any user messages earlier in this context are preserved verbatim from the compacted conversation; where a system-reminder note among them marks an omitted middle section, the user messages it replaced are covered by this summary. | |||
| The conversation so far has been compacted to free up context. What follows is your own working summary of this task — use it to continue your train of thought rather than starting over. Treat it as notes, not proof: where it says a step was done, tests passed, or a fix worked, verify that yourself before relying on it. Any user messages earlier in this context are preserved verbatim from the compacted conversation; where a system-reminder note among them marks an omitted middle section, the user messages it replaced are covered by this summary. Respond to the latest genuine user message — earlier requests recorded in the summary were already addressed. | |||
There was a problem hiding this comment.
Do not mark every earlier request as completed
When the user steers an active turn with a follow-up such as “also add tests” or answers a clarification, the governing unfinished request is an earlier request that the summary must preserve. This new unconditional assertion tells the resumed model that request was already addressed, contradicting the summary's pending work and potentially causing the model to abandon the original task. Limit this statement to requests the summary identifies as completed instead of treating all earlier requests as finished.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 8d4968c — the absolute claim is gone; the prefix now only points out that the summary records which earlier requests were already addressed, so unfinished earlier requests (follow-ups, clarifications) are not falsely marked as completed.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8d4968c23e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| messages: [ | ||
| ...keptMessages, | ||
| createCompactionSummaryMessage(contextSummary), | ||
| continuationMessage, |
There was a problem hiding this comment.
Preserve token-anchor indices when replaying old compactions
When reopening a session whose compaction was written by a pre-upgrade build, the record's keptUserMessageCount still selects this non-legacy rebuild path, so replay inserts the new continuation message even though later durable token_counting.* anchors retain their original message lengths. This shifts every subsequent message by one; under the default measured-plus-estimated strategy, the last message after an old anchor is then estimated again despite already being included in the measured token total. A large final response can consequently make a resumed session appear over budget and trigger an unnecessary compaction. Version the new compaction shape or adjust replayed token-anchor lengths when retroactively inserting this message.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 07c4d35 — the compaction record now carries an explicit hasContinuation flag written by new compactions; replay inserts the continuation message only when the flag is present, so pre-upgrade records rebuild to their original message count and token anchors stay aligned. Fold-length recovery uses the same flag.
…s so old records replay unchanged
|
@codex review |
|
Codex Review: Didn't find any major issues. Keep them coming! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
Related Issue
Related #2680, #3487 — prompt-layer mitigation of the post-compaction derailment pattern; does not fully resolve them (harness-layer items are intentionally out of scope, see below).
Problem
After automatic compaction in long sessions, the rebuilt context has three structural properties that combine into a derailment mode:
What changed
Prompt-layer only, minimal by design (validated against 6 peer CLI compaction implementations — all use report-style handoffs rather than first-person notes, and position semantics is the one point they defend heavily):
compaction-instruction.md): reframe "write a first-person handoff note to yourself" as "create a handoff summary for the model that will resume this task". Drops both the first-person mandate and the third-person prohibition — no new restriction, the voice follows the framing. "Let the shape follow the task" is kept; no fixed sections are imposed.compaction-summary-prefix.md): append one position-semantics sentence — "Respond to the latest genuine user message — earlier requests recorded in the summary were already addressed." This is information the model cannot infer (the answers were deleted), not a behavioral rule.compactionHandoff.ts): append oneorigin: injectionsystem-reminder after the summary ("resume from the latest user message; if a turn was in flight when compaction began, finish that turn first"), so the summary is never the last message. The anchor is dropped by the next compaction like the elision marker, and skipped by undo/transcript like other injections.contextTranscript.ts):recoverFoldedLengthcounts the anchor so transcript fold length stays at parity with the live context (the anchor stays hidden from the transcript view, same as the elision marker).Intentionally NOT in this draft (harness layer, needs separate design): post-compaction authorization invalidation for irreversible actions (#3487 case 1), extending
historySafeToCompactto background-task/TODO state (#3487 case 3), mechanical summary appendix (anchor index / high-value tool-call quoting), attachment rebuild.Tests: updated the compacted-shape expectations across
fullCompaction,contextMemory,undo,splice-replay,contextTranscriptsuites;agent-core-v2full suite passes except pre-existing environment failures in plugin archive/manager tests (spawnSync zip ENOENT, network-dependent);kap-serverfull suite passes (1324/1324).Checklist
/approve).gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update (internal prompt/behavior tuning, no user-facing surface change).