Skip to content

feat: implement issue #1018 — [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry) - #1021

Merged
don-petry merged 3 commits into
mainfrom
dev-lead/issue-1018-20260702-1540
Jul 2, 2026
Merged

feat: implement issue #1018 — [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry)#1021
don-petry merged 3 commits into
mainfrom
dev-lead/issue-1018-20260702-1540

Conversation

@don-petry

@don-petry don-petry commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Closes #1018

Implemented by dev-lead agent. Please review.

Summary by CodeRabbit

  • Bug Fixes
    • Timeouts are now treated as a non-retryable failure, so the app escalates to human review right away instead of retrying.
    • Timeout details are now included in the report, with clearer context about what happened and whether any local changes were present.
    • Stale timeout information is cleared between runs, preventing old diagnostics from affecting new failures.
    • Added coverage for timeout handling and retry behavior to ensure consistent results.

…s reason=timeout and escalate to human (no same-budget retry)
@don-petry
don-petry requested a review from a team as a code owner July 2, 2026 15:56
Copilot AI review requested due to automatic review settings July 2, 2026 15:56
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@don-petry, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 50 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7c9eb94f-11bc-43f0-a3ba-1b37c75d3285

📥 Commits

Reviewing files that changed from the base of the PR and between 304b805 and 00c0317.

📒 Files selected for processing (1)
  • tests/dev-lead/unit/test_engine_fallback.bats
📝 Walkthrough

Walkthrough

Adds first-class timeout handling to dev-lead engine failure flow: scripts/engine.sh classifies exit code 124 as reason=timeout with tier/budget/elapsed sidecar files, and scripts/dev-lead-fix-issue.sh escalates timeouts immediately to needs-human without retry, surfacing unpushed work. Corresponding bats tests are added.

Changes

Timeout classification and escalation

Layer / File(s) Summary
Engine timeout classification
scripts/engine.sh
Clears stale timeout sidecar files before fallback attempts, times run_writer execution, and on rc=124 writes reason=timeout plus tier/budget/elapsed sidecars instead of generic engine-error.
Engine fallback tests
tests/dev-lead/unit/test_engine_fallback.bats
Teardown removes new timeout sidecars; new tests verify reason=timeout classification, sidecar contents, and that no same-budget fallback retry occurs on exit 124.
Immediate escalation on timeout
scripts/dev-lead-fix-issue.sh
handle_engine_failure() adds a reason=timeout branch reading timeout sidecars, detecting unpushed local changes, posting a dev-lead:needs-human comment with tier/elapsed/budget guidance, and exiting 1 before retry logic.
Fix-issue escalation tests
tests/dev-lead/unit/test_fix_issue.bats
New tests assert timeout escalates without a retry marker, non-124 transient failures still retry, and late-phase timeouts surface unpushed work in the comment.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant EngineSh as engine.sh
  participant Sidecar as /tmp/dev-lead-* sidecars
  participant FixIssue as dev-lead-fix-issue.sh
  participant GitHub as GitHub Issue

  EngineSh->>EngineSh: run_writer_with_fallback starts
  EngineSh->>Sidecar: clear stale timeout sidecars
  EngineSh->>EngineSh: run_writer (rc=124)
  EngineSh->>Sidecar: write reason=timeout, tier, budget, elapsed
  FixIssue->>Sidecar: read reason and timeout metadata
  alt reason=timeout
    FixIssue->>FixIssue: check for unpushed local changes
    FixIssue->>GitHub: post needs-human comment (tier, elapsed, budget)
    FixIssue->>FixIssue: exit 1 (no retry marker)
  else other failure
    FixIssue->>GitHub: post retry marker (status=failed)
  end
Loading

Possibly related issues

Possibly related PRs

Suggested labels: needs-human-review

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: treating exit-124 timeouts as non-retryable and escalating to human review.
Linked Issues check ✅ Passed The changes match #1018: rc=124 is classified as timeout, escalates before retries, preserves late work visibility, and tests cover both paths.
Out of Scope Changes check ✅ Passed The patch stays focused on timeout classification, escalation, and tests, with no obvious unrelated code changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev-lead/issue-1018-20260702-1540

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces first-class handling for stage timeouts (exit 124) in the dev-lead workflow. Instead of triggering a same-budget retry, timeouts are treated as non-retryable and immediately escalated to a human by applying the dev-lead:needs-human label and posting a detailed comment. The changes include capturing elapsed time and budget context, clearing stale sidecar files, and preserving/notifying about unpushed completed work. Unit tests were added to verify these behaviors. A review comment points out a redundant git stub block in tests/dev-lead/unit/test_fix_issue.bats that is immediately overwritten by a subsequent stub block and should be removed.

