fix: add session-growth guard to prevent unbounded session store growth#11999
fix: add session-growth guard to prevent unbounded session store growth#11999reverendrewind wants to merge 3 commits into
Conversation
…th (#11971) Context pruning (cache-ttl) and DM history limiting modify messages in-flight before the API call but never touch the session store. This masks the true session size from the pi-coding-agent library's auto-compaction trigger, causing the JSONL store to grow unbounded. Non-Anthropic providers then receive the full unpruned history (854K+ tokens observed in production). Add a pre-prompt guard in runEmbeddedPiAgent that estimates actual stored tokens via SessionManager and forces compaction when the store exceeds 80% of the context window. The guard is provider-agnostic, best-effort (errors are logged, never block the prompt), and runs once before the retry loop. - Add estimateSessionFileTokens() to compact.ts - Add SESSION_GROWTH_COMPACTION_THRESHOLD (0.8) and guard in run.ts - Add 6 tests in run.session-growth-guard.test.ts - Existing overflow-compaction tests unaffected (8/8 pass) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| it("skips guard when no session file is provided", async () => { | ||
| const paramsNoFile = { ...baseParams, sessionFile: undefined as unknown as string }; | ||
|
|
||
| mockedRunEmbeddedAttempt.mockResolvedValueOnce(makeAttemptResult()); |
There was a problem hiding this comment.
Invalid param type cast
RunEmbeddedPiAgentParams.sessionFile is a required string (src/agents/pi-embedded-runner/run/params.ts:57), but this test forces sessionFile to undefined via undefined as unknown as string. That defeats type-safety and makes the test cover a state that can’t occur for real callers, while also hiding that if (params.sessionFile) in run.ts is effectively dead under the current type.
Consider either (a) making sessionFile optional in the real params type (if “no session file” is a valid runtime scenario), or (b) update the test to pass a real string and instead cover the “missing file on disk” path (which estimateSessionFileTokens already handles) without type casting.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-runner/run.session-growth-guard.test.ts
Line: 269:272
Comment:
**Invalid param type cast**
`RunEmbeddedPiAgentParams.sessionFile` is a required `string` (src/agents/pi-embedded-runner/run/params.ts:57), but this test forces `sessionFile` to `undefined` via `undefined as unknown as string`. That defeats type-safety and makes the test cover a state that can’t occur for real callers, while also hiding that `if (params.sessionFile)` in `run.ts` is effectively dead under the current type.
Consider either (a) making `sessionFile` optional in the real params type (if “no session file” is a valid runtime scenario), or (b) update the test to pass a real string and instead cover the “missing file on disk” path (which `estimateSessionFileTokens` already handles) without type casting.
How can I resolve this? If you propose a fix, please make it concise.Address Greptile review: remove `undefined as unknown as string` cast that defeats type-safety. Replace with empty-string test (valid falsy string) and add nonexistent-file test covering the real runtime path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
bfc1ccb to
f92900f
Compare
|
This pull request has been automatically marked as stale due to inactivity. |
|
Closing as AI-assisted stale-fix triage. Linked issue #11971 ("Bug: contextPruning (cache-ttl) masks session size from compaction, causing unbounded growth for non-Anthropic models") is currently CLOSED and was closed on 2026-02-23T04:33:33Z with state reason NOT_PLANNED. If the underlying bug is still reproducible on current main, please reopen this PR (or open a new focused fix PR) and reference both #11971 and #11999 for fast re-triage. |
|
Closed after AI-assisted stale-fix triage (closed issue duplicate/stale fix). |
Summary
Fixes #11971.
runEmbeddedPiAgentthat estimates actual stored tokens viaSessionManager.open()and forces compaction when the store exceeds 80% of the context window.Changes
src/agents/pi-embedded-runner/compact.tsestimateSessionFileTokens()helpersrc/agents/pi-embedded-runner/run.tsSESSION_GROWTH_COMPACTION_THRESHOLDand pre-prompt guard with try/catchsrc/agents/pi-embedded-runner/run.session-growth-guard.test.tsDesign decisions
limitHistoryTurns(DM sessions)Test plan
🤖 Generated with Claude Code
Greptile Overview
Greptile Summary
Adds a pre-prompt “session-growth guard” to
runEmbeddedPiAgentthat estimates the stored token count from the session JSONL and forces compaction when it exceeds 80% of the model context window. This is intended to prevent unbounded session store growth when downstream pruning/history-limiting modifies messages only in-flight.Also introduces
estimateSessionFileTokens()to compute an approximate token count from the on-disk session context, and adds a dedicated test suite for the guard behavior.Confidence Score: 4/5
undefinedto a requiredstring, which can mask mismatches between intended and actual runtime states.(2/5) Greptile learns from your feedback when you react with thumbs up/down!
Context used:
dashboard- CLAUDE.md (source)dashboard- AGENTS.md (source)