Skip to content

chore(deps): bump wasm-encoder from 0.258.0 to 0.261.0 - #1346

Closed
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/cargo/wasm-encoder-0.259.0
Closed

dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/cargo/wasm-encoder-0.259.0

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Bumps wasm-encoder from 0.258.0 to 0.261.0.

Commits

@dependabot dependabot Bot added the dependencies Dependency updates label Sep 21, 2026
@temper-pulseengine
temper-pulseengine Bot enabled auto-merge (squash) September 21, 2026 21:45
@github-actions
github-actions Bot disabled auto-merge September 21, 2026 21:54
@github-actions github-actions Bot added the major-bump-hold Breaking-class dep bump (major / 0.x-minor / 0.0.x) held from auto-merge — #866/#965 label Sep 21, 2026
@github-actions

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch from 92fac8d to 37894a3 Compare September 22, 2026 21:36
@github-actions

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch 2 times, most recently from 37894a3 to 18a1919 Compare September 23, 2026 13:09
@github-actions

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch from 18a1919 to a1a3de8 Compare September 24, 2026 03:05
@github-actions

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch 2 times, most recently from a1a3de8 to 585fb2f Compare September 24, 2026 15:05
@github-actions

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch from 585fb2f to e28a001 Compare September 24, 2026 22:32
@github-actions

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch from e28a001 to ee7de1f Compare September 25, 2026 06:55
@github-actions

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch from ee7de1f to 760c517 Compare September 29, 2026 21:28
@github-actions

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch from 760c517 to 1e422ef Compare September 30, 2026 08:26
@github-actions

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch from 1e422ef to 5263e59 Compare September 30, 2026 22:13
@github-actions

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch from 5263e59 to 717719d Compare October 1, 2026 19:21
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch from 717719d to 2f3ef01 Compare October 2, 2026 19:22
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@avrabe

avrabe commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

@dependabot recreate

@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch from 2f3ef01 to 5dbb511 Compare October 3, 2026 16:03
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@dependabot dependabot Bot changed the title chore(deps): bump wasm-encoder from 0.258.0 to 0.259.0 chore(deps): bump wasm-encoder from 0.258.0 to 0.261.0 Oct 5, 2026
@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch from 5dbb511 to a8036b4 Compare October 5, 2026 22:09
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch from a8036b4 to 1b24a39 Compare October 6, 2026 23:50
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

avrabe added a commit that referenced this pull request Oct 8, 2026
…, 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
@avrabe

avrabe commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Held, with a measured reason — and this PR stays open deliberately.

v0.82 tried to land this bump together with its three siblings (wasmparser, wasm-encoder,
wit-parser, wit-component all move to 0.261.0 as one upstream wasm-tools train) in PR #1492.
The full test suite refused it.

What breaks. synth-core does not compile:

error[E0277]: the type `[u8]` cannot be indexed by `std::ops::Range<u64>`

wasm-tools 0.261.0 widened wasmparser's section-range types from Range<usize> to Range<u64>
— the 64-bit-memory change. synth indexes a &[u8] with those ranges directly at four sites in
crates/synth-core/src/arena_bind.rs:

line expression payload
493 &wasm[reader.range()] FunctionSection
501 &wasm[reader.range()] GlobalSection
520 &wasm[range.clone()] CodeSectionStart
554 &wasm[range] copy_raw, via payload.as_section()

The failure is universal, not platform-specific. Run 37790630310: 50 of 54 completed jobs
failed — 46 ubuntu-latest (x86), 2 ubuntu-24.04-arm, 2 macos-latest. The only green jobs
were self-hosted ones that compile nothing.

Four sites is a floor, not the job size. synth-core is the base crate, so compilation
stopped there; the consumer surface downstream of it was never reached and is unmeasured.

Why this PR is not being dismissed. Dependabot does not re-raise a version that was manually
dismissed, so dismissing this now would drop the bump silently while the work is still owed. It
stays open until the narrowing conversion lands.

What the fix needs (tracked for v0.83 in artifacts/release-v0.82/RQ-82-DEPS.yaml): one
helper performing a checked u64 → usize narrowing that refuses loudly on overflow and on
a range past the buffer end, applied at the four sites — never as usize, which would silently
truncate a malformed 4 GiB-plus section offset into a wrong-bytes read.

Refs #965

