Skip to content

A run whose engine died at step 1 reported 'running' for 4.35 hours with a fresh lastProgressAt, and wrote nothing to the trace #580

Description

@serge-ivo

A dead run reported "running" for 4.35 hours, and the only record of the truth was the pane

Measured live 2026-08-15, instance e4d2d031-833b-4ccf-8b39-8af08337075b (PAS Coder), run
70ea298e-bd0c-487e-a210-0efc2f019191, session csess_88a4de4b-045b-4814-b978-b55626f62375.

What each surface said, at the same moment

Surface Answer
check_instance_loop status:"running", stopReason:null, finishedAt:null, iteration:1/30
check_instance_loop.lastProgressAt 3.5 minutes ago
coding_session_capture.runState "idle"
coding_session_capture.pane [14:20:57] Please read GitHub issue #57…
[14:20:58] You've hit your weekly limit · resets Aug 17 at 4pm
[error] You've hit your weekly limit…
agent_trace source:"coding" no event for this run; newest coding event is 2026-08-13 02:53:55

startedAt 1786767644486 → observed 1786783320834 = 4.35 hours, on iteration 1 of 30.
The engine died one second after receiving the objective.

Three separate defects

1. lastProgressAt measures liveness, not progress. It advanced to within 3.5 minutes of the
observation on a run that has not left iteration 1 since 14:20. Whatever touches it is not gated
on the run advancing, so the single field a stall detector would read is precisely the field that
conceals a stall. #579 §1 proposes distinguishing a stalled run from a clean failure; on this
evidence a stall is currently undetectable from the run record.

2. Two tools disagree about one session. check_instance_looprunning;
coding_session_capturerunState:"idle". Both read server state for the same session id.
The capture is correct.

3. The run wrote nothing to the unified trace. workflows/coding-session.ts contains
zero logEvent calls and zero logError calls:

$ grep -c logEvent workflows/coding-session.ts   → 0   (browser-task 6, job-apply 6, pipeline-run 7, agent-loop 3)
$ grep -c logError workflows/coding-session.ts   → 0   (browser-task 4, job-apply 4, pipeline-run 5, agent-loop 3)

Coding events DO reach the trace, but only via lib/coding-failure.ts:341, on a classified
failure
. A run that simply stops classifies nothing and therefore records nothing. The only
durable account of this run's death is the pane, retrievable only by someone who already knows the
session id.

The same shape, three more times

Instance a1d3522f-6b91-4cd9-bf7b-380e470192b7 (AIPA coder), objective git pull — a
two-second command — three runs:

run elapsed iteration outcome
82739cb6 3.15 h 1/10 failed — stuck not resolved in time
1dbb3e54 3.41 h 1/10 failed — stuck not resolved in time
ebc70ac1 0.26 h 3/10 failed — stuck not resolved in time

So a stuck-run timeout exists, but at a scale of hours, and it produces a message that names no
cause. Two of the three never left iteration 1.

Relationship to existing issues

Acceptance criteria

  1. A run whose engine has emitted a terminal error does not remain status:"running". State where
    the transition is made and why that point is correct.
  2. lastProgressAt reflects progress, or is renamed and joined by a field that does. Whichever
    is chosen, a stall must be detectable from the run record alone.
  3. check_instance_loop and coding_session_capture cannot disagree about whether a session is
    working. A test drives both off one state.
  4. coding-session.ts writes the trace/error events its four peer workflows write — enough to
    answer "what happened" without the pane. A guard asserts the coding driver is not an exception,
    stated over the whole workflow set per ADR 0002, not a hand-listed subset.
  5. A provider limit that resets days away fails the run immediately, naming the reset time — it is
    not a takeover-shaped wait ([bug] The dominant live cause of dead runs: the Engine's own subscription usage limit is handled as a 15-minute human takeover, so a run dies 41 minutes before the CLI comes back #541).
  6. Tests reproduce this exact case: engine emits a terminal provider error at step 1; assert the
    run record goes terminal, the trace carries the cause, and no surface reports running.

Verified vs inferred

  • Verified: every value in the tables, read live 2026-08-15 from check_instance_loop,
    coding_session_capture and agent_trace; the elapsed arithmetic; both grep -c counts and
    their peer-file comparisons; coding-failure.ts:341 as the coding trace writer; the three AIPA
    run records.
  • Inferred: what advances lastProgressAt — the field is observably fresh on a run that has
    not advanced, but the writer was not traced. AC2 should start by finding it; if it turns out
    to be a legitimate progress signal on a sub-iteration unit, this is a naming and surfacing
    problem rather than a correctness one, and should be re-rated.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions