docs: record Ε-W3 as landed and Phase Ε as complete

This commit is contained in:
2026-08-02 15:57:06 -04:00
parent c0c56ab2a7
commit 24569956cf
2 changed files with 50 additions and 48 deletions
+36 -2
View File
@@ -1039,5 +1039,39 @@ genuine folder-name collision (`sanitizeRenameCount` vs `collisionRenameCount`)
a hostile or foreign-spelled entry name (e.g. an unexpected extension) always a hostile or foreign-spelled entry name (e.g. an unexpected extension) always
lands sanitized rather than verbatim. lands sanitized rather than verbatim.
**Ε-W3 (`package-compat-fixtures`) has not landed** and is the only remaining ### Ε-W3 — The compatibility fixtures
wave of Phase Ε.
The phase's third and final wave, and with it Phase Ε's implementation is complete: the
version-compatibility policy stated in `docs/product/bank-package.md` is now a property
proven against frozen bytes rather than an assertion in a doc.
**Ε-W3-T1 — `package-compat-fixtures`.** A new checked-in corpus of 23 frozen `.rsbank`
fixtures under `tests/fixtures/package_compat/` — one v1 package written by the shipping
build (`1.4.0`), a synthetic additive-forward package (`formatVersion` 2 /
`minReaderVersion` 1) carrying three keys this build has never heard of, a synthetic
structural-refusal package (2/2), nine truncations (one per distinct decode failure
site, including one cut at `additive_forward.rsbank`'s own payload boundary), and eleven
hostile-name packages (six bad entry names, five bad nested `relativePath` values) —
every payload a single 300-byte 16-bit mono WAV, ~15 KB for the whole corpus. Two new
test targets decode and exercise it: `package_compat_tests` (frozen bytes decode to
exactly what the shipping build wrote, the additive fixture reads with every unknown key
skipped, every truncation classifies `Malformed` and never `TooNew`, every hostile name
is refused before any planner runs) and `package_round_trip_tests` (the same corpus
driven through the actual verbs — export → import → export over `v1_shipping.rsbank`
yields byte-identical payloads, and every refusal fixture refuses the whole import with
nothing landed and nothing in the index). A new repo-root `.gitattributes` (`*.rsbank
binary`) is load-bearing, not decoration: under `core.autocrlf = true`, git's NUL-sniffing
heuristic would text-classify a future short, ASCII-heavy fixture and CRLF-mangle it on a
Windows checkout, silently breaking the frozen-bytes premise the whole corpus rests on. A
standalone DAW verification script, `docs/verify-package-transfer.md`, covers the one
claim no unit test can make — a real cross-machine transfer, including the too-new
refusal, the truncated-download refusal, and mid-payload corruption, each read off as an
exact message string. **Open question resolved:** the recommendation (one-sample
packages, a few hundred bytes of payload each) was followed — the corpus holds
one-sample packages with a 300-byte payload each. **Deviation from spec:** the plan
called for a truncation cut mid-layout; RSBK stores no layout section (the layout is
derived from the manifest's entries, not stored as its own section), so the fixture that
exercises "the manifest parses, the layout computes, the exact-size proof fails" lands at
the payload boundary instead. No production module was touched — the wave adds test-tree
files, the corpus, its README, the verification script, and one path variable in the root
`CMakeLists.txt`.
+14 -46
View File
@@ -2404,6 +2404,9 @@ import gate can key on `LedgerStatus` alone without going through `pruneDryRun()
enumeration+scan). **No Ε track touches `core/instrument/`, `shell/instrument/`, or any enumeration+scan). **No Ε track touches `core/instrument/`, `shell/instrument/`, or any
capture backend.** capture backend.**
**All three waves have landed — Phase Ε is complete.** W1 through W3 each carry their own
landed note below; see `docs/COMPLETED.md` for every track's full narrative.
--- ---
### Ε-W1 — The contract, the filesystem, and the ledger's new kind ### Ε-W1 — The contract, the filesystem, and the ledger's new kind
@@ -2568,52 +2571,17 @@ against a package this build is incapable of writing.
**One track.** The whole deliverable is one corpus and the harness over it; splitting it **One track.** The whole deliverable is one corpus and the harness over it; splitting it
would mean two tracks writing two halves of one fixture set. would mean two tracks writing two halves of one fixture set.
#### Ε-W3-T1 — `package-compat-fixtures` **Ε-W3-T1 has landed**`package-compat-fixtures` — see `docs/COMPLETED.md` for the full
narrative. 23 frozen `.rsbank` fixtures now live under `tests/fixtures/package_compat/`
**Goal.** Turn the version-compatibility policy from an assertion in a doc into a property (three version fixtures, nine truncations, eleven hostile-name packages, ~15 KB total),
proven against **frozen bytes**, so a later format change cannot silently break either decoded by a new `package_compat_tests` and driven through export → import → export by a
direction. new `package_round_trip_tests`, plus the DAW script `docs/verify-package-transfer.md` for
the one claim no unit test can make. A repo-root `.gitattributes` (`*.rsbank binary`)
**Spec:** `docs/product/bank-package.md` §"Version tagging: both directions". keeps the frozen bytes frozen under `core.autocrlf`. No production module was touched.
**Open question resolved:** the recommendation was followed — the corpus is one-sample
**Surface boundary — owns:** a new checked-in fixture corpus under the package modules' test packages with a 300-byte payload each. **Deviation from spec:** RSBK stores no layout
tree, the harness that decodes it, and one `docs/` verification script for the DAW half. section (it is derived from the manifest), so the planned "mid-layout" truncation lands
**Does not own:** any production module — if a fixture reveals a defect, the fix is filed at the payload boundary instead, where the manifest parses but the exact-size proof fails.
against the owning track's module and this track carries the failing test, not the patch.
**Behavior.**
- **Frozen bytes, not regenerated ones.** The corpus holds real `.rsbank` bytes committed to
the repo: a v1 package written by the shipping build, a synthetic
`formatVersion` = N+1 / `minReaderVersion` = current package (the additive-forward case),
and a synthetic `formatVersion` = N+1 / `minReaderVersion` = N+1 package (the refuse case).
A test that regenerates its own fixture proves only that the code agrees with itself —
which is precisely the failure mode a format ladder exists to catch.
- **A truncation corpus.** The valid package truncated at a spread of offsets, each asserted
`Malformed` rather than `TooNew`, so the two recoveries never get crossed.
- **A hostile-name corpus.** Packages whose entry names carry `..`, separators, and absolute
prefixes, each refused.
- **The round-trip anchor.** Export → import → export over the v1 fixture yields
byte-identical payloads.
- **A standalone DAW verification script** in `docs/`, following the
`docs/verify-track-scope-multitrack.md` precedent — the cross-machine transfer is the one
claim no unit test can make.
- **The corpus is append-only.** When a future format version ships, its fixture is added;
no existing fixture is ever regenerated or edited. Stated in the corpus's own README so the
rule survives the person who wrote it.
**Acceptance criteria.**
- All three version fixtures classify as specified, and the additive-forward one imports with
every known field intact and every unknown key skipped.
- Every truncation offset classifies `Malformed`; none classifies `TooNew`, `Readable`, or
crashes.
- Every hostile-name fixture is refused at decode, before any planner runs.
- The round-trip fixture's payloads are byte-identical after export → import → export.
- The DAW script exists and names its steps concretely enough to run without reading this
plan.
**Open questions.** **[propose at review]** how large the committed corpus is allowed to be —
the recommendation is one-sample packages with a few hundred bytes of payload each, since the
properties under test are structural and a large payload proves nothing extra.
--- ---