Skip to content

Stalled browser runs report 'response streaming' indefinitely, and dead runs stay 'running' in oracle status forever #391

Description

@postoso

Version: oracle 0.17.3, browser engine, GPT-5.6 Sol at Pro thinking time, 60 minute auto-timeout

Two related gaps, both visible in one run.

1. The progress line computes a stall signal and discards it

Verbatim tail of ~/.oracle/sessions/<slug>/output.log for a run that died:

[browser] ChatGPT thinking - 1m 0s elapsed; status=response streaming; last change 30s ago; source=inline
[browser] ChatGPT thinking - 5m 59s elapsed; status=response streaming; last change 5m 29s ago; source=inline
[browser] ChatGPT thinking - 8m 29s elapsed; status=response streaming; last change 7m 59s ago; source=inline
<log ends here — no completion, no timeout, no error>

The page stopped changing at the 30 second mark. Every subsequent line's "last change" tracks exactly 30 seconds behind "elapsed", which means zero DOM change after 0:30. Oracle went on reporting status=response streaming for another eight minutes.

The information needed to detect the stall is already computed and printed on the same line that reports health. Nothing consumes it. A threshold on "last change" (say, no change for N minutes while claiming to stream) would turn eight minutes of false confidence into an actionable state.

I realize thinking-state detection has been touched before (#284, closed). This is not about misreading the UI: the reading is correct and the log is accurate. The gap is that the derived value is never acted on.

2. A dead run's session record is never reaped

That same run's process stopped writing at the timestamp above. Sixty-eight minutes after launch, well past the documented 60 minute auto-timeout, oracle status still listed it as:

running   GPT-5.6 Sol   br/fg   <timestamp>   2698   -  <slug>

There is no reaper for the session status record. It reports running indefinitely.

Why 2 has a cost beyond tidiness

oracle status is the documented way to check whether the profile is busy before launching, since concurrent launches against one profile can interfere. An orphaned running row is indistinguishable from a live run from the outside, so the correct and the safe behavior diverge: a well-behaved caller waits on a corpse. This happened here — a second session held its launch for over an hour on a run that had been dead the whole time, and resolving it required inspecting session metadata by hand.

Worth noting the asymmetry: the browser tab lease does self-heal, since tabLeaseRegistry prunes on PID liveness. It is only the status record that persists. So the resource is actually free while the thing callers are told to consult still says it is taken.

Suggested direction

For 2, the PID-liveness check the lease registry already performs would settle it: a record whose process is gone, or which has exceeded the auto-timeout with no writes, could be marked stale or died rather than left as running. Distinguishing "died" from "completed" would also make 1 easier to surface.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Urgent regression or broken agent/channel workflow affecting real users now.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:session-stateThis issue is about session, memory, transcript, context, or agent state drift.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions