epiphany/crates/epiphany-bundle/src
Levi Neuwirth bc06706e41 Container major 1: the format epoch carries base provenance
FORMAT_MAJOR becomes 1 and FORMAT_MINOR restarts at 0. The decoder
stops being exact-major-only: it classifies three ways through a named
FormatEpoch carried on FixedHeader, so major 0 is decoded deliberately
as legacy rather than refused. Old readers already fail closed on an
unknown major, so that half needed no mechanism — which is why the major
is the right carrier, and why the header's immutability, fatal to
FORMAT_MINOR as a provenance field, is what makes it sound as an epoch
field.

The matrix: a major-0 bundle with no base may open; one carrying a base
is refused; one attempting to add a base is refused and told to repack.
That last row is the non-inheritance rule. Three errors, none of which
degrades to read-only: two permanent legacy/repack errors, and
ReductionAuthorityUnavailable, which is temporary, names P13-S27, and
must not say repack — a major-1 container is already the right epoch.

Until P13-S27 lands, both major-1 base boundaries are closed: opening a
major-1 bundle that already carries a base, and committing one into it.
Neither may be left open while the epoch asserts a validation that never
ran.

Text projection cannot mint a base. serialize_document staged a carried
base into a fresh bundle and build_manifest wrote it, so an old or
hand-authored document could be laundered straight through the boundary.
All three sides now refuse: projection, parsing, and a new dedicated
SerializeError variant — none of which existed to be "retained".
COMPANION_VERSION moves to 0.14.0 and the corpus is rebuilt to 20
vectors and ten rejection classes, with canonical_bases reach dropping
2 -> 0. That is a real capability loss and is recorded as one.

Corruption keeps precedence in both epochs: a corrupt major-1 base fails
as malformed, never as the temporary authority error a user would
reasonably retry.

All 11 mutations were run and observed, not reasoned about. M4 is the
signing one — with the legacy commit refusal removed, a legacy container
gains a base in place, which is exactly the counterexample that killed
FORMAT_MINOR. M11 confirms the third error is distinct while test 3
stays green, proving the mutation stayed inside the major-1 branches. M7
fails on both epoch halves. M8 falls through to
SerializeError::Bundle(ReductionAuthorityUnavailable), confirming the
text layer's own refusal is what the test asserts.

Two touch-table gaps surfaced during execution, both the same shape: a
.tex requirement addition moves hardcoded counts in
requirement_labels.rs, and the companion bump moves a second normative
version literal spelled version~0.13.0 rather than (0 13 0). Neither
file was in any touch table; the second was caught only because a test
exists for exactly that failure.

P13-S27 is unblocked — its pin 2a is resolved from outside, as its own
prohibition required — and inherits three obligations: both interim
refusals converted to validation, M8's deferred laundering
demonstration, and pin 3c's two suspended conformance assertions.
P13-S16 remains blocked on S27.

Workspace green at 1569.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QjsEnYhm1gPpf6ii2iFxFV
2026-08-07 12:51:14 -04:00
..
block.rs Pushes 1+3: fix the MUST-level violations, wire the types-only machinery 2026-07-02 17:10:50 -04:00
bundle.rs Container major 1: the format epoch carries base provenance 2026-08-07 12:51:14 -04:00
chunk.rs Make the exhaustive tests exhaustive, and stop the record overclaiming 2026-07-09 19:39:30 -04:00
codec.rs Pushes 1+3: fix the MUST-level violations, wire the types-only machinery 2026-07-02 17:10:50 -04:00
crc.rs A B C D F 2026-06-19 12:42:31 -04:00
error.rs Container major 1: the format epoch carries base provenance 2026-08-07 12:51:14 -04:00
fuzz.rs Push 5 / P4: the decode conformance corpus, and the tag it could not read back 2026-07-09 20:16:15 -04:00
header.rs Container major 1: the format epoch carries base provenance 2026-08-07 12:51:14 -04:00
ids.rs G2b coverage repairs: the second stale rationale, and three guards that could not fail 2026-07-29 09:48:41 -04:00
lib.rs Container major 1: the format epoch carries base provenance 2026-08-07 12:51:14 -04:00
manifest.rs G2b: unconflate the corpus version domains, unscope t10, and sign the mutations 2026-07-29 10:09:49 -04:00
opindex.rs Push 5 / P3: fuzz the bundle wire, and find a lenient codec hiding behind a guard 2026-07-09 19:12:34 -04:00
store.rs A B C D F 2026-06-19 12:42:31 -04:00
superblock.rs Pass 11 follow-up: golden-lock the ratified discriminant tables; fix three spec-text inaccuracies 2026-06-22 09:22:55 -04:00
vectors.rs One tag vocabulary the compiler owns, and ratify the corpus in the companion 2026-07-09 20:32:35 -04:00