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
perf(lanes): measure work-resolve-issue's idle time to a transient re-fire, 7 days before and after #12804 #13073
#12804 (merged 2026-11-03T16:07Z) shortened work-unblock's stranded re-fire backoff to 1 hour for the transient causes (no-run, failed-mint, kill-switch) and kept 3 hours for the rest (docs/conventions/pr-pipeline.yaml:1085-1090). #12635's last done-when item asks for the measured effect; #12635 closed with its other items delivered and this one carried here. It is a measurement over time, which an unattended lane run cannot perform, so it is host work.
Done when
On or after 2026-11-10T16:07Z: the median idle time from a transient failure to the re-fire is measured for 7 days before and after, and posted here.
The after window runs from 2026-11-03T16:07Z, so this cannot finish before 2026-11-10T16:07Z.
Proposed work class: work-class: read-only
Basis: automated intake triage; the lanes App applied this class.
Size: Small
Complexity: Low
Uncertainty: Known
Flags: none
Blocked by: none
Understood: this asks for the median idle time from a transient failure to the re-fire, measured over 7 days before and 7 days after #12804 merged, with the result posted here. It is a measurement over time, so it is host work. The after-window cannot finish before 2026-11-10T16:07Z. The scope is clear and nothing is missing. #13073 is related to #12804's follow-up work but is not a duplicate of any open issue.
Not admitted to the issue lane: its done-when asks for what an unattended lane run cannot perform: item 1 (tracker-output: "The median idle time from a transient failure to the re-fire is measured for ..."); no done-when item is left for the lane, so it goes to the host queue (host-run); it carries host-run. Admission takes the issue once each of those is met, when intake triages it again (.github/actions/resolve-config/admission-rules.json).
Claimed by poteto (desk session 789d5794). The 7-day BEFORE and an interim AFTER (from the change's merge until now) get posted here today, with the method and the script path, so the final AFTER is the same command run over the full window once it closes. That final AFTER, and this issue's close, can't come before the 7-day after window ends.
Before measurement and interim after: idle time from a stranded failure to work-unblock's re-fire
The changed paths almost never fired. In the 7 days before #12804, and in the 23 hours since, the paths whose wait #12804 shortened fired zero times: the no-run first re-fire, the kill-switch backoff after trip 4, and the no-run and failed-mint backoff re-fires. Every transient re-fire measured went through the kill-switch clamp path, and #12804 did not change that path. So far the change has nothing to act on. A before/after delta on the pooled "transient" group would come from other changes, not from #12804.
Method
Script: .work/gh-monitor/trends/13073-measure.py <from> <to> (hub-local, run with python3 -I). Line numbers below are on origin/main at e5554b8.
no-run first re-fire: waits hoursFor["no-run"] (.github/scripts/work-unblock/label-unblocked.mjs:1763-1782), 3 h before, 1 h after.
kill-switch: hoursFor["kill-switch"] applies only from trip limit-stops-per-issue + 1 = 4. Trips 1-3 wait ended + clamp, where clamp is 0 at the broker check and otherwise reset-clamp-min = 1 h (label-unblocked.mjs:1817-1818, .github/scripts/work-resolve-issue/limits.mjs:11,17). That clamp path is unchanged.
failed-mint: the per-cause hours apply only to the backoff after 3 re-fires on one workflow key (label-unblocked.mjs:1836). A first failed mint is clamp-timed, and its record carries the generic failed-run text.
backoff re-fires: backoffDue doubles the cause's hours (label-unblocked.mjs:415, 1744-1758).
Re-fire event: a bot (melodic-automation-lanes) unlabel then relabel of agent-ready no more than 120 s apart (label-unblocked.mjs:2070-2095 posts or edits the record, removes the label, then adds it back). Each pair is attributed by the bot comment created or edited in the 180 s before it:
<!-- work-unblock refired KEY breaker --> is kill-switch (label-unblocked.mjs:1284, report-outcome.mjs:862).
<!-- work-unblock refired KEY --> with a strandedCause text is no-run, no-report or failed-again (label-unblocked.mjs:1273-1277). With the generic FAILED_CAUSE text it is a first failed run or a first failed mint; the text cannot tell these two apart.
<!-- work-unblock infrastructure KEY -->, created or edited (userContentEdits), is a backoff re-fire, with its cause taken from its text (MINT_CAUSE at label-unblocked.mjs:1279).
The workflow-stale text (report-outcome.mjs:866) is the run re-firing itself straight away. It is out of scope and reported apart.
A relabel after an outcome= marker (a limit-stop restart) or a recurrence relabel is out of scope.
Clock start:
kill-switch: the refused run's end, as the record states it ("that run ended at ...").
no-run: the last agent-ready add before the pair.
every other cause: the end of the issue's newest completed work-resolve-issue run (event=issues, title ending #N) created after that add and ended before the re-fire.
Inclusion: a re-fire counts in a window when its clock start is in [from, to) and the re-fire is before to. Re-fires that straddle a window edge are dropped and counted.
Incident: re-fires whose clock-to-re-fire interval overlaps the GitHub incident of 2026-11-04T09:54Z to 11:44Z are excluded, and counted.
Reads: GraphQL search repo:… is:issue "to start a fresh run" updated:>=<from − 30 h>, then each issue's timeline (comments, labeled and unlabeled events) since from − 30 h. Lane runs are listed per UTC day, only for the days the run-clock rows need.
Statistics: median, and p90 by nearest rank, of idle hours.
BEFORE: 2026-10-27T16:07Z to 2026-11-03T16:07Z
group
path
median idle h
p90 idle h
n
transient
no-run, first re-fire (changed 3 h -> 1 h)
-
-
0
transient
kill-switch, clamp path (trip 1-3, unchanged)
1.27
4.98
206
transient
kill-switch, backoff path (trip 4+, changed)
-
-
0
transient
backoff re-fire: no-run (changed)
-
-
0
transient
backoff re-fire: failed-mint (changed)
-
-
0
control
no-report, first re-fire (3 h)
3.27
5.25
8
control
failed-again, first re-fire (3 h)
-
-
0
control
backoff re-fire: no-report / failed-again (3 h)
-
-
0
control
generic first failed run or first failed mint (clamp)
1.71
4.67
74
out of scope
workflow-stale immediate re-fire
0.28
0.64
14
transient
pooled
1.27
4.98
206
control
pooled
1.81
4.67
82
Issues read: 311. Excluded: 31 that straddle a window edge, 36 limit-stop restarts or recurrence relabels, and 4 relabel pairs with no record. Of the counted rows, 8 have no matching lane run, so their clock is the label add.
Interim AFTER: 2026-11-03T16:07Z to 2026-11-04T15:15Z (interim, about 23 h of 7 days)
group
path
median idle h
p90 idle h
n
transient
no-run, first re-fire (changed 3 h -> 1 h)
-
-
0
transient
kill-switch, clamp path (trip 1-3, unchanged)
0.26
1.16
22
transient
kill-switch, backoff path (trip 4+, changed)
-
-
0
transient
backoff re-fire: no-run (changed)
-
-
0
transient
backoff re-fire: failed-mint (changed)
-
-
0
control
no-report, first re-fire (3 h)
-
-
0
control
failed-again, first re-fire (3 h)
-
-
0
control
backoff re-fire: no-report / failed-again (3 h)
-
-
0
control
generic first failed run or first failed mint (clamp)
0.29
0.32
3
out of scope
workflow-stale immediate re-fire
0.72
1.35
23
transient
pooled
0.26
1.16
22
control
pooled
0.29
0.32
3
Interim n = 25 in scope (22 transient, 3 control). Excluded: 15 that straddle a window edge, 1 that overlaps the incident, and 2 limit-stop restarts. The interim window is right-censored: a failure from the last hours that has not been re-fired yet is missing, which biases it low. The 18 rows with no matching lane run are the workflow-stale rows, whose run ends after its own re-fire.
Run it with no --cache, so it reads fresh. Expected cost: about 20 GraphQL calls and about 30 run-listing calls.
UNVERIFIED
"Listed human" for the kill-switch trip floor is approximated: any non-bot account that added agent-ready, or any outcome= marker, within the 30 h lookback. With no floor inside the lookback, every breaker record in the lookback counts. That can only push a re-fire toward the trip 4+ path, and none landed there.
The cause of a backoff re-fire comes from the infrastructure comment's current text, not from the text of the edit made at that re-fire. No backoff re-fires occurred, so this did not affect these numbers.
The 4 BEFORE relabel pairs with no record were not inspected one by one.
Activity
github-actions commentedon Nov 4, 2026
Proposed work class: work-class: read-only
Basis: automated intake triage; the lanes App applied this class.
Size: Small
Complexity: Low
Uncertainty: Known
Flags: none
Blocked by: none
Understood: this asks for the median idle time from a transient failure to the re-fire, measured over 7 days before and 7 days after #12804 merged, with the result posted here. It is a measurement over time, so it is host work. The after-window cannot finish before 2026-11-10T16:07Z. The scope is clear and nothing is missing. #13073 is related to #12804's follow-up work but is not a duplicate of any open issue.
Automated triage, applied by the lanes App.
melodic-automation-lanes commentedon Nov 4, 2026
Not admitted to the issue lane: its done-when asks for what an unattended lane run cannot perform: item 1 (tracker-output: "The median idle time from a transient failure to the re-fire is measured for ..."); no done-when item is left for the lane, so it goes to the host queue (
host-run); it carries host-run. Admission takes the issue once each of those is met, when intake triages it again (.github/actions/resolve-config/admission-rules.json).melodic-automation-lanes commentedon Nov 4, 2026
The latest triage verdict holds nothing: admission moved the issue to
status: confirmed; its comment says why.kyle-sexton commentedon Nov 4, 2026
Claimed by poteto (desk session 789d5794). The 7-day BEFORE and an interim AFTER (from the change's merge until now) get posted here today, with the method and the script path, so the final AFTER is the same command run over the full window once it closes. That final AFTER, and this issue's close, can't come before the 7-day after window ends.
kyle-sexton commentedon Nov 4, 2026
Before measurement and interim after: idle time from a stranded failure to work-unblock's re-fire
The changed paths almost never fired. In the 7 days before #12804, and in the 23 hours since, the paths whose wait #12804 shortened fired zero times: the no-run first re-fire, the kill-switch backoff after trip 4, and the no-run and failed-mint backoff re-fires. Every transient re-fire measured went through the kill-switch clamp path, and #12804 did not change that path. So far the change has nothing to act on. A before/after delta on the pooled "transient" group would come from other changes, not from #12804.
Method
Script:
.work/gh-monitor/trends/13073-measure.py <from> <to>(hub-local, run withpython3 -I). Line numbers below are on origin/main at e5554b8.docs/conventions/pr-pipeline.yaml:1082-1094(stranded-backoff-hours: no-run 1, no-report 3, failed-again 3, failed-mint 1, kill-switch 1).git log -Gshows perf(lanes): configure work-unblock's stranded re-fire backoff per cause and shorten it for transient causes #12804 (ea71ee1) is the only commit since 2026-10-26 to touchstranded-backoff-hours,reset-clamp-minorlimit-stops-per-issue.hoursFor["no-run"](.github/scripts/work-unblock/label-unblocked.mjs:1763-1782), 3 h before, 1 h after.hoursFor["kill-switch"]applies only from triplimit-stops-per-issue+ 1 = 4. Trips 1-3 waitended + clamp, where clamp is 0 at the broker check and otherwisereset-clamp-min= 1 h (label-unblocked.mjs:1817-1818,.github/scripts/work-resolve-issue/limits.mjs:11,17). That clamp path is unchanged.label-unblocked.mjs:1836). A first failed mint is clamp-timed, and its record carries the generic failed-run text.backoffDuedoubles the cause's hours (label-unblocked.mjs:415, 1744-1758).melodic-automation-lanes) unlabel then relabel ofagent-readyno more than 120 s apart (label-unblocked.mjs:2070-2095posts or edits the record, removes the label, then adds it back). Each pair is attributed by the bot comment created or edited in the 180 s before it:<!-- work-unblock refired KEY breaker -->is kill-switch (label-unblocked.mjs:1284,report-outcome.mjs:862).<!-- work-unblock refired KEY -->with astrandedCausetext is no-run, no-report or failed-again (label-unblocked.mjs:1273-1277). With the genericFAILED_CAUSEtext it is a first failed run or a first failed mint; the text cannot tell these two apart.<!-- work-unblock infrastructure KEY -->, created or edited (userContentEdits), is a backoff re-fire, with its cause taken from its text (MINT_CAUSEatlabel-unblocked.mjs:1279).report-outcome.mjs:866) is the run re-firing itself straight away. It is out of scope and reported apart.outcome=marker (a limit-stop restart) or a recurrence relabel is out of scope.agent-readyadd before the pair.#N) created after that add and ended before the re-fire.to. Re-fires that straddle a window edge are dropped and counted.repo:… is:issue "to start a fresh run" updated:>=<from − 30 h>, then each issue's timeline (comments, labeled and unlabeled events) since from − 30 h. Lane runs are listed per UTC day, only for the days the run-clock rows need.BEFORE: 2026-10-27T16:07Z to 2026-11-03T16:07Z
Issues read: 311. Excluded: 31 that straddle a window edge, 36 limit-stop restarts or recurrence relabels, and 4 relabel pairs with no record. Of the counted rows, 8 have no matching lane run, so their clock is the label add.
Interim AFTER: 2026-11-03T16:07Z to 2026-11-04T15:15Z (interim, about 23 h of 7 days)
Interim n = 25 in scope (22 transient, 3 control). Excluded: 15 that straddle a window edge, 1 that overlaps the incident, and 2 limit-stop restarts. The interim window is right-censored: a failure from the last hours that has not been re-fired yet is missing, which biases it low. The 18 rows with no matching lane run are the workflow-stale rows, whose run ends after its own re-fire.
Reading
stranded-backoff-hours. Candidate causes, UNVERIFIED: fix(ci): end a check-mode kill-switch refusal as a stop, not a failure #12759 (40b756e, 2026-11-03T07:14Z, a check-mode kill-switch refusal ends as a stop), feat(pr-pipeline): sweep work-unblock when an issue lane run completes #12531 (00a7507, 2026-11-02T23:17Z, a sweep kicked when a lane run completes), and how long each breaker trip lasted in each window. feat(pr-pipeline): sweep work-unblock when an issue lane run completes #12531 also changes the sweep cadence inside BEFORE.Final AFTER (after 2026-11-10T16:07Z)
Run it with no
--cache, so it reads fresh. Expected cost: about 20 GraphQL calls and about 30 run-listing calls.UNVERIFIED
agent-ready, or anyoutcome=marker, within the 30 h lookback. With no floor inside the lookback, every breaker record in the lookback counts. That can only push a re-fire toward the trip 4+ path, and none landed there.