SessionProcessor closure state claims session-scope but resets per-step (warning false-positive + doom-loop detector silently degraded)
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- typescript
- Domain
- backend
Research direction
Start by auditing the closure variables in processor.ts:43, 57, and 207-219, then trace SessionProcessor.create() and the per-step loop in session/prompt.ts:485. Determine which state is per-step versus session-wide, add the regression coverage described in the acceptance criteria, and verify the warning and cross-turn doom-loop behavior match their intended scope.
Written by the indexing model from the issue text.
Description
Symptom
State declared in SessionProcessor.create()'s closure scope is documented as "session-scoped, accumulates across process() invocations within a session" (see processor.ts:207-210), but loop() in session/prompt.ts:485 creates a fresh SessionProcessor every step. The closure variables therefore reset on each step, not each session.
This is a documentation/implementation mismatch — the comments describe an intent that the code does not deliver.
Known victims
-
plan_no_tool_generationwarning —sessionToolCallsMade(processor.ts:57). On a multi-step plan session that runs tools across early steps and produces a final text-only step, the warning fires on the last step even though the agent did its job correctly. Patched as a targeted workaround in #888 (PR for #887) by also scanningstreamInput.messagesfor prior assistant tool-call content at warning-evaluation time. Not a structural fix. -
Doom-loop detector —
toolCallCounts(processor.ts:43, used in 207-219). The comment explicitly states "cross-turn accumulation catches slow-burn loops that stay under the threshold per-turn but add up over the session" — but because the counter resets per step, slow-burn loops that cross step boundaries cannot trigger the threshold. The detector still catches within-step hot loops (e.g. todowrite 2,080x in a single step) and is presumably what saved us from realising sooner, but the documented cross-turn behavior is broken. Unpatched in #888.
There may be other consumers of the same closure variables (e.g. toolcalls map at line 41) where per-step vs session scoping matters for correctness — worth an audit.
Proper fix (options)
The targeted workaround in #888 only addresses victim 1, and only by reading from the conversation history (which the warning happens to have access to). It does not generalize to the doom-loop detector, whose state has no equivalent representation in the message stream.
-
Move
SessionProcessor.create()outside the per-stepwhile (true)body inloop()so a single processor instance handles all steps of a session. This is the change that most closely matches the comments' intent. Risk: anything else increate()'s closure that should be per-step would silently break. Needs an audit of all closure variables before flipping. -
Lift the two affected counters to a session-keyed
Map<sessionID, …>at module scope. Smaller blast radius than #1, but adds memory-leak surface (need explicit cleanup when sessions end / abort). -
Keep the per-step semantics and update the comments + variable names to match reality. Then re-derive the cross-turn doom-loop signal from the message stream the same way the plan-no-tool workaround does (count
tool-callcontent parts across the session). Risk: every consumer that thinks it's session-scoped has to be migrated individually.
I'd lean toward option 1 if the closure audit comes back clean. Otherwise option 3 is the safest; it doesn't pretend the bug is fixed and forces each consumer to make an explicit choice.
Acceptance criteria
- Closure variables in
SessionProcessor.create()are audited; each one is documented as either intentionally per-step or session-wide. - Variables that should be session-wide actually behave that way at runtime.
-
toolCallCountscross-turn behavior matches its comment, OR the comment is rewritten to match the implementation. -
plan_no_tool_generationwarning is driven by whatever the canonical session-wide signal is (not the workaround scan added in #888). - Regression test for cross-turn doom-loop detection.
- Dominant language
- TypeScript
- Stars
- 813
- Forks
- 134
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 62
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from AltimateAI/altimate-code
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
AltimateAI/altimate-code#1323 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
AltimateAI/altimate-code#1288 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
AltimateAI/altimate-code#1285 ·
-
privacy: Altimate Base consent dialog no longer discloses persistent per-installation identifier Open
Difficulty 1/5 Under an hour Newbie friendliness 88/100
AltimateAI/altimate-code#1284 ·
-
Difficulty 2/5 Under an hour Newbie friendliness 72/100
AltimateAI/altimate-code#1283 ·
All issues in AltimateAI/altimate-code
Similar issues
-
Browser Waiting for: Product Owner
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
getsentry/sentry-javascript#24577 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
agilepathway/label-checker#640 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
copse-dev/agent-pane#2953 ·
-
agentic-workflows
Difficulty 1/5 Under an hour Newbie friendliness 85/100
githubnext/rig#534 ·
-
automation missing-model model-sync provider:pioneer
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
anomalyco/models.dev#7701 ·