Ratify the G-minor epoch ladder, and narrow the Manifest::SCHEMA rule

Documentation only. No Rust, no .tex, no vectors, no implementation.

Records the ratified schema-minor epochs (minors 2-9, one per additive event:
M2c, Push 3, Phase-3 tranche 1, Pass-12 G-pass, schema-major-2 repeat revision,
Push 4a, G1, G2a). These are schema-minor epochs, not companion semver.

The ladder is complete against spec/AUDIT_GMINOR_VOCABULARIES.md - every
post-baseline variant appears exactly once - and monotonic in the topological
order of the commits that introduced each variant, which is what makes a
declared minor prefix-closed. Verified against git rather than assumed,
including the two events sharing 2026-07-07.

Major baselines unchanged: V0 minor 1, V1-V3 minor 0. Baseline variants impose
no additive override; M2c's operation kinds stay baseline while its
PreconditionFailureReason append requires epoch 2.

Manifest::SCHEMA is narrowly superseded. Changed child ChunkRefs still never
raise the manifest minor, but emitted barrier tags do: a manifest naming a tag
in 24-33 takes that tag's epoch. Major stays 0. The derivation seam is left to
the implementation contract, with the case that must not be discovered late
written down - epiphany-bundle depends on neither ops nor layout-ir and
preserves barrier bytes verbatim, so a repack can carry a blob it cannot
decode, and "decode and inspect" does not cover it.

PLAN_GENESIS_OPS.md:257 no longer says "per-kind minor". That policy was
rejected; the paragraph now carries the ratified rule and records why.

Every gate in PLAN_GMINOR_SCHEMA_MINOR.md section 5 is discharged. The
implementation contract may now be drafted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QjsEnYhm1gPpf6ii2iFxFV
This commit is contained in:
Levi Neuwirth 2026-07-28 18:39:28 -04:00
parent c90d662a0c
commit 2c7191482a
2 changed files with 107 additions and 25 deletions

View File

@ -254,11 +254,29 @@ record, and G2a takes that to **3233** knowingly. Filed as **P13-S14**. Ruled
one retroactive sweep over 2433 after G2a, rather than blocking G2a on a debt
already eight kinds deep or paying for two partial sweeps.
What the rung owes: a minor-assignment policy (which minor each past append
belongs to — a retroactive judgement, not a derivation), a per-kind minor, block
minor = max over payloads, a `for_major` replacement that accepts one, and both
staging paths. **Scope it only after checking whether the chunk header's minor
reaches a pinned corpus** — that decides whether it is a vector-moving change.
What the rung owes — **policy and epoch ladder both ratified 2026-07-28**; see
`spec/PLAN_GMINOR_SCHEMA_MINOR.md` §4 and the governing inventory
`spec/AUDIT_GMINOR_VOCABULARIES.md`:
* a **global additive epoch** (minors 29, one per additive event), **not** the
per-kind minor this paragraph originally proposed — that was rejected,
because it cannot represent multiple independent vocabularies inside one
block, and its obvious generalisation is worse: an old `OperationKind` 23
would numerically mask a newly appended `OperationPayload` 3;
* `introduced_minor` assigned **per variant, per vocabulary**, co-located with
the discriminant in an exhaustive macro/match with **no wildcard arm**, so a
new variant cannot compile without an epoch;
* an **envelope's** required minor = the max over **every discriminant it
actually emits** (outer payload variant, primitive kind, every nested
additive variant), and a **block's** = the max over its envelopes;
* **content-minimal derivation for the other payload roles** — including the
manifest, which takes a barrier tag's epoch when it names one;
* a `for_major` replacement that accepts a minor, and both staging paths.
**The scope is not "kinds 2433."** The audit found appends in three further
vocabularies (`OperationPayload` 3, `ReanchorReason` 6,
`PreconditionFailureReason` 1015) and a reachability path to
`OperationKindTag` through the *manifest* with no operation envelope involved.
Orthogonal to the *major* accept-set, which stays 2 through G2a and rises to 3
only at G2b.

