Summary
Safety requirement SR-31 "Multiply-instantiated module detection" is marked verified in docs/verification-matrix.md (and safety/requirements/traceability.yaml, sw-verifications.yaml), evidenced by the unit test merger::tests::ls_m_5_multiply_instantiated_module_rejected. But the shipped behavior is the opposite: on the live fuse path a component that instantiates one core module 2×/3× is accepted (fused rc=0), not rejected. The DuplicateModuleInstantiation reject the test verifies is dead code on real input, so SR-31's "verified" status is vacuous vs the actual behavior — the classic "verification that doesn't cover the shipped path" gap.
Root cause
feat(adr7): multiply-instantiated module support (#362, commit cf3c55d) wired expand_multiply_instantiated_modules unconditionally into fuse_with_stats:
meld-core/src/lib.rs:419-425
for component in &mut self.components {
duplicated_modules += crate::core_instance_topology::expand_multiply_instantiated_modules(component);
}
Its own inline comment states this makes the reject "an unreachable backstop". Because the expansion runs before resolve/merge, the DuplicateModuleInstantiation returns at merger.rs:686 and resolver.rs:2432 never fire for the ordinary (instantiate $m) shape. The verifying test ls_m_5_multiply_instantiated_module_rejected calls the merger reject in isolation, bypassing fuse_with_stats, so it still passes while the live path does the opposite.
The commit's own message even contradicts the code: "Deliberately NOT wired … 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." The code wires it on all input.
Reproduction (meld 0.41.3, fresh release)
meld fuse dup.wasm -o out.wasm # component instantiating one core module 2× → rc=0 "Fusion complete!"
meld fuse tri.wasm -o out.wasm # 3× → rc=0
Both should be rejected per SR-31. The output is a multi-memory module with N independent memories (func0→mem0, func1→mem1, func2→mem2) — for this simple shape it is correct (no aliasing, verified by execution). So this is not a miscompile; it is a safety-claim / traceability defect: SR-31 is certified verified while its property does not hold on the shipped path.
Why it matters
A functional-safety consumer reading the verification matrix believes multiply-instantiation is rejected pending the execution-oracle + Mythos gate the commit describes. That gate is bypassed on all user input. The corners the commit itself flags as un-execution-verified — per-instance import wiring and shared-memory duplicate instantiation — are now reachable by users with no guard, while SR-31 asserts they cannot occur. (Shared+--address-rebase is separately blocked by the #352 missing-reloc hard-fail — verified.)
Suggested action
Either (a) restore the DuplicateModuleInstantiation reject on the live fuse_with_stats path until the execution oracle + Mythos gate land (matching the commit message + SR-31), or (b) if the feature is intended to ship, update SR-31's status and verifying evidence to a test that exercises the live fuse path (not the isolated merger reject), and add execution verification for the per-instance import wiring + shared-memory duplicate-instantiation corners.
Summary
Safety requirement SR-31 "Multiply-instantiated module detection" is marked
verifiedindocs/verification-matrix.md(andsafety/requirements/traceability.yaml,sw-verifications.yaml), evidenced by the unit testmerger::tests::ls_m_5_multiply_instantiated_module_rejected. But the shipped behavior is the opposite: on the live fuse path a component that instantiates one core module 2×/3× is accepted (fused rc=0), not rejected. TheDuplicateModuleInstantiationreject the test verifies is dead code on real input, so SR-31's "verified" status is vacuous vs the actual behavior — the classic "verification that doesn't cover the shipped path" gap.Root cause
feat(adr7): multiply-instantiated module support(#362, commitcf3c55d) wiredexpand_multiply_instantiated_modulesunconditionally intofuse_with_stats:Its own inline comment states this makes the reject "an unreachable backstop". Because the expansion runs before resolve/merge, the
DuplicateModuleInstantiationreturns atmerger.rs:686andresolver.rs:2432never fire for the ordinary(instantiate $m)shape. The verifying testls_m_5_multiply_instantiated_module_rejectedcalls the merger reject in isolation, bypassingfuse_with_stats, so it still passes while the live path does the opposite.The commit's own message even contradicts the code: "Deliberately NOT wired … 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." The code wires it on all input.
Reproduction (meld 0.41.3, fresh release)
Both should be rejected per SR-31. The output is a multi-memory module with N independent memories (func0→mem0, func1→mem1, func2→mem2) — for this simple shape it is correct (no aliasing, verified by execution). So this is not a miscompile; it is a safety-claim / traceability defect: SR-31 is certified
verifiedwhile its property does not hold on the shipped path.Why it matters
A functional-safety consumer reading the verification matrix believes multiply-instantiation is rejected pending the execution-oracle + Mythos gate the commit describes. That gate is bypassed on all user input. The corners the commit itself flags as un-execution-verified — per-instance import wiring and shared-memory duplicate instantiation — are now reachable by users with no guard, while SR-31 asserts they cannot occur. (Shared+
--address-rebaseis separately blocked by the #352 missing-reloc hard-fail — verified.)Suggested action
Either (a) restore the
DuplicateModuleInstantiationreject on the livefuse_with_statspath until the execution oracle + Mythos gate land (matching the commit message + SR-31), or (b) if the feature is intended to ship, update SR-31's status and verifying evidence to a test that exercises the live fuse path (not the isolated merger reject), and add execution verification for the per-instance import wiring + shared-memory duplicate-instantiation corners.