exec phase idles until run.timeout after the worker opened the PR, then reports 'Out of credits' from a stale rate-limit event
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 42/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- typescript
- Domain
- devtools
Research direction
Start by tracing the Claude Code driver’s phase-completion handling and the rate-limit path through isRateLimitFailureInfo, hasBillingMarkers, and billingHaltReason; the issue names no files or tests. Compare how a final worker result and a timeout are handled, and how rate-limit event status reaches errorMetadata. Done means completed work does not idle until timeout, and a timeout is not attributed to a non-rejected stale event.
Written by the indexing model from the issue text.
Description
Summary
Two exec phases in one sequant run finished their work (PR opened, final assistant message posted) 18 and 24 minutes before run.timeout, then sat idle until the timeout ended them. The run table reported both as ✘ failed · Out of credits, although the subscription window was open and a follow-up run executed normally minutes later. State was left at exec: failed with open, green PRs and no exec marker on the issue, so --resume would re-run exec.
Two separate problems:
- Phase-complete detection waits on process exit. A worker that has pushed, opened the PR and posted its final message is done, but the phase stays open until the Claude Code process exits or
run.timeoutfires. - A timeout is labelled with a stale rate-limit event. The driver retains any
rate_limit_eventwith billing markers (overageDisabledReason: out_of_credits, five-hour window, liveresetsAt) regardless of status (isRateLimitFailureInfo→hasBillingMarkers), andbillingHaltReasonthen names it as the cause of a later, unrelated failure. The run log'serrorContextcarried{category: billing, errorType: BillingError, errorMetadata: {rateLimitType: five_hour, overageDisabledReason: out_of_credits, resetsAt: …}}on a phase whose real end wasdurationSeconds ≈ 1803. The event'sstatusis not retained, so the log cannot show whether it wasallowed_warningorrejected.
Environment
- sequant 2.20.0, Claude Code driver,
--no-tui -v,--resume --concurrency 2, phasesspec,exec,qa,run.timeout1800 - macOS, Claude Max subscription (overage disabled)
- Next.js/TypeScript repo, three small issues, exec on Sonnet
Timeline (UTC, from the run log and the worker transcripts)
| Issue | exec start | PR opened + final message | phase end | idle |
|---|---|---|---|---|
| A | 01:32:21 | 01:37:53 | 02:02:25 (1803.9 s, "Out of credits") | 24 min |
| B | 01:51:14 | 02:03:36 | 02:21:17 (1802.8 s, "Out of credits") | 18 min |
- The third issue in the same run passed exec → qa normally (exec 2 min, qa 16 min).
- A one-word
claude -pprobe answered at 02:20, andsequant run A B --phases qaran and passed at 02:25–02:27, an hour before the recordedresetsAt. - Worker B had a 120 s
tsccommand that Claude Code moved to the background; its output file ends in[killed]stamped at the phase end, so that background task was alive at the kill. Worker A's background command had finished three minutes before its final message, so a lingering background task does not explain both. - Earlier timeouts in the same repo (four judgment issues on Opus, Oct 13–15) were a different shape: the worker was still active 1–5 min before the timeout and had no PR. Those were genuine time-outs.
Expected
- A phase whose worker has opened the PR and posted a final message completes when the stream yields the final result, or after a short grace period, not at
run.timeout. - A phase that ends by timeout is reported as
Timeout after 1800s(as the Oct 13–15 runs were) unless the captured rate-limit event hasstatus: rejected. RetainingstatusinerrorMetadatawould make this checkable after the fact. - On a timeout where the branch has a commit and an open PR, state should not be left as
exec: failedwithout an exec marker; at minimum the summary should say the PR exists.
Repro (best effort)
Run an exec phase on a subscription account that is near its five-hour cap with overage disabled (so a rate_limit_event with overageDisabledReason: out_of_credits is emitted during the session), with a worker that starts a long tsc/jest command that Claude Code moves to the background, and let the worker finish and open the PR. Observe whether the phase ends at the final message or at run.timeout, and what reason the run table prints.
Happy to attach the two run logs (with repo-specific paths redacted) on request.
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 1
- Avg merge
- 11h 3m
- Merged PRs (30d)
- 84
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing 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 sequant-io/sequant
-
graph-2026-11-simplify
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
sequant-io/sequant#1650 ·
Maintainers usually reply within 1 day
-
run: --phases does not suppress the UI-label test phase (determinePhasesForIssue adds it to an explicit list)Possibly taken @admarble claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
sequant-io/sequant#1631 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
sequant-io/sequant#1601 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
sequant-io/sequant#1582 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 76/100
sequant-io/sequant#1381 ·
Maintainers usually reply within 1 day
All issues in sequant-io/sequant
Similar issues
-
content triage
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
tensorflow/tfjs#8754 ·
-
tool-submission
Difficulty 1/5 Under an hour Newbie friendliness 83/100
BraveOPotato/NoSignups#2348 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
code-yeongyu/oh-my-openagent#12784 ·
Maintainers usually reply within 1 day
-
external-issue to-triage
Difficulty 2/5 1-3 hours Newbie friendliness 71/100
Maintainers usually reply within 1 day