Repository navigation
[Phase 4] Initiative driver counts human-gated and zombie sub-issues as in-flight — epic #1402 silently deadlocked at slots=0 for days #1494
Description
Story
As a maintainer relying on the initiative driver to keep an epic's ready work flowing,
I want the in-flight cap to count only sub-issues an agent can actually still act on,
so that human-gated or already-delivered items cannot silently consume slots forever and starve the rest of the epic.
Problem — three dead slots deadlocked epic #1402 for days
scripts/initiative-driver.sh counts in-flight as: every OPEN sub-issue carrying the dev-lead label. Observed on epic #1402 (2026-08-11):
- [Phase 2] Generalized CI compliance test: reject SHA / # main pins on any first-party reusable #687 — implementation PR merged 2026-08-08, issue kept open only for comment-extended follow-up scope,
dev-leadlabel lingering. A zombie slot: nolabeledevent will ever re-fire, nobody is working it, yet it counts as in-flight indefinitely. - [Phase 4] pr-review runs are ~49% cancelled-while-pending — cancel-in-progress:false protects in-flight only, and cancelled renders as a failing check #1422 —
dev-lead:needs-humansince 2026-08-03 (timeout). Paused by design, but still counted. - [Phase 4] A review bot that can create blocking threads but is not in dev-lead's TRUSTED_BOTS creates an unclearable merge block (graphite-app; root cause of the 2026-08-02 deadlock) #1425 —
dev-lead:needs-humansince 2026-08-09 (3/3 engine-error). Same.
Result: in-flight = 3 vs MAX_IN_FLIGHT = 2 → slots = 0 → the driver ran successfully every ~25 minutes for days while releasing nothing, with 5+ unblocked stories waiting (#1482, #1406, #1408, #1486, #1468, #1469). Every run logged success; the starvation was invisible without manually computing the in-flight set. Resolved manually today by maintainer decisions (split-and-close #687 → #1493, park #1422, retry #1425) — but the class remains.
This is the throughput-level sibling of the two known single-item strand mechanics: the cleared-gate-never-refires issue strand (#1407, see #1402 close-out 2026-08-11) and the merge-ready-PR strand (#1469).
Acceptance Criteria
- Sub-issues carrying
dev-lead:needs-humando NOT count toward the in-flight cap (they cannot progress without a human; holding a slot buys nothing). They must also not be re-released while gated (already true via label logic — keep it that way). - Zombie detection: an open sub-issue whose
dev-leadlabel predates a merged implementation PR (or that has had no dev-lead activity for a configurable staleness window, default ≥72h) is surfaced — at minimum a driver log line + a comment on the epic naming the stale slot-holder; it must not silently occupy a slot forever. - The driver's per-epic log line reports the slot math explicitly (
in-flight=N (M gated excluded), cap=K, releasing R), so a starved epic is visible in any single run log. - A unit/bats test covers: gated items excluded from the count; the release path still respects the cap; a zombie is reported.
- No change to release ordering or to the hands-off/hold label semantics (
dev-lead:hands-off/initiative:holdstill never release).
Tasks
- Exclude
dev-lead:needs-humancarriers from the in-flight count ininitiative-driver.sh. (AC: 1) - Add staleness/zombie reporting. (AC: 2, 3)
- Tests. (AC: 4)
Dev Notes
- Counting logic is at
scripts/initiative-driver.sh(~lines 142–162):in_flightincrements for every open child withDEV_LEAD_LABEL. - Be careful NOT to release additional items merely because gated ones stop counting if the maintainer considers gated items "still consuming attention" — that is exactly the behavior change requested here, but call it out in the PR body so the cap's new meaning ("actively workable items") is an explicit, reviewable decision.
- Do not auto-remove labels from gated/zombie items (that erases human-readable state); exclude/report only.
References
- Epic: Formalize the agentic PR-interaction model (event-first, timers-as-backstop) — clear, repeatable, enforceable #1402 (deadlock observed 2026-08-09 → 2026-08-11)
- Slot-holders resolved manually: [Phase 2] Generalized CI compliance test: reject SHA / # main pins on any first-party reusable #687→[Phase 2 follow-up] Complete the #1184 legacy→major-scoped pin migration in the reusable-pin compliance check (split from #687 ACs 7–13) #1493 (split+close), [Phase 4] pr-review runs are ~49% cancelled-while-pending — cancel-in-progress:false protects in-flight only, and cancelled renders as a failing check #1422 (parked), [Phase 4] A review bot that can create blocking threads but is not in dev-lead's TRUSTED_BOTS creates an unclearable merge block (graphite-app; root cause of the 2026-08-02 deadlock) #1425 (retried)
- Sibling strand mechanics: [Phase 4] Detect merge-ready PRs stranded with no agent acting and no signal #1469 (PR-side), [Phase 4] Demote dev-lead-retry from normal-path driver to a true backstop — resume blocked states event-first #1407 label-event gap (Formalize the agentic PR-interaction model (event-first, timers-as-backstop) — clear, repeatable, enforceable #1402 close-out comment 2026-08-11)
Activity
don-petry commentedon Aug 19, 2026
Dev-Lead Implementation Plan
Issue: #1494 — [Phase 4] Initiative driver counts human-gated and zombie sub-issues as in-flight
Scope
Make the in-flight cap in
scripts/initiative-driver.shcount only sub-issues an agent can still act on: excludedev-lead:needs-humancarriers from the count, surface stale "zombie" slot-holders (driver log + one idempotent epic comment), and report the slot math explicitly in the per-epic log line.Implementation Checklist
NEEDS_HUMAN_LABEL(defaultdev-lead:needs-human) andSTALE_HOURS(default72) env vars + validation, documented in the header.dev-lead:needs-humancarriers asreleased(so they are never re-released) but exclude them fromin_flight; track a separategatedcount.dev-leadlabeledevent is older thanSTALE_HOURS— log a line and collect it.in-flight=N (M gated excluded), cap=K, releasing R.Tests to Write (tests/test_initiative_driver.bats)
dev-lead:needs-humancarrier excluded from in-flight → a ready story is released in the freed slot; asserts the AC3 log line.slotsitems released even when more are ready).Test Command
bats tests/test_initiative_driver.bats(full suite via.dev-lead/scripts/dev-lead-lint.shfor shellcheck)don-petry commentedon Aug 19, 2026
Dev-Lead: Progress (in progress — not yet durable)
Plan Execution (intended)
dev-lead:needs-humancarriers from the in-flight count inscripts/initiative-driver.sh; gated carriers stay inreleased[]so they are still never re-released while paused (AC1, AC5).dev-leadlabeledevent is older thanSTALE_HOURS(default 72h) is logged and surfaced via one idempotent epic comment keyed on the exact zombie set. No labels are auto-removed (AC2).in-flight=N (M gated excluded), cap=K, releasing R(AC3).Cap-semantics call-out (for the PR body)
The in-flight cap's meaning changes from "every open
dev-leadcarrier" to "actively workable carriers" — gated (dev-lead:needs-human) items no longer consume a slot, so an epic can release more work than before. This is the requested behavior change (per the issue's Dev Notes) and is an explicit, reviewable decision. Zombies still count toward the cap (surfaced, not auto-freed) so no slot is silently released without a human deciding.Local check output (provisional — not the pushed run)
Files touched (this workspace, not yet pushed)
scripts/initiative-driver.sh: gated exclusion, zombie detect + idempotent epic comment, AC3 slot-math log line,NEEDS_HUMAN_LABEL/STALE_HOURSenv + validation, header docs.tests/test_initiative_driver.bats: three new tests (gated excluded, cap respected, zombie reported).Notes
≥ STALE_HOURS). In practice this also catches the observed [Phase 2] Generalized CI compliance test: reject SHA / # main pins on any first-party reusable #687 case (label ~3 days old after its PR merged). The stricter "label predates a specific merged PR" correlation was not added — the age heuristic covers the documented deadlock without new PR-lookup API traffic.issues/*/eventsAPI failure trips errexit and aborts that epic (consistent with the existinglabels_of/blocked_byerror posture — a failure surfaces rather than masking as a false no-op).don-petry commentedon Aug 19, 2026
Dev-Lead: Implementation Complete — PR #1543
The implementation for issue #1494 is durable: commits are pushed and a pull request is open. This record is backed by verifiable artifacts you can confirm in one click.
6a1b05d550c8a33b34783823c603d2a021a72a0dReview happens on the PR. Acceptance criteria and test results are evidenced by the PR's diff and CI checks — not asserted here. If a later stage fails, this claim is retracted in place.
feat: implement issue #1494 — [Phase 4] Initiative driver counts huma…