Commit graph

2 commits

Author SHA1 Message Date
fa9da37f11 audit: bind the scalar statements, and make the accounting identity mean audit
Closes four round-7/8 findings. Certified by the round-12 sweep: five
repositories, both buttons and every self-test, 48/48 GREEN.

── `scalar-statements-unbound` (gpt, round 7, CRITICAL) ────────────────────
The main button bound its 31 certificates' elaborated statements and reachable
specification bodies. This button bound NONE of its thirteen, while
TRUSTED-BASE item 8 said the audit covers "every certificate" — false across
the 44-certificate surface. The finding was raised in round 7, lost from the
round-8 work list by an F-number collision between two reviewers, and re-raised
in round 8.

Proofs/ScalarAudit.lean is generated from each fork's OWN Audit.lean, so the
canonicalisation is provably the same code: pp.all rendering, whitespace
normalisation, transitive specification closure. check-scalar.sh Phase 3c pins
the block's digest, requires the committed copy to match byte-for-byte so a
mismatch can be DIFFED, and cross-checks the auditor's certificate set against
the button's CERTS array.

  dalek ecf3a3f8 · anza 0d942e47 · risc0 4b550a61 · betrusted 4b550a61

risc0 and betrusted share a digest and that is correct, not a collision: their
ScalarSubSpec.lean differs only in doc prose and in `black_box` entries inside
`simp only [...]` lists AFTER `:= by`. Proof scripts. They bind the same
statements over the same specifications, which is the documented scope.

selftest-scalar-statements.sh ships the two attacks the reviewer asked for:

  ok  gutted statement caught (cone unchanged)
  ok  rewritten specification body caught (name and cone unchanged)

The second rewrites a reachable reference body to `id (…)` — DEFINITIONALLY
EQUAL, so the corpus compiles and every proof typechecks and the cone is
byte-identical. Every earlier phase is blind to it.

── `drv-surface-no-cones` + `accounting-certifies-enumeration` (claude) ────
The round-7 accounting identity proved every kernel constant was ENUMERATED.
The reviewer showed enumeration is not audit: their planted claim WAS
enumerated, as DRV|LTLAccAudit.bait.smuggled|theorem with a real cone, and
nothing examined it — rows had no cone, no allowlist covered them, the
statement digest does not reach instruments, and Phase 2b gates DECLARED
AXIOMS, a different question. "Progress of one step, not two."

DRV rows now carry their axiom cone and are pinned in driver-allowlist.txt by
inventory_gate.sh with a DRV tag — the same implementation that pins the
corpus, in both directions, because a second copy of a coverage gate is a
second thing to drift. The axiom policy is per-surface and enforced per
surface: the corpus admits exactly the sanctioned boundary, the instruments
admit none, and an instrument axiom fails EVEN WHEN ALLOWLISTED.

Verified with the reviewer's own payload, both placements:
  before the walk -> UNCLASSIFIED: DRV|…|bait.smuggled|theorem|Classical.choice,Quot.sound,propext
  after  the walk -> ACCOUNTING FAILED names it (kernel-side)

── `drv-naming-heuristic` (claude, round 7) ────────────────────────────────
Retired as load-bearing rather than patched. The rule admits a theorem whose
name extends a constant declared alongside it, and "breaks in one line" —
declare `def bait`, then `theorem bait.smuggled` walks through. It stays as a
fast readable first check; membership in a committed allowlist is what now
carries the weight, and a new row fails closed whatever it is called.

── what round 11 caught, which was mine ───────────────────────────────────
DRV rows first shipped WITHOUT their originating driver. dalek and anza run
two drivers, each declaring its own `corpus`; keyed on name alone those two
distinct declarations produced one byte-identical row, `sort -u` collapsed
them, and the trailers summed to 37 against 36. The estate had already learned
this on the corpus walk — INV rows carry their module because two modules both
declare CurveFieldProofs.zero_spec — and I rebuilt the record without it.

Rows now carry their driver, and the gate FAILS CLOSED ON DUPLICATE RECORDS
naming the collision: two declarations sharing one entry means one is covered
by the other's, which is exactly how a real declaration hides. The trailer
now checks what the drivers EMITTED, not what survives de-duplication —
conflating "the run was truncated" with "two rows were identical" is what let
a record-format defect present itself as an arithmetic complaint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 12:15:26 +02:00
afc545e408 verification: close the two-button seam and level up the scalar button (P0-b)
THE SEAM. This repository is checked by two scripts, and until now neither
asserted anything about the other's scope. check.sh's dead-file gate simply
SKIPPED anything named Scalar*, so a new Proofs/ScalarX.lean was gated by
nothing at all: absent from one manifest by exemption, from the other by
omission, compiled by neither, inventoried by neither. Each button now reads
the other's manifest and requires every shipped proof source to belong to
EXACTLY ONE of them — neither orphaned nor double-claimed, both directions,
plus a phantom check on entries naming files that do not exist. Negative-tested
four ways, including the exact hole this item names.

THE SCALAR BUTTON. Closing the seam exposed it as the estate's weakest link,
having been left behind by every hardening round while the main button gained
five phases. 45 lines to 227:

  - source-integrity check over its sources;
  - harness-pin verification, so running THIS button alone is protected and not
    only running it after check.sh;
  - a kernel-side axiom-declaration gate over the compiled artifacts, replacing
    a source-text grep that is evadable four ways on v4.30.0-rc2;
  - a declaration inventory of ~1880 constants against its own allowlist,
    diffed both directions with a count trailer. These 13 modules were the only
    part of the proof corpus with no inventory: check.sh Phase 2c named them as
    uncovered on every run, and now names the button that covers them instead;
  - per-certificate exact-cone assertions replacing `-eq 13` over matching
    output lines. A count cannot say WHICH certificate is clean and passes just
    as happily if one cone is reported twice.

Every fork-specific fact was read from the existing script rather than assumed:
risc0 and betrusted audit sub_loop1_one_spec where dalek and anza audit
cond_add_l_one_spec, untouched.

THREE BUGS, ONE ROOT CAUSE, all found by the gates rather than by review. Each
reasoned about how a thing is SPELLED instead of what it BELONGS TO, and the
corpus punished each: Proofs/ScalarPackSpec.lean is named like the scalar layer
and owned by the main button.

  - the scalar dead-file gate globbed Scalar* and demanded ScalarPackSpec be
    scalar-owned. REMOVED rather than special-cased: the seam check tests
    membership in exactly one manifest, which is strictly stronger than any
    prefix;
  - the scalar axiom gate scanned Scalar*.olean, reporting "14 modules" for a
    13-module manifest. On a tree where check.sh had not run that artifact is
    absent and the button would have failed for a false reason. It now scans
    the manifest by membership and fails closed on a missing artifact;
  - Phase 2c's driver discovery globbed Inventory*.lean and claimed the other
    button's driver, then correctly complained its own manifest lacked those
    modules.

This is the family the campaign began with: a source-text axiom grep reasoning
about spelling. Recorded in TRUSTED-BASE.md because it generalises.

Also fixed: the first negative test of the scalar gate's absence check passed
for the wrong reason — the button recompiles before the gate runs, so removing
an artifact merely caused it to be rebuilt. Retested against the lifted phase,
where absence is a persistent condition.

Verified green: 24 runs across the four repositories — four main buttons, four
scalar buttons, and sixteen self-tests — zero red.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 12:30:29 +02:00