docs(adr): ADR-7 — ABI & linking-strategy architecture (canonical mix-and-match vs symmetric/PIC fast lane) - #354
Merged
Merged
Conversation
LS-N verification gate✅ 59/59 approved LS entries verified
Approved Failed LS entries(none) Missing regression tests(none) Updated automatically by |
avrabe
added a commit
that referenced
this pull request
Jul 16, 2026
…erified stack Human decision (2026-07-16): status open → resolved. - Identity: balanced/dual — meld is BOTH the RFC-46 canonical reference AND the sealed-safety (symmetric+PIC) product; both first-class. - Ownership: own + formally verify the FULL lowering stack (canonical FACT + symmetric + PIC), no external lowering dependency — a safety tool must own a frozen verifiable trusted base (overrides the review's track-upstream default). - Reconciliation: own the IMPLEMENTATION; ABIs/conventions stay open standards (symmetric→BA, PIC→tool-conventions); path-H canonical fallback keeps mix-and-match, so this is not fragmentation. - Accepted risks named (scope/budget, parity treadmill, proof surface); the heterogeneous-composition theorem is now mandatory. - Next increments: extract address strategy; formalize call-lowering seam; RFC-46 Q1 multiply-instantiated; #353 Path-A PIC flatten. Refs #353, #354, RFC-46 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uestion) Frames how meld should support the shared-address-space fast lane (PIC #353 + symmetric ABI) WITHOUT sacrificing RFC-46 canonical mix-and-match. Recommends path-H: an ABI-agnostic verified core + pluggable per-boundary call-lowering (canonical-FACT default / symmetric-direct opt-in, canonical as universal fallback) + pluggable address strategy (multi / shared-rebase / static-base-PIC). Grounds the 'split not rewrite' verdict in current coupling (adapter already separable; reloc interleaved) and ties in the RFC-46 multiply-instantiated- modules gap. Status: open — for human decision. Refs #353, RFC-46 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…identity choice Adds the decision-independent consensus from a 10-persona strategic review as requirements on ADR-7 (status stays open): - give away the ABIs, keep the proofs/attestation (the moat is verification) - silent downgrade = hard error (per-boundary strategy declared/attested/observable) - symmetric ABI must be standardized (BA/wit-bindgen) before a safety product; gated experimental/non-portable until then - concrete shape = one binary, two attested profiles (open/ecosystem + sealed-safety) - new heterogeneous-composition theorem as the key proof obligation - frames the one open decision: meld's identity + the load-bearing track-upstream-FACT-vs-own-the-fork sub-choice Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…erified stack Human decision (2026-07-16): status open → resolved. - Identity: balanced/dual — meld is BOTH the RFC-46 canonical reference AND the sealed-safety (symmetric+PIC) product; both first-class. - Ownership: own + formally verify the FULL lowering stack (canonical FACT + symmetric + PIC), no external lowering dependency — a safety tool must own a frozen verifiable trusted base (overrides the review's track-upstream default). - Reconciliation: own the IMPLEMENTATION; ABIs/conventions stay open standards (symmetric→BA, PIC→tool-conventions); path-H canonical fallback keeps mix-and-match, so this is not fragmentation. - Accepted risks named (scope/budget, parity treadmill, proof surface); the heterogeneous-composition theorem is now mandatory. - Next increments: extract address strategy; formalize call-lowering seam; RFC-46 Q1 multiply-instantiated; #353 Path-A PIC flatten. Refs #353, #354, RFC-46 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
avrabe
force-pushed
the
docs/adr7-abi-linking-strategy
branch
from
July 16, 2026 21:46
1209467 to
adcca29
Compare
avrabe
added a commit
that referenced
this pull request
Jul 17, 2026
…th-H inc 1) (#359) * refactor(adr7): extract the address strategy seam from the merger (path-H inc 1) Executes ADR-7 path-H, increment 1: extract the per-module address/memory strategy resolution out of Merger::merge into a dedicated address_strategy module, behavior-preservingly. This is the pluggable seam the decided architecture hangs off — the shared-rebase strategy lives here now; multi-memory resolves to an empty plan; static-base PIC (#353) and the per-boundary call-lowering seam come in later increments. - address_strategy.rs: AddressPlan + resolve_address_plan — the full decision + validation (path-F MissingRelocMetadata, memory64 reject, #351 MisalignedReloc backstop). has_direct_memory_access passed as a closure to keep the original lazy short-circuit exactly. - merger.rs: the ~50-line reloc-consumption block replaced with one call. - 4 unit tests (rebasing-off/base-0/no-reloc-direct-fail/bulk-only + laziness). No behavior change: canonical gating fixtures (test_326_reloc_const_rebasing, test_address_rebasing) + drop_realloc + full meld-core suite all green; fmt/clippy clean. Refs #354 (ADR-7) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(adr7): clarify address-plan scope — empty plan is not fusion disabled A colleague reading #359 read "multi-memory resolves to an empty plan" as "multi-memory + FACT fusion is stopped". It is not: an AddressPlan carries only which reloc sites to shift for a shared-memory base. An empty plan means no address rebasing is needed (multi-memory keeps each component's memory at its own base) — it does not touch cross-component adapter (FACT) generation, which runs identically. Spell that out in the module doc so the seam can't be misread. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 17, 2026
avrabe
added a commit
that referenced
this pull request
Jul 21, 2026
…C-46 Q1, inc 3) Completes RFC-46 Q1 "duplicate": meld now SUPPORTS a component that instantiates the same core module more than once, instead of rejecting it. The `core_instance_topology` normalization pass is wired into `Fuser::fuse_with_stats` before resolve/merge. It gives each instantiation a distinct module identity, so the merger's per-module machinery (proven correct for N distinct modules) allocates each instance independent functions / memory / tables / globals — no shared mutable state (STPA H-1), no (component, module)- keyed map overwrites. After the pass no module is instantiated more than once, so the DuplicateModuleInstantiation reject becomes an unreachable backstop (retained; its ls_m_5 unit test still passes). The pass is a no-op for single-instantiation components and idempotent for a repeated fuse. Differential EXECUTION oracle (the gate for flipping this safety behavior): tests/multiply_instantiated_runtime.rs — a component instantiating one core module (a mutable counter) TWICE is fused (MultiMemory, CoreModule), VALIDATED, and executed on wasmtime. The two instances' counters advance independently (inc→1,2; inc$0→1; inc→3; inc$0→2); a shared-state H-1 corruption would fail the load-bearing `inc$0` first-call == 1 assertion. - lib.rs: wire the normalization pass (with an info log of how many modules were duplicated). - multiply_instantiated_runtime.rs: the differential execution oracle. - safety-requirements.yaml: SR-55 draft→implemented (mechanism + wiring + oracle green locally; verified pending CI/merge); SR-31 noted as superseded for handleable cases, reject retained as backstop. Full meld-core suite green (0 failures, no regression); fmt + clippy clean; rivet validate PASS. Refs #354 (ADR-7 path-H inc 3), RFC-46 Q1 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
avrabe
added a commit
that referenced
this pull request
Jul 21, 2026
…inc 3) (#362) * feat(adr7): core-instance topology normalization — RFC-46 Q1 mechanism (path-H inc 3, slice 1) RFC-46 Q1 (multiply-instantiated modules) "duplicate" resolution: meld currently REJECTS a component that instantiates the same core module more than once (SR-31, DuplicateModuleInstantiation). This lands the MECHANISM to support it instead — as a bounded, structurally-verified first slice. `core_instance_topology::expand_multiply_instantiated_modules` deep-clones a module per 2nd..Nth instantiation and rewrites that instantiation to the clone, so after the pass no module is instantiated more than once. Each instance then gets its OWN functions/memory/tables/globals via the merger's per-module machinery (already proven correct for N distinct modules) — no shared mutable state (STPA H-1), and every (component, module)-keyed merge map gets a distinct key per instance (no silent overwrite). The whole class of duplication-corruption bugs is dissolved by reusing the existing proof. Deliberately NOT wired: activating this (dropping the reject) flips a verified safety requirement and must be gated on a differential EXECUTION oracle proving two instances keep independent mutable state end-to-end (identical-content module duplication can stress export-name / segment handling a structural test can't see). Until that oracle + a Tier-5 Mythos pass on the wiring land, meld still rejects multiply-instantiated modules; this module is exercised only by its own 6 structural unit tests. - core_instance_topology.rs: the pass + 6 unit tests (single/distinct unchanged; double/triple/interleaved → N distinct module identities; FromExports ignored). - lib.rs: register the module. - safety-requirements.yaml: SR-55 (draft) — the duplicate-support capability, refines SR-31, mitigates LS-M-5; verification-description records the execution-oracle gate. rivet validate PASS. Full meld-core lib suite green (487, unaffected — pass is unwired); fmt + clippy clean. Refs #354 (ADR-7 path-H inc 3), RFC-46 Q1 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(adr7): wire multiply-instantiated support + execution oracle (RFC-46 Q1, inc 3) Completes RFC-46 Q1 "duplicate": meld now SUPPORTS a component that instantiates the same core module more than once, instead of rejecting it. The `core_instance_topology` normalization pass is wired into `Fuser::fuse_with_stats` before resolve/merge. It gives each instantiation a distinct module identity, so the merger's per-module machinery (proven correct for N distinct modules) allocates each instance independent functions / memory / tables / globals — no shared mutable state (STPA H-1), no (component, module)- keyed map overwrites. After the pass no module is instantiated more than once, so the DuplicateModuleInstantiation reject becomes an unreachable backstop (retained; its ls_m_5 unit test still passes). The pass is a no-op for single-instantiation components and idempotent for a repeated fuse. Differential EXECUTION oracle (the gate for flipping this safety behavior): tests/multiply_instantiated_runtime.rs — a component instantiating one core module (a mutable counter) TWICE is fused (MultiMemory, CoreModule), VALIDATED, and executed on wasmtime. The two instances' counters advance independently (inc→1,2; inc$0→1; inc→3; inc$0→2); a shared-state H-1 corruption would fail the load-bearing `inc$0` first-call == 1 assertion. - lib.rs: wire the normalization pass (with an info log of how many modules were duplicated). - multiply_instantiated_runtime.rs: the differential execution oracle. - safety-requirements.yaml: SR-55 draft→implemented (mechanism + wiring + oracle green locally; verified pending CI/merge); SR-31 noted as superseded for handleable cases, reject retained as backstop. Full meld-core suite green (0 failures, no regression); fmt + clippy clean; rivet validate PASS. Refs #354 (ADR-7 path-H inc 3), RFC-46 Q1 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
avrabe
added a commit
that referenced
this pull request
Jul 21, 2026
… verified (#363) Strengthens the RFC-46 Q1 (multiply-instantiated modules) verification: the merged inc-3 oracle proved only GLOBAL-state independence. This adds the other critical mutable-state axis — independent LINEAR MEMORY and DATA SEGMENTS. `two_instances_keep_independent_memory_and_data_segments`: a core module keeps its counter in linear memory, seeded to 5 by a DATA segment, instantiated twice. Fused + validated + executed on wasmtime: bump→6,7; bump$0→6 (its own data-seeded 5, independent); bump→8; bump$0→7. A shared memory / mis-based segment (the segment-duplication risk an index-space audit flagged) would make bump$0's first call observe the other instance's writes. With globals + memory + data-segments all execution-proven, the H-1 hazard is comprehensively covered → SR-55 status implemented→verified. One axis remains un-execution-tested and is noted in SR-55: per-instance IMPORT wiring (distinct args per instance); the fixtures are import-free. Not a mutable-state hazard. Test + requirement only (no src change). Both oracles green; fmt clean; rivet validate PASS. Refs #362, #354 (ADR-7 path-H inc 3), RFC-46 Q1 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
avrabe
added a commit
that referenced
this pull request
Jul 23, 2026
…s + static-PIC + same-memory transcoding (#369) Ships the full ADR-7 path-H arc (address-strategy seam #359, call-lowering seam #360, multiply-instantiated modules #362/#363, static-PIC fold #365, ADR record #354) plus the extended-const fold completion (#368), the #364 safety fix (#366), and same-memory string transcoding (#367). New capabilities: multiply-instantiated module support (RFC-46 Q1, MultiMemory, SR-55), static-PIC data/element offset folding (#353), same-memory string transcoding (#361). Safety: multiply-instantiated gated to the execution- verified MultiMemory case (#364); the sync same-memory cross-encoding miscompile closed (#360/#361). Falsification statements in CHANGELOG. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
ADR-7 (open design question): how should meld support the shared-address-space
fast lane (PIC #353 + Christof's symmetric ABI) without sacrificing RFC-46
canonical mix-and-match? Drafted per the "be careful / stay true / think if we
need a rework to split" steer.
Not a code change — a decision artifact for review (@cpetig too). Status open;
humans promote.
The core argument
"staying true" and must not be traded away.
ABI turns cross-component calls into ordinary linking of mangled symbols
(zero-copy, no dynamic alloc — the ASIL-D property), retiring most of the
~16.4k-line FACT/adapter subsystem for that input class.
does not mix with stock canonical components.
strategy with canonical as the universal fallback — direct wiring only
where both sides opt in, FACT adapter everywhere else. Composability is never
lost; zero-copy is only gained.
has 0 merger refs (separable); reloc/rebasing has ~26 (extract it); the
Rocq-proven core is untouched.
Error::DuplicateModuleInstantiationrejects them) is the same core-instancetopology work Evaluate PIC / shared-everything dynamic linking as an input ABI (dissolves the #351 reloc-drift class) — revisit ADR-6 #353 needs; path-H does it once and shares it.
Paths
G bolt-on (rejected) · H clean strategy-split (recommended) · I separate tool
(rejected) · J do-nothing/canonical-only (baseline).
Does not block
#352 (canonical
--emit-relocsbackstop) ships regardless — it serves themix-and-match path today.
Refs #353, RFC-46, ADR-4, ADR-6.