The S3 Socratic re-audit found incl_sound was kernel-perfect but VACUOUS:
its '... ∨ HasCollision' disjunct (∃ x y, x≠y ∧ sha256 x = sha256 y) is
provable by pigeonhole ALONE (sha256: infinite List UInt8 → finite
32-byte Hash), so the theorem said nothing about forgeries. Even a
data-carrying {p // IsCollision p} disjunct fails (Classical.choice
inhabits it). The only faithful rendering of the paper's 'explicit
algorithm 𝓔' is a NAMED FUNCTION whose correctness is a claim about ITS
OUTPUT.
- extractIncl (m D d P): total function that walks the honest tree and
returns the concrete colliding preimage pair at the first divergence
(a node preimage pair, or the leaf preimage pair at the bottom).
- extractIncl_correct: d ≠ D[m] ∧ accepting-receipt →
IsCollision (extractIncl …).1 (extractIncl …).2. A statement ABOUT the
fixed function's output; pigeonhole cannot discharge it.
ADVERSARIAL CHECK (probe, since removed): proved
¬ IsCollision (extractIncl 0 [[7]] [7] []) — i.e. on a NON-forgery input
the output is provably NOT a collision, so the conclusion is genuinely
false for some inputs ⇒ non-vacuous, choice-proof.
- Removed the vacuous theorems entirely (incl_sound, root_binding,
hnode/hleaf_inj_or_collision, HasCollision def) so no hollow statement
survives in a corpus destined for the log. Kept the real building
blocks (hnode_preimage_inj [propext]; eq_dropLast helper moved to
Completeness; Binding.lean deleted).
extractIncl_correct cone [propext, Classical.choice, LTLAcc.sha256,
Quot.sound]. THE button green (14 certs). Fable statement-audit passed.
LTL untouched (12 leaves, bcd15f9d).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The crux layer — the statement whose HAND proof once carried the frontier
coverage bug is now kernel-checked.
- gen: hash outputs refactored to Hash = {l : List UInt8 // l.length = 32}.
MECHANIZATION FINDING: the paper's pair-coincidence step ('equal hnode
values of distinct argument pairs are a collision') is load-bearing on
FIXED-WIDTH outputs — with unconstrained byte strings x++s = X++Y does
not split. hnode_preimage_inj (cone: propext) makes this explicit via
List.append_inj on equal-length components. Queued as a half-sentence
for the paper's next cycle.
- HasCollision := ∃ x y, x ≠ y ∧ sha256 x = sha256 y — appears ONLY as a
conclusion, never a hypothesis (no collision-resistance assumed).
- hnode_inj_or_collision / hleaf_inj_or_collision: the per-node dichotomy.
- root_binding: any accepting reconstruction from (v,P) to the honest root
either IS the honest receipt (leaf hash AND full path P = Path m D — case
(ii) pinning every consumed sibling) or exhibits a collision. Motive
quantifies (v,P); induction on Path; k-fold discipline.
- incl_sound (Theorem 2, position binding): accepting a wrong leaf at m
yields a collision. Cone [propext, Classical.choice, LTLAcc.sha256,
Quot.sound] — the single hash axiom, pinned in check.sh. ALL GREEN.
Also: Root n=1 branch changed from list-match to decidable 'if P = []'
(well-founded unfolding generated a spurious exhaustiveness obligation);
Root_one_cons added. Fable-5 statement-audit passed. LTL untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adversarial statement-level re-verification of everything S2 shipped,
against paper SS5.3 and the deployed Python verifier: Path recursion,
Root_left/Root_right fold shapes (none exactly where the deployed code
rejects), incl_complete as Theorem 1 verbatim (getD default unreachable
under m < |D|), MTH([]) = H(epsilon) per RFC. All faithful.
One genuine gap found and closed: the kbelow lemmas bounded k but never
established k is a power of two, leaving 'our split point = the RFC
split point' as by-construction folklore. kbelow_pow2 (cone: propext,
Quot.sound) now pins it: 2^j = k < n <= 2k = 2^(j+1) uniquely
determines the RFC 9162 split. THE button green. LTL untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Path (prover-side inclusion path, paper SS5.3) with termination via the
kbelow bounds; self-contained list lemmas (getD_take, getD_drop - no
stdlib-name dependence); equation lemmas MTH_single/MTH_split/Root_one/
Root_left/Root_right (Option.map form; matcher side conditions closed
explicitly); Theorem 1 by functional induction on Path with a k-fold
discipline against the let-bound split point.
incl_complete cone: [propext, Classical.choice, LTLAcc.sha256,
Quot.sound] - pinned exactly in check.sh alongside Path.
THE button green end to end. LTL untouched.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Accumulator pyramid layers 1-2, mechanizing paper SS5.3/SS6 groundwork:
- gen/LTLAcc/HashExternal.lean: the single sanctioned axiom, opaque
sha256 (no properties assumed - the soundness theorems downstream are
constructive collision extractors).
- Proofs/Basic.lean: hleaf/hnode (0x00/0x01 domain stamps); Lemma 1
(domsep) proven AXIOM-FREE; kbelow (largest power of two below n)
with pos/lt/le-two bound lemmas; MTH, Root (Option = rejection),
ConsRec (four cases, b-flag, pinned anchor) - all with kernel-checked
termination via the kbelow bounds.
- check.sh: estate discipline (stub audit, axiom-smuggling gate,
lean-guard compilation, boundary-exact per-certificate cone audit).
All green; observed cones pinned exactly.
Zero contact with the live LTL: no appends, no server, accumulator
frozen at 12 leaves throughout this project.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>