View File

@ -3,10 +3,12 @@
**Filed as** P13-S14. **Ruled** 2026-07-28: its own rung, sequenced **after
G2a and before G2b** (`spec/PLAN_GENESIS_OPS.md` §4).
**Status:** scoped; policy ratified 2026-07-28 (§4); vocabulary audit landed
(§5.1, `spec/AUDIT_GMINOR_VOCABULARIES.md`, c63258d). **Not contracted** — the
**epoch ladder remains unratified**, and §4 records why it cannot be ratified
as written. That ratification is now the only gate.
**Status:** policy ratified 2026-07-28 (§4); vocabulary audit landed (§5.1,
`spec/AUDIT_GMINOR_VOCABULARIES.md`, c63258d); **epoch ladder ratified
2026-07-28** (§4, minors 29). **Every gate in §5 is now discharged — the
implementation contract may be drafted.** Two things it must carry that are
not yet designed: the manifest derivation seam across bundle-opaque barrier
bytes (§4), and the `binary_format.tex:2373` correction (§5.1).
> **Revision 2026-07-28.** The first draft of this plan got three things wrong
> and recommended a policy that cannot work. Corrections are marked inline
@ -153,15 +155,40 @@ without being assigned an epoch. That assignment is an unavoidable schema
decision, not a fallible parallel list — the same reasoning that made
`operation_kind_tag_vocabulary!` safe.
**Tentative epoch mapping** — Phase 3 → 2, repeats → 3, Push 4a → 4, G1 → 5,
G2a → 6. **Still not ratified, and now known to be incomplete.** The audit
(§5.1) placed three families this mapping never considered: `OperationPayload`
3 (Push 3) and `ReanchorReason` 6 (Pass-12 G-pass) have no rung at all, and
`PreconditionFailureReason` 1015 spans four tranches of which M2c and the
G-pass are unplaced. Ratification owes at least two new epochs plus an M2c
decision, and must confirm the Phase-3 and Push-4a rungs cover their
`PreconditionFailureReason` contributions and not only their `OperationKind`
ones.
### The epoch mapping — RATIFIED 2026-07-28
**These are schema-minor epochs, not companion semver numbers.** The two
numbering spaces are unrelated and must not be cross-read.
| Minor | Additive event | Variants introduced |
|---|---|---|
| 2 | M2c | `PreconditionFailureReason::ContainerNotEmpty` = 10 |
| 3 | Push 3 | `OperationPayload::ResolveEquivocation` = 3 |
| 4 | Phase-3 first tranche | `OperationKind`/`OperationKindTag` 2427; `PreconditionFailureReason::TempoMapMalformed` = 11 |
| 5 | Pass-12 G-pass | `ReanchorReason::SameCanvasNearer` = 6; `PreconditionFailureReason` 1213 |
| 6 | Schema-major-2 repeat revision | `OperationKind`/`OperationKindTag` 2829 |
| 7 | Push 4a | `OperationKind`/`OperationKindTag` 30; `PreconditionFailureReason` 1415 |
| 8 | Genesis G1 | `OperationKind`/`OperationKindTag` 31 |
| 9 | Genesis G2a | `OperationKind`/`OperationKindTag` 3233 |
**The ladder is complete against the audit** — every post-baseline variant in
`AUDIT_GMINOR_VOCABULARIES.md` appears exactly once: all ten kind/tag pairs,
`OperationPayload` 3, `ReanchorReason` 6, and all six
`PreconditionFailureReason` appends.
**And it is monotonic in real time**, which is what makes a minor prefix-closed
(a reader declaring minor *n* supports every epoch ≤ *n*). Verified against the
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) →
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
correctly: the G-pass precedes the repeat revision.
**Existing major baselines are unchanged**: `V0` uses minor 1; `V1``V3` use
minor 0. **Baseline variants impose no additive override** — M2c's *operation
kinds* stay baseline (inside the golden-locked 0..=23) while M2c's
`PreconditionFailureReason` append requires epoch 2. Same tranche, two
vocabularies, two answers.
**Baseline boundaries are per vocabulary, even though the epoch space is
global.** The epoch answers *which revision introduced this variant*; the
@ -184,9 +211,43 @@ vocabulary**.
draft's "is the base exempt?", which was the wrong binary question: the base
is neither exempt nor automatically dragged, it is content-minimally
stamped like everything else.)*
* **`Manifest::SCHEMA` stays unchanged.** A changed child `ChunkRef` is changed
manifest *data*, not a new manifest-layout discriminant; its body, id, and
chunk hash move naturally without raising the manifest's own schema.
* ~~**`Manifest::SCHEMA` stays unchanged.**~~ **NARROWLY SUPERSEDED
2026-07-28 by the audit.** The original call was right about its own case and
wrong as an unconditional rule:
* **Still true** — a changed child `ChunkRef` is changed manifest *data*, not
a new manifest-layout discriminant. Its body, id, and chunk hash move
naturally, and **that alone never raises the manifest minor.**
* **Newly true** — **emitted barrier tags do.** The manifest reaches
`OperationKindTag` through `ExtensionDeclaration::edit_barriers`
`EditBarrier::prohibited_operation_kinds` (audit §5.1, Part 2). **A
manifest containing an edit barrier naming a tag in 2433 takes that tag's
epoch**; a manifest naming only baseline tags retains its baseline. This is
content-minimal stamping applied to the manifest like any other role — the
original call had simply not seen that the manifest emits an additive
vocabulary at all.
* **The manifest major remains 0.**
**The implementation contract must design the derivation seam across the
bundle-opaque barrier bytes**, and this is the hard part, not a detail.
`epiphany-bundle`'s entire dependency list is `epiphany-determinism` and
`zstd` — **not `epiphany-ops`, not `epiphany-layout-ir`, not
`epiphany-core`**. It holds `edit_barriers` as `Vec<u8>` by design
(`manifest.rs:283`: the barrier family "is owned by Agents C and E"), so the
layer that stamps the manifest is structurally incapable of reading the tags
that determine its minor. Three shapes are available — a new dependency edge,
a producer-supplied minor travelling beside the blob, or a
decode-and-inspect step at a higher layer that already depends on both —
and choosing among them is contract work.
**The genuinely hard case, which must not be discovered during
implementation:** barrier bytes are *preserved verbatim* across writes,
including for extensions the writer does not understand. A repack can
therefore carry a barrier blob it cannot decode, whose tags it cannot
enumerate, and whose epoch it cannot derive. The contract must rule on that
case explicitly — preserve the manifest's existing minor, refuse, or require
the minor to travel with the blob — because the "decode and inspect" shape
silently does not cover it.
* **No migration.** Existing bundles are accepted as-is; newly emitted or
repacked blocks are stamped correctly.
* **Scope is "all additive discriminants reachable in affected chunk
@ -195,11 +256,14 @@ vocabulary**.
## 5. What must complete before a contract
1. ~~**The vocabulary audit** (§3).~~ **DONE** — see §5.1.
2. Ratify the epoch mapping. **This is now the gating work**, and per §4 it
cannot be the tentative ladder as written.
3. Confirm no third staging path has appeared beside the two in §1.
2. ~~Ratify the epoch mapping.~~ **DONE** — §4, minors 29, complete against
the audit and monotonic in real time.
3. Confirm no third staging path has appeared beside the two in §1. *(Contract
work — cheap, but a check rather than an assumption.)*
4. Decide whether `decode_vectors.txt` moves — it is value-level, so it should
not, but that is a check rather than an assumption.
not, but that is a check rather than an assumption. *(Contract work.)*
Items 3 and 4 are checks the contract performs, not gates on drafting it.
### 5.1 The audit landed — and it is the governing inventory