You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[dev-lead timeout follow-up 2/3] Dedup handle_engine_failure escalation branches into a shared helper #1029
Follow-up to #901 (Story B / #1018). Maintainability cleanup deferred from #1021.
Problem
scripts/dev-lead-fix-issue.shhandle_engine_failure() has three near-identical escalation branches — missing-binary, timeout (#1018), and retries-exhausted — each doing the same five steps: emit ::error::, ensure_needs_human_label, post an issue comment carrying a <!-- dev-lead-issue N status=needs-human attempt=K reason=X run=ID --> marker + cause + run link + redacted session snippet, then exit 1. As more non-retryable reasons are added, the copies drift.
Why it matters: those markers are parsed by two systems — the retry cron (dev-lead-retry.sh, which skips dev-lead:needs-human) and the fleet-monitor timeout observability (#1019, which counts reason=X). Divergence between branches silently breaks those parsers.
Goal
Extract a single shared helper (e.g. escalate_needs_human <reason> <cause_markdown>) that all three branches call, so the marker format + escalation steps are defined once.
Acceptance criteria
A shared helper emits: ::error::, ensure_needs_human_label, the status=needs-human marker comment (byte-identical marker format to today), + run link + snippet, then exit 1.
The three branches call it, passing only their reason-specific cause text. The timeout branch retains its extra specifics (tier / elapsed / budget / split-or-raise guidance / completed-but-unpushed work note).
Tests (tests/dev-lead/unit/test_fix_issue.bats): existing missing-binary / timeout / retries-exhausted escalation tests still pass; add an assertion that all three produce the same marker shape (only reason= differs).
Thanks for the detailed write-up and for linking the upstream context — this is a well-scoped refactor with clear acceptance criteria. Before diving in: should escalate_needs_human be defined as a top-level function in dev-lead-fix-issue.sh, or is there a preferred shared-library pattern (e.g., a sourced scripts/lib/ file) that other scripts in this repo already use for helpers?
Issue:#1029 — [dev-lead timeout follow-up 2/3] Dedup handle_engine_failure escalation branches into a shared helper
Scope
Extract a single escalate_needs_human helper in scripts/dev-lead-fix-issue.sh that owns the five common escalation steps (::error::, ensure_needs_human_label, the byte-identical status=needs-human marker comment, run link + redacted snippet, then exit), and route the missing-binary / timeout / retries-exhausted branches through it — passing only their reason-specific cause text. Pure refactor, no marker/behavior change.
Added escalate_needs_human <reason> <attempt> <snippet> <error_line> <cause_markdown> [exit_code] helper — single source for the five common escalation steps (::error::, ensure_needs_human_label, byte-identical status=needs-human marker comment, redacted snippet, exit)
Routed the missing-binary branch through the helper (cause text only)
Routed the timeout branch through the helper — retains its tier / elapsed / budget / split-or-raise guidance / completed-but-unpushed work note
Routed the retries-exhausted branch through the helper, preserving the exit-2-on-rate-limit contract via the helper's exit_code arg
Added a bats assertion that all three branches emit the same needs-human marker shape (only reason= differs)
No behavior change
The emitted marker <!-- dev-lead-issue N status=needs-human attempt=K reason=X run=ID --> is byte-identical to before, so dev-lead-retry.sh (skips status=needs-human) and the #1019 fleet-monitor (summarize_dev_lead_timeouts parses reason=) are unaffected. The only cosmetic shift: the trailing human guidance in the missing-binary / retries-exhausted comments now renders above the redacted snippet instead of below it, matching the canonical cause + run link + snippet order (the timeout comment was already in that order → byte-identical).
Test Results
tests/dev-lead/unit/test_fix_issue.bats — 20/20 passing (was 19; +1 new marker-shape guard)
1..20
ok 14 fix-issue: missing-binary → escalates to needs-human, no retry marker
ok 15 fix-issue: stage timeout (exit 124) → escalates to needs-human, reason=timeout, no retry marker
ok 18 fix-issue: attempt ceiling (prior attempt=2) → escalates to needs-human
ok 19 fix-issue: all three escalation branches emit the same needs-human marker shape (only reason differs)
ok 20 fix-issue: lint fails → posts lint-failure comment on the issue
bash scripts/dev-lead-lint.sh — all checks passed (shellcheck clean on 85 files + agent-profile/CODEOWNERS validation)
Files Changed
scripts/dev-lead-fix-issue.sh: extracted escalate_needs_human helper; the three non-retryable branches now call it with only their reason-specific cause text.
tests/dev-lead/unit/test_fix_issue.bats: added the cross-branch marker-shape assertion (AC4).
Activity
github-actions commentedon Jul 3, 2026
Thanks for the detailed write-up and for linking the upstream context — this is a well-scoped refactor with clear acceptance criteria. Before diving in: should
escalate_needs_humanbe defined as a top-level function indev-lead-fix-issue.sh, or is there a preferred shared-library pattern (e.g., a sourcedscripts/lib/file) that other scripts in this repo already use for helpers?don-petry commentedon Jul 3, 2026
Dev-Lead Implementation Plan
Issue: #1029 — [dev-lead timeout follow-up 2/3] Dedup handle_engine_failure escalation branches into a shared helper
Scope
Extract a single
escalate_needs_humanhelper inscripts/dev-lead-fix-issue.shthat owns the five common escalation steps (::error::,ensure_needs_human_label, the byte-identicalstatus=needs-humanmarker comment, run link + redacted snippet, then exit), and route the missing-binary / timeout / retries-exhausted branches through it — passing only their reason-specific cause text. Pure refactor, no marker/behavior change.Implementation Checklist
escalate_needs_human <reason> <attempt> <snippet> <error_line> <cause_markdown> [exit_code]helper (byte-identical marker + shared heading/label/snippet/exit)missing-binarybranch through the helper (cause text only)timeoutbranch through the helper (retains tier/elapsed/budget/split-or-raise/work-note specifics)retries-exhaustedbranch through the helper (exit 2 preserved when engine_rc==2)Tests to Write
tests/dev-lead/unit/test_fix_issue.bats: all three escalation branches emit the same needs-human marker shape (onlyreason=differs)Test Command
bats tests/dev-lead/unit/test_fix_issue.bats(full unit dir:bats tests/dev-lead/unit/); lint viabash scripts/dev-lead-lint.shdon-petry commentedon Jul 3, 2026
Dev-Lead: Implementation Complete
Plan Execution
escalate_needs_human <reason> <attempt> <snippet> <error_line> <cause_markdown> [exit_code]helper — single source for the five common escalation steps (::error::,ensure_needs_human_label, byte-identicalstatus=needs-humanmarker comment, redacted snippet, exit)missing-binarybranch through the helper (cause text only)timeoutbranch through the helper — retains its tier / elapsed / budget / split-or-raise guidance / completed-but-unpushed work noteretries-exhaustedbranch through the helper, preserving the exit-2-on-rate-limit contract via the helper'sexit_codeargreason=differs)No behavior change
The emitted marker
<!-- dev-lead-issue N status=needs-human attempt=K reason=X run=ID -->is byte-identical to before, sodev-lead-retry.sh(skipsstatus=needs-human) and the #1019 fleet-monitor (summarize_dev_lead_timeoutsparsesreason=) are unaffected. The only cosmetic shift: the trailing human guidance in the missing-binary / retries-exhausted comments now renders above the redacted snippet instead of below it, matching the canonicalcause + run link + snippetorder (the timeout comment was already in that order → byte-identical).Test Results
Files Changed
scripts/dev-lead-fix-issue.sh: extractedescalate_needs_humanhelper; the three non-retryable branches now call it with only their reason-specific cause text.tests/dev-lead/unit/test_fix_issue.bats: added the cross-branch marker-shape assertion (AC4).Notes
tests/dev-lead/unit/test_engine_mcp.batsrefactor: migrate to machine user PAT auth (closes #27) #28 (REVIEW_MCP_DEBUG set + healthy handshake …) fails on a clean checkout with my changes stashed — it is not caused by this refactor and is out of scope for [dev-lead timeout follow-up 2/3] Dedup handle_engine_failure escalation branches into a shared helper #1029.dev-lead-retry.sh,fleet_report.sh) were read to confirm thestatus=needs-human/reason=contract; both remain satisfied.fix(escalation): guard escalate_needs_human arg count under set -u (#…
feat: implement issue #1029 — [dev-lead timeout follow-up 2/3] Dedup …