Skip to content

plan(v0.67): scope the release — "One root cause, not five symptoms" (7 artifacts) - #1268

Merged
avrabe merged 2 commits into
mainfrom
plan/v067-callee-save
Sep 15, 2026
Merged

avrabe merged 2 commits into
mainfrom
plan/v067-callee-save

Conversation

@avrabe

@avrabe avrabe commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Scopes v0.67 and moves the release anchor to v0.66.0. Seven artifacts, no code changes.

Why this theme

v0.66 built oracles that had never existed and ran them on code that had never been executed — the self-contained corpus images were compiled roughly 400 times per survey run and never once booted, and the boot sweep's first run found two silent miscompiles. It closed 77 of 103 pinned parity entries and still ended with known_open_pins at 127, because the instruments kept finding things faster than the fixes closed them.

The residue is a cluster that reads as separate defects and is not. #1204, #1241 and a run of optimized-path wrong answers all report R9/R10/R11 clobbered. #1241 asks the question in its own title — "(#1204's pair class?)". #1204 already names the mechanism:

register role in a self-contained image
R11 the direct selector's linear-memory base, seeded 0x2000_0100 by the generated startup
R10 the register the software bounds guard compares against
R9 allocatable, observed clobbered alongside the other two

liveness::ensure_callee_saved_prologue (#490) saves R4-R8. The optimized path's allocator hands out R9-R11. The return values are correct; it is the next function that breaks.

Artifacts

id pri issue one line
RQ-67-CALLEESAVE must #1204 fix the callee-saved set, then measure which issues closed
RQ-67-VFPREACH must #1267 synth allocates from half the VFP register file
RQ-67-HIGHWORD must #1240 i64 clz/ctz/popcnt high word — the #916 class on the other selector
RQ-67-SUBTRACT must #242 make selector_lines_code fall for the first time
RQ-67-PINDOWN should #242 known_open_pins must end below 127
RQ-67-NOTESGATE should #1259 give the release notes a gate
RQ-67-ARCHMODEL carried #1136 seventh consecutive N/A, re-verified at cut

Added after the plan was written, from a user report (#1267)

Filed by gale against shipped v0.66.0 while this PR was in CI. The falcon flight cascade lowers 21 of 22 functions on --target cortex-m7dp and declines exactly one — the tick — with VFP register file exhausted (S0..S15 all live).

Reading the source rather than the message: the selector allocates inside S0-S15/D0-D7 (vfp_home: &[bool; 16]), the encoder already encodes VfpReg::S0 through S31, VPUSH/VPOP appear nowhere, and liveness.rs:5977 says in so many words that D8-D15 are callee-saved and out of scope. Every FPU target synth supports has S0-S31. The file is not exhausted when that error fires — half of it is unused, because using it needs a prologue that cannot be emitted.

That makes the release more coherent, not less. It is RQ-67-CALLEESAVE's shape one register file over:

integer float
prologue saves R4-R8 nothing
allocator wants R9-R11 D8-D15
failure clobbers it — silent wrong answer (#1204) refuses to use it — loud decline (#1267)

One root shape — the callee-saved contract and the allocator disagreeing about which registers exist — failing in opposite directions.

The reporter asked which of two remedies was intended. Neither: they already tried guest-side #[inline(never)] and the decline moved with the body (#952, then #1102), and VFP spilling was never going to cover a tick this size against half a register file. Answered on the issue.

Two things deliberately fixed in the plan rather than discovered during it

The attribution is a measurement, not a prediction. CALLEESAVE's done-when requires re-running the boot sweep and the parity oracle over the whole cluster and naming which issues closed. v0.66's five both-selectors-wrong classes turned out to be four root causes — two issues were one defect, one issue was two independent causes. Five fixes for one bug is worse than one honestly attributed, and so is one fix claimed to have closed five things it never touched. HIGHWORD stays a separate artifact as the negative control: it is explicitly a different mechanism, so if it closes as a side effect the attribution is wrong somewhere and the release says so.

The subtraction lever is named before the work starts. "Find something to delete" is the instruction that produced eight consecutive rises. v0.66 killed the previous lever honestly — all four "DEAD" sites were reachable, and all four sat outside the ratchet's population anyway, so deleting every one would have moved the metric by zero. What remains is v0.58's own correction, which makes sel_dsl_rules rising the precondition for selector_lines_code falling: one artifact, not two. The candidate is the i64 immediate family — i32 carries sixteen proven _imm rules, i64 carries zero of the 80, the hand-written arms exist in select_with_stack.rs, and the Rocq proofs follow a pattern already discharged.

The anchor move, and the gate that caught it

status_evidence_check reported ANCHOR-LAG 1 and named the values it needed (v0.66.0, delivery 69, programme 417). Moving the constant without the matching ledger pin reddened Claim Check on the first attempt here — the gate working exactly as designed, since the anchor is pinned in claims.yaml precisely so it cannot drift silently. Both move in this PR.

Gates

claim_check 0 · status_evidence 0 · oracle_wiring 0 · version_pins 0

rivet validate reports 40 errors, unchanged from the pre-existing baseline. The six new artifacts add only the same two WARN classes every v0.66 artifact already produces (req-type: process and the commit-trailer id shape).

Refs #1204 #1240 #1259 #1267 #1136 #242

🤖 Generated with Claude Code

https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L

avrabe and others added 2 commits September 15, 2026 20:28
…(6 artifacts)

v0.66 built oracles that had never existed and ran them on code that had never
been executed: the self-contained corpus images were COMPILED roughly 400 times
per survey run and never once BOOTED, and the first run of the boot sweep found
two silent miscompiles. It closed 77 of 103 pinned parity entries and still
ended with `known_open_pins` at 127, because the instruments kept finding things
faster than the fixes closed them.

THE RESIDUE IS A CLUSTER THAT READS AS SEPARATE DEFECTS AND IS NOT. #1204,
#1241 and a run of optimized-path wrong answers all report R9/R10/R11 clobbered.
#1241 asks the question in its own title — "(#1204's pair class?)". #1204 names
the mechanism: `ensure_callee_saved_prologue` (#490) covers R4-R8 while the
allocator hands out R9-R11, and in a self-contained image R11 is the
LINEAR-MEMORY BASE and R10 backs the software bounds guard.

So v0.67 does what RQ-66-BOTHWRONG got right and generalises it: triage by root
cause, and write the attribution as a MEASUREMENT rather than a prediction. The
NEGATIVE CONTROL is built in — #1240 is explicitly the #916 zero-fill class, a
different mechanism with its own artifact. If it closes as a side effect, the
attribution is wrong somewhere and the release publishes that.

THE SUBTRACTION LEVER IS NAMED BEFORE THE WORK STARTS, because "find something
to delete" is what produced eight consecutive rises. v0.66 killed the previous
lever honestly: all four "DEAD" sites were REACHABLE, and all four sat outside
the ratchet's population anyway, so deleting every one would have moved the
metric by zero. What remains is v0.58's own correction — a rule is done when the
hand-written arm it replaces is DELETED — which makes `sel_dsl_rules` RISING the
precondition for `selector_lines_code` FALLING. One artifact, not two. The
candidate is the i64 IMMEDIATE family: i32 carries sixteen proven `_imm` rules,
i64 carries ZERO of the 80, the hand-written arms exist, and the Rocq proofs
follow a pattern already discharged.

ARTIFACTS: CALLEESAVE (must, #1204), HIGHWORD (must, #1240), SUBTRACT (must,
#242), PINDOWN (should, #242), NOTESGATE (should, #1259), ARCHMODEL (carried,
#1136 — a SEVENTH consecutive N/A, re-verified at cut rather than copied).

THE RELEASE ANCHOR MOVES TO v0.66.0 in this PR, which is what the window rule
requires: `status_evidence_check` reported ANCHOR-LAG 1 and named the values it
needed (delivery 69, programme 417). Moving it later reds A0; moving the
constant without the ledger pin reds Claim Check, which it did on the first
attempt here and is the gate working as designed.

    claim_check 0 · status_evidence 0 · oracle_wiring 0 · version_pins 0
    rivet validate: 40 errors — UNCHANGED from the pre-existing baseline; the
    six new artifacts add only the same two WARN classes every v0.66 artifact
    already produces.

Refs #1204 #1240 #1259 #1136 #242

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
…he VFP register file

A USER REPORT on shipped v0.66.0, filed while this plan PR was in CI. The falcon
flight cascade lowers 21 of 22 functions on --target cortex-m7dp and declines
exactly one, the tick, with "VFP register file exhausted (S0..S15 all live)".

DERIVED FROM THE SOURCE, not inferred from the message:

  instruction_selector.rs  `vfp_home: &[bool; 16]`, "These reside in S0..S15,
                           which are AAPCS-VFP CALLER-saved"
  arm_encoder.rs           encodes VfpReg::S0 through VfpReg::S31 already
  VPUSH / VPOP             appear NOWHERE in the encoder
  liveness.rs:5977         "D8..D15 are CALLEE-saved, out of scope"

Every FPU target synth supports has D0-D15 = S0-S31. THE FILE IS NOT EXHAUSTED
WHEN THAT ERROR FIRES — HALF OF IT IS UNUSED, because using it needs a VPUSH/VPOP
prologue the encoder cannot emit.

THE REPORTER ASKED WHICH OF TWO REMEDIES WAS INTENDED. Neither is: they already
tried guest-side #[inline(never)] and the decline MOVED WITH THE BODY (#952 then
#1102), and VFP spilling was never going to cover a tick this size against half a
register file.

IT IS RQ-67-CALLEESAVE IN THE OTHER REGISTER FILE. Integer: the prologue saves
R4-R8 while the allocator hands out R9-R11, so a callee-saved register is
clobbered — a SILENT WRONG ANSWER. Float: nothing saves D8-D15, so the allocator
refuses to hand them out — a LOUD DECLINE. One root shape, opposite directions.

    claim_check 0 · status_evidence 0

Refs #1267 #1204

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YJK5LZZEkV5smCY1jKn18L
@avrabe avrabe changed the title plan(v0.67): scope the release — "One root cause, not five symptoms" (6 artifacts) plan(v0.67): scope the release — "One root cause, not five symptoms" (7 artifacts) Sep 15, 2026
@codecov

codecov Bot commented Sep 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@avrabe
avrabe merged commit b2a29b0 into main Sep 15, 2026
69 checks passed
@avrabe
avrabe deleted the plan/v067-callee-save branch September 15, 2026 18:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant