Amend the G-minor plan: the seam ruling, the companion consequence, one wrong hash
Documentation only. No Rust, no .tex, no vectors, no implementation. Corrects G2a's introducing commit to7df5ca1- where kinds/tags 32-33 enter payload.rs.55eff00is the later review-fix and introduces no discriminant. The hashes are the evidence for the ladder's monotonicity, so citing a follow-up commit would make it unverifiable at exactly the rung a reader is most likely to re-derive. Records the ruled seam. epiphany-bundle stays opaque with no ops or layout-ir dependency; producers supply the aggregate manifest SchemaVersion explicitly and CommitContext exposes the previous one so unchanged barrier content preserves it. That is new plumbing rather than a read-through: Manifest has no schema-version field, it lives in the superblock, and it must not gain one - a field addition is schema-major regardless of type, which would defeat the rung. Changed barrier bytes require an aware producer that computes the exact epoch or refuses, because blindly retaining the previous aggregate over-stamps once a contributing barrier is removed. Manifest::SCHEMA becomes a baseline constant rather than the universally emitted version. Three sites silently select it, not two - bundle.rs:220, bundle.rs:724, and the re-exported helper manifest_chunk_hash at bundle.rs:1298, which is public API and so a signature change. The major-only check at bundle.rs:301 stays as-is and stays correct. Consequently G-minor does bump the text companion: 0.9.0 to 0.10.0 with corpus regeneration, because TextDocument must carry the manifest SchemaVersion that the projection cannot derive from deliberately opaque bytes. Not because of op-block stamping, which remains projection-invisible - section 2's "no companion bump" correction is still true about op blocks and now carries a forward pointer so it does not read as the whole answer. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QjsEnYhm1gPpf6ii2iFxFV
This commit is contained in:
parent
2c7191482a
commit
0def1563c8
|
|
@ -75,6 +75,13 @@ rung is not a patch.
|
||||||
> base. **No companion bump is required for op-block stamping.** A separate
|
> base. **No companion bump is required for op-block stamping.** A separate
|
||||||
> decision to move canonical-base or extension schemas would change this;
|
> decision to move canonical-base or extension schemas would change this;
|
||||||
> the op-block sweep alone does not.
|
> the op-block sweep alone does not.
|
||||||
|
>
|
||||||
|
> **Still true, but no longer the whole answer (2026-07-28).** The manifest
|
||||||
|
> seam ruling (§4) makes the manifest's aggregate `SchemaVersion` a *carried*
|
||||||
|
> `TextDocument` attribute, so **G-minor does bump the companion** — 0.9.0 →
|
||||||
|
> 0.10.0, with corpus regeneration. Op-block stamping remains
|
||||||
|
> projection-invisible exactly as this correction says; the bump comes from the
|
||||||
|
> manifest, not from it.
|
||||||
|
|
||||||
**Sixty-six** occurrences of `SchemaVersion::{V0, new, for_major}` across
|
**Sixty-six** occurrences of `SchemaVersion::{V0, new, for_major}` across
|
||||||
sixteen files (corrected from 62), concentrated in `epiphany-bundle`,
|
sixteen files (corrected from 62), concentrated in `epiphany-bundle`,
|
||||||
|
|
@ -181,8 +188,15 @@ numbering spaces are unrelated and must not be cross-read.
|
||||||
introducing commits rather than assumed: M2c `a207077` (2026-06-25) → Push 3
|
introducing commits rather than assumed: M2c `a207077` (2026-06-25) → Push 3
|
||||||
`92aaccf` (07-02) → Phase-3 `0316160` (07-02) → G-pass `e4edea6` (07-07) →
|
`92aaccf` (07-02) → Phase-3 `0316160` (07-02) → G-pass `e4edea6` (07-07) →
|
||||||
repeat pair `9b5339f` (07-07) → Push 4a `2740a6c` (07-09) → G1 `3b09595`
|
repeat pair `9b5339f` (07-07) → Push 4a `2740a6c` (07-09) → G1 `3b09595`
|
||||||
(07-24) → G2a `55eff00` (07-28). The two events sharing 2026-07-07 are ordered
|
(07-24) → **G2a `7df5ca1`** (07-28). The two events sharing 2026-07-07 are
|
||||||
correctly: the G-pass precedes the repeat revision.
|
ordered correctly: the G-pass precedes the repeat revision.
|
||||||
|
|
||||||
|
> **Correction 2026-07-28.** G2a's introducing commit is **`7df5ca1`**, where
|
||||||
|
> kinds/tags 32–33 enter `ops/src/payload.rs`. `55eff00` is the *subsequent
|
||||||
|
> review-fix* commit and introduces no discriminant. The distinction matters
|
||||||
|
> because these hashes are the evidence for monotonicity: citing a follow-up
|
||||||
|
> commit would make the ladder unverifiable at the one rung a future reader is
|
||||||
|
> most likely to re-derive.
|
||||||
|
|
||||||
**Existing major baselines are unchanged**: `V0` uses minor 1; `V1`–`V3` use
|
**Existing major baselines are unchanged**: `V0` uses minor 1; `V1`–`V3` use
|
||||||
minor 0. **Baseline variants impose no additive override** — M2c's *operation
|
minor 0. **Baseline variants impose no additive override** — M2c's *operation
|
||||||
|
|
@ -240,14 +254,69 @@ vocabulary**.
|
||||||
decode-and-inspect step at a higher layer that already depends on both —
|
decode-and-inspect step at a higher layer that already depends on both —
|
||||||
and choosing among them is contract work.
|
and choosing among them is contract work.
|
||||||
|
|
||||||
**The genuinely hard case, which must not be discovered during
|
**The genuinely hard case:** barrier bytes are *preserved verbatim* across
|
||||||
implementation:** barrier bytes are *preserved verbatim* across writes,
|
writes, including for extensions the writer does not understand. A repack can
|
||||||
including for extensions the writer does not understand. A repack can
|
carry a barrier blob it cannot decode, whose tags it cannot enumerate, and
|
||||||
therefore carry a barrier blob it cannot decode, whose tags it cannot
|
whose epoch it cannot derive. **"Decode and inspect" silently does not cover
|
||||||
enumerate, and whose epoch it cannot derive. The contract must rule on that
|
this** — it looks complete until a foreign extension is present.
|
||||||
case explicitly — preserve the manifest's existing minor, refuse, or require
|
|
||||||
the minor to travel with the blob — because the "decode and inspect" shape
|
### The seam — RULED 2026-07-28
|
||||||
silently does not cover it.
|
|
||||||
|
**`epiphany-bundle` stays opaque. No `epiphany-ops` or `epiphany-layout-ir`
|
||||||
|
dependency is added.** The producer supplies the aggregate manifest
|
||||||
|
`SchemaVersion` explicitly; the bundle records it and never derives it.
|
||||||
|
|
||||||
|
1. **Producers supply the aggregate.** The write paths take the manifest's
|
||||||
|
`SchemaVersion` as an input instead of selecting a constant.
|
||||||
|
2. **`CommitContext` must expose the previous manifest version**, so unchanged
|
||||||
|
barrier content can preserve it. **This is new plumbing, not a read-through:**
|
||||||
|
`CommitContext::previous_manifest` is a `&Manifest`, and **`Manifest` has no
|
||||||
|
schema-version field at all** — the version lives in the *superblock*
|
||||||
|
(`superblock.rs:174`, bytes 64..68). It must therefore travel as its own
|
||||||
|
`CommitContext` field.
|
||||||
|
3. **It must NOT become a `Manifest` body field.** Adding one is a schema
|
||||||
|
**major** change regardless of type (`binary_format.tex:2360`), which would
|
||||||
|
defeat the entire rung. The wire slot already exists in the superblock; no
|
||||||
|
new one is needed.
|
||||||
|
4. **Changed barrier bytes require an aware producer.** One that cannot
|
||||||
|
establish the exact new epoch **must refuse**. Blindly retaining the previous
|
||||||
|
aggregate is specifically wrong: **removing the sole barrier that contributed
|
||||||
|
the maximum would leave the manifest over-stamped**, claiming a vocabulary
|
||||||
|
level its content no longer needs.
|
||||||
|
5. **Ordinary repacks preserving the complete barrier content preserve the
|
||||||
|
carried version exactly.** This is the common path and it stays cheap.
|
||||||
|
|
||||||
|
**Consequently `Manifest::SCHEMA` becomes a baseline constant, not the
|
||||||
|
universally emitted version** (`manifest.rs:591`, currently
|
||||||
|
`SchemaVersion::V0` = `{0, 1}`). **Three** sites silently select it for
|
||||||
|
hashing and must stop: `bundle.rs:220` (create), `bundle.rs:724` (commit), and
|
||||||
|
the re-exported harness helper `manifest_chunk_hash` (`bundle.rs:1298`) —
|
||||||
|
which is **public API**, so it is a signature change, not an internal edit. The
|
||||||
|
major check at `bundle.rs:301` stays as-is and stays correct: it compares
|
||||||
|
`.major` only, which is exactly the v0 rule that the minor is a record, not a
|
||||||
|
gate.
|
||||||
|
|
||||||
|
### The text-projection consequence — G-minor DOES need a companion bump
|
||||||
|
|
||||||
|
**This reverses Correction 2 in §2 for the manifest, though not for op
|
||||||
|
blocks.** The reasoning there still holds where it was aimed: op-block minors
|
||||||
|
are discarded during projection, so **op-block stamping remains
|
||||||
|
projection-invisible**. But the seam above makes the manifest's aggregate
|
||||||
|
`SchemaVersion` a **carried document attribute**, and the projection cannot
|
||||||
|
derive it — that is the whole point of keeping the bundle opaque, and the bytes
|
||||||
|
may come from a future or unknown extension.
|
||||||
|
|
||||||
|
So `TextDocument` gains the carried manifest `SchemaVersion`
|
||||||
|
(it currently has no such field), which is a document-surface change:
|
||||||
|
|
||||||
|
* **`COMPANION_VERSION` 0.9.0 → 0.10.0** (`textproj/src/lib.rs:34`).
|
||||||
|
* **Corpus regeneration**, on the same reasoning as G2a's kind-production bump:
|
||||||
|
holding the version while changing the surface would leave two incompatible
|
||||||
|
grammars both claiming `(0 9 0)`.
|
||||||
|
|
||||||
|
**Not** because of op-block stamping — because the manifest schema becomes a
|
||||||
|
carried attribute. Recording the distinction because §2's "no companion bump"
|
||||||
|
is otherwise still true and will read as contradictory.
|
||||||
* **No migration.** Existing bundles are accepted as-is; newly emitted or
|
* **No migration.** Existing bundles are accepted as-is; newly emitted or
|
||||||
repacked blocks are stamped correctly.
|
repacked blocks are stamped correctly.
|
||||||
* **Scope is "all additive discriminants reachable in affected chunk
|
* **Scope is "all additive discriminants reachable in affected chunk
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue