Problem
scripts/escalate-workflow-outage.ts (#10146) counts the leading non-successes at the head of a workflow's run history and escalates at 3. That signal cannot tell a standing outage from a maintainer retrying by hand, because it does not look at how each run was triggered.
Confirmed live on #10171. Six consecutive publish-miner.yml failures escalated to an issue; every one was a manual workflow_dispatch against main, by JSONbored, failing ETARGET on @loopover/contract@^3.19.0 because that version was not yet published. The next run after contract published succeeded with no code change. The workflow was never broken.
Why the distinction matters
The premise the escalation rests on is stated in its own comment: "a deterministic failure fails identically every time." That holds — but so does a human retrying a publish before its dependency is live, and only the first one is an outage nobody is watching. mcp-release-please.yml's reconciliation job already sequences contract → engine → dependents with dispatch_and_wait precisely so the automated path cannot hit this; a hand dispatch bypasses it.
An alert that fires on maintainer-driven retries is the unread-noise failure mode #9951 filed this machinery to escape, just relocated.
Suggested scope
Restrict the failure-streak count to runs the automation dispatched, rather than every run at the head of the history. The GitHub API exposes what is needed on each run (event, triggering_actor, and head_branch — the automation dispatches --ref <tag_name>, a hand dispatch here used main), so no new state is required.
Worth deciding explicitly whether a manual run should be excluded from the count or merely not reset it — excluding is the safer default, since a maintainer's own failed dispatch is already visible to the maintainer who ran it.
Deliverables
Problem
scripts/escalate-workflow-outage.ts(#10146) counts the leading non-successes at the head of a workflow's run history and escalates at 3. That signal cannot tell a standing outage from a maintainer retrying by hand, because it does not look at how each run was triggered.Confirmed live on #10171. Six consecutive
publish-miner.ymlfailures escalated to an issue; every one was a manualworkflow_dispatchagainstmain, byJSONbored, failingETARGETon@loopover/contract@^3.19.0because that version was not yet published. The next run after contract published succeeded with no code change. The workflow was never broken.Why the distinction matters
The premise the escalation rests on is stated in its own comment: "a deterministic failure fails identically every time." That holds — but so does a human retrying a publish before its dependency is live, and only the first one is an outage nobody is watching.
mcp-release-please.yml's reconciliation job already sequences contract → engine → dependents withdispatch_and_waitprecisely so the automated path cannot hit this; a hand dispatch bypasses it.An alert that fires on maintainer-driven retries is the unread-noise failure mode #9951 filed this machinery to escape, just relocated.
Suggested scope
Restrict the failure-streak count to runs the automation dispatched, rather than every run at the head of the history. The GitHub API exposes what is needed on each run (
event,triggering_actor, andhead_branch— the automation dispatches--ref <tag_name>, a hand dispatch here usedmain), so no new state is required.Worth deciding explicitly whether a manual run should be excluded from the count or merely not reset it — excluding is the safer default, since a maintainer's own failed dispatch is already visible to the maintainer who ran it.
Deliverables