Comment thread tests/dev-lead/unit/test_fix_issue.bats Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements issue #1018 by treating GNU timeout exit code 124 as a first-class non-retryable failure in the dev-lead writer pipeline, persisting reason=timeout (plus tier/budget/elapsed sidecars) and escalating immediately to a dev-lead:needs-human outcome without emitting a retry marker.

Changes:

  • Classify exit 124 in run_writer_with_fallback() as reason=timeout and persist timeout context sidecars (tier, budget, elapsed), while ensuring no fallback engine is attempted.
  • In dev-lead-fix-issue.sh, add an early reason=timeout branch that escalates to needs-human immediately (no same-budget retry marker) and includes tier/elapsed/budget + split/raise guidance.
  • Add unit tests covering timeout classification, no-fallback behavior, escalation behavior, and “completed work not silently discarded” signaling.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
scripts/engine.sh Writes reason=timeout and timeout context sidecars on exit 124 and avoids fallback-engine retries for timeouts.
scripts/dev-lead-fix-issue.sh Escalates reason=timeout immediately to needs-human with detailed guidance and a “work completed but not pushed” note when applicable.
tests/dev-lead/unit/test_engine_fallback.bats Adds coverage for timeout sidecar classification and ensures no same-budget fallback to another engine on 124.
tests/dev-lead/unit/test_fix_issue.bats Adds coverage for timeout escalation behavior, non-timeout transient retry behavior, and late-phase timeout with completed work signaling.

Comment thread scripts/dev-lead-fix-issue.sh
Comment thread tests/dev-lead/unit/test_fix_issue.bats Outdated
…d test stub

