Skip to content

stall-guard budget census prints the same slack for two guarded steps that share one job clock, so the later step's smaller real headroom is invisible #12959

Description

@os-elon

Observation only, found while re-measuring the stall guard's headroom. Not a wrong verdict — a census line that reads as more independent than it is.

What the census prints

check-stall-guard-budget.mjs --list reports, per guard-wrapped step, window / cap / budget / slack, where slack = T - C. On this tree five ci.yml-family sites all print slack 10m:

ci.yml:573 job `test` step `Run this shard's tests` slack 10m
ci.yml:969 job `temporal-conformance` step `Run driver-sql suite ...` slack 10m
ci.yml:1009 job `temporal-conformance` step `Run the non-SQL temporal backends ...` slack 10m
ci.yml:1152 job `dogfood` step `Boot example apps ...` slack 10m
coverage-nightly.yml:59 job `coverage` step `Generate coverage report` slack 10m

Two of those are the same job. timeout-minutes runs one clock for the whole job, so those two steps do not each get 10 minutes of room — they share it, and the second one starts with the first one's runtime already spent.

Measured

Runner timestamps, three consecutive merge_group runs of 2026-08-28 (33160601033, 33162164422, 33163163494). p measured from job start, which is the clock timeout-minutes actually runs on:

stepworst pworst sworst p + s
Run driver-sql suite against both live servers1m42s1m08s2m50s
Run the non-SQL temporal backends under the skewed process zone4m08s1m28s5m36s

The second step's p is 2m26s larger than the first's, and essentially all of that difference is the first guarded step's own runtime. Both rows print slack 10m.

Why this is only a legibility defect, not a wrong gate

The gate's criterion is T - C >= W, and its header is explicit that it does not model p or s at all — it deliberately refuses to encode the run length, because no static sweep can read it. Against that criterion slack 10m is correct for both rows.

The problem is that the census is also the thing a human reads to judge whether a family is comfortable, and there the two rows are not equivalent: a reader comparing them has no way to see that one of them is a first step and the other is a second step on the same clock. Today the numbers are small enough that it does not bite (worst p + s on that job is 5m36s against a 30m budget). It would bite on a job whose earlier guarded step grew.

Suggested remedy

Have the census name the sibling count when a job holds more than one guard-wrapped step — e.g. slack 10m (1 of 2 guarded steps in this job; they share one timeout clock). That keeps the criterion exactly as it is and only stops the line from reading as an independent per-step budget.

No behaviour change is proposed to the gate's verdict.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions