Repository navigation
Description
Problem
The attention classifier's stuck-retrying state is unreachable for every live session entry: the only producer of repeatedErrorCount always sets lastTurnError on the same entries, and classifyAttention checks lastTurnError first.
classifyAttention(pm-stack/aggregator/src/derive.ts:197-215) is first-match-wins:awaitingQuestion→lastTurnError("errored", :203-205) → only thenrepeatedErrorCount >= RETRY_LOOP_THRESHOLD (3)("stuck-retrying", :206-209).- The sole live producer, the OpenCode mapper
mapOne(pm-stack/aggregator/src/sources/opencode.ts), setsentry.lastTurnErrorwhenever the last turn has any error (:246if (lastTurnError) entry.lastTurnError = lastTurnError) and setsentry.repeatedErrorCountonly as an addition to that same run of errors (:232-240, consecutive identical errors at the head of the run). Every entry that could ever satisfy the retry-loop test therefore already matched theerroredbranch one check earlier. - Even the shipped fixture entry designed to demo this state (
ses_f_phase13, src/sources/fixtures.ts:525-539:repeatedErrorCount: 4andlastTurnError: "claude_session_limit (retry)") classifies as plainerrored. - The existing unit test (test/render.test.ts:233-237) passes only because it constructs the one shape no producer emits —
repeatedErrorCount: 4with nolastTurnError.
Evidence (verified this run on main 3a425552)
Laptop Bun probe driving the real modules (aggregator src/ copied verbatim; probe ~/git/fleet/probe-2026-10-30-laneB-retryloop/): a fake v2 OpenCode server returns one session whose newest turn is 4 consecutive assistant messages carrying the identical tool error boom; the probe runs the real mapServerSessions and feeds its output to the real classifyAttention:
mapper entry: {"sessionId":"ses-retry","lastTurnError":"boom","repeatedErrorCount":4}
classifyAttention state: errored | evidence: Last turn error: boom
RETRY_LOOP_THRESHOLD: 3
control (no lastTurnError) state: stuck-retrying
The mapper emits repeatedErrorCount: 4 (≥ threshold 3) with lastTurnError set — exactly as the code predicts — and the classifier returns errored. The control entry with the test's shape (count only) does return stuck-retrying, confirming the branch works only for shapes no live producer creates.
Why it matters
stuck-retrying is a distinct published state with its own label ("stuck retrying", derive.ts:245), sort rank (ORDER, derive.ts:182), and orchestrator playbook ("Orchestrator breaks the retry loop and reroutes the work", derive.ts:294, applied via tierEntry's ORCHESTRATOR_NOTES[e.state]). A session spinning on the same error — the exact failure the state exists to surface — is instead shown as a generic one-off error, sorted and narrated as such, so the retry-loop intervention never triggers and the taxonomy silently overstates its own coverage: the state lights up in tests and never in the live feed.
Acceptance criteria
- An entry with
lastTurnErrorset andrepeatedErrorCount >= RETRY_LOOP_THRESHOLDclassifies asstuck-retrying(treatment pinned at triage: reorder the checks inclassifyAttention, or split the states in the mapper — either way the pinned precedence vsawaitingQuestionand vs the credential-error tiering intierEntryis stated explicitly). - A regression test classifies the mapper-shaped entry (both fields set, count ≥ 3) as
stuck-retrying, plus a count of exactlyRETRY_LOOP_THRESHOLD - 1still classifying aserrored, and a single error with no count stayingerrored. - The fixture entry
ses_f_phase13renders asstuck-retryingin the fixture attention view (or the fixture is adjusted to the shape triage pins). - Existing derive/render tests stay green.
Dedup
- Searched open + closed issues for
stuck-retrying,classifyAttention,RETRY_LOOPthis run: no issue covers the classifier/producer shadowing. design(aggregator): 'needs you' attention view — session state taxonomy, machine-first #852 (OPEN) is the original attention-taxonomy design that created the state — it does not track the state being unreachable. - aggregator(opencode): mapServerSessions never validates the v2 wire containers — a non-array data on any endpoint, or one null session entry, throws out of the mapper and drops every session from that server; an id-less entry fabricates an undefined-sessionId row #2543 (OPEN) is
mapServerSessionswire-container validation in the same mapper file (non-array data / null entries throw) — different failure: here both modules behave exactly as written on well-formed data; the defect is the precedence between them. - aggregator(opencode): iso() throws RangeError on out-of-range server timestamps — one bad session drops every session from that server #2286 (OPEN) is the mapper's
iso()RangeError on out-of-range timestamps — unrelated mechanism.
Activity
dezren39 commentedon Oct 30, 2026
🤖 Agent note · filed
17 remaining items
dezren39 commentedon Nov 1, 2026
🤖 Agent note · parked
repo-worker-code)ses_e5e69850bcaffeLF07FcV6aSvp; queue task5388repo-health-code-pilotsrc/feed.ts:350-352.dezren39 commentedon Nov 1, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 1, 2026
🤖 Agent note · parked
dezren39 commentedon Nov 1, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 1, 2026
🤖 Agent note · parked
dezren39).dezren39 commentedon Nov 1, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 1, 2026
🤖 Agent note · done