Address advisory review on #1021:
- Copilot: the completed-but-unpushed work_note overpromised ("not silently
  lost", snippet "captured the changes"). The runner-local branch is not
  pushed and the runner is ephemeral, so the work is NOT recoverable from the
  run. Reword to state that honestly: surface that work was attempted (not a
  silent black hole), but it is unrecoverable and the snippet is context only;
  re-run after splitting/raising the budget to regenerate.
- Gemini + Copilot: remove the redundant first git stub in the late-phase
  timeout test (immediately overwritten by the rev-parse-counter stub).

shellcheck clean; fix-issue bats green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 2, 2026
@don-petry

Copy link
Copy Markdown
Collaborator Author

@donpetry-bot review

@donpetry-bot

Copy link
Copy Markdown
Contributor

@don-petry I'm on it — starting a fresh review now. Results will appear in a few minutes.

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — review-changes (no-changes)

No changes were needed for this PR.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/engine.sh (1)

1314-1348: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make exit 124 win before rate-limit normalization.

Line 1314 receives run_writer’s normalized status. In run_writer, a non-zero rc can still be converted to 2 when captured output matches is_rate_limited_files, so an actual 124 can bypass the Line 1341 timeout branch and re-enter fallback/retry handling. Exclude 124 from that remap.

Proposed fix
-  if [ "$rc" -ne 0 ] && [ -n "$_tmp" ] && is_rate_limited_files "$_tmp"; then
+  if [ "$rc" -ne 0 ] && [ "$rc" -ne 124 ] && [ -n "$_tmp" ] && is_rate_limited_files "$_tmp"; then
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/engine.sh` around lines 1314 - 1348, The retry/timeout handling in
engine.sh is letting a real timeout be normalized into a rate-limit exit and
then fall through to fallback behavior; update the status mapping around
run_writer and the rc handling so exit 124 is preserved and cannot be remapped
to 2 by the rate-limit path. In the logic near run_writer, set/read rc so the
timeout branch remains authoritative, and keep the special 124 classification in
the main fallback loop so it reaches the timeout reason files instead of
continuing to the next engine.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/dev-lead-fix-issue.sh`:
- Around line 128-176: The timeout handling in the main reason-dispatch block
duplicates the same human-escalation flow already used by the missing-binary
path. Extract the shared echo/label/comment/exit-1 sequence into a helper such
as escalate_to_human in scripts/dev-lead-fix-issue.sh, and have both the timeout
branch and the existing missing-binary branch call it with only their
reason-specific message/body content.

In `@tests/dev-lead/unit/test_engine_fallback.bats`:
- Around line 317-330: The timeout fallback test currently only verifies Gemini
is not retried, so it can miss an unwanted Copilot retry. Update the `sidecar:
timeout (124) does NOT fall through to another engine` test in
`test_engine_fallback.bats` to also stub or record `copilot_chat`, since the
fallback order goes through Copilot before Gemini. After `run
run_writer_with_fallback`, assert that both `copilot_chat` and `gemini` were not
called, keeping the existing timeout and failure-reason checks intact.

---

Outside diff comments:
In `@scripts/engine.sh`:
- Around line 1314-1348: The retry/timeout handling in engine.sh is letting a
real timeout be normalized into a rate-limit exit and then fall through to
fallback behavior; update the status mapping around run_writer and the rc
handling so exit 124 is preserved and cannot be remapped to 2 by the rate-limit
path. In the logic near run_writer, set/read rc so the timeout branch remains
authoritative, and keep the special 124 classification in the main fallback loop
so it reaches the timeout reason files instead of continuing to the next engine.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 56c473b9-433a-4a55-8a6e-d4b61b36553a

📥 Commits

Reviewing files that changed from the base of the PR and between ceb78c0 and 304b805.

📒 Files selected for processing (4)
  • scripts/dev-lead-fix-issue.sh
  • scripts/engine.sh
  • tests/dev-lead/unit/test_engine_fallback.bats
  • tests/dev-lead/unit/test_fix_issue.bats

Comment thread scripts/dev-lead-fix-issue.sh
Comment thread tests/dev-lead/unit/test_engine_fallback.bats
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 2, 2026
Address CodeRabbit on #1021: the 'does NOT fall through' test only recorded
gemini, so a regression that retried copilot (next in the claude→copilot→gemini
order) and returned before gemini could still pass. Enable copilot (non-ghp
token + gh-copilot recording stub) and assert BOTH fallback engines are
untouched on a 124 timeout.

The escalation-branch dedup (timeout / missing-binary / exhausted) is deferred
to a shared-helper follow-up under #901 to keep this behavior fix focused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU
@sonarqubecloud

sonarqubecloud Bot commented Jul 2, 2026

Copy link
Copy Markdown

donpetry-bot
donpetry-bot previously approved these changes Jul 2, 2026

@donpetry-bot donpetry-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review — APPROVED ✓

Risk: MEDIUM
Reviewed commit: 00c0317f997373e6d504564ee7b799561edb43f4
Review mode: triage-approved (single reviewer)

Summary

Implements issue #1018: classifies per-tier stage timeouts (exit 124) as a first-class, non-retryable 'timeout' failure reason in engine.sh, and adds an immediate needs-human escalation branch in dev-lead-fix-issue.sh (before the retry/attempt-ceiling logic) that surfaces tier/elapsed/budget, split-or-raise-budget guidance, and any completed-but-unpushed work. Five new bats tests cover timeout classification, no cross-engine same-budget retry, escalation content, transient (rate-limit) retry non-regression, and late-phase-timeout work surfacing. Triage assessment confirmed; classified MEDIUM (non-trivial logic in Actions-executed orchestration scripts) which is within auto-approve bounds.

Linked issue analysis

Closes #1018 (timeout Story B/3). All six acceptance criteria are substantively addressed: (1) exit 124 → reason=timeout distinct from engine-error, written to the existing /tmp sidecar mechanism plus new tier/budget/elapsed sidecars (stale copies cleared at run start); (2) no same-budget retry — engine.sh returns immediately on 124 without falling through to fallback engines, and fix-issue escalates on first occurrence with no retry marker (status=needs-human, so the retry cron skips it); (3) the needs-human comment includes tier, elapsed, budget, and split/raise vars.${raise_var} guidance; (4) non-124 transients (rate-limit) still take the retry path — covered by a dedicated regression test; (5) completed-but-unpushed work is surfaced in the comment (the issue's 'at minimum surface it' option), honestly noting the runner-local branch is not recoverable; (6) tests added in tests/dev-lead/unit/ for both scripts.

Findings

No blocking findings. Verified: the new timeout branch in handle_engine_failure references locals (pre_engine_sha, branch, snippet, run_url, attempt) that are dynamically in scope — the handler is invoked from the function that declares them. Sidecar-file pattern in /tmp matches the pre-existing dev-lead-failure-reason mechanism (no new attack surface on ephemeral runners). Minor, non-blocking: engine.sh only ever writes tier=action in this path, while the fix-issue reader also handles deep/writer tiers and defaults to DEEP_TIMEOUT_SEC when the sidecar is absent — consistent with the deep tier being classified elsewhere. All 5 prior bot review threads (gemini, Copilot, CodeRabbit) are resolved; CodeRabbit's changes-requested review was dismissed after the dev-lead review-changes pass concluded no changes were needed. The run_secret_scanning MCP tool was not available in this environment; the gitleaks CI check passed.

CI status

All completed checks green: shellcheck, bats, unit-tests, CodeQL (actions + python), gitleaks secret scan, AgentShield, Agent Security Scan, SonarCloud quality gate, validate-fixtures, holdout-guard, and all stub/permission guards SUCCESS. Cancelled entries (dev-lead dispatch / review relay) are superseded automation runs, not failures; dependency-audit sub-jobs skipped (no matching ecosystems). CodeRabbit status SUCCESS.


Reviewed automatically by the PR-review agent (single-reviewer mode: fable 5). Reply if you need a human review.

@donpetry-bot

donpetry-bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor
Superseded by automated re-review at 00c0317f997373e6d504564ee7b799561edb43f4 — click to expand prior review.

Review — fix requested (cycle 1/3)

The automated review identified the following issues. Please address each one:

Findings to fix

Automated review — NEEDS HUMAN REVIEW

Risk: MEDIUM
Reviewed commit: 00c0317f997373e6d504564ee7b799561edb43f4
Review mode: triage-approved (single reviewer)

Summary

Solid implementation of first-class timeout (exit 124) escalation: reason=timeout sidecar + tier/budget/elapsed context, immediate needs-human escalation with split/raise guidance, stale-sidecar cleanup, and good bats coverage. One functional-correctness gap remains unaddressed that undermines the issue's core acceptance criterion (see Findings).

Linked issue analysis

Linked issue #1018 (timeout B/3). Acceptance criteria 1, 3, 4, 5, 6 are met: exit 124 is classified as a distinct reason=timeout; the needs-human comment includes tier/elapsed/budget + split/raise guidance and no retryable status=failed marker; non-124 rate-limit transients still retry (regression test added); completed-but-unpushed work is surfaced honestly; tests cover classification, no-fallback, escalation, and the late-phase-timeout mode. Criterion 2 ("a timeout is NOT retried with the same budget at either layer") is NOT fully guaranteed — see finding 1.

Findings

  1. [MEDIUM — unaddressed] Exit 124 can be masked by the rate-limit remap, re-enabling the same-budget retry this PR exists to prevent. In run_writer (scripts/engine.sh:1249), any non-zero rc — including 124 — is remapped to exit 2 when the captured session output matches is_rate_limited_files. A timed-out session that emitted rate-limit phrases mid-run would therefore return 2 to run_writer_with_fallback, bypass the new 124 branch (scripts/engine.sh:1341), and drive a fallback-engine retry — violating issue [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry) #1018 acceptance criterion 2. The new tests don't catch this because the 124 stub output ("operation timed out after 2100s") doesn't match rate-limit patterns. CodeRabbit flagged this as a Major outside-diff-range finding in its (since-dismissed) CHANGES_REQUESTED review; no commit or reply addressed it. Fix is one line: exclude 124 from the remap ([ "$rc" -ne 0 ] && [ "$rc" -ne 124 ] && ...), ideally with a test (124 + rate-limit-phrase output → still reason=timeout, no fallback). If the current behavior is intentional (a rate-limit-stall timeout may succeed on a non-rate-limited fallback engine), state that rationale on the PR instead.
  2. All inline review threads are resolved: the dead git-stub in test_fix_issue.bats and the misleading "not silently lost" wording were fixed (304b805); the copilot-not-called assertion was added (00c0317); the escalation-branch dedup was explicitly deferred to the dev-lead engine repeatedly times out (engine-error) on larger issues — exhausts retries without delivering (e.g. .github#518) #901 parent with a recorded rationale.
  3. Secret scan: the run_secret_scanning MCP tool is not available in this environment; gitleaks CI check passed. No secrets in the diff; session snippets posted to issues are redacted upstream.

CI status

All material checks green: shellcheck/ShellCheck, bats, unit/unit-tests, CodeQL (actions+python), SonarCloud quality gate (0 new issues), agent-shield, Secret scan (gitleaks), Lint, holdout-guard, validate-fixtures, gh-aw-compile, permissions/stub checks. Cancelled entries (dev-lead dispatch/ci-relay, review) are superseded automation runs, not failures; dependency-audit ecosystem jobs skipped (no matching ecosystems).


Reviewed automatically by the PR-review agent (single-reviewer mode: fable 5). Reply if you need a human review.

Additional tasks

  1. Resolve all unresolved review thread comments from other reviewers
  2. Ensure all CI checks pass after your changes
  3. Rebase on the target branch if behind
  4. Do NOT modify files unrelated to the findings above

The review cascade will automatically re-review after new commits are pushed.

@donpetry-bot
donpetry-bot dismissed their stale review July 2, 2026 16:19

Superseded by automated re-review at 00c0317.

@don-petry

Copy link
Copy Markdown
Collaborator Author

@donpetry-bot review

@donpetry-bot

Copy link
Copy Markdown
Contributor

@don-petry I'm on it — starting a fresh review now. Results will appear in a few minutes.

@donpetry-bot

Copy link
Copy Markdown
Contributor

CI checks on this PR are still running. Once they complete, re-mention @donpetry-bot to trigger a fresh review.

Posted by the donpetry-bot PR-review cascade.

@donpetry-bot

Copy link
Copy Markdown
Contributor

@donpetry-bot I'm on it — starting a fresh review now. Results will appear in a few minutes.

@don-petry

Copy link
Copy Markdown
Collaborator Author

Dev-Lead — waiting on PR blockers (intent: fix-reviews)

PR: #1021
No changes were committed, but the PR still has blocking checks or reviews (failing or cancelled checks, or changes-requested reviews). The retry cron will re-attempt automatically. Next attempt after: 2026-07-02T16:59:01Z

@don-petry
don-petry enabled auto-merge (squash) July 2, 2026 16:29

@donpetry-bot donpetry-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review — APPROVED ✓

Risk: MEDIUM
Reviewed commit: 00c0317f997373e6d504564ee7b799561edb43f4
Review mode: triage-approved (single reviewer)

Summary

Confirmation review (triage-approved mode) of the exit-124 timeout handling fix. The PR classifies a per-tier stage timeout (GNU timeout exit 124) as a first-class, non-retryable reason=timeout in scripts/engine.sh (with tier/budget/elapsed sidecars, stale copies cleared at the start of each run), and adds an escalation branch in scripts/dev-lead-fix-issue.sh that applies dev-lead:needs-human and posts a comment with tier, elapsed, budget, and split/raise guidance on the FIRST occurrence — no retry marker, no same-budget fallback-engine retry. Completed-but-unpushed work is surfaced honestly as unrecoverable context. The triage assessment holds: scope is tight, changes match the linked issue, and prior reviewer feedback was addressed in follow-up commits.

Linked issue analysis

Closes #1018 ([dev-lead timeout B/3]). All six acceptance criteria are substantively addressed: (1) exit 124 → distinct reason=timeout sidecar; (2) timeout is never retried at the same budget — the classification happens on the immediate-propagation path and a dedicated test asserts neither copilot nor gemini fallback runs; (3) the needs-human comment includes tier + elapsed + budget + split-or-raise-vars.*TIMEOUT_SEC guidance; (4) a regression test confirms non-124 transients (rate-limit) still take the retry path; (5) late-phase timeouts with prior commits/staged changes surface a note that work existed but was not pushed (wording made honest per review feedback — the ephemeral-runner branch is not recoverable); (6) bats coverage added in both test_engine_fallback.bats and test_fix_issue.bats.

Findings

No blocking findings.

  • All 5 inline review threads (gemini-code-assist, Copilot, CodeRabbit) are resolved; CodeRabbit's final review is APPROVED. Feedback was addressed in commits 304b805 (honest unrecoverable-work wording, dead git-stub removal) and 00c0317 (assert no copilot OR gemini fallback on 124).
  • Informational: one resolved thread reply mentions extracting a shared escalate_to_human helper, but the head diff keeps the timeout branch inline — consistent with the earlier agreed decision (with CodeRabbit) to keep escalation branches explicit in this behavior-fix PR and consolidate under #901.
  • Informational: the timeout classification is wired into run_writer_with_fallback (action tier, hardcoded tier=action); the escalation handler tolerates missing sidecars with safe defaults, so other tiers degrade gracefully.
  • Secret scan: run_secret_scanning MCP tool not available in this run; gitleaks CI check passed and the diff contains only obvious test-fixture stub tokens.

CI status

All checks on the latest runs are green: shellcheck, bats, unit-tests, CodeQL, SonarCloud (quality gate passed), gitleaks secret scan, agent-shield, holdout-guard, validate-fixtures, and all structural guards SUCCESS. CANCELLED entries are superseded runs of the same workflows; SKIPPED entries are inapplicable ecosystem audits.


Reviewed automatically by the PR-review agent (single-reviewer mode: fable 5). Reply if you need a human review.

@don-petry
don-petry merged commit e713192 into main Jul 2, 2026
47 of 71 checks passed
@don-petry
don-petry deleted the dev-lead/issue-1018-20260702-1540 branch July 2, 2026 16:32
don-petry added a commit that referenced this pull request Aug 2, 2026
…s reason=timeout and escalate to human (no same-budget retry) (#1021)

* feat: implement issue #1018 — [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry)

* fix(timeout-escalation): honest unrecoverable-work wording + drop dead test stub

Address advisory review on #1021:
- Copilot: the completed-but-unpushed work_note overpromised ("not silently
  lost", snippet "captured the changes"). The runner-local branch is not
  pushed and the runner is ephemeral, so the work is NOT recoverable from the
  run. Reword to state that honestly: surface that work was attempted (not a
  silent black hole), but it is unrecoverable and the snippet is context only;
  re-run after splitting/raising the budget to regenerate.
- Gemini + Copilot: remove the redundant first git stub in the late-phase
  timeout test (immediately overwritten by the rev-parse-counter stub).

shellcheck clean; fix-issue bats green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

* test(timeout): assert no fallback to copilot OR gemini on a 124 timeout

Address CodeRabbit on #1021: the 'does NOT fall through' test only recorded
gemini, so a regression that retried copilot (next in the claude→copilot→gemini
order) and returned before gemini could still pass. Enable copilot (non-ghp
token + gh-copilot recording stub) and assert BOTH fallback engines are
untouched on a 124 timeout.

The escalation-branch dedup (timeout / missing-binary / exhausted) is deferred
to a shared-helper follow-up under #901 to keep this behavior fix focused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 3, 2026
…s reason=timeout and escalate to human (no same-budget retry) (#1021)

* feat: implement issue #1018 — [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry)

* fix(timeout-escalation): honest unrecoverable-work wording + drop dead test stub

Address advisory review on #1021:
- Copilot: the completed-but-unpushed work_note overpromised ("not silently
  lost", snippet "captured the changes"). The runner-local branch is not
  pushed and the runner is ephemeral, so the work is NOT recoverable from the
  run. Reword to state that honestly: surface that work was attempted (not a
  silent black hole), but it is unrecoverable and the snippet is context only;
  re-run after splitting/raising the budget to regenerate.
- Gemini + Copilot: remove the redundant first git stub in the late-phase
  timeout test (immediately overwritten by the rev-parse-counter stub).

shellcheck clean; fix-issue bats green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

* test(timeout): assert no fallback to copilot OR gemini on a 124 timeout

Address CodeRabbit on #1021: the 'does NOT fall through' test only recorded
gemini, so a regression that retried copilot (next in the claude→copilot→gemini
order) and returned before gemini could still pass. Enable copilot (non-ghp
token + gh-copilot recording stub) and assert BOTH fallback engines are
untouched on a 124 timeout.

The escalation-branch dedup (timeout / missing-binary / exhausted) is deferred
to a shared-helper follow-up under #901 to keep this behavior fix focused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 3, 2026
…s reason=timeout and escalate to human (no same-budget retry) (#1021)

* feat: implement issue #1018 — [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry)

* fix(timeout-escalation): honest unrecoverable-work wording + drop dead test stub

Address advisory review on #1021:
- Copilot: the completed-but-unpushed work_note overpromised ("not silently
  lost", snippet "captured the changes"). The runner-local branch is not
  pushed and the runner is ephemeral, so the work is NOT recoverable from the
  run. Reword to state that honestly: surface that work was attempted (not a
  silent black hole), but it is unrecoverable and the snippet is context only;
  re-run after splitting/raising the budget to regenerate.
- Gemini + Copilot: remove the redundant first git stub in the late-phase
  timeout test (immediately overwritten by the rev-parse-counter stub).

shellcheck clean; fix-issue bats green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

* test(timeout): assert no fallback to copilot OR gemini on a 124 timeout

Address CodeRabbit on #1021: the 'does NOT fall through' test only recorded
gemini, so a regression that retried copilot (next in the claude→copilot→gemini
order) and returned before gemini could still pass. Enable copilot (non-ghp
token + gh-copilot recording stub) and assert BOTH fallback engines are
untouched on a 124 timeout.

The escalation-branch dedup (timeout / missing-binary / exhausted) is deferred
to a shared-helper follow-up under #901 to keep this behavior fix focused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…s reason=timeout and escalate to human (no same-budget retry) (#1021)

* feat: implement issue #1018 — [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry)

* fix(timeout-escalation): honest unrecoverable-work wording + drop dead test stub

Address advisory review on #1021:
- Copilot: the completed-but-unpushed work_note overpromised ("not silently
  lost", snippet "captured the changes"). The runner-local branch is not
  pushed and the runner is ephemeral, so the work is NOT recoverable from the
  run. Reword to state that honestly: surface that work was attempted (not a
  silent black hole), but it is unrecoverable and the snippet is context only;
  re-run after splitting/raising the budget to regenerate.
- Gemini + Copilot: remove the redundant first git stub in the late-phase
  timeout test (immediately overwritten by the rev-parse-counter stub).

shellcheck clean; fix-issue bats green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

* test(timeout): assert no fallback to copilot OR gemini on a 124 timeout

Address CodeRabbit on #1021: the 'does NOT fall through' test only recorded
gemini, so a regression that retried copilot (next in the claude→copilot→gemini
order) and returned before gemini could still pass. Enable copilot (non-ghp
token + gh-copilot recording stub) and assert BOTH fallback engines are
untouched on a 124 timeout.

The escalation-branch dedup (timeout / missing-binary / exhausted) is deferred
to a shared-helper follow-up under #901 to keep this behavior fix focused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…s reason=timeout and escalate to human (no same-budget retry) (#1021)

* feat: implement issue #1018 — [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry)

* fix(timeout-escalation): honest unrecoverable-work wording + drop dead test stub

Address advisory review on #1021:
- Copilot: the completed-but-unpushed work_note overpromised ("not silently
  lost", snippet "captured the changes"). The runner-local branch is not
  pushed and the runner is ephemeral, so the work is NOT recoverable from the
  run. Reword to state that honestly: surface that work was attempted (not a
  silent black hole), but it is unrecoverable and the snippet is context only;
  re-run after splitting/raising the budget to regenerate.
- Gemini + Copilot: remove the redundant first git stub in the late-phase
  timeout test (immediately overwritten by the rev-parse-counter stub).

shellcheck clean; fix-issue bats green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

* test(timeout): assert no fallback to copilot OR gemini on a 124 timeout

Address CodeRabbit on #1021: the 'does NOT fall through' test only recorded
gemini, so a regression that retried copilot (next in the claude→copilot→gemini
order) and returned before gemini could still pass. Enable copilot (non-ghp
token + gh-copilot recording stub) and assert BOTH fallback engines are
untouched on a 124 timeout.

The escalation-branch dedup (timeout / missing-binary / exhausted) is deferred
to a shared-helper follow-up under #901 to keep this behavior fix focused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…s reason=timeout and escalate to human (no same-budget retry) (#1021)

* feat: implement issue #1018 — [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry)

* fix(timeout-escalation): honest unrecoverable-work wording + drop dead test stub

Address advisory review on #1021:
- Copilot: the completed-but-unpushed work_note overpromised ("not silently
  lost", snippet "captured the changes"). The runner-local branch is not
  pushed and the runner is ephemeral, so the work is NOT recoverable from the
  run. Reword to state that honestly: surface that work was attempted (not a
  silent black hole), but it is unrecoverable and the snippet is context only;
  re-run after splitting/raising the budget to regenerate.
- Gemini + Copilot: remove the redundant first git stub in the late-phase
  timeout test (immediately overwritten by the rev-parse-counter stub).

shellcheck clean; fix-issue bats green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

* test(timeout): assert no fallback to copilot OR gemini on a 124 timeout

Address CodeRabbit on #1021: the 'does NOT fall through' test only recorded
gemini, so a regression that retried copilot (next in the claude→copilot→gemini
order) and returned before gemini could still pass. Enable copilot (non-ghp
token + gh-copilot recording stub) and assert BOTH fallback engines are
untouched on a 124 timeout.

The escalation-branch dedup (timeout / missing-binary / exhausted) is deferred
to a shared-helper follow-up under #901 to keep this behavior fix focused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…s reason=timeout and escalate to human (no same-budget retry) (#1021)

* feat: implement issue #1018 — [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry)

* fix(timeout-escalation): honest unrecoverable-work wording + drop dead test stub

Address advisory review on #1021:
- Copilot: the completed-but-unpushed work_note overpromised ("not silently
  lost", snippet "captured the changes"). The runner-local branch is not
  pushed and the runner is ephemeral, so the work is NOT recoverable from the
  run. Reword to state that honestly: surface that work was attempted (not a
  silent black hole), but it is unrecoverable and the snippet is context only;
  re-run after splitting/raising the budget to regenerate.
- Gemini + Copilot: remove the redundant first git stub in the late-phase
  timeout test (immediately overwritten by the rev-parse-counter stub).

shellcheck clean; fix-issue bats green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

* test(timeout): assert no fallback to copilot OR gemini on a 124 timeout

Address CodeRabbit on #1021: the 'does NOT fall through' test only recorded
gemini, so a regression that retried copilot (next in the claude→copilot→gemini
order) and returned before gemini could still pass. Enable copilot (non-ghp
token + gh-copilot recording stub) and assert BOTH fallback engines are
untouched on a 124 timeout.

The escalation-branch dedup (timeout / missing-binary / exhausted) is deferred
to a shared-helper follow-up under #901 to keep this behavior fix focused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 7, 2026
…s reason=timeout and escalate to human (no same-budget retry) (#1021)

* feat: implement issue #1018 — [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry)

* fix(timeout-escalation): honest unrecoverable-work wording + drop dead test stub

Address advisory review on #1021:
- Copilot: the completed-but-unpushed work_note overpromised ("not silently
  lost", snippet "captured the changes"). The runner-local branch is not
  pushed and the runner is ephemeral, so the work is NOT recoverable from the
  run. Reword to state that honestly: surface that work was attempted (not a
  silent black hole), but it is unrecoverable and the snippet is context only;
  re-run after splitting/raising the budget to regenerate.
- Gemini + Copilot: remove the redundant first git stub in the late-phase
  timeout test (immediately overwritten by the rev-parse-counter stub).

shellcheck clean; fix-issue bats green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

* test(timeout): assert no fallback to copilot OR gemini on a 124 timeout

Address CodeRabbit on #1021: the 'does NOT fall through' test only recorded
gemini, so a regression that retried copilot (next in the claude→copilot→gemini
order) and returned before gemini could still pass. Enable copilot (non-ghp
token + gh-copilot recording stub) and assert BOTH fallback engines are
untouched on a 124 timeout.

The escalation-branch dedup (timeout / missing-binary / exhausted) is deferred
to a shared-helper follow-up under #901 to keep this behavior fix focused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 8, 2026
…s reason=timeout and escalate to human (no same-budget retry) (#1021)

* feat: implement issue #1018 — [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry)

* fix(timeout-escalation): honest unrecoverable-work wording + drop dead test stub

Address advisory review on #1021:
- Copilot: the completed-but-unpushed work_note overpromised ("not silently
  lost", snippet "captured the changes"). The runner-local branch is not
  pushed and the runner is ephemeral, so the work is NOT recoverable from the
  run. Reword to state that honestly: surface that work was attempted (not a
  silent black hole), but it is unrecoverable and the snippet is context only;
  re-run after splitting/raising the budget to regenerate.
- Gemini + Copilot: remove the redundant first git stub in the late-phase
  timeout test (immediately overwritten by the rev-parse-counter stub).

shellcheck clean; fix-issue bats green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

* test(timeout): assert no fallback to copilot OR gemini on a 124 timeout

Address CodeRabbit on #1021: the 'does NOT fall through' test only recorded
gemini, so a regression that retried copilot (next in the claude→copilot→gemini
order) and returned before gemini could still pass. Enable copilot (non-ghp
token + gh-copilot recording stub) and assert BOTH fallback engines are
untouched on a 124 timeout.

The escalation-branch dedup (timeout / missing-binary / exhausted) is deferred
to a shared-helper follow-up under #901 to keep this behavior fix focused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 8, 2026
…s reason=timeout and escalate to human (no same-budget retry) (#1021)

* feat: implement issue #1018 — [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry)

* fix(timeout-escalation): honest unrecoverable-work wording + drop dead test stub

Address advisory review on #1021:
- Copilot: the completed-but-unpushed work_note overpromised ("not silently
  lost", snippet "captured the changes"). The runner-local branch is not
  pushed and the runner is ephemeral, so the work is NOT recoverable from the
  run. Reword to state that honestly: surface that work was attempted (not a
  silent black hole), but it is unrecoverable and the snippet is context only;
  re-run after splitting/raising the budget to regenerate.
- Gemini + Copilot: remove the redundant first git stub in the late-phase
  timeout test (immediately overwritten by the rev-parse-counter stub).

shellcheck clean; fix-issue bats green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

* test(timeout): assert no fallback to copilot OR gemini on a 124 timeout

Address CodeRabbit on #1021: the 'does NOT fall through' test only recorded
gemini, so a regression that retried copilot (next in the claude→copilot→gemini
order) and returned before gemini could still pass. Enable copilot (non-ghp
token + gh-copilot recording stub) and assert BOTH fallback engines are
untouched on a 124 timeout.

The escalation-branch dedup (timeout / missing-binary / exhausted) is deferred
to a shared-helper follow-up under #901 to keep this behavior fix focused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
don-petry added a commit that referenced this pull request Aug 8, 2026
…s reason=timeout and escalate to human (no same-budget retry) (#1021)

* feat: implement issue #1018 — [dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry)

* fix(timeout-escalation): honest unrecoverable-work wording + drop dead test stub

Address advisory review on #1021:
- Copilot: the completed-but-unpushed work_note overpromised ("not silently
  lost", snippet "captured the changes"). The runner-local branch is not
  pushed and the runner is ephemeral, so the work is NOT recoverable from the
  run. Reword to state that honestly: surface that work was attempted (not a
  silent black hole), but it is unrecoverable and the snippet is context only;
  re-run after splitting/raising the budget to regenerate.
- Gemini + Copilot: remove the redundant first git stub in the late-phase
  timeout test (immediately overwritten by the rev-parse-counter stub).

shellcheck clean; fix-issue bats green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

* test(timeout): assert no fallback to copilot OR gemini on a 124 timeout

Address CodeRabbit on #1021: the 'does NOT fall through' test only recorded
gemini, so a regression that retried copilot (next in the claude→copilot→gemini
order) and returned before gemini could still pass. Enable copilot (non-ghp
token + gh-copilot recording stub) and assert BOTH fallback engines are
untouched on a 124 timeout.

The escalation-branch dedup (timeout / missing-binary / exhausted) is deferred
to a shared-helper follow-up under #901 to keep this behavior fix focused.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HUhVsBbihbTjVvbcVf1WuU

---------

Co-authored-by: donpetry-bot <{}+donpetry-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[dev-lead timeout B/3] Catch exit-124 as reason=timeout and escalate to human (no same-budget retry)

3 participants