avrabe added a commit that referenced this pull request Oct 8, 2026
… is the binding constraint (#1492)

* v0.82 VALUELESSKEY lane (#1458): removing the idiom DISARMED the gate 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

* v0.82 BAZELPOTENCY lane (#1456): the artifact said two cold builds; the 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

* v0.82 ARCHMODEL lane (#1136): the twentieth filing, ordinal derived by 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

* v0.82 PAGESIZE4 lane (#1441): the pre-read first, the relocation left 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.82 NPM lane (#1460): rotating the token would have changed nothing — 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

* v0.82 PINBYVALUE lane (#1439): the premise said SEVERAL and it is ONE — 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

* v0.82 COMPLIANCE2 lane (#1453): the trigger was fixed and the job still 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

* v0.82 DEPS lane (#965): five held dependabot PRs in one, because four 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

* v0.82 lane wave: stamp the delivering PR (#1492) into each lane's landed 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

* v0.82 DEPS lane (#965) REFUTED: the suite named as the oracle said no, 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

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@avrabe

avrabe commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Correction to the figures in my earlier comment. The substance is unchanged — this bump
still breaks synth-core at the four arena_bind.rs sites listed above, and the hold stands —
but two numbers were wrong and the public record should be right.

stated actual
"50 of 54 completed jobs failed" 63 of 71 jobs failed (69 of the 71 were non-cancelled)
failures on ubuntu-latest / ubuntu-24.04-arm / macos-latest four labels — those three plus 13 self-hosted…rust-cpu
"the only green jobs were self-hosted ones that compile nothing" five survivors, two of them rust-cpu; none compiles synth

Why it was wrong: the first figure was read while run 37790630310 was still in flight, so
it was true only at an instant. The run has since completed and been cancelled; these figures are
final. The replacement figure was then wrong too — "68 non-cancelled" was failure+success and
dropped the one SKIPPED job, where 71 minus 2 cancelled is 69.

The conclusion is if anything firmer: failures spanned four labels including the self-hosted
pool, and not one of the five survivors (Format, Version Pin Sweep, Claim Check, Rivet
Validation, Advisories) compiles synth — so what a job does is the discriminator, not which
pool it runs on.

Bumps [wasm-encoder](https://github.com/bytecodealliance/wasm-tools) from 0.258.0 to 0.261.0.
- [Release notes](https://github.com/bytecodealliance/wasm-tools/releases)
- [Commits](https://github.com/bytecodealliance/wasm-tools/commits)

---
updated-dependencies:
- dependency-name: wasm-encoder
  dependency-version: 0.259.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot
dependabot Bot force-pushed the dependabot/cargo/wasm-encoder-0.259.0 branch from 1b24a39 to 7fa7a68 Compare October 8, 2026 18:27
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown

🔒 HELD — not auto-mergeable (class: zerox-minor). 0.258.0 -> 0.259.0: for a 0.x crate the MINOR is the de-facto major (ordeal 0.9->0.12; object 0.39->0.40 / #938)

Auto-merge has been actively disabled and asserted off by the hold gate (#965). For a 0.x crate the MINOR component is the de-facto major (and for 0.0.x, the patch): ordeal 0.9→0.12 auto-merged as "minor" and hung Test+Z3 for days; object 0.39→0.40 (#938) broke 16 call sites across three unrelated newtype surfaces. Merge this BY HAND only once the FULL suite is green, including the separate --features z3-solver path (required context "Z3 Verification") — the discriminator is CI, not a read of the diff.

@avrabe

avrabe commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Superseded: this bump is applied, with its downstream surface measured.

Cargo.toml now declares wasmparser = "0.261", wasm-encoder = "0.261", wit-parser = "0.261" and wit-component = "0.261" — all four moved together in one change rather than four, because synth-core is the base crate and a partial move cannot be validated.

v0.82 held these open deliberately. Its reasoning was that dependabot does not re-raise a manually dismissed version, so dismissing them while the work was still owed would have dropped the bumps silently. The work is no longer owed.

What the move needed, and why it was not a flag flip: wasmparser 0.261 widened its section-range types from Range<usize> to Range<u64>, and arena_bind.rs indexes a &[u8] with them at four sites. Those are now routed through a checked narrowing that refuses loudly rather than as usize, which would turn a malformed 4 GiB-plus section offset into a wrong-bytes read. The downstream consumer surface behind synth-core — never reached by v0.82's compiler run, because it stopped at the first failing crate — measures zero: cargo check --workspace --all-targets is rc=0 with no errors and no warnings, and cargo test --workspace is rc=0.

Superseded by PR #1498, which carries the bump, the checked narrowing and the measurement. If dependabot raises a later wasm-tools train it is welcome to — the declared floor is now 0.261.

@avrabe avrabe closed this Oct 9, 2026
@dependabot @github

dependabot Bot commented on behalf of github Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

OK, I won't notify you again about this release, but will get in touch when a new version is available. If you'd rather skip all updates until the next major or minor version, let me know by commenting @dependabot ignore this major version or @dependabot ignore this minor version. You can also ignore all major, minor, or patch releases for a dependency by adding an ignore condition with the desired update_types to your config file.

If you change your mind, just re-open this PR and I'll resolve any conflicts on it.

@dependabot
dependabot Bot deleted the dependabot/cargo/wasm-encoder-0.259.0 branch October 9, 2026 00:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Dependency updates major-bump-hold Breaking-class dep bump (major / 0.x-minor / 0.0.x) held from auto-merge — #866/#965

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant