actions/issueflow-reconcile — a triage-authored issue arrival must not abort the sweep
#91
Labels
No labels
attention
blocked
blocker:ci-red
blocker:conflict
blocker:drill-pending
blocker:unrequested
bug
claimed
documentation
enhancement
epic
merge-next
needs-ruling
needs-triage
offsite
post-merge
ready
release
scope:docs
scope:guards
scope:labels
scope:release-flow
stale
state:addressing
state:bots-reviewing
state:building
state:needs-human
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: heavy-duty/ceremony#91
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
Every issue this repo has minted today failed its
labelsrun, silently. Found in triage hygiene against the live board.reconcile_opened_issueruns first inmain, before the sweep body. Its two "nothing to do here" early exits are barereturns, and a barereturncarries the exit status of the test that just failed —1. The script is executed by the action, soset -euo pipefailis live (L3-L7), and that1kills the run before a single issue is reconciled.The common case is the one that breaks. An issue opened by a triage actor needs no
needs-triage—author_decisioncorrectly saysKEEP— and that correct answer is what aborts the run (L373):L369has the same shape: when the arriving item is a PR, not an issue, the guard aborts instead of standing down.Evidence
Three
issuesruns failed in the observable window (run history reaches back to 16:12Z today); all three are triage-authoredopenedevents, all three failed the same step,reconcile issue flow (dogfood — the workspace IS ceremony), each in ~400ms with zero stdout:The #84 and #86 opens produced runs cancelled by concurrency, so they never reported. Of the triage-authored arrivals that ran to completion, the failure rate is 3/3.
Reproduced against the real repo at
bb37c15, exactly matching CI — exit 1, no output:Control — the same script with no
openedevent takes the schedule path and completes:issueflow: reconciled., exit 0.Blast radius
Degraded, not dead: the
*/15schedule still sweeps, so a mint's reconciliation is deferred to the next tick rather than lost. What is lost is the arrival path itself and the run's honesty — a red X on every mint, and any conflict the sweep would have flagged goes unreported for that event.Why the suite is green
author_decisionis tested and correct —test/issueflow-reconcile.test.sh:157asserts a triage-authored arrival yieldsKEEP. The bug is in the wrapper's exit status, not the decision, and the suite sources the script, which takes theset -u-only branch of L3-L7. Under sourcing the barereturn 1is inert. The suite cannot catch this class of bug by construction: it never runs the script the way the action runs it.Shipped 2026-07-22 in
a811da8("fix: enforce triage author only on issue arrival"), part of #18 / PR #32.Spec
Decisions, not options. Do not reopen these in the PR.
return 0. L369 and L373 mean "no arrival work to do, carry on", and must say so. This is the whole defect.main's call at L392 stays bare. A genuine failure on the arrival path — the API down, malformed JSON — must still fail the run loudly, matching this file's stated doctrine. Do not soften it with|| log. Only the two deliberate stand-downs change; real errors keep aborting.|| log ... continuingat L415 is unchanged. That guard is for one issue failing inside a batch; the arrival path is not a batch.ghonPATHand run the script as a subprocess, following the house pattern already intest/release-chain.test.sh:21-30. Without this the fix is unguarded and regresses the next time someone writes|| return.Tasks
L369:|| return→|| return 0L373:|| return→|| return 0ghstub and an executed-subprocess test covering the three arrival outcomes: triage author (stand down, sweep still runs), outside author (labelsneeds-triage, sweep still runs), arrival is a PR (stand down, sweep still runs)|| returnwhose intent is "stand down" and give it an explicit statusAcceptance criteria
issues:openedrun exits 0 and its output reachesissueflow: reconciled.issues:openedrun still addsneeds-triageand still reachesissueflow: reconciled.issues:openedevent whose subject is a PR exits 0 and reachesissueflow: reconciled.reconcile_opened_issuestill fails the run non-zero (D2 is preserved, not accidentally fixed away)bb37c15and passes against the fixTest plan
The case that must fail first: run the new triage-authored-arrival test against unfixed
bb37c15and confirm it reports exit 1 with empty output. A fix whose test never failed has proven nothing here — the suite was already green through three production failures.Then, with the fix:
issueflow: reconciled.— exit status alone would pass on a script that stood down and skipped the sweepghreturning non-zero for the issue fetch) still exits non-zeroauthor_decisioncases at L157-L159 unchanged and passingDRY_RUN=1 REPO=heavy-duty/ceremony EVENT_NAME=issues EVENT_ACTION=opened EVENT_ISSUE=90exits 0 and reconcilesDependencies
Part of #1 (the sweep's line, alongside #18 and #61). Blocked by nothing.
Minting this issue reproduced it a fourth time. The
issues: openedevent for #91 itself — run 30040681213, 20:05:54Z — failed the same step,reconcile issue flow (dogfood — the workspace IS ceremony), with the same silent exit 1. The evidence table above is 4/4 now.Tracked on #1's sweep line beside #18 and #61 — triage 2026-07-23.
Claiming — starting now. Draft PR shortly.