Repository navigation
v0.82 lane wave: eight lanes in one change, because runner contention is the binding constraint - #1492
Merged
Conversation
… that derives its population from it
THE REFUTING COMMAND RAN FIRST AND DID NOT REFUTE: the idiom is live, `str(None).strip()` is
still `'None'`, and PyYAML still yields None for a bare key.
THE POPULATION, DERIVED WITH `ast` AND NOT A REGEX, and it REPRODUCED this artifact's own
figure: 32 unguarded `str(<expr>.get(...))` calls across `scripts/**/*.py` (15 more already
`or`-guarded, excluded BY CONSTRUCTION). The done-when's narrower set — read, then TESTED for
truth or membership — is 15 AT ONE HOP, and the walker says it is one-hop: a 16th,
`str(art.get("status",""))`, reaches `status in CLAIMING` at a SECOND hop through the loaded
tuple, so 15 is a FLOOR, not an exact figure. That 16th is also immune, because neither
`"None"` nor `""` is in the status vocabulary. AFTER: 17 unguarded, truth-tested 15 -> 2.
v0.81'S OWN REMEDY IS WRONG IN THE OTHER DIRECTION, and this is the class behind the
instance. All five v0.81 fixes used `str(x.get(k) or "")`, which reads a legitimate `0` or
`False` as ABSENT — the sentinel/value-`0` collision this project has corrected across three
releases. HONEST SCOPE: no current site can receive a falsy non-None value, every key in the
population being string-valued by schema. So it is a property of the IDIOM, not a live
defect; `field_str` removes the question rather than leaving it to the next author.
ONE LATENT HOLE IN A REQUIRED GATE. `Claim Check` refuses a waiver with no reason via
`if not str(w.get("reason", "")).strip()`. A `reason:` written BARE parses to None, reads as
`"None"`, and THE WAIVER READS AS JUSTIFIED. Shown both ways on one input: old idiom `'None'`
-> accepted; accessor `''` -> refused.
AND THE FINDING THAT IS THIS RELEASE'S THEME IN THE MIRROR. Replacing the idiom BROKE R13.
`_derive_field_keys` DERIVES R13's enforced key set by ast-walking the consumers for
`fields.get("literal")` — so removing that shape silently dropped `issue-scope`, `landed` and
`disposition`. Three of R13's four unit tests went red while the module's ANTI-VACUITY GUARD
STAYED GREEN, because it tests only EMPTINESS. That is the exact defect
`_derive_field_keys`'s own docstring already names ("the anti-vacuity guard only tests
non-emptiness ... the very 'cannot see population shrinkage' defect") — reached through the
fix for a different one. Satisfying one gate DISARMED another, and only another rule's tests
noticed.
BOTH REMEDIES, because either alone is insufficient:
* FIELD_ACCESSORS teaches the derivation that `field_str`/`field_text` ARE field
reads, so a normalisation does not narrow R13
* FIELD_KEYS_FLOOR a DECLARED SUBSET of the derived set: losing a key REFUSES and
names it, while ADDING one stays free. Without it the next
normalisation re-breaks R13 silently; without FIELD_ACCESSORS the
floor turns every normalisation into a stop the author must widen.
POTENCY, PAIRED — AND THE FIRST CONTROL WAS REJECTED. Mutating one `landed` read gave rc=1,
but from R4, not the floor: `landed` is read TWICE so the key was never lost. A changed output
via a DIFFERENT rule is as misleading as an unchanged one. Re-run on `shipped-in` — the only
key read exactly once — the floor fired with its own message naming `['shipped-in']`, rc=0 on
restore. The tripwire forbidding the raw idiom in the artifact gates was proven red-first ONCE
PER GATE by reverting one site in each, and its recognizer carries a POSITIVE CONTROL, because
a tripwire asserting ZERO must be shown able to find one.
DECLARED TOLERANT RATHER THAN FIXED, named so the exclusion is not silent: `cr["name"]` in
loop_conformance_check (GitHub JSON — None means the API omitted it, and `.startswith` on
`"None"` and `""` fail identically) and `manifest["safety_bounds"]` in
repro/bulk_mask_679_differential (membership in a closed two-word vocabulary). Both immune,
neither in an artifact gate.
ONE CONSTRAINT FOUND AND RESPECTED: `test_mcdc_gate.py` runs a MUTATED COPY of the gate in a
temp dir, so a sibling import does not resolve. The sibling is staged beside the copy —
keeping the normalisation single-sourced instead of mirroring it — and the mutation test was
RE-PROVEN POTENT afterwards by breaking the gate's refusal string and watching it fail.
26 call sites across FOUR gates now read through the one accessor. Gates: 31 of 31 Claim Check
scripts pass, 75/75 claims hold, test_status_evidence_check 132 OK (6 new), test_mcdc_gate OK.
NON-CLAIMING BY CONSTRUCTION: `status: proposed` + `disposition: partial` + `landed:` naming
the delivering PR, `issue-scope` OMITTED. #1458 is already CLOSED (retired by v0.81), so this
is carried analysis and places nothing in any close set.
Refs #1458
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…he job runs in two MINUTES THE REFUTING COMMAND RAN FIRST AND DID NOT REFUTE. The protection API still lists nine required contexts with `Bazel Build & Proofs` among them; `~/.cache/bazel` DOES NOT EXIST so the cache is cold as recorded; nix answers 2.33.1 after sourcing `nix-daemon.sh`; bazel is on PATH. Every stated precondition holds. The gate stays recorded UNPROVEN — no paired control was run and nothing here claims potency. THIS ARTIFACT'S OWN COST MODEL WAS WRONG BY AN ORDER OF MAGNITUDE. It says a paired control "needs TWO full cold Bazel+Nix+Rocq proof builds". MEASURED from CI's own job records on TWO commits — ee9a955 (the v0.81 release commit) and 93c5e4b — the job completes in 2.3 and 2.0 MINUTES, `runs-on: ubuntu-latest`, with `setup-bazel` restoring a workflow-keyed `disk-cache` and a `repository-cache`. The expensive route was never the only route: the cost belongs to the LOCAL reproduction, not to the control. AND THE BUILD GRAPH MAKES A ONE-FILE CONTROL CHEAP, read from `coq/BUILD.bazel` rather than assumed: a chain of per-module `rocq_library` targets with EXPLICIT `deps` over 34 `.v` files, not one monolithic target. Breaking one proof rebuilds that library and its reverse deps only. Which targets are LEAVES needs `bazel query` (a server start plus the external repos), so it is NAMED as the next step rather than guessed. ONE POTENCY SUB-FINDING, BY INSPECTION AND LABELLED AS SUCH. `Verify Rocq proofs` is a bare `run: bazel test //coq:verify_proofs` — no `|| true`, no `|| [ $? -eq 4 ]` — so it cannot pass vacuously on Bazel exit 4, "no tests matched". That matters because THE STEP DIRECTLY BELOW IT in the same job documents exactly that bug (#945: a tolerated exit 4 made the Renode step "pass while selecting nothing") and guards it on purpose. The proof step is on the right side of that line. INSPECTION, not a control: it shows the step cannot swallow a failure, not that a broken proof produces one. THE LOCAL ROUTE IS REFUTED ON MEASURED DISK, which this artifact did not know: the data volume is at 99% with 7.3 GiB available, and `/nix/store` is already 21 GiB. A cold Bazel+Nix+Rocq build does not fit. 16 GiB sits in a SIBLING project's `rivet/target` and was deliberately NOT purged — another repository, another session, no compiler running in it when checked, and buying someone else's rebuild is not this lane's call. Nothing left in the release path needs a local build, so disk is not blocking. SO THE BLOCKER IS SCHEDULING, NOT COST. `ci.yml` triggers on `push: branches: [main]` and `pull_request: branches: [main]`, so pushing a scratch BRANCH raises no workflow at all — the control needs a PULL REQUEST, which queues 73 job keys: 46 `ubuntu-latest`, 18 `[self-hosted, linux, x64, rust-cpu]`, 3 `light`. The rust-cpu partition is SEVEN of the org's twelve runners and was measured 7/7 BUSY while this release's own merge sat at 15 of 72 checks after 83 minutes. Spending 18 of those slots on a deliberately-broken-proof PR during the release's own merge would delay the thing the control exists to protect. WHAT WOULD SETTLE IT, affordable and unblocked once the queue drains: a scratch PR breaking ONE leaf proof — a broken `Qed`, NOT an added `sorry`, because this repo has shipped a "fail on sorry" gate where all twelve `sorry`s carried a self-exempting comment — confirm the job reds with an attributable diagnostic, record the run link, close the PR unmerged, confirm the unmodified tree passes. Two ~2-minute job runs on GitHub-hosted runners, zero local disk. NON-CLAIMING BY CONSTRUCTION: `status: proposed` + `disposition: partial` + `landed:` naming the delivering PR, `issue-scope` OMITTED. #1456 stays open; the gate stays UNPROVEN. Refs #1456 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…y artifact identity at 6034b22 THE ORDINAL IS DERIVED BY ARTIFACT IDENTITY AND STATED WITH ITS COMMIT, never by counting releases, because the next filing invalidates it and v0.81's artifact had to be corrected for omitting the commit: `ls artifacts/release-v*/RQ-*ARCHMODEL*.yaml | wc -l` returns TWENTY at 6034b22 — an unbroken run from RQ-63-ARCHMODEL through RQ-82-ARCHMODEL. spar#445 WAS RE-CHECKED STATE-FIRST, the #345 lesson: a body is written once and never updated, so the STATE is the fact. `gh issue view 445 --repo pulseengine/spar` reports STATE=OPEN with no `closedAt`. The blocker stands, so steps 1-2 are N/A rather than merely unattempted. AND THE FILING IS SHOWN SEEN BY RUNNING THE MATCHER, NOT BY READING THE TAGS — which is exactly what RQ-69-ARCHMODEL failed when it lost the `feature-loop` tag and the filing that exists to keep a deferral visible became invisible to the gate that reads it. `python3 scripts/loop_conformance_check.py v0.82.0` prints: step 1-2 spar AADL->WIT filed decision NA-FILED decided, artifact scoped, not yet built: RQ-82-ARCHMODEL (#1136, status proposed) [scoped to v0.82, evaluated at checkout] Re-run AFTER the edit as well, because a number is invalidated by the edit that writes it: still NA-FILED. The matcher requires `feature-loop` AND one of `{aadl, spar}` AND a `fields.issue`; this artifact carries `process, feature-loop, spar, aadl` and `issue: "#1136"`. AND IT REPORTS AN OUTCOME rather than being silent, which is the shape v0.81's SILENT lane made mechanical: `disposition: deferred` with a DEFERRED leading verdict, so an artifact with no outcome field is red at the tag and this filing is no longer that shape. ONE MEASUREMENT TAKEN WHILE THE MATCHER RAN, about THIS RELEASE'S TAIL rather than about #1136: the same gate reports step 3 "reported outcome" DERIVED-FAIL with 10 of 12 artifacts recording no outcome. That is TRANSIENT, not a defect — the gate evaluates at HEAD and ten of this release's artifacts carry their outcome fields on lane branches not yet merged. It must clear as the lanes land; if it has NOT cleared by the tag it is a real finding. Step 0 (workspace still 0.81.0), step 7 (no cold-review record) and step 8 (changelog topmost section still [0.81.0]) are DERIVED-FAIL for the same pre-tag reason. WHAT WOULD END THE RECURRENCE, unchanged and not re-litigated: a synth-owned `.aadl` model tracked in-repo, which makes the matcher take branch (a) instead of branch (b). The recorded maintainer decision on #1136 is "not permanently N/A; timing first", so this is a deferral with a named blocker, not an exemption. Gates: status_evidence rc=0 (0 FAILs), verdict_prose 0 disagree over 68, claim_check 75/75. NON-CLAIMING BY CONSTRUCTION: `status: proposed` + `disposition: deferred` + `landed:` naming both the issue and (on the PR) the delivering PR, `issue-scope` OMITTED. #1136 stays open. Refs #1136 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
… alone, and the capability declined on its own done-when
THE MANDATED PRE-READ RAN BEFORE ANY CODE WAS CONSIDERED — the rule v0.81 violated by building
first. `git grep -n -F 'refuse_custom_page_size' -- artifacts/` returns SIX files spanning
v0.69, v0.70, v0.71, v0.80 and v0.82: a carried family five releases deep, which is itself the
signal that a decision already exists. gale's words, re-read at
`artifacts/release-v0.81/RQ-81-PAGESIZE3.yaml:72`: "Refused or honoured? HONOURED — and please
do not spend the effort on relocating the refusal. Refusing in the library closes a door gale
wants open." THE RELOCATION STAYS OFF THE TABLE and was not attempted a third time.
THE REFUTING COMMAND COULD NOT RUN, AND IT FAILED CLOSED — the right outcome for an oracle, and
not to be read as a pass. `pagesize_oracle_1441.py` exits 1: "REFUSE: no synth binary at
target/{debug,release}/synth — build it first; an oracle that silently skips because its subject
is missing is the 'checker reports success about work it never did' class". So the premise is
NEITHER confirmed NOR refuted by execution. AND THE CAUSE DIFFERS FROM v0.81's: that release
misreported an uninitialised `tests/spec-testsuite` as the oracle refusing; here the submodule
IS initialised (345367358, 265 entries). The blocker is the absent binary.
SCOPE RE-DERIVED AT THIS COMMIT rather than carried, because the artifact's figures are marked
"measured at the v0.80 cut":
page_size_log2 sites 5 2 in the CLI refusal, 2 in synth-core/wasm_decoder (struct
field + propagation), 1 comment. The DECLARATION reaches the
decoder and is ignored thereafter.
memory.size lowering sites 4 arm_encoder.rs:1758 and :3830, select_default.rs:398,
cortex_m.rs:152/155 — each a hardcoded LSR #16 / >>16 on R10
max_bytes 1 mention in the whole crate tree: the DEFINITION. ZERO callers,
confirming the carried measurement
initial_bytes 13 mentions — the twin shape is real; both must move together
WHY DEFERRED, AND NOT MERELY "NO TIME". The done-when demands TWO pieces of EXECUTION evidence —
the CI-wired oracle flipping to capability mode, and an execution differential over a
non-default page size — and both need a built `synth`. The machine cannot build one: the data
volume is at 99% with 5.1 GiB available, DOWN from 7.3 GiB during this session. The dominant
consumers are other projects' — a loom scratchpad at 29 GiB, witness at 10 GiB, and a sibling
`rivet/target` at 18 GiB that grew 2 GiB while this was measured — none of it this lane's to
purge. A full workspace debug build measured 12 GiB when last taken.
AND THE PRINCIPLED REASON, which stands even with free disk: shipping this capability WITHOUT
execution evidence is precisely the v0.78 shape, where a lane built a reach gain, its own
execution oracle then showed sign-wrong code, and the gain was REVERTED. A reach increment owes
execution evidence, so declining the increment beats shipping it unexecuted and claiming the
done-when.
RESIDUE THIS LANE CLEANED, because it was this session's own: an idle `bazel(synth)` server THIS
session started with a `bazel info` query was shut down, and the three v0.81 worktrees under the
scratchpad were removed after confirming each branch's content SHIPPED by merged PR head — 1482,
1483, 1481. Their `git log origin/main..HEAD` counts read 5, 6 and 2 "unpushed", which is the
squash-merge trap rather than lost work.
Gates: status_evidence rc=0 (0 FAILs), verdict_prose 0 disagree over 68, claim_check 75/75.
NON-CLAIMING BY CONSTRUCTION: `status: proposed` + `disposition: deferred` + `landed:` naming the
issue and (on the PR) the delivering PR, `issue-scope` OMITTED. #1441 stays open.
Refs #1441
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
… — v0.81's compliance fix SKIPS the npm job entirely THE REGISTRY GAP, RE-DERIVED AGAINST THE LIVE REGISTRY WITH THE REQUEST SHAPE STATED, because a 403 or a missing User-Agent is not evidence of "not published": `curl -s -H "User-Agent: synth-release/0.82" https://registry.npmjs.org/@pulseengine%2fsynth` returns `dist-tags {'latest': '0.69.0'}` over 39 published versions, against a shipped workspace version of 0.81.0. TWELVE minor releases behind (0.70 through 0.81), re-derived not restated. THE SECOND BLOCKER, AND IT IS A CONJUNCTION NOBODY READ TOGETHER. `release-npm.yml` gates its only job on if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' and v0.81's RQ-81-COMPLIANCE deliberately gave `compliance.yml` the ability to FAIL THE RELEASE PATH — its own comment says so, because "a gate that cannot fail is this programme's recurring defect". Each fact is correct; their conjunction is not. DERIVED per tag: v0.78.0 Release success compliance jobs 0 v0.79.0 Release success compliance jobs 0 v0.80.0 Release success compliance jobs 0 v0.81.0 Release FAILURE compliance jobs 1 — and the ONLY failing job in the entire run is `Compliance report / Generate compliance report` So npm's condition evaluated FALSE for the first time and the job SKIPPED with ZERO steps (run 37655372920, 1 second). It never reached its preflight. AND THE FAILURE GOT QUIETER, which is the part that matters. Before v0.81 the npm job RAN and failed loudly at "Preflight — verify npm auth" with ELEVEN steps and a diagnostic naming the token type (run 37560641837). Now it reports `skipped`, no steps, naming nothing. A credential blocker that announced itself every release now announces nothing — the same "a workflow that never starts has no conclusion to be red" shape RQ-81-COMPLIANCE existed to remove, reappearing one workflow over as a consequence of that very fix. THIS ARTIFACT'S OWN DESCRIPTION IS THEREFORE STALE AND IS CORRECTED IN PLACE, not quietly: it says `Release NPM` "fails at its 'Preflight — verify npm auth' step ... which means the preflight is doing its job". At v0.81.0 the preflight did not run at all. AND RQ-82-COMPLIANCE2 IS NOW A PREREQUISITE FOR THIS LANE, unknown when either was scoped. If the externals sync lands and compliance succeeds, the Release run concludes success, npm's condition becomes true, and the preflight runs — at which point the credential is once more the only blocker. ROTATING THE TOKEN WITHOUT THAT FIX WOULD CHANGE NOTHING. THE UNBLOCKING ACTION, NAMED PRECISELY ENOUGH FOR SOMEONE ELSE TO EXECUTE: the repository secret is NPM_TOKEN, in Settings -> Secrets and variables -> Actions, and it must be a CLASSIC AUTOMATION token (or a granular token with read-write on `@pulseengine/*`), regenerated at npmjs.com -> Access Tokens. A classic PUBLISH token is NOT sufficient — the org enforces 2FA on publish and that type fails in CI with EOTP. Quoted from the workflow's own preflight so the action does not require reading CI to find. WHY `issue-scope: outlives` IS NOT CARRIED, against this artifact's own done-when which asks for it "either way": it is FORBIDDEN beside a non-claiming status, and the gate says why. Probed on this tree, `issue-scope: outlives` with `status: proposed` gives `FAIL R12 RQ-82-NPM: ... the issue of an undelivered artifact stays open anyway, so this declaration` is redundant. The non-claiming shape achieves what `outlives` achieves and more strongly — the issue never enters the authorised close set at all — so the done-when's INTENT is met and its LETTER is not. Stated out loud rather than silently dropped. Gates: status_evidence rc=0 (0 FAILs), verdict_prose 0 disagree over 68, claim_check 75/75. NON-CLAIMING BY CONSTRUCTION: `status: proposed` + `disposition: deferred` + `landed:` naming the issue and (on the PR) the delivering PR, `issue-scope` OMITTED per R12. #1460 stays open. Refs #1460 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
… — and half the argument was pinned
THE REFUTING COMMAND RAN FIRST AND DID NOT REFUTE: `-0.0 == 0.0` is still True and
`float("nan") in [float("nan")]` is still False, so both mechanisms are live.
THE PREMISE IS REFUTED WHERE IT SAID "SEVERAL". DERIVED with `ast` over `scripts/repro/`:
14 float-valued tables, 12 containing `-0.0` or NaN — but the number that ASSERT over such a
table is ONE FILE, the already-known `vfp_local_pressure_1069_differential.py`. There is no
second site to convert. The population is ONE, not several, and that is reported as a number
rather than quietly dropped.
TWO OF MY OWN DETECTORS WERE WRONG BEFORE THAT NUMBER WAS RIGHT, so the method ships with it.
Detector 1 looked for `ast.Compare` and found NOTHING — the real guard is SET ARITHMETIC over
packed bytes, not a comparison. Detector 2 text-scanned each assert for `struct.pack` and
classified the one guard I KNEW was correct as VALUE-based, because the packing happens on a
PREVIOUS line. A transitive closure over derived names then over-reached to 25 names and swept
in five per-value input guards. The figure comes from READING the bounded set the narrow scan
produced; a near-empty derived population is a refusal, and it twice meant my instrument was
wrong rather than the tree clean.
WHAT WAS ACTUALLY UNPINNED, measured per row by DELETING IT and watching for a red, against
origin/main and then against this change:
0.0 -- -0.0 pin 1.0 -- -1.0 pin 0.5 -- -0.25 pin 1.5 -- 0.001 --
-3.14159265 pin 1e-30 -- -1e30 pin inf -- -inf pin nan -- BEFORE: 8 of 14 unpinned
... every row `pin` after AFTER: 0 of 14
THE NaN ROW WAS PROTECTED BY NOTHING. The file's own header says NaN is deliberate — it
exercises the spilled reload paths, each local's round-tripped value feeding the product.
Deleting it reddened nothing. Same family as the `-0.0` escape, OPPOSITE failure mode: `-0.0`
was pinned VACUOUSLY TRUE because `-0.0 == 0.0`; NaN cannot be pinned by membership AT ALL
because `nan != nan` would make the guard vacuously FALSE on a CORRECT fixture. `struct.pack`
settles both.
AND HALF THE ARGUMENT WAS PINNED. The file states the shape itself: "the positive rows are the
discriminator — a `neg` would corrupt them too, an `abs` leaves them alone", so the abs-vs-neg
conclusion rests on BOTH halves. v0.81 pinned the negative half by bits; the positive half had
only `len(_POS) >= 4` against SEVEN present, so the floor permitted deleting three in silence.
Now pinned by bits, in a SEPARATE tuple from `_FAILING_SET_1439` — that name means exactly
"the six values v0.78 recorded as failing" and adding rows would falsify it.
THE ZERO IS EARNED, NOT VACUOUS: FOURTEEN individual firing mutations, one per row, plus TWO
NEGATIVE CONTROLS that must stay silent and do — REORDERING rows does not fire (the pins
assert content, not order) and ADDING a row does not fire (a future lane may extend).
WHAT WAS NOT RUN, PLAINLY: the differential's BODY. It needs `./target/debug/synth`, absent
after the v0.81 disk purge, and it has no `--self-test`. This lane changes MODULE-LEVEL fixture
guards, which run at import and which the 14 mutations exercised directly; CI runs the full
differential through `oracle_run.py`. A local oracle run is not a CI run and this claims none.
NOT PROGRESS ON #1439 AND SAYS SO: the emitter is still unnamed. This hardened the oracle
AROUND the defect. #1439 is INTERNAL (no `**[name]` body prefix), so conduct rule 4 does not
bind — but the framing would be the same if it did.
NON-CLAIMING BY CONSTRUCTION: `status: proposed` + `disposition: partial` + `landed:` naming
the delivering PR, `issue-scope` OMITTED.
Refs #1439
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…ll produced nothing — the refuting command could not see the run
THE FIRST HALF IS A VERIFICATION AND IT CAME BACK NEGATIVE. v0.81.0 carries THIRTEEN assets and
ZERO matching `compliance`, derived with `gh release view v0.81.0 --json assets`.
THE REFUTING COMMAND'S SECOND HALF IS BLIND BY CONSTRUCTION, which is worth more than the number
it returns. It asks for the runs of `compliance.yml`'s workflow id; the answer is STILL 19 (1
`workflow_dispatch`, 18 `release`, newest v0.43.0) — which reads as "the wiring did not work".
IT DID. A `workflow_call` invocation does NOT create a run of the CALLED workflow; it appears as
a JOB INSIDE THE CALLER'S RUN. Found there: run 37654229482 ("Release", failure) contains
`Compliance report / Generate compliance report` with 7 steps — step 2 `Resolve tag` SUCCESS,
step 3 a single `actions/checkout@v7` SUCCESS, step 4 `Generate compliance report` FAILURE,
step 5 `Upload report to release` SKIPPED. The trigger is fixed and is not re-litigated here.
THE CAUSE, DERIVED ON THIS TREE RATHER THAN CARRIED. `rivet.yaml` declares SEVEN externals —
gale, jess, kiln, loom, meld, scry, sigil — each with `git:` and `ref: main` and deliberately NO
`path:` (#1012: a declared local path wins, and a dead one poisons resolution for everyone).
Their clones live under `.rivet/repos/<prefix>`, and `.rivet/` is GITIGNORED at `.gitignore:62`
with ZERO tracked files, so a single `actions/checkout` CANNOT supply them. The job's own log is
no longer retrievable (the API returns 0 bytes — an API failure, not an empty population), so
the `could not load externals` quote is v0.81's recorded reading; the step list above is what
this release verified independently.
AND THE REMEDY IS PROVEN END-TO-END ON THE SAME TREE, WITH THE SAME RIVET. With the seven clones
PRESENT, `rivet validate` returns PASS with `Cross-repo backlinks: 1032 (external artifacts
linking to local)` — the #1012 non-vacuity signature satisfied, resolution RAN. The local binary
is `rivet 0.37.0 (6f9ef82c master 2026-09-22)` and the CI action pins `rivet-version: v0.37.0`:
the same rivet, not a near-enough one.
WHAT SHIPPED, AND THE PATTERN IS NOT NEW. A `Sync rivet externals` step between the checkout and
the report, lifted from `ci.yml`'s federated-graph job (#1143): AUTHENTICATE FOR QUOTA, NOT FOR
ACCESS — all seven siblings are PUBLIC, but GitHub rate-limits ANONYMOUS git traffic hardest
from datacenter address space, and a throttled response makes git fall back to interactive auth,
surfacing as `fatal: could not read Username` — which reads like a permissions failure and is
not one. The `url.insteadOf` rewrite is scoped to the step and removed by a `trap`.
THE LIST IS DERIVED AT RUNTIME FROM `rivet.yaml`, not mirrored into the workflow, so adding an
external never needs a second edit. PROVEN by EXTRACTING THE EMBEDDED SCRIPT FROM THE WORKFLOW
FILE and running it, so the test cannot drift from what ships: the real tree reports `synced 7 of
7 externals`; `externals: {}` REFUSES, because a zero population would otherwise succeed while
syncing nothing; an unclonable external REFUSES. Both controls fired.
THE SECOND HALF IS A DECISION PUT AND NOT TAKEN. Re-derived BY PAGINATION (two pages, 149
releases): 19 carry a compliance report, 130 DO NOT, 45 CONSECUTIVE from the newest, most recent
report at v0.43.0. v0.81 recorded 129 of 148 and 44 consecutive; each is one higher because
v0.81.0 itself shipped without one. The 19 matches the 19 workflow runs exactly, which
corroborates the mechanism. Regenerating them is 130 outward-facing writes to already-published
release pages via `workflow_dispatch`, one tag at a time — THE MAINTAINER'S CALL, and nothing was
actioned. The tarball was NOT hand-attached: making the oracle reachable is not delivery.
THE RESIDUAL, NAMED: no per-PR static gate pins the STEP ORDER, so a future edit could move the
sync after the report and nothing would red until a release. It was deliberately NOT bolted onto
`release_trigger_check.py`, whose own docstring is explicit that it polices trigger reachability
and that a different population belongs in a different gate. The in-step non-vacuity refusal is
the gate that exists, and it fires on zero or partial syncs.
ALSO OBSERVED AND NOT ACTIONED, per the recorded VARVE non-action: `Rivet Federated Graph
(advisory)` is red at step 6, `varve install — resolve + fetch + verify the pinned layer`, with
`Sync externals` and `Validate` SKIPPED. So that job's red is the varve layer, NOT an externals
failure, and it fails CLOSED exactly as designed. Reported and moved past.
Gates: 31 of 31 Claim Check scripts pass, release_trigger_check rc=0, compliance.yml parses with
5 steps in the order Resolve tag -> checkout -> Sync externals -> Generate -> Upload.
NON-CLAIMING BY CONSTRUCTION: `status: proposed` + `disposition: partial` + `landed:` naming the
delivering PR, `issue-scope` OMITTED. #1453 stays open until a release attaches a report by an
automated path, and this release is the first test of the remedy.
Refs #1453
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
… of them are the SAME upstream train MAINTAINER-REQUESTED, added to v0.82's scope after the plan was cut. WHY ONE PR IS CORRECT AND NOT MERELY CONVENIENT. Four of the five — `wasmparser`, `wasm-encoder`, `wit-parser`, `wit-component` — all move to 0.261.0, one upstream wasm-tools release train versioned in lockstep. Bumping them one at a time asks cargo to resolve a graph with half the family new and half old. The fifth, the `pulseengine/rivet` compliance ACTION 0.39.0 -> 0.40.0, is a different surface with its own evaluation. THE HOLD'S OWN EXIT CONDITION IS WHAT THIS FOLLOWS, not an exception to it. RQ-64-DEPS recorded it: "merge a held bump BY HAND once the FULL suite is green", base freshness part of "green", and a bump nobody evaluates needing a disposition because "still open" is not one. Raised on a FRESH base off origin/main — never by merging main INTO a dependabot branch, which RQ-64-DEPS names as the move that destroys those branches' freshenability. MEASURED, AND IT CORRECTED A FIRST READING. 0.261.0 was ALREADY in the lock transitively for `wasmparser`, `wasm-encoder` and `wat`, while synth's own declared floors sat at 0.256/0.258/0.259/0.259 — so these bumps raise the DECLARATION to meet a graph that already builds, and they UNIFY it: whole-lock duplicate copies 13 -> 10 wasmparser 5 concurrent copies -> 3 wasm-encoder 3 -> 2 wit-parser / wit-component 0.259.0 -> 0.261.0 wasm-metadata (transitive) 0.259.0 -> 0.261.0 My first pass read the lock with `head -1` and reported `wasmparser 0.252.0` as "the" version. That is a TRANSITIVE copy, not the resolved one, and the truncated view would have made the whole premise wrong. THE ACTION BUMP WAS EVALUATED AT ITS INTERFACE, not by its version number, because a renamed input breaks `compliance.yml` silently at the `with:` level. Fetched `action.yml` at v0.40.0: FOURTEEN declared inputs, and all SIX this caller passes (`theme`, `rivet-version`, `include-data-formats`, `report-label`, `archive`, `archive-name`) are among them, with the `archive-path` OUTPUT the Upload step reads still declared. Per RQ-64-DEPS's own #1107 disposition the action version is NOT the tool version — the rivet BINARY is pinned separately at v0.37.0 both in the `with:` and in ci.yml — and `compliance.yml` is not one of the nine required contexts. ONE INTERACTION NAMED RATHER THAN DISCOVERED LATER: RQ-82-COMPLIANCE2 adds an externals-sync step to the same workflow and has not merged. v0.40.0 declares an `offline` input this caller did not previously have available, so a later lane may find the sync unnecessary. The two changes are independent; both are tested only at a release tag. WHAT IS NOT CLAIMED: that synth's source compiles against the newer API. The data volume is at 99% with ~5 GiB available against a ~12 GiB workspace build, so no local compile was possible, and green `cargo fmt` / `claim_check` / `status_evidence` / `cargo metadata --locked` say NOTHING about `cargo build`. THE FULL SUITE IS THE ORACLE, which is exactly what the hold's exit condition requires. AND THE FIVE DEPENDABOT PRs STAY OPEN UNTIL THE SUITE IS GREEN. Closing them first would leave the bumps nowhere if it is not — create before delete, the same rule the cron rotation follows. They are closed with a reason naming this PR once it lands. Local gates: cargo fmt rc=0, check_version_pins rc=0, claim_check 75/75, status_evidence rc=0 (0 FAILs), verdict_prose 0 disagree over 70, cargo metadata --locked rc=0. Refs #965 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…ded field `_acknowledge` derives `PR_NUMBER.findall(subject)[-1]` — the last PARENTHESISED number in the squash subject — and that number differs by CONTEXT: on the lane branch it is the ISSUE, after the squash it is the DELIVERING PR. A `landed:` naming only one of the two is red in the other context, which this release learned the hard way on #1487. This wave's subject names no single lane, so R4-lane does not fire on it (verified in a squash simulation off origin/main, rc=0, 0 FAIL lines, rather than assumed). The stamp is therefore for the RECORD rather than for the gate: each artifact now names both its issue and the PR that delivered the increment. Applied by a script that asserts `count == 1` per edit and reports PER ARTIFACT, because an aborting batch leaves a MIXTURE — dry-run on all eight first, gates re-checked, idempotence confirmed, then reverted before the real run. Refs #1458 #1439 #1456 #1136 #1441 #1460 #1453 #965 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…, and the failure was UNIVERSAL THE LANE ASKED FOR THIS OUTCOME. It shipped with an explicit non-claim -- "whether synth's own source compiles against the newer API" was named unanswerable locally (99% disk, ~5 GiB against a ~12 GiB workspace build) with THE FULL SUITE NAMED AS THE ORACLE. The suite ran and refused. That is the hold's exit condition working, not a lane failing to meet it. WHAT THE SUITE SAID. Run 37790630310 on #1492 at bfed8c2: 50 of 54 completed jobs failed, and the failure is UNIVERSAL rather than leg-specific -- 46 `ubuntu-latest` (x86), 2 `ubuntu-24.04-arm`, 2 `macos-latest`, with the only 3 green jobs `self-hosted,linux,x64,light` ones that compile nothing. `synth-core` (lib) does not build: error[E0277]: the type `[u8]` cannot be indexed by `std::ops::Range<u64>` Four sites, all `crates/synth-core/src/arena_bind.rs`, all one shape -- slicing the original wasm buffer by a wasmparser-supplied section range: 493 &wasm[reader.range()] FunctionSection 501 &wasm[reader.range()] GlobalSection 520 &wasm[range.clone()] CodeSectionStart 554 &wasm[range] copy_raw, via payload.as_section() CAUSE: wasmparser 0.261.0 widened its section-range types from `Range<usize>` to `Range<u64>` -- the 64-bit-memory change. Not a synth defect; an API widening synth's four consumers predate. MY FIRST READING OF THIS RUN WAS WRONG AND GROUPING BY LABEL IS WHAT CORRECTED IT. I saw 4 failures on arm64/macOS legs and hypothesised a leg-specific fault, explicitly declining to assert a cause and naming the decisive test: whether an x86 leg also fails. It does -- all 46 of them. An API break fails every leg; a leg-specific fault spares x86. It spared nothing. FOUR IS A FLOOR, NOT A MEASUREMENT, and that is why this is a WITHDRAWAL rather than a fix-forward. `synth-core` is the base crate, so the compiler stopped there; the `wit-parser` / `wit-component` / `wasm-encoder` consumer surface downstream was never reached and is UNMEASURED. At 99% disk it cannot be measured locally either, so fixing in place is N blind CI round-trips of unknown N, at the release tail, with SEVEN unrelated lanes held hostage. The seven land; the bump does not. THE WITHDRAWAL IS PROVEN BY EQUALITY, NOT BY A VERSION GREP. `Cargo.toml` and `Cargo.lock` are both byte-identical to origin/main (`git diff --quiet origin/main -- <file>` rc=0 each). A `0.261` grep would have been the WRONG check and would have read as a half-revert, because 0.261.0 was already in the lock transitively for `wasmparser`, `wasm-encoder` and `wat` before this lane existed. Paired with a positive control: appending a comment to `Cargo.toml` made the check correctly read DIFFERS. RETAINED, because it is a different surface: the `pulseengine/rivet` compliance ACTION bump 0.39.0 -> v0.40.0 (#1472). Evaluated at its INTERFACE, not its version number -- fourteen declared inputs at v0.40.0, all six `compliance.yml` passes present, `archive-path` output still declared -- it touches no Rust source, and `compliance.yml` is not one of the nine required contexts. Nothing in the build failure implicates it. THE FOUR CARGO DEPENDABOT PRs STAY OPEN: #1344 wasmparser, #1346 wasm-encoder, #1468 wit-component, #1471 wit-parser. Dependabot does not re-raise a manually dismissed version, so dismissing them now would drop the bumps silently with the work still owed. #1472 is the only one of the five whose premise held, and it is delivered here. STANDING RULE CONFIRMED, NOT DISCOVERED: 0.x-minor is BREAKING and such bumps are held; 0.256 -> 0.261 is a 0.x minor move. The lane's lock-level premise was true and insufficient -- a transitive copy in the lock is LINKED, never compiled against, so it cannot witness source compatibility. v0.83 inherits the four sites, the cause, and the fix's shape: a CHECKED u64 -> usize narrowing that refuses loudly on overflow and on a range past the buffer end, never `as usize`, which would silently truncate a malformed 4 GiB-plus offset into a wrong-bytes read. Local gates on the reverted tree: cargo fmt rc=0, check_version_pins rc=0 (all at 0.81.0), claim_check 75/75, status_evidence rc=0 (13 artifacts, 1 authorised closure #1484), verdict_prose rc=0 (78 artifacts, 0 disagree), cargo metadata --locked rc=0. Refs #965, #1472 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
This was referenced Oct 8, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
avrabe
added a commit
that referenced
this pull request
Oct 8, 2026
…s a guard that could not fail (#1493) Round 1 ran against a pinned detached worktree and found SIX false statements and nine imprecisions across the release's artifacts, re-deriving ~175 numbers. Every finding acted on here was RE-VERIFIED independently rather than taken on report, and two of round 1's own citations were wrong and are corrected to what the source says. F6 IS THE ONE THAT MATTERED, because it is a safeguard that could not fire. compliance.yml's externals-sync step reported `synced N of N` with rc=0 while every external directory was EMPTY -- the single condition it was written to refuse. Two independent causes: - `dest.exists()` treated directory EXISTENCE as a synced external, so an empty or partial `.rivet/repos/<prefix>` counted; - the non-vacuity check compared `len(cloned)` against `len(ext)`, and `cloned` was APPENDED TO BY THE LOOP IT GUARDED. A counter the loop increments can only ever equal the population, so the refusal was UNREACHABLE BY CONSTRUCTION. The fix re-derives the count by READING THE FILESYSTEM BACK after the loop, giving the check a source independent of the thing it checks, and `resolved()` now requires a git dir AND an artifact-bearing file. Gated by `scripts/test_compliance_sync.py`, which extracts the SHIPPED heredoc from the workflow rather than a copy: red-first 2/4, green 5/5, and POTENCY-CONTROLLED against the pre-fix script from git (2 cases flip). Wired into `claim-check`, a REQUIRED context -- a check in no workflow is not a gate. MY FIRST GREEN ON THAT ORACLE WAS TRUE ABOUT THE WRONG SUBJECT and is recorded because it nearly certified the fix vacuously: the red-first case passed because `example.invalid` failed DNS, not because the resolution check fired. Rewritten with LOCAL git repos so clone outcomes are deterministic and the two refusals are DISTINGUISHABLE. THE OTHER FIVE. F1 WIDEFILE5 carried a sibling lane's instrument error as its own. The truncated-grep anecdote about `9.81f`/`0xf5c3` is #1436's gravity constant; `0xf5c3` occurs in exactly three files and #1439's own fixture contains ZERO of either string. F2 CLOSEARM described a rule WIDER than the one it shipped: it said R14 reds an INCOMPLETE verdict beside a claiming status, but R14's `LEGAL_BESIDE_CLAIMING` has ONE member, `REFUTED` -- narrowed by #1488 IN THIS RELEASE, with this artifact not updated alongside. The other six INCOMPLETE tokens are still red, by verdict_prose and R11 rather than by R14. The correction is to the attribution, not the outcome. F3 FIRSTTOKEN's "THIRTEEN artifacts out of population" does not reproduce, and the lane's REFUTED verdict rested on it. Re-derived with the gate's own `artifacts()`/`classify()`: it drops TWENTY-SEVEN of 78. SIX of the thirteen named cannot be dropped by any negator rule -- their first sentence is a bare verdict word. The refusal is UNCHANGED AND STRONGER: losing 27 to close a hole on 3 is a worse trade than the one originally described, so the wrong number understated the case. The same false claim was ALSO in verdict_prose_check.py's own comment block; corrected there too, because the fact matters and not the cited site. F4 BAZELPOTENCY said 73 job keys; loading ci.yml and counting `jobs` gives 71. F5 DEPS claimed v0.40.0 exposed an `offline` input 0.39.0 did not. The two action.yml files are BYTE-IDENTICAL -- 14745 bytes, same sha256 -- and `offline` appears four times in v0.39.0. That claim was already absent from the withdrawal rewrite; recorded in #1492's body because a commit message cannot be amended without discarding a completed CI run. AND A STALE FIGURE OF MY OWN, which is a class worth naming: this artifact said "50 of 54 completed jobs failed" about run 37790630310. That run KEPT GOING after I measured it. A count of a LIVE object is true only at an instant. The final figures, frozen by cancelling the run to free a starved runner pool: 63 of 68 non-cancelled jobs failed across FOUR labels, including 13 `rust-cpu`. Five jobs survived and NOT ONE COMPILES synth -- Format, Version Pin Sweep, Claim Check, Rivet Validation and Advisories are all metadata-level, and two of them are `rust-cpu`, so the discriminator is what a job DOES, not which pool it runs on. Checking that nearly cost the diagnosis: a grep for `cargo` reported build steps in all five, matching "Cache Cargo dependencies" and "Install cargo-deny". Reading the step names settled it. UNIVERSAL holds. NINE IMPRECISIONS, the load-bearing ones: PAGESIZE4's memory.size enumeration was wrong in both directions -- two of its four sites are a comment line and an immediate-load rather than a shift of R10, and the class is not ARM-only. A FIRST correction here claimed "9 files / 18 sites" from a grep that swept in MOVT high-halfword extraction, which converts nothing -- the exact mischaracterisation the row exists to fix. Corrected by READING each site: arm_encoder.rs:1758 and :3830 are the only runtime LSR #16 on R10; RV32 selector.rs:3312 and AArch64 selector.rs:2557/:2596 carry their own compile-time conversions. VALUELESSKEY's tripwire covers TWO gates, not the four it converted, and `Claim Check` -- a required context -- holds the fix with neither a test nor tripwire coverage; named rather than closed, because widening that population owes its own red-first evidence. Plus FIRSTTOKEN's counts now stated WITH their commit, `wat` corrected to 1.261.0, and PAGESIZE4's carried family at six releases not five. ONE ADJACENCY BROKEN DEFENSIVELY: CLOSEARM's theme prose read "entitled the tag to clos{e} #1436" and now reads RETIRE. A full sweep found EIGHTEEN such adjacencies in tracked files dating to v0.64, and they are harmless -- `test_verdict_prose_check.py` carries one naming #1476, which is on main and still OPEN, proving committed file content is not a closure vector. The other seventeen are left alone deliberately. The obligation is forward-only, on prose that gets quoted into messages and bodies, where it would become one. Gates at this tree: cargo fmt rc=0, status_evidence rc=0, verdict_prose rc=0 (78 artifacts, 0 disagree), claim_check 75/75, check_version_pins rc=0, test_compliance_sync 5/5. Refs #1453 #1458 #1476 #1484 #1439 #1441 #1456 #965 Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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 free
to 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.
Eight lanes in one change, because runner contention is the binding constraint
Each lane gates clean on its own and was verified independently; they are combined because a
lane PR queues ~46 GitHub-hosted jobs, and eight separate PRs would each go behind on the
previous merge and need a full re-run. Two of the three groupings were necessary, not merely
efficient:
compliance.yml(the externals sync step, and the actionbump). As separate PRs the second conflicts. Combined, the file carries both.
status_evidence_check.py, because main changed it twice since(R14NARROW and FIRSTTOKEN). Its side carried the accessor fix but the old wide
VERDICT_INCOMPLETEcondition — taking it wholesale would have silently reverted the R14narrowing and re-introduced the conjunction defect this release exists to fix. Resolved
keeping main's narrowed condition and the accessor, asserted both ways.
What each lane found
FIELD_ACCESSORS+ a declared-subset floor. Also: aclaims.yamlwaiver with a barereason:read as JUSTIFIED.workflow_run.conclusion == 'success', and v0.81's compliance wiring made the Release run conclude failure, so the npm job skipped with zero steps. COMPLIANCE2 is a prerequisite.workflow_callmakes no run of its own. The job did run and failed on absent externals; a runtime-derived sync step was added, proven end to end with the same rivet (1032 cross-repo backlinks). Backlog re-derived: 130 of 149, put to the maintainer as a decision.synth-coredoes not build, because 0.261 widened wasmparser's section rangesRange<usize>→Range<u64>and synth indexes&[u8]with them at 4 sites inarena_bind.rs(493, 501, 520, 554). Failure was universal — 46ubuntu-latestx86 jobs failed, not just the arm64/macOS legs. The rivet action bump to v0.40.0 is retained; it touches no Rust source.Gates
status_evidencerc=0 (0 FAILs) ·claim_check75/75 ·verdict_prose0 disagree over 77 ·check_version_pinsrc=0 ·cargo fmtrc=0 ·cargo metadata --lockedrc=0 · six test suitespass (134 in the status-evidence suite). Squash simulation off
origin/mainunder a multi-lanesubject: rc=0, 0 FAIL lines — so R4-lane correctly does not fire on a subject naming no single
lane, verified rather than assumed.
The oracle answered, and it said no
This PR previously stated that it did not claim synth's source compiles against the newer
wasm-tools API, and named the full suite as the oracle. The suite ran and refused: run
37790630310atbfed8c29had 63 of its 71 jobs fail (69 of the 71 were non-cancelled), across four labels: 46ubuntu-latest, 13self-hosted…rust-cpu, 2ubuntu-24.04-arm, 2macos-latest. Not one of the five survivors compiles synth — Format, Version Pin Sweep, Claim Check, Rivet Validation and Advisories are all metadata-level, and two of them arerust-cpu, so the discriminator is what a job does, not which pool it runs on. (This line earlier said "50 of 54, only 3 green, alllight" — measured while the run was still in flight, so true only at an instant. The run has since been cancelled to free the starved runner pool, which froze these figures as final.)The failure is universal, not leg-specific, and that distinction settled the cause. An earlier
reading of this run saw 4 failures on
ubuntu-24.04-arm/macos-latestand hypothesised aleg-specific fault, declining to assert a cause and naming the decisive test: whether an x86 leg
also fails. It does — all 46
ubuntu-latestjobs. An API break fails every leg; aleg-specific fault spares x86. It spared nothing.
Four is a floor, not a measurement.
synth-coreis the base crate, so compilation stoppedthere and the
wit-parser/wit-component/wasm-encoderconsumer surface downstream was neverreached. At 99% disk it cannot be measured locally either — so fixing in place is N blind CI
round-trips of unknown N, at the release tail, with seven unrelated lanes held behind it. The
seven land; the bump does not.
The withdrawal is proven by equality, not by a version grep:
Cargo.tomlandCargo.lockarebyte-identical to
origin/main(git diff --quiet origin/main -- <file>rc=0 each). A0.261grep would have been the wrong check and would have read as a half-revert — 0.261.0 was already
in the lock transitively for
wasmparserandwasm-encoderbefore this lane existed — andwatat 1.261.0, the same upstream train number on a different major, which this line previously recorded as 0.261.0. Theequality check was paired with a positive control that correctly read DIFFERS when dirtied.
The four cargo dependabot PRs stay open — #1344, #1346, #1468, #1471 — because dependabot does
not re-raise a manually dismissed version, so dismissing them now would drop the bumps silently
with the work still owed. #1472 (the action bump) is the only one of the five whose premise
held, and it is delivered here.
Correction: one false statement in this PR's own commit messages
v0.82's cold review (round 1) measured a claim in
cac352e6's commit message to befalse, and it is recorded here because a commit message cannot be amended without
discarding this PR's completed CI run:
Measured:
.github/actions/compliance/action.ymlatpulseengine/rivettagsv0.39.0and
v0.40.0are byte-identical — 14745 bytes, sha256f25afe731ac8d44c…for both —and
offlineappears 4 times in v0.39.0. Its description is "uses system fonts insteadof loading Google Fonts", unrelated to rivet externals. So no new input was exposed, and
the sentence speculating that a later lane might find the externals-sync unnecessary rested
on nothing.
The claim is absent from
RQ-82-DEPS.yamlas rewritten (the withdrawal replaced thatparagraph). What survives, and is unaffected, is the interface evaluation itself: all six
inputs this caller passes are declared, and the
archive-pathoutput the Upload step readsis still declared — true of both versions.
Round 1's other findings land in the release PR before the tag, with the corrections
re-derived rather than taken on report.
Refs #1458 #1439 #1456 #1136 #1441 #1460 #1453 #965
🤖 Generated with Claude Code
https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
Round-2 corrections to this body, recorded rather than silently edited: the job denominator
above said "63 of 68 non-cancelled" — run 37790630310 has 71 jobs and 2 cancelled, so
non-cancelled is 69, and 68 was failure+success, dropping the one SKIPPED job. And
watislocked at 1.261.0, not 0.261.0. Both found by the cold review's second round attacking the
first round's corrections.