Uh oh!
There was an error while loading. Please reload this page.
fix(scripts): name the shared job clock in the stall-guard budget census - #13119
Merged
Conversation
The census prints one `slack` per guard-wrapped site, but `timeout-minutes` runs one clock per JOB. Two guarded steps in the same job therefore do not each get the slack printed beside them -- the later one starts with the earlier one's entire runtime already spent -- and nothing in the line said so. Sibling grouping is derived from job membership, keyed on (file, job id): a job id is unique only within its file, and this tree reuses three of them across files today. Grouping by file, or by a matching --stall-minutes value, would invent shared clocks that do not exist; the self-test pins both. Census wording only. The criterion `T - C >= W` does not move. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CPrUz21stTFhJRUirdc4yw
This was referenced Aug 29, 2026
os-elon
marked this pull request as ready for review
August 29, 2026 05:52
os-elon
enabled auto-merge
August 29, 2026 05:52
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#12959
The census prints one
slackper guard-wrapped site, buttimeout-minutesruns one clock per job. Two guarded steps in the same job therefore do not each get the slack printed beside them — the later one starts with the earlier one's entire runtime already spent — and nothing in the line said so.Census wording only. The criterion
T - C >= Wdoes not move, and nop/smodelling is introduced: the gate's header already explains why it refuses to model them. Every ablation below re-confirms the verdict path staysexit 0.What the census prints now
Four of the seven rows gain the clause; the other three are unchanged. The consequence clause is the load-bearing half —
1 of 2alone leaves a reader still not knowing what it means.Measured: the brief's population assumption did not survive
The brief assumed
temporal-conformancewas the only job holding two guarded steps. Re-running--liston today's tree says otherwise:temporal-conformancererun-safetytest,dogfood,coveragererun-safetyrunsTest suite — pass 1andTest suite — pass 2 (same working tree)back to back on one 120m clock — the sharing is at its most extreme there, since the second site'spis an entire preceding suite run. So the population is two sibling jobs, and the wording had to be right at N greater than 2 as well; a fixture pins3 of 3.The card's five
slack 10mci.yml-family rows do still hold verbatim, at the same line numbers. The card's runner-timestamp figures forp/swere not re-measurable from this seat (repo-scoped REST is 403 here) and are not load-bearing for a wording-only change.The header paragraph describing the population named only
temporal-conformanceand still claimed the census "prints each site'sslackindependently". Both halves were stale in the same defect class as the census line itself, so they are corrected in the same edit rather than left contradicting the output two screens below.The grouping key, and the two wrong derivations pinned against
Sibling grouping is derived from job membership, keyed on
(file, job id). Each half is load-bearing:publish(docker-publish.yml, release.yml),patrol(half-state-patrol.yml, release-coverage-patrol.yml),registry-canary(publish-smoke.yml, scaffold-e2e.yml). None currently holds a guarded step, so this mistake would be green on the live tree while inventing a shared clock that does not exist.--stall-minutesvalue. One file holds many independent job clocks; five of the seven real sites are 10m across four different jobs.The ordinal is trustworthy because a site's position within its job comes from
job.steps— an array — so document order is guaranteed by construction, not by object-key iteration order.2 of 2really is the later step on the clock.Verification — all on
e05512ed6b, the final commitnode scripts/check-stall-guard-budget.mjs --self-test— 61 assertions, exit 0 (was 47). Includes triage's acceptance requirement as a test, not a glance: a job with a single guarded step must show no sibling note.Ablations. Count predicted before each run; all three restored and byte-verified against the HEAD blob (
git diff HEADempty andgit hash-objectequal toHEAD:scripts/check-stall-guard-budget.mjs). Each mutation was confirmed on disk by counting the injected marker and the deleted anchor separately — a zero-hit edit exits 0 and would otherwise read as a passing ablation. No rebuild leg applies: this script is run from source by node, there is nodist/between the edit and the run.--stall-minutesThe three negative controls stayed green under ablation 1 — they assert absence of the note, so they cannot be the thing proving it exists; the six that failed are the ones that assert it does.
Gate family, derived with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackon this commit (not a stale tree — it reported the same sha), all exit 0:check:agent-test-spelling·check:bash32-floor·check:cli-command-ids·check:cross-package-test-inputs·check:entry-guard·check:parse-guard·check:pnpm-filter-targets·check:stall-guard-budget·check:watch-hint-literal·check-ci-filter-parity·check-cross-package-test-inputs·check-shard-attestation·check:nul-bytesBoth convention-triggered obligations for editing a gate script, exit 0:
scripts/pm/bare-root-worklist.mjs --self-test(47 live rows, none stale/missing/contradicted) andpnpm check:pm-dispatch-gates(872 cases).Two things the derivation did not name and a human would still run:
node scripts/measure-stall-guard-headroom.mjs --self-test— exit 0, 13 assertions. It is the one machine consumer of this file, importingscanandguardDefaults; it reads site fields, so the added fields are additive to it.node scripts/check-test-completeness.mjswas in the derived list but is not measured here: bare, it exits 1 on a usage line because it takes a turbo test log argument (CI passes one). The unmodified script does the same, so it is a wrong invocation, not a finding.No pin on the census wording exists to break: no test file, snapshot, or doc quotes the line format — checked before changing it.
Lint — declared narrowing, not a skipped run. Repo-wide eslint is CI's run. Narrowed to the touched file, with the three things that make the narrowing a measurement: (1) the population came from eslint's own config, which accepted the file rather than ignoring it; (2)
--format jsonreports 1 file linted, 0 errors, 0 warnings; (3)eslint.configenables no type-aware linting anywhere (no parserOptions.project, no typed @typescript-eslint rules, its own words), so a single-file diff cannot move the verdict on any untouched file.Changeset: deliberately none, derived
skip-changesetis applied. Derived rather than asserted: no non-private package'sfileswhitelist namesscripts/, and the root manifest isprivate: true, so ascripts/-only diff publishes nothing.Deliberate boundaries
slack; the card asks for the census. Widening it would add output the card did not ask for.timeout-minutesis what binds, the census already says so in thebudget ...m (step timeout-minutes)field printed immediately before the clause.Generated by Claude Code
Generated by Claude Code