Repository navigation
W0 gate: gate convention, w0.sh exit gate, and fixes for its false greens - #475
Conversation
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 35 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
|
Status of the red checks on the previous head (7236e9d). None of them is caused by this PR's gate code; the first two now have a fix ported in:
Generated by Claude Code |
Codex Review Summary: ❌ FailedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
This security review couldn’t start because the paying account has exhausted its Codex allowance and has insufficient available credits. The payer can check their balance and add credits in the Codex usage dashboard, then try again. If you do not manage the paying account, contact this repository's admins. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9ff728af28
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if ! rules=$(gh_get "repos/$REPO/rules/branches/main"); then | ||
| fail "$id" "cannot read the live ruleset for $REPO main"; return | ||
| fi | ||
| if ! req=$(jq -er '[.[] | select(.type == "required_status_checks") | .parameters.required_status_checks[].context] | unique | .[]' <<<"$rules"); then |
There was a problem hiding this comment.
Preserve the required check's integration ID
When a ruleset pins a required context to an expected GitHub App, this extraction discards integration_id, and the later match accepts any successful check run or legacy status with the same name. GitHub defines integration_id as the optional integration from which the check must originate (GitHub REST rules documentation), so an unrelated app can make this gate pass while GitHub still blocks the probe PR; retain each (context, integration_id) pair and compare it with the check run's app.id.
Useful? React with 👍 / 👎.
| rg --no-filename --no-line-number --glob '*.rs' '^\s*\.route\(' src/rust \ | ||
| | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//' | sort > "$out/routes.txt" || true |
There was a problem hiding this comment.
Keep router ownership in the route golden
Using --no-filename and globally sorting the route lines erases which router owns each endpoint. This tree already has separate router builders in src/rust/server.rs and src/rust/groove.rs, so accidentally moving an unchanged .route(...) line from the served application router into the other router produces an identical golden even though the endpoint disappears from the application; preserve file/router grouping rather than comparing a global bag of lines.
Useful? React with 👍 / 👎.
| # strip_hash_comments <file>: the file without shell/YAML `#` comment lines. | ||
| strip_hash_comments() { grep -vE '^[[:space:]]*#' "$1"; } |
There was a problem hiding this comment.
Exclude inline comments from hygiene detection
This helper removes only full-line comments, so YAML such as run: echo ok # grep postulate survives and makes check 07a report PASS even though no command scans for postulate; the same issue can satisfy the command searches in 07c. Inspect actual run commands or otherwise remove YAML inline comments before using textual matches as proof that these checks execute.
Useful? React with 👍 / 👎.
| if ! runs=$(check_runs "$REPO" "$c") || ! statuses=$(gh_get "repos/$REPO/commits/$c/status") \ | ||
| || ! nr=$(jq -e 'length' <<<"$runs") || ! ns=$(jq -e '.statuses | length' <<<"$statuses"); then |
There was a problem hiding this comment.
Paginate legacy commit statuses
When a commit has more than 30 legacy status contexts, this fetch reads only the first page of the combined-status response and check 2 inspects only that partial .statuses array. GitHub documents a default page size of 30 and exposes the aggregate state across all contexts (GitHub commit-status API documentation), so a failed or pending context omitted from page one can leave bad and st empty and make the merge-history gate pass; paginate the statuses or require the top-level combined state to be success.
Useful? React with 👍 / 👎.
| curl -fsS --retry 2 \ | ||
| ${auth[@]+"${auth[@]}"} \ |
There was a problem hiding this comment.
When DNS, connection establishment, or response transfer stalls, --retry 2 does not impose a deadline, so any API-backed check can block the entire W0 gate indefinitely. The curl documentation specifically recommends --max-time to prevent batch jobs from hanging and notes that retries require their own total bound (curl man page); add connection, per-transfer, and retry time limits here.
Useful? React with 👍 / 👎.
| if ! hit=$(jq -e '[.. | objects | ||
| | select(([.id, .name, .claim] | map(strings) | join(" ")) | test("\\blake[ _-]build\\b|\\blean4?[ _-]build\\b"; "i")) |
There was a problem hiding this comment.
Require the claims ledger root to be an object
The documented contract requires claims.json to hold an object, but this recursive query accepts any JSON root containing a qualifying object. For example, a root array containing one green Lean-build entry passes check 13 even though consumers expecting the ledger object schema cannot read it; validate type == "object" before searching its descendants.
Useful? React with 👍 / 👎.
| if ! rules=$(gh_get "repos/$REPO/rules/branches/main"); then | ||
| fail "$id" "cannot read the live ruleset for $REPO main"; return |
There was a problem hiding this comment.
Paginate all rules that apply to main
When more than 30 rules apply to main, this request reads only the first page, yet check 1 treats the returned subset as the complete live ruleset. GitHub documents a default page size of 30 for this endpoint (GitHub rules API documentation), so if page one contains one required-status rule while another appears later, the probe can pass without checking the later rule's contexts; collect every page before extracting required checks.
Useful? React with 👍 / 👎.
| /^==+[[:space:]]/ { | ||
| named = "" | ||
| for (k = 1; k <= n; k++) | ||
| if (match($0, "(^|[^A-Za-z0-9-])" id[k] "([^A-Za-z0-9]|$)")) named = named " " id[k] | ||
| print NR named |
There was a problem hiding this comment.
Exclude AsciiDoc block comments from ruling sections
This parser treats every raw == line as a ruling section without accounting for AsciiDoc comment blocks. A ledger can therefore place all required headings and :status: open lines between //// delimiters and still pass check 10a even though the rendered document contains none of those rulings; strip block comments and other verbatim blocks before identifying headings and attributes, or parse the AsciiDoc structure.
Useful? React with 👍 / 👎.
|
This security review couldn’t start because the paying account has exhausted its Codex allowance and has insufficient available credits. The payer can check their balance and add credits in the Codex usage dashboard, then try again. If you do not manage the paying account, contact this repository's admins. |
1 similar comment
|
This security review couldn’t start because the paying account has exhausted its Codex allowance and has insufficient available credits. The payer can check their balance and add credits in the Codex usage dashboard, then try again. If you do not manage the paying account, contact this repository's admins. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f4dcd2b0f5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if ! [[ ${W0_PROBE_PR:-} =~ ^[0-9]+$ ]]; then | ||
| fail "$id" "W0_PROBE_PR is not set to the no-op probe PR number ($(wc -l <<<"$req") required contexts to check)"; return | ||
| fi | ||
| if ! sha=$(gh_get "repos/$REPO/pulls/$W0_PROBE_PR" | jq -er '.head.sha'); then |
There was a problem hiding this comment.
Reject closed or unrelated probe PRs
When W0_PROBE_PR names an old closed or merged PR, or a PR targeting another branch, this extracts only its head SHA, so historical green runs with the same context names can make check 1 pass without any live no-op probe demonstrating that the current main rules are satisfiable. Require the pull response to describe an open probe targeting main before accepting its statuses.
Useful? React with 👍 / 👎.
|
|
||
| check_7() { | ||
| local wf=.github/workflows/idris2-abi-ci.yml ipkg=src/abi/echidnaabi.ipkg rel mod mods missing=() | ||
| if [ -f "$wf" ] && strip_hash_comments "$wf" | grep -E '\bpostulate\b' | grep -qE 'grep|rg |for pattern in'; then |
There was a problem hiding this comment.
Require an actual hygiene command
The inline-comment case is fixed, but a workflow line such as run: echo "grep postulate" still survives stripping and satisfies both grep stages even though it scans neither src/abi nor any other file; the analogous echoed agda ...AxiomTrackerCompleteness.agda also satisfies 07c. Parse the workflow's executable run commands or otherwise verify the command and target path rather than accepting arbitrary textual mentions.
Useful? React with 👍 / 👎.
| ruled) grep -qE 'https://github\.com/hyperpolymath/[^[:space:]]+' <<<"$block" \ | ||
| || problems+=("$r: ruled without a link to the owner's record on github.com/hyperpolymath") ;; |
There was a problem hiding this comment.
Ignore AsciiDoc line comments when validating ruling links
Although delimited comment blocks are now stripped, a ruled section whose only record is // https://github.com/hyperpolymath/... still passes this grep even though AsciiDoc omits that line from the rendered ledger. Strip single-line // comments as well before treating the URL as the owner's ruling record.
Useful? React with 👍 / 👎.
| elif handover_ok "$repo" "$sub"; then | ||
| deferred "$id" "no-push:$repo" "$C_DETAIL; handover committed under $(handover_dir "$repo")/" |
There was a problem hiding this comment.
Fail consumer checks when their API cannot be read
When a committed handover exists and a consumer API request is rate-limited, unreachable, or unparseable, consumer_eval merely leaves C_GREEN empty and stores an error detail, after which this branch reports DEFERRED(no-push:...). The gate can therefore exit successfully without reading the consumer's state, contrary to its contract that an unreadable API is a failure; propagate a distinct evaluation-error state and fail before considering the handover.
Useful? React with 👍 / 👎.
| *.patch|*.diff) [[ ${base,,} == *"${sub,,}"* ]] && patch=1 ;; | ||
| esac | ||
| [[ ${base,,} == *issue* ]] && issue=1 |
There was a problem hiding this comment.
Require separate patch and issue files in handovers
When the patch is named issue.patch (or, for check 12, agda-issue.patch), the same file sets both patch here and issue below, so adding PUSH-REFUSED.txt makes handover_ok accept only two files. This permits a deferred consumer check without the separate issue text required by the documented three-file handover contract; retain the matched paths and require them to be distinct.
Useful? React with 👍 / 👎.
| gate_cmd "$id" "help, route table and just --list match $GOLDENS" -- \ | ||
| "$here/hotspot-goldens.sh" check --dir "$GOLDENS" |
There was a problem hiding this comment.
Keep the hotspot baseline immutable
When the hotspot-split change also recaptures and commits $GOLDENS, this invocation compares the generated output only with that modified working-tree directory, so changed help, routes, or recipes and their newly captured goldens match and the supposedly pure move passes. Verify that the golden directory is unchanged from W0_BASE (or read it directly from that immutable revision) before running the comparison.
Useful? React with 👍 / 👎.
Gate convention (NEW:gate-convention): scripts/gates/lib.sh records each check as PASS, FAIL or DEFERRED(reason). DEFERRED is accepted only for ruling:, secret:, hardware:, owner-host: and no-push: reasons with a name; any other reason is recorded as a FAIL. The summary prints at the end and the gate exits 0 iff nothing failed. An empty gate and a duplicated check id fail. GATE_REPORT writes JCS JSON Lines for STATUS. scripts/gates/lib.selftest.sh covers all-pass, FAIL, every permitted DEFERRED kind, eight forbidden reasons, the empty gate and the report. scripts/gates/w0.sh scripts the 13 W0 exit checks. The GitHub checks read GITHUB_TOKEN and are DEFERRED(secret:GITHUB_TOKEN) without it. Checks whose artefacts come from other W0 lanes fail on main today. scripts/gates/hotspot-goldens.sh captures and diffs the hotspot-split goldens: every `echidna <sub> --help`, the .route( table under src/rust and `just --list`. CI-2 follow-up: cargo audit on main exited 0 with two allowed warnings. Cargo.lock now takes tokio 1.53.1 -> 1.53.3 (RUSTSEC-2026-0386, unsound AsyncFd constructors) and clipboard-win 5.4.1 -> 5.4.3 (yanked). Only the two version and checksum pairs change. cargo update would also have re-resolved windows-sys in nine Windows-only entries, so the two entries were edited directly and checked with --locked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WS4mfQeC3N1DWjcCQJaQqw
A review of the integ lane reproduced eight ways the W0 gate reported green, or deferred, without checking anything. Each is fixed here, and each has a fixture case in the new scripts/gates/w0.selftest.sh. - check_runs passed the accumulated runs to jq through argv. On a commit with more than 100 runs, page 2 hit E2BIG, jq printed nothing, and checks 2 and 11 read the empty result as green. 2ab7574 (159 runs) and a81467b (144) were silently skipped. Pages are now collected in a file. Any unreadable page, unparseable page or page overflow returns an error. - Check 11 matched the bare word "conformance", which governance's UUID and KYAML jobs already satisfy. It now requires an exact job name, or that name after " / ": prove-result-conformance, and verisim-api-list for verisimdb. Check 12 requires agda-proofs. The header states these names as the contract the consumer lanes implement. - A handover deferred checks 11 and 12 on any file name, empty or untracked, and before the live check ran. Now the live check runs first. DEFERRED(no-push) needs a committed, clean handover with a non-empty patch, the issue text and PUSH-REFUSED.txt. - No GITHUB_TOKEN deferred checks 1, 2, 11 and 12. The repositories are public, so the API is now read anonymously when no token is set. A rate limit or an unreadable API is a FAIL. - 06a: blank, multi-word and glob backend names slipped through an unquoted loop. Names must now match ^[a-z0-9_]+$ and are read line by line. - Check 9 passed `{}` and nudged copies of the fabricated metrics. It now requires the file to be absent, or to carry provenance.commit and provenance.run_id, and it still refuses the fabricated values. - 10a accepted one heading that named all 19 rulings, the document title, and any URL as the owner's record. It now requires one section per ruling, exactly one :status: line, and a github.com/hyperpolymath link for a ruled section. 10b passes the W0 range to ruling-cited.sh. - Check 13 matched "flake" and "14.13.01". It now requires a whole "lake build" or "lean build" token and the whole version 4.13.0. A repair counts only as an object with an id and "before": "F-3". - Check 7 read comments: 7a and 7c ignore comments now, and 7b parses the ipkg modules list in both layouts. 7c follows check-agda.sh, which is how the meta-checker job runs MetaChecker.agda, so main's real import passes. - Check 1 now treats a context that is not green as an answer, not as an evaluation error. The selftest caught this. lib.sh changes: - A report that cannot be written now fails the gate. The report is written to a temporary file and moved into place, so a failed write leaves no partial or stale file. - gate_cmd keeps recording under a caller's `set -e`. - Newlines in a detail are flattened, so a detail cannot print a forged PASS line. lib.selftest.sh gains four cases. The old lib.sh fails all four. w0.sh now prints its effective configuration first. W0_CHECKS runs a subset, which always exits non-zero: a subset is a diagnostic, not a gate result. Check 2 still counts skipped and neutral runs as green, but the PASS detail now counts them. The ultraplan's "at success" is unmet on every merge on main, because schedule-only and matrix jobs record as skipped. That reading is stated in the header. It is a departure from the letter of exit check (2), recorded rather than hidden. hotspot-goldens.sh: - It captures router composition (Router::new, merge, nest, with_state, layer, fallback), so routes moved into a sub-router that is never mounted show as a diff. - It joins help file names with "." so `foo-bar` and `foo bar` cannot collide. The self-tests run in MVP Smoke and through `just test-gates`. Checking the tests themselves: a faithful copy of the old check_runs fails the 150-run case, and each of seven planted regressions fails at least one case. Live run against GitHub (checks 1, 2 and 6-13): every artefact still missing on main FAILs. 7c PASSes. Check 2 now lists main's real failures, including 2ab7574. The original commit's CI-2 Cargo.lock change is already on main through a81467b (#455), so after merging main this lane changes no lockfile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WS4mfQeC3N1DWjcCQJaQqw
Each finding is fixed at its source in scripts/gates/w0.sh and covered by a w0.selftest.sh case that fails on the previous gate and passes now. 1. (P1) Check 2 read only the first 30 legacy commit statuses. Statuses are now read over every page (per_page=100) and must add up to total_count, and GitHub's combined state must also be success whenever any status exists: it is computed over every context, so even a page the gate failed to read cannot hide a red status. Cases: "check 2 reads a red legacy status on page 2 of the statuses", "check 2 fails closed when a statuses page is missing", "check 2 requires the combined legacy state to be success". 2. (P1) Check 1 dropped integration_id from required contexts. It keeps (context, integration_id) pairs; a pinned context needs a green check run from that app (runs are now kept latest per name and app), and a legacy status cannot satisfy it. Unpinned contexts are unchanged. Cases: "a run from another app does not satisfy a pinned context", "a legacy status does not satisfy a pinned context". 3. (P2) Check 1 read one page of branch rules. Every page is collected (per_page=100) before required checks are extracted. Cases: "a required context in rules page 2 still gates check 1", "check 1 fails closed when a rules page is missing". 4. (P2) gh_get's curl was unbounded. It sets --connect-timeout 10, --max-time 60 and --retry-max-time 120. Case: "every GitHub API request sets connect, total and retry time limits" (the stub curl logs its arguments). 5. (P2) strip_hash_comments kept inline `#` comments. It now cuts a `#` at line start or after whitespace outside quotes; an apostrophe inside a word does not open a quote. Cases: "a postulate grep in an inline comment fails 07a", "an agda call in an inline comment fails 07c", "an apostrophe does not hide an inline comment from 07c". 6. (P2) Check 10a counted headings and :status: lines inside AsciiDoc blocks. Comment (////), listing (----), literal (....), passthrough (++++) and fenced (```) blocks are blanked first, line numbers kept. Cases: "a section inside a //// comment block does not count for 10a", "status lines and headings in listing blocks do not count for 10a". 7. (P2) Check 13 accepted a claims.json whose root is an array. The root must be an object. Case: "a claims.json whose root is an array fails 13". Shared paging lives in gh_pages, used by check_runs, commit_statuses and the rules read; any unreadable page, non-array page or page 21 is a FAIL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WS4mfQeC3N1DWjcCQJaQqw
The route golden was a global, sorted bag of `.route(...)` lines. A route moved from the served application router into the groove router gave an identical golden while dropping the endpoint from the app (Codex P1). Each line is now prefixed with its owning module: the first path component under src/rust/, with `.rs` removed. server.rs and server/prove.rs both map to `server`, and groove.rs maps to `groove`. Moving a route between routers now changes the golden, while splitting a module into files does not. Checked on the W0 split. Labelled routes (18 server, 2 groove) and router composition are byte-identical before (535274c) and after the server.rs split. w0.selftest: 68/68. shellcheck clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WS4mfQeC3N1DWjcCQJaQqw
f4dcd2b to
7304141
Compare
|
This security review couldn’t start because the paying account has exhausted its Codex allowance and has insufficient available credits. The payer can check their balance and add credits in the Codex usage dashboard, then try again. If you do not manage the paying account, contact this repository's admins. |
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7304141dca
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if [ "$nr" -eq 0 ] && [ "$ns" -eq 0 ]; then | ||
| problems+=("${c:0:9} has no check runs"); continue | ||
| fi |
There was a problem hiding this comment.
Require the expected checks on every W0 commit
When one workflow never creates a check run—for example because it has a startup failure, is accidentally disabled, or stops matching the commit—this accepts the commit as long as any unrelated check or legacy status is green. Consequently check 2 can report that every run succeeded while most of the intended W0 validation never ran; compare each commit against the applicable expected contexts rather than rejecting only commits with zero total results.
Useful? React with 👍 / 👎.
| is_jcs() { | ||
| local f="$1" | ||
| [ "$(jq -s 'length' "$f" 2>/dev/null)" = 1 ] || return 1 | ||
| cmp -s <(jq -cS . "$f") "$f" |
There was a problem hiding this comment.
Validate JCS numbers with an actual canonicalizer
When either ledger contains a decimal such as 1.0, jq 1.7 preserves that numeric lexeme, so jq -cS produces identical bytes and this check accepts the file even though JCS canonicalizes the value as 1; exponent spelling and Unicode key ordering have similar differences. Thus checks 06a and 13 can claim a noncanonical ledger is JCS, so use an RFC 8785 canonicalizer rather than jq's compact sorted output.
Useful? React with 👍 / 👎.
…pre-split goldens (#483) ## Summary This is the W0 "split" lane. It is stacked on #475, which carries the gate it is checked against. Three hotspot files are broken into modules by area. Behaviour is held fixed by goldens captured on the pre-split tree, and W0 exit check 5 compares them. Nothing is renamed or redesigned. ## Changes - **Goldens first** (535274c). `tests/golden/hotspot/` holds 27 files captured before any move: every route, the router composition, and `--help` for each CLI command and subcommand. `scripts/gates/hotspot-goldens.sh` regenerates them and compares. - **`src/rust/server.rs` → `server/{mod,agent,prove,search,session,status,ui,verify}.rs`** (a2fb862). Handlers move by route family. `mod.rs` keeps router composition and shared state. - **`src/rust/main.rs` → `cli/{args,util,prove,verify,search,session,provers,lexicon,corpus,design}.rs`** (ee2ed98). `main.rs` keeps only parsing, tracing set-up and dispatch; `cli/mod.rs` re-exports the command functions. - **`Justfile` → `just/*.just`** (9444837). There are 14 files, one per area, pulled in by `import`. The contractile import stays last. Recipe names and bodies are unchanged; `just --list` matches before and after. - **Merged from #475's base:** the #465 fix for the red checks on `main` (rmcp 3.9.0, rustfmt on `proof_search.rs`, and the Zig-cast annotations). ## RSR Quality Checklist ### Required - [x] Tests pass. W0 check 5 (hotspot goldens) passes, and so does `cargo check --bins` after the merge. I have not run the full `just test` on this branch: disk here is limited. This PR's CI runs it. - [x] Code is formatted (`cargo fmt --all -- --check` is clean). - [x] Linter is clean (`cargo clippy` was clean when the split landed). - [x] No banned language patterns. - [x] No new `unsafe`. - [x] No banned functions. - [x] SPDX headers on all new files. - [x] No secrets. ### As Applicable - [ ] Documentation: `CLAUDE.md`'s structure tree still lists `server.rs` and `main.rs`. That reconcile is reserved for the rulings lane (#58), so this PR does not edit `CLAUDE.md`. ## Testing - `bash scripts/gates/hotspot-goldens.sh check` exits 0: routes, router composition and CLI help are byte-identical to the pre-split capture. - `cargo check --bins` and `cargo fmt --all -- --check` pass on the merged head. - Already broken on the pre-split tree, and not changed here: `echidna corpus import-octads --help` panics (exit 101). It has its own follow-up. Refs #416 --- _Generated by [Claude Code](https://claude.ai/code/session_01WS4mfQeC3N1DWjcCQJaQqw)_ --------- Co-authored-by: Claude <noreply@anthropic.com>



Summary
This PR adds the W0 exit gate (ultraplan
NEW:gate-convention, and W0 exit checks 1-13). Every other W0 lane is judged by this gate, so it has to be sound first. A skeptic review of the first version found eight ways it reported green or deferred without checking anything. The second commit fixes each of them and adds a fixture test for each.Changes
scripts/gates/lib.shrecords each check as PASS, FAIL or DEFERRED(reason).ruling:,secret:,hardware:,owner-host:andno-push:.GATE_REPORTwrites JCS JSON Lines atomically. A failed write fails the gate.gate_cmdkeeps working under a caller'sset -e.scripts/gates/w0.shruns the 13 exit checks. Fixes from review:check_runsdropped results on large commits. It passed runs to jq through argv, which hit E2BIG past 100 runs. jq printed nothing and that read as green. 2ab7574 (159 runs) and a81467b (144 runs) were silently skipped. It now collects pages in a file and fails closed.prove-result-conformance, andverisim-api-listfor verisimdb. Check 12 requiresagda-proofs. The script header states these as the contract the consumer lanes implement.PUSH-REFUSED.txt.{}and nudged copies of the fabricated metrics.W0_CHECKSruns a subset, which always exits non-zero. The effective configuration is printed first.scripts/gates/hotspot-goldens.shalso captures router composition, so routes moved into a sub-router that is never mounted show as a diff. It now joins help file names with.instead of-, sofoo-barandfoo barcannot collide.scripts/gates/w0.selftest.sh(new) has 50 fixture cases with a stubcurland no network.lib.selftest.shnow has 24 cases. Both run in MVP Smoke and throughjust test-gates.One reading for the owner to see. Exit check (2) says "at success". Every merge on main carries schedule-only and matrix jobs that GitHub records as skipped, so the literal reading can never pass. The gate counts skipped and neutral as green and states the count in its PASS line. This is recorded in the script header, not hidden.
RSR Quality Checklist
Required
just test-gatesgives lib 24/24 and w0 50/50.shellcheck -x scripts/gates/*.shgives no findings. The disabled rules are named with the reason.unsafeblocks.As Applicable
Testing
bash scripts/gates/lib.selftest.shgives 24 cases with 0 failed, andbash scripts/gates/w0.selftest.shgives 50 cases with 0 failed.check_runsfails the 150-run case.lib.shfails all four new library cases.Generated by Claude Code