@@ -1306,3 +1306,168 @@ references = [
13061306 "docs/PACKAGING.adoc (INT-04; the JS-package half)",
13071307 "docs/specs/SETTLED-DECISIONS.adoc (ADR-019 section)",
13081308]
1309+
1310+ [[adr]]
1311+ id = "ADR-020"
1312+ status = "accepted"
1313+ date = "2026-05-23"
1314+ ratified = "2026-05-24"
1315+ title = "Ownership-section schema versioning (0xAF sentinel + u8 version)"
1316+ context = """
1317+ The `affinescript.ownership` Wasm custom section has been frozen at
1318+ v1 since typed-wasm Level 10 closure (2026-04-19) and is emitted in
1319+ identical form by AffineScript (`lib/codegen.ml`) and by ephapax
1320+ (`hyperpolymath/ephapax/src/ephapax-wasm`). The Rust verifier in
1321+ `hyperpolymath/typed-wasm` consumes it as the cross-compat target.
1322+
1323+ V1 has *no version field*. Today this is fine because both
1324+ producers are at v1 and the verifier expects v1 unconditionally.
1325+ The first multi-producer ABI change — when L1–6 / L14–16 emission
1326+ lands — will need version discrimination. Adding the version field
1327+ *now*, while we are still at v1, is much cheaper than retrofitting
1328+ it under load.
1329+
1330+ This ADR is filed alongside the broader typed-wasm widening roadmap
1331+ in `docs/specs/TYPED-WASM-ROADMAP.adoc` §"Tranche B".
1332+ """
1333+ decision = """
1334+ Move from v1 (unversioned) to v2 (versioned, with sentinel):
1335+
1336+ v1 payload:
1337+ u32 entry_count
1338+ entry*
1339+
1340+ v2 payload:
1341+ u8 version_tag ; 0xAF — "AffineScript Format"
1342+ u8 version ; 0x02 for v2.0
1343+ u32 entry_count
1344+ entry* ; same entry shape as v1; no new entry fields in v2.0
1345+
1346+ The 0xAF sentinel is byte-distinct from any plausible v1 entry-count
1347+ low byte for a module with ≤ 0xAE entries — i.e. practically every
1348+ module in existence. v1 readers fail cleanly on a v2 section (bad
1349+ entry-count); v2 readers see the sentinel and dispatch.
1350+
1351+ Coordinated landing protocol:
1352+ 1. Land ADR-020 in `hyperpolymath/affinescript` (this repo).
1353+ 2. Mirror ADR in `hyperpolymath/typed-wasm` (Rust verifier
1354+ dispatches on sentinel; accepts both v1 and v2 during
1355+ migration).
1356+ 3. Mirror ADR in `hyperpolymath/ephapax` (second producer emits
1357+ v2).
1358+ 4. Verifier ships v2-parse FIRST. Producers stay on v1 emit.
1359+ 5. Once verifier is deployed (in both OCaml + Rust paths),
1360+ producers flip to v2 emit together.
1361+ 6. After a deprecation window, v1-parse path is removed from
1362+ verifier.
1363+
1364+ The v2.0 entry shape is identical to v1 — this ADR introduces no
1365+ new ownership kinds, no new per-entry fields. Future widening
1366+ (e.g. v2.1 adding a region-id field per entry) is a separate ADR.
1367+ """
1368+ consequences = """
1369+ - Forward-compatible: any future widening (L1–6 / L14–16 carriers,
1370+ per-entry annotations) can negotiate via the version byte without
1371+ another sentinel-or-no-sentinel war.
1372+ - v1 callers fail cleanly on v2 sections (bad entry-count parse) —
1373+ no silent corruption.
1374+ - Single coordinated landing across three repos; complexity is in
1375+ the coordination, not the bytes.
1376+ - This decision is PROPOSED. Land or supersede explicitly; do not
1377+ silently drift.
1378+ - Cross-references the typed-wasm roadmap in
1379+ `docs/specs/TYPED-WASM-ROADMAP.adoc` §"B1".
1380+ """
1381+ references = [
1382+ "docs/specs/TYPED-WASM-INTERFACE.adoc",
1383+ "docs/specs/TYPED-WASM-INTERFACE.a2ml",
1384+ "docs/specs/TYPED-WASM-ROADMAP.adoc",
1385+ "lib/codegen.ml (build_ownership_section, ~line 159)",
1386+ "lib/tw_verify.ml (parse_ownership_section)",
1387+ "hyperpolymath/typed-wasm (Rust verifier crate — coordination target)",
1388+ "hyperpolymath/ephapax (second producer — coordination target)",
1389+ ]
1390+
1391+ [[adr]]
1392+ id = "ADR-021"
1393+ status = "accepted"
1394+ date = "2026-05-23"
1395+ ratified = "2026-05-24"
1396+ title = "Multi-producer ABI coordination model for typed-wasm carriers"
1397+ context = """
1398+ typed-wasm is a separate, language-agnostic compilation target with
1399+ its own repository (`hyperpolymath/typed-wasm`) and its own
1400+ producers (today: AffineScript + ephapax; potentially more later).
1401+ The `affinescript.ownership` custom section is the first
1402+ multi-producer ABI we own.
1403+
1404+ Today coordination happens by `Refs #N` across repositories and
1405+ good intent. As the typed-wasm widening proposals land (ADR-020
1406+ schema versioning, then carriers for L1–6 and L14–16), this
1407+ informal model will break. The session-note record makes clear that
1408+ each ABI conversation has been one-off and ad-hoc; the failure mode
1409+ is two producers landing incompatible changes in parallel because
1410+ nobody owns "the protocol".
1411+
1412+ This ADR is filed alongside the typed-wasm widening roadmap in
1413+ `docs/specs/TYPED-WASM-ROADMAP.adoc` §"Tranche D" — D1 explicitly.
1414+ The reason to land *this* ADR before any concrete widening proposal
1415+ is that the coordination model is cheap now (no code), expensive
1416+ later (under conflicting pressure from multiple in-flight proposals).
1417+ """
1418+ decision = """
1419+ Adopt a formal four-axis multi-producer coordination model:
1420+
1421+ (1) Spec authority — which artefact is the source of record:
1422+ - Today: `lib/tw_verify.ml` (OCaml) is the spec of record.
1423+ - On C5.1 closure (INT-12 / CONV-05): authority flips to
1424+ `hyperpolymath/typed-wasm` Rust verifier crate.
1425+ - The flip is itself an ADR — does not happen silently.
1426+ - Until the flip, OCaml binds; on conflict, OCaml wins.
1427+
1428+ (2) Coordinated landing protocol:
1429+ - All ABI-touching ADRs live in all three repos (originated in
1430+ one, mirrored in the other two with `Mirrors hyperpolymath/X#N`
1431+ cross-references).
1432+ - Verifier always ships parse-support FIRST.
1433+ - Producers flip to emit support together, in a coordinated
1434+ window.
1435+ - Deprecation: a removed format MUST have a deprecation window
1436+ of at least the cycle between two coordinated landings.
1437+
1438+ (3) Test parity protocol:
1439+ - Every producer maintains a fixture corpus matching the
1440+ typed-wasm cross-compat suite (INT-12 / C5.1).
1441+ - Each ABI change requires a new fixture in the cross-compat
1442+ suite from each producer.
1443+ - Verifier accepts a producer's emit only if the cross-compat
1444+ corpus is up-to-date for that producer.
1445+
1446+ (4) Conflict resolution:
1447+ - In-flight ABI proposals from different producers MUST be
1448+ serialised — no parallel ABI ADRs.
1449+ - The serialisation queue is owned by `hyperpolymath/typed-wasm`
1450+ (today via issues; future a dedicated coordination ledger).
1451+ - A proposal blocked behind another in the queue is paused, not
1452+ refused.
1453+ """
1454+ consequences = """
1455+ - Single coordination ledger replaces ad-hoc Refs trails.
1456+ - ABI change cost goes up (more paperwork) but predictability goes
1457+ way up.
1458+ - Compatible with the existing Hypatia / gitbot rules (Hypatia
1459+ DOC-FORMAT / STACK-SIGNAL apply; ISSUE-CLOSURE applies to the
1460+ shared ADR mirrors).
1461+ - This decision is PROPOSED. Owner ratification required before any
1462+ ABI ADR (ADR-020 included) lands; ADR-020 is a "first test" of
1463+ this model and its own landing exercises the protocol.
1464+ - Cross-references the typed-wasm roadmap in
1465+ `docs/specs/TYPED-WASM-ROADMAP.adoc` §"D1".
1466+ """
1467+ references = [
1468+ "docs/specs/TYPED-WASM-INTERFACE.adoc",
1469+ "docs/specs/TYPED-WASM-ROADMAP.adoc",
1470+ ".claude/CLAUDE.md §Hypatia and gitbot-fleet standing rules",
1471+ "hyperpolymath/typed-wasm (coordination target)",
1472+ "hyperpolymath/ephapax (second producer — coordination target)",
1473+ ]
0 commit comments