You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On GJC 0.13.2, a long but otherwise healthy managed session can abort during message_end when its transcript reaches the 64 MiB per-file limit. The dominant growth is not user/model prose or rendered diffs: every successful apply_patch tool result persists the complete pre-edit and post-edit file contents in message.details.oldText and message.details.newText.
Repeated small edits to one large source file therefore add roughly 2 × file_size to the JSONL on every patch. Once the next tool result no longer fits, managed append raises content_too_large; AgentSession aborts the active turn, and the just-applied source mutation may exist without its tool result or subsequent verification being durably recorded.
GJC_SESSION_CONTEXT_BUDGET_BYTES, whose current 512 MiB default governs context materialization rather than the managed transcript file.
I found no existing issue covering live append amplification from edit-result metadata.
Observed evidence
A real session ended with:
Session persistence error
SessionAppendPersistenceError: content_too_large
at appendManagedFileStreamingSync (.../managed-session-storage.ts:3053)
at #appendManagedRecordsSync (.../session-manager.ts:15630)
Sanitized measurements from that transcript:
transcript at failure: 66,553,990 bytes (63.4708 MiB)
per-file limit: 67,108,864 bytes (64 MiB)
remaining capacity before the failed append: 554,874 bytes
entries: 1,387
apply_patch tool results: 180
bytes attributable to those results: about 57.05 MiB (about 90% of the transcript)
assistant entries: about 3.77 MiB
all other tool-result families combined: about 2.63 MiB
The edited file was roughly 395–397 KiB. Individual small apply_patch results were about 0.76 MiB because their persisted details contained both full-file snapshots. The final append exceeded the remaining 0.53 MiB and failed deterministically.
The provider request itself had not failed for context overflow; the logged terminal cause was local persistence content_too_large.
Current code path
In tagged 0.13.2 and current dev:
packages/coding-agent/src/edit/modes/patch.ts returns full oldText and newText in EditToolDetails.
packages/coding-agent/src/edit/index.ts retains those fields in single-file and aggregated apply_patch results.
packages/coding-agent/src/session/session-manager.ts persists the complete toolResult to the managed JSONL.
packages/coding-agent/src/session/internal/managed-session-storage.ts rejects append when predecessor size plus appended bytes exceeds MANAGED_ARTIFACT_MAX_FILE_BYTES (64 MiB).
packages/coding-agent/src/session/agent-session.ts treats a normal tool-result SessionAppendPersistenceError as fatal and aborts the agent. Only todo_write has specialized reconciliation handling.
Compaction does not reliably prevent this boundary: the observed session compacted once, then accumulated another 34.66 MiB after the compaction, primarily through repeated edit results. Cold spill also preserves data elsewhere and does not change the hard per-file append contract by itself.
Minimal reproduction
A synthetic test does not need private session content:
Create a managed session and a source file around 400 KiB.
Apply many one-line apply_patch updates to that same file.
Inspect each persisted tool result and confirm it contains the complete old and new file bodies.
Continue until the transcript is just below 64 MiB.
Apply one more small patch.
Expected current result: the file mutation succeeds, then persistence of the tool result raises content_too_large and aborts the turn.
The same behavior can be reproduced faster with a larger synthetic file while remaining below the edit input/output guards.
Expected behavior
A small edit should have persistence cost proportional to its bounded result evidence, not twice the entire target file. Reaching a storage boundary must not leave an applied mutation followed by an unrecorded tool result and silently skipped verification.
Suggested fix boundary
The exact representation is a maintainer decision, but a complete fix likely needs both parts:
Bound persisted edit-result details. Keep the rendered diff, path, operation, diagnostics, and content identities/digests needed for replay. Do not inline complete oldText/newText into every durable tool result. If full snapshots are required for UI/fidelity, place them in a bounded content-addressed artifact and persist references, or strip them before session persistence after their process-local consumer is finished.
Handle near-limit live append explicitly. Preflight the serialized record against remaining transcript capacity and perform a typed recovery (for example a fresh linked session/handoff or a recoverable terminal receipt) before mutation where possible. At minimum, surface a structured error that states the source mutation may already have committed and provides an exact recovery path; do not continue emitting repeated message_end persistence warnings.
Simply raising the 64 MiB constant would delay the same amplification and increase resume/memory risk.
Acceptance criteria
A regression test repeatedly applies small patches to a large synthetic file and proves durable transcript growth is bounded independently of full file size.
Persisted edit results retain enough bounded evidence for rendering, diagnostics, replay/fidelity, and source-change accounting without duplicating both complete file bodies per edit.
A synthetic near-64-MiB live append cannot terminate with an unclassified SessionAppendPersistenceError after a source mutation.
The recovery result states whether the edit committed and how to continue safely.
Summary
On GJC 0.13.2, a long but otherwise healthy managed session can abort during
message_endwhen its transcript reaches the 64 MiB per-file limit. The dominant growth is not user/model prose or rendered diffs: every successfulapply_patchtool result persists the complete pre-edit and post-edit file contents inmessage.details.oldTextandmessage.details.newText.Repeated small edits to one large source file therefore add roughly
2 × file_sizeto the JSONL on every patch. Once the next tool result no longer fits, managed append raisescontent_too_large;AgentSessionaborts the active turn, and the just-applied source mutation may exist without its tool result or subsequent verification being durably recorded.This is distinct from:
GJC_SESSION_CONTEXT_BUDGET_BYTES, whose current 512 MiB default governs context materialization rather than the managed transcript file.I found no existing issue covering live append amplification from edit-result metadata.
Observed evidence
A real session ended with:
Sanitized measurements from that transcript:
66,553,990bytes (63.4708 MiB)67,108,864bytes (64 MiB)554,874bytesapply_patchtool results: 18057.05 MiB(about 90% of the transcript)3.77 MiB2.63 MiBThe edited file was roughly 395–397 KiB. Individual small
apply_patchresults were about 0.76 MiB because their persisted details contained both full-file snapshots. The final append exceeded the remaining 0.53 MiB and failed deterministically.The provider request itself had not failed for context overflow; the logged terminal cause was local persistence
content_too_large.Current code path
In tagged 0.13.2 and current
dev:packages/coding-agent/src/edit/modes/patch.tsreturns fulloldTextandnewTextinEditToolDetails.packages/coding-agent/src/edit/index.tsretains those fields in single-file and aggregatedapply_patchresults.packages/coding-agent/src/session/session-manager.tspersists the completetoolResultto the managed JSONL.packages/coding-agent/src/session/internal/managed-session-storage.tsrejects append when predecessor size plus appended bytes exceedsMANAGED_ARTIFACT_MAX_FILE_BYTES(64 MiB).packages/coding-agent/src/session/agent-session.tstreats a normal tool-resultSessionAppendPersistenceErroras fatal and aborts the agent. Onlytodo_writehas specialized reconciliation handling.Compaction does not reliably prevent this boundary: the observed session compacted once, then accumulated another 34.66 MiB after the compaction, primarily through repeated edit results. Cold spill also preserves data elsewhere and does not change the hard per-file append contract by itself.
Minimal reproduction
A synthetic test does not need private session content:
apply_patchupdates to that same file.Expected current result: the file mutation succeeds, then persistence of the tool result raises
content_too_largeand aborts the turn.The same behavior can be reproduced faster with a larger synthetic file while remaining below the edit input/output guards.
Expected behavior
A small edit should have persistence cost proportional to its bounded result evidence, not twice the entire target file. Reaching a storage boundary must not leave an applied mutation followed by an unrecorded tool result and silently skipped verification.
Suggested fix boundary
The exact representation is a maintainer decision, but a complete fix likely needs both parts:
oldText/newTextinto every durable tool result. If full snapshots are required for UI/fidelity, place them in a bounded content-addressed artifact and persist references, or strip them before session persistence after their process-local consumer is finished.message_endpersistence warnings.Simply raising the 64 MiB constant would delay the same amplification and increase resume/memory risk.
Acceptance criteria
SessionAppendPersistenceErrorafter a source mutation.Environment