P13-S17: restore G2b to the Binary Format revision history
The Revision History chapter ran G2a straight to G-minor to G3a, with no row
for genesis tranche G2b anywhere -- so the accept-set raise
OperationEnvelopeBlock 2 to 3, the first accept-set move since G2a explicitly
recorded staying at 2, reached the normative tables and never the history.
G2b's own contract required that row; 13c3d2f edited 99 lines of
binary_format.tex and added none of it.
The stack is unpublished, so the chronology is restored rather than patched:
G2b lands as its own row between G-minor and G3a, G3a renumbers up, and the
PDF is regenerated.
The new epiphany-testkit guard makes recurrence detectable. Bare name-presence
would not have: with the G2b row deleted, "G2b" still occurs inside the chapter
in G3a's prose, so a substring guard would have been born green. The guard
requires a principal marker -- the rung name preceded by the row's separator --
strictly ordered across the four standalone-row rungs G2a, G-minor, G2b, G3a,
with G2b's content anchored inside its own row segment so G3a's row cannot
satisfy it. G1 is deliberately unguarded: it has no standalone row, being
recorded retroactively inside G2a's. No document version number appears in the
test, in its comments, or in this message.
Executed against spec/CONTRACT_GENESIS_G3A_UNDO_REPAIR.md Packet B.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QjsEnYhm1gPpf6ii2iFxFV
This commit is contained in:
parent
ffe313cd73
commit
6170015a8c
|
|
@ -0,0 +1,217 @@
|
|||
//! A scoped guard on `spec/binary_format.tex`'s Revision History chapter
|
||||
//! (Packet B of `spec/CONTRACT_GENESIS_G3A_UNDO_REPAIR.md`, pins B5/B6),
|
||||
//! filed against P13-S17: the chapter once ran genesis tranche G2a straight
|
||||
//! to G-minor to G3a, omitting G2b entirely — including the accept-set
|
||||
//! raise `OperationEnvelopeBlock` 2 -> 3 that G2b performed, which reached
|
||||
//! the normative tables but never the history.
|
||||
//!
|
||||
//! Two constraints from pin B6 pull against each other and both must hold:
|
||||
//!
|
||||
//! * Bare name-presence is not enough. `"G2b"` already occurs inside the
|
||||
//! chapter in prose — the G3a row observes that the accept-set "stays at
|
||||
//! 3 where genesis tranche G2b left it" — so a guard that only checked
|
||||
//! for the substring `"G2b"` would stay green even with the G2b row
|
||||
//! deleted. The guard below requires a *principal marker*: the rung name
|
||||
//! immediately preceded by the row's `---` separator (e.g.
|
||||
//! `--- Genesis tranche G2b`), which a prose mention where the separator
|
||||
//! *follows* the name (as in "genesis tranche G1 --- landed at",
|
||||
//! `binary_format.tex:3603`) cannot satisfy.
|
||||
//! * No document version number appears anywhere in this file — not in the
|
||||
//! assertions and not in this comment, which is why none is quoted here
|
||||
//! even as an example. Encoding one would pin a number a future chronology
|
||||
//! correction would have to move, reintroducing the stale hand-maintained
|
||||
//! parallel list this project keeps rediscovering. Assert rung identity and
|
||||
//! ordering; never the number attached to a rung.
|
||||
//!
|
||||
//! **G1 is deliberately unguarded.** `binary_format.tex:3603` states
|
||||
//! outright that genesis tranche G1 has no standalone Revision History row
|
||||
//! — it is recorded retroactively *inside* the G2a row ("genesis tranche G1
|
||||
//! --- landed at `3b09595` with no matching entry here"). Demanding a
|
||||
//! principal marker for G1 would make this guard born red against a
|
||||
//! document that pin B2 leaves correct, so only G2a, G-minor, G2b, and G3a
|
||||
//! get principal-marker assertions here. Do not "fix" this by adding a
|
||||
//! fifth marker; that rediscovers the contradiction pin B6 already resolved.
|
||||
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
/// The rung name immediately preceded by the row's `---` separator, in the
|
||||
/// exact spelling each row uses (G-minor is never prefixed "Genesis
|
||||
/// tranche" in the document; the other three are).
|
||||
const PRINCIPAL_MARKERS: [(&str, &str); 4] = [
|
||||
("G2a", "--- Genesis tranche G2a"),
|
||||
("G-minor", "--- G-minor"),
|
||||
("G2b", "--- Genesis tranche G2b"),
|
||||
("G3a", "--- Genesis tranche G3a"),
|
||||
];
|
||||
|
||||
fn binary_format_source() -> String {
|
||||
let path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../spec/binary_format.tex");
|
||||
fs::read_to_string(&path).unwrap_or_else(|error| {
|
||||
panic!("failed to read {}: {error}", path.display());
|
||||
})
|
||||
}
|
||||
|
||||
/// Collapse whitespace runs to a single space so a future rewrap of a row's
|
||||
/// LaTeX source lines cannot silently break a substring search that this
|
||||
/// guard depends on. Byte offsets after this pass are relative to the
|
||||
/// normalized string, which is all the ordering assertion needs — nothing
|
||||
/// here reports a source line number.
|
||||
fn normalize_whitespace(text: &str) -> String {
|
||||
let mut out = String::with_capacity(text.len());
|
||||
let mut last_was_space = true;
|
||||
for ch in text.chars() {
|
||||
if ch.is_whitespace() {
|
||||
if !last_was_space {
|
||||
out.push(' ');
|
||||
last_was_space = true;
|
||||
}
|
||||
} else {
|
||||
out.push(ch);
|
||||
last_was_space = false;
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
/// Every non-overlapping byte offset at which `needle` occurs in `haystack`.
|
||||
fn find_all(haystack: &str, needle: &str) -> Vec<usize> {
|
||||
let mut offsets = Vec::new();
|
||||
let mut cursor = 0;
|
||||
while let Some(relative) = haystack[cursor..].find(needle) {
|
||||
let offset = cursor + relative;
|
||||
offsets.push(offset);
|
||||
cursor = offset + needle.len();
|
||||
}
|
||||
offsets
|
||||
}
|
||||
|
||||
/// Slice the normalized document down to the Revision History chapter: from
|
||||
/// its own `\chapter{Revision History}` heading to the next `\chapter{`
|
||||
/// (there is none after it today, so this also tolerates a future chapter
|
||||
/// being appended afterward) or the end of the document.
|
||||
fn revision_history_slice(normalized: &str) -> &str {
|
||||
const CHAPTER: &str = r"\chapter{Revision History}";
|
||||
const NEXT_CHAPTER: &str = r"\chapter{";
|
||||
|
||||
let start = normalized
|
||||
.find(CHAPTER)
|
||||
.expect("binary_format.tex has no \\chapter{Revision History}");
|
||||
let after = start + CHAPTER.len();
|
||||
let end = normalized[after..]
|
||||
.find(NEXT_CHAPTER)
|
||||
.map(|relative| after + relative)
|
||||
.unwrap_or(normalized.len());
|
||||
&normalized[start..end]
|
||||
}
|
||||
|
||||
/// Each rung's principal marker exactly once in the slice. A prose-only
|
||||
/// mention (bare name, no preceding `---`) does not count, and neither
|
||||
/// does a duplicated row.
|
||||
#[test]
|
||||
fn revision_history_has_exactly_one_principal_marker_per_rung() {
|
||||
let source = binary_format_source();
|
||||
let normalized = normalize_whitespace(&source);
|
||||
let slice = revision_history_slice(&normalized);
|
||||
|
||||
for (rung, marker) in PRINCIPAL_MARKERS {
|
||||
let offsets = find_all(slice, marker);
|
||||
assert_eq!(
|
||||
offsets.len(),
|
||||
1,
|
||||
"expected exactly one principal marker {marker:?} for rung {rung} in the \
|
||||
Revision History chapter, found {} (offsets {offsets:?})",
|
||||
offsets.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// The four marked rungs appear in ladder order: G1 -> G2a -> G-minor ->
|
||||
/// G2b -> G3a. G1 has no marker of its own (see the module comment), so
|
||||
/// this checks the remaining four.
|
||||
#[test]
|
||||
fn revision_history_rungs_are_strictly_ordered() {
|
||||
let source = binary_format_source();
|
||||
let normalized = normalize_whitespace(&source);
|
||||
let slice = revision_history_slice(&normalized);
|
||||
|
||||
let offsets: Vec<(&str, usize)> = PRINCIPAL_MARKERS
|
||||
.iter()
|
||||
.map(|(rung, marker)| {
|
||||
let found = find_all(slice, marker);
|
||||
assert_eq!(
|
||||
found.len(),
|
||||
1,
|
||||
"expected exactly one principal marker {marker:?} for rung {rung}, found \
|
||||
{found:?}"
|
||||
);
|
||||
(*rung, found[0])
|
||||
})
|
||||
.collect();
|
||||
|
||||
for window in offsets.windows(2) {
|
||||
let (earlier_rung, earlier_offset) = window[0];
|
||||
let (later_rung, later_offset) = window[1];
|
||||
assert!(
|
||||
earlier_offset < later_offset,
|
||||
"expected {earlier_rung} (offset {earlier_offset}) to precede {later_rung} \
|
||||
(offset {later_offset}) in the Revision History chapter; ladder order is \
|
||||
G2a < G-minor < G2b < G3a"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// The G2b row states what G2b actually did (pin B3), and the search is
|
||||
/// bounded to the G2b row's own segment — from its principal marker to the
|
||||
/// next principal marker (or the slice end) — so that G3a's row, which also
|
||||
/// names `OperationEnvelopeBlock` 3 and mentions G2b in prose, cannot
|
||||
/// satisfy this after the G2b row itself is deleted. Unbounded searching is
|
||||
/// exactly the hole P13-S17 was filed over.
|
||||
#[test]
|
||||
fn revision_history_g2b_row_states_what_g2b_did() {
|
||||
let source = binary_format_source();
|
||||
let normalized = normalize_whitespace(&source);
|
||||
let slice = revision_history_slice(&normalized);
|
||||
|
||||
const G2B_MARKER: &str = "--- Genesis tranche G2b";
|
||||
let g2b_offsets = find_all(slice, G2B_MARKER);
|
||||
assert_eq!(
|
||||
g2b_offsets.len(),
|
||||
1,
|
||||
"expected exactly one G2b principal marker, found {g2b_offsets:?}"
|
||||
);
|
||||
let g2b_start = g2b_offsets[0];
|
||||
let after_g2b = g2b_start + G2B_MARKER.len();
|
||||
|
||||
let next_marker_offset = PRINCIPAL_MARKERS
|
||||
.iter()
|
||||
.filter_map(|(_, marker)| {
|
||||
find_all(&slice[after_g2b..], marker)
|
||||
.first()
|
||||
.map(|relative| after_g2b + relative)
|
||||
})
|
||||
.min()
|
||||
.unwrap_or(slice.len());
|
||||
|
||||
let row_segment = &slice[g2b_start..next_marker_offset];
|
||||
|
||||
assert!(
|
||||
row_segment.contains("SetTuningContext"),
|
||||
"G2b row segment does not name SetTuningContext: {row_segment:?}"
|
||||
);
|
||||
assert!(
|
||||
row_segment.contains(r"\tablenums{34}"),
|
||||
"G2b row segment does not carry discriminant 34: {row_segment:?}"
|
||||
);
|
||||
assert!(
|
||||
row_segment.contains("TuningContextSettings"),
|
||||
"G2b row segment does not name the TuningContextSettings payload subset: \
|
||||
{row_segment:?}"
|
||||
);
|
||||
assert!(
|
||||
row_segment.contains("OperationEnvelopeBlock")
|
||||
&& row_segment.contains(r"\tablenums{2}~$\rightarrow$~\tablenums{3}"),
|
||||
"G2b row segment does not record the OperationEnvelopeBlock accept-set raise \
|
||||
2 -> 3: {row_segment:?}"
|
||||
);
|
||||
}
|
||||
|
|
@ -94,3 +94,4 @@ visible — a value with a wire form and no canonical carrier to reach it.)
|
|||
| P13-S14 | **The chunk schema *minor* is a normative MUST that no writer has ever honoured, so every appended operation discriminant is unattributable to version skew.** `binary_format.tex:2330` requires a writer to raise the chunk schema minor when it emits any discriminant appended after the minor it otherwise declares, with a stated rationale: so that a decode failure on an unknown appended discriminant is attributable to a version skew rather than to corruption. `SchemaVersion::for_major` (`bundle/src/ids.rs:204`) maps a major to a fixed constant — `V0` is `{0, 1}`, not `{0, 0}` (`ids.rs:173`), and `V1`/`V2`/`V3` carry minor 0 — and, decisively, **takes only a major**, so no per-kind additive minor can reach it — and **both** writer-side staging paths derive nothing but the major (`testkit/src/bundle_harness.rs:25`, `textproj/src/serialize.rs:183`, each mapping `max(OperationEnvelope::schema_major)` through `for_major`). So every kind appended after the initial vocabulary has no additive-version record: **24–27** (Phase-3 first tranche), **28–29** (the schema-major-2 repeat revision), **30** (Push 4a `TransposeInterval`), and **31** (genesis G1 `CreateInstrument`). The requirement's own failure mode is exactly what the gap produces: a reader meeting kind 31 from a newer writer cannot distinguish "my vocabulary is stale" from "these bytes are damaged" | this file (found 2026-07-28 during G2a contract review; verified against the working tree — `for_major`'s signature admits no minor, and neither staging path computes one) | **RESOLVED at `ff9bd0f`** (the G-minor rung, 2026-07-28). Epoch ladder ratified as minors 2–9, one per additive event, complete against `spec/AUDIT_GMINOR_VOCABULARIES.md` and monotonic in the introducing commits' order. `introduced_minor()` landed on the five vocabularies with post-baseline variants, exhaustive and wildcard-free; envelope minor = max over emitted, block = max over envelopes, major and minor derived independently; baselines not normalised. **Two things the filing did not anticipate**, both from the audit that gated the rung: the scope was never just `OperationKind` (`OperationPayload` 3, `ReanchorReason` 6 and `PreconditionFailureReason` 10–15 also append), and the **manifest** reaches `OperationKindTag` through `edit_barriers` with no operation envelope in it — so the "no companion bump" note below is **superseded**: `TextDocument` carries the manifest `SchemaVersion` it cannot derive, and the companion moved 0.9.0 → 0.10.0. Op-block stamping did remain projection-invisible, exactly as scoped. Gate `[7f]` guards the manifest aggregate with an exact-equality oracle. *Original filing follows.* Ruled 2026-07-28: policy ratified 2026-07-28 as a **global additive epoch with content-minimal stamping** (`spec/PLAN_GMINOR_SCHEMA_MINOR.md` §4); the fix is its own rung, sequenced **after G2a and before G2b** — G2b appends kind 34, so running it first would either grow this sweep mid-flight or ship 34 with the very defect the rung retires. G2a appends kinds 32/33 and takes the violation from eight kinds to ten, knowingly — the debt is already eight deep, the +2 is immaterial against it, and one retroactive sweep over 24–33 is strictly less work than 24–31 now and 32–33 later. **What the rung owes:** a minor-assignment policy (which minor each past append belongs to — this is a retroactive judgement, not a derivation), a per-kind `schema_minor()` or equivalent, block minor = max over payloads, a `for_major` replacement that accepts one, and both staging paths. **Scoped 2026-07-28:** the minor IS in the chunk content-address preimage (`chunk_content_hash`, `chunk.rs:177`), so raising it moves every affected `ChunkId` and the manifest body naming it — real address churn, though **not** a `req:format:manifest-id` problem, since that promise is conditional on the same manifest body. It does **not** reach the text projection: op-block schemas are discarded during projection (`textproj/src/project.rs:424`), so no companion bump. And the problem is **not** per-`OperationKind`: an envelope also emits the outer `OperationPayload` discriminant (`ResolveEquivocation` = 3 carries no kind at all), so the gating work is an audit of every append-only vocabulary reachable from an affected payload. Note this is orthogonal to the *major* accept-set: `OperationEnvelopeBlock` stays at 2 through G2a and rises to 3 only at G2b |
|
||||
| P13-S15 | **The `OperationKind` wire golden lock stops at discriminant 29, so kinds 30–33 have no byte-level lock at all.** `operation_kind_wire_discriminants_are_golden` (`crates/epiphany-ops/src/payload.rs:1959`) declares `let table: [(OperationKind, u8); 30]`, covering 0..=29 and asserting for each that `kind.discriminant()` has not moved *and* that the discriminant byte truly leads the canonical encoding. **`TransposeInterval` (30, Push 4a), `CreateInstrument` (31, G1), `SetCanvasLayoutDefaults` (32) and `SetSpellingPrecedence` (33, G2a) are absent from that table**, so their wire discriminants are unlocked: a hand edit to `OperationKind::discriminant()`'s match — itself the site Push 4a got wrong — would move any of the four silently, and the encoding-leads-with-the-byte assertion never runs for them. The macro-guarded `OperationKindTag` half is unaffected (`operation_kind_tag_vocabulary!` is compile-enforced); this is the hand-written half. **The shape is the failure this project keeps rediscovering:** a hand-maintained parallel table that quietly stopped being extended, exactly like the four literal sites found at Push 4a and the six found during G2a — and the golden lock is the one guard specifically meant to catch that class, so its own staleness is the worst place for it | this file (found 2026-07-28 by the G-minor implementation while building s1's coverage; independently verified against the working tree at `ff9bd0f` — the array length literal is `30` and no arm for 30–33 appears in the table) | **open.** Deliberately no code change yet. **Not a live incorrectness:** every one of the four discriminants is currently correct, and `binary_format.tex:1443-1457`/`:1526-1527` carry them normatively — the gap is the *absence of a guard*, not a wrong byte. Fixing it is mechanical (extend the table to `; 34` and add the four rows), and the mutation that proves the fix is to change one of the four discriminants and watch the extended lock fail where it previously stayed green. **Worth doing as its own rung rather than as a rider**, because a golden-lock extension should land with its mutation evidence and nothing else in the diff. Note the sibling `phase3_tag_discriminants_are_golden` should be checked for the same drift at the same time |
|
||||
| P13-S16 | **`StaffGroup.members` and `Staff.group` may disagree in both directions, and nothing detects it.** The two fields encode the same relation twice. `Staff.group` (`core_spec.tex:5578`, `graph.rs:819`) names the group a staff belongs to; `StaffGroup.members` (`core_spec.tex:4231`, `graph.rs:1614`) lists the staves in a group. **The specification declares both and states neither an authority nor an agreement requirement.** Graph invariant 10 checks that each side *resolves* — a staff's group is declared (`invariants.rs:1126`), a group's members are declared (`:1135`) — and never that the two agree, so **both stale forms pass every check in the tree**: a *missing* member (`s.group == Some(g)` while `g.members` omits `s`) and a *spurious* member (`g.members` contains `s` while `s.group` is `None` or names a different group). Genesis G3a ruled `Staff.group` the sole authority and `StaffGroup.members` a non-authoritative denormalized projection (`spec/CONTRACT_GENESIS_G3A_ENTITIES.md` §1.1, disposition B, ratified 2026-07-29) — a normative semantic ruling that makes the disagreement *defined* rather than merely undetected, but does not make it *impossible*: G3a stores the projection without maintaining it | `spec/CONTRACT_GENESIS_G3A_ENTITIES.md` §1.1 (found 2026-07-29 during G3a contract review; the authorship cycle is what surfaced it — with mints only, no authoring order produces an agreeing pair, since `CreateStaff` requires its group live at `reduce.rs:4117` and `CreateStaffGroup` requires its members live) | **open.** Deliberately no code change in G3a. The fix is disposition **A**: maintain the projection under reduction — `create_staff` with `group: Some(g)` appends to `g.members` — plus a candidate **graph invariant 21** enforcing agreement in both directions, and a decision on whether a re-carried `CreateStaffGroup` compares against its *carried* `members` (empty) or the current derived state. **Consumers must read `Staff.group`, never `StaffGroup.members`, for membership** until that lands. Sequence it after G3b so an invariant append is not competing with G3b's invariant 20 |
|
||||
| P13-S17 | **Binary Format revision history omitted genesis tranche G2b entirely, including the accept-set raise it performed.** `spec/binary_format.tex`'s Revision History chapter ran G2a 0.12.0 straight to G-minor 0.13.0 to G3a 0.14.0, with no row anywhere recording G2b (`spec/CONTRACT_GENESIS_G2B_TUNING.md`, kind/tag 34, `SetTuningContext`) — even though `OperationEnvelopeBlock`'s accept-set raise 2→3, the first accept-set move since genesis tranche G2a explicitly recorded staying at 2, reached the normative tables (the per-chunk-role accept-set prose at `binary_format.tex:2353`–`:2363`, which names the `OperationEnvelopeBlock` role's maximum as 3 "as of genesis tranche G2b", and the `OperationKind` minor-additive bullet at `:2395`–`:2418`, which records "genesis tranche G2b took 34 (`SetTuningContext`)") and never the history. G2b's own contract touch table row 27 required "version, Revision History row" among the four-document ritual, and the rung was signed off without it — the gate did not catch a documentation MUST because nothing tests the revision history | `spec/CONTRACT_GENESIS_G3A_UNDO_REPAIR.md` §0 (found 2026-07-29 during the G3a undo-repair contract review, verified against the working tree: `binary_format.tex:3599`, `:3628`, `:3643` before this rung's edit) | **RESOLVED in this same commit.** The chronology is restored: G2b lands as its own 0.14.0 row between G-minor and G3a, and G3a renumbers to 0.15.0 (`spec/CONTRACT_GENESIS_G3A_UNDO_REPAIR.md` Packet B, pins B2–B3). A new scoped guard in `epiphany-testkit` makes the omission recurrence-detectable — a distinct principal marker per standalone-row rung (G2a, G-minor, G2b, G3a — G1 is deliberately unguarded, having no standalone row of its own), strictly ordered, with G2b's content anchored within its own row segment — so the entry is filed and closed by the same packet that finds it, unlike **P13-S15** and **P13-S16**, which stay open because their fixes are sequenced to later rungs |
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -240,7 +240,7 @@
|
|||
{\Large\scshape\color{epiphanyslate}Binary Format}\\[6pt]
|
||||
{\large\itshape\color{epiphanyslate}A companion to the Core Specification}\\[14pt]
|
||||
{\color{epiphanygold}\rule{3in}{0.8pt}}\\[24pt]
|
||||
{\normalsize\color{epiphanyink}Version 0.14.0 --- The genesis operation tranche completes the root-level entity mints (G3a)}\\[4pt]
|
||||
{\normalsize\color{epiphanyink}Version 0.15.0 --- The genesis operation tranche completes the root-level entity mints (G3a)}\\[4pt]
|
||||
{\small\color{epiphanyslate}Normative for the byte layouts it defines}
|
||||
\vfill
|
||||
\end{titlepage}
|
||||
|
|
@ -3640,7 +3640,29 @@ only}: implementations need not agree on an error taxonomy.
|
|||
current. No discriminant, wire layout, or accept-set changes: this is a
|
||||
correction to prose and a new writer-side derivation, not a new appended
|
||||
variant. \\
|
||||
\today & Operation wire forms & 0.14.0 --- Genesis tranche G3a
|
||||
\today & Operation wire forms & 0.14.0 --- Genesis tranche G2b
|
||||
(\texttt{spec/CONTRACT\_GENESIS\_G2B\_TUNING.md}): appends
|
||||
\texttt{OperationKind} wire discriminant \tablenums{34}
|
||||
(\texttt{SetTuningContext}) with its payload layout, and the matching
|
||||
\texttt{OperationKindTag} discriminant \tablenums{34} (name-verbatim,
|
||||
following the three most recent prior additions rather than the tag
|
||||
space's older Create$\rightarrow$Insert convention) --- a
|
||||
schema-\emph{minor} evolution (epoch~10,
|
||||
\texttt{spec/PLAN\_GMINOR\_SCHEMA\_MINOR.md} \S4) under this document's
|
||||
own append-only rules; no existing assignment changed. The payload
|
||||
carries \texttt{epiphany\_core::TuningContextSettings}, the
|
||||
\textbf{five-field authored subset} of \texttt{ScoreTuningContext} ---
|
||||
not the full graph type --- byte-identical to the existing
|
||||
schema-major-3 wire walk, so that \texttt{accidental\_extensions}
|
||||
(staged off the wire) cannot diverge between a live-authored session and
|
||||
the same document reloaded from bytes. \texttt{SetTuningContext} is the
|
||||
\textbf{sole genesis payload born at v3 unconditionally}
|
||||
(Section~\ref{sec:evolution:major3}), so \texttt{OperationEnvelopeBlock}'s
|
||||
accept-set raises \tablenums{2}~$\rightarrow$~\tablenums{3} --- the
|
||||
first accept-set move since genesis tranche G2a explicitly recorded
|
||||
staying at \tablenums{2}. Semantics: Operation Catalog
|
||||
\sectionsc{SetTuningContext}, 0.11.0. \\
|
||||
\today & Operation wire forms & 0.15.0 --- Genesis tranche G3a
|
||||
(\texttt{spec/CONTRACT\_GENESIS\_G3A\_ENTITIES.md}): appends
|
||||
\texttt{OperationKind} wire discriminants \tablenums{35}--\tablenums{38}
|
||||
(\texttt{CreateStaffGroup}, \texttt{CreatePartDefinition},
|
||||
|
|
|
|||
Loading…
Reference in New Issue