fix(determinism): replace HashMap.iter().find with sorted-key iteration (LS-A-15)#154
Conversation
Mythos delta-pass requiredThis PR modifies one or more Tier-5 source files (per Before merge, run the Mythos discover protocol on the
Why this gate exists: LS-A-10 The gate check on this PR will pass once the label is |
|
Mythos delta-pass evidence Tier-5 files touched: The post-v0.8.0 sweep ran fresh agents on both files. Both surfaced the HashMap-iteration non-determinism finding (resolver F1 + merger B) with concrete PoCs. The PoCs are folded into the regression test ( Other findings from those file scans not in this PR (will land in follow-up PRs):
|
Three sites resolved cross-component routing via HashMap::iter().find() over keyed maps. HashMap iteration order is hash-seed-randomised per process, so when more than one entry matched the lookup predicate the chosen entry varied across runs — producing non-reproducible fused output bytes and, in some cases, routing a call to the wrong target. Affected sites: - merger.rs::component_realloc_index fallback (2907-2919) - merger.rs handle-table fallbacks (~1040 and 1090-1100) - resolver.rs::resolve_resource_positions last-resort (1295-1308) Wasm validator does not catch any of these because structural types match across candidates (all reallocs share (i32,i32,i32,i32) -> i32; all resource-rep imports share (i32) -> i32). Fix: collect candidate keys, sort, pick .first(). Deterministic tie-breaking by lowest module index / smallest type-id / lexicographic key. Picks may still be semantically wrong if multiple distinct resources share a prefix (Step 6 alias propagation is the right structural mitigation), but the output is now reproducible across runs. Tests (2 new): - ls_a_15_component_realloc_index_picks_lowest_module_deterministically - ls_a_15_component_realloc_index_prefers_module_0 LS-A-15 added to safety/stpa/loss-scenarios.yaml. Discovered by the post-v0.8.0 Mythos delta-pass sweep on merger.rs and resolver.rs. Refs: LS-A-15 (UCA-M-10, H-7, H-3, H-4.3) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
afb7687 to
9583011
Compare
Summary
Third fix from the post-v0.8.0 Mythos delta-pass sweep. Three sites in
meld-core resolved cross-component routing via `HashMap::iter().find(...)`,
which picks a hash-seed-randomised entry. When multiple entries
matched, the chosen entry varied per run.
The bugs
The wasm validator does not catch any of these because structural types match across candidates: all reallocs share `(i32,i32,i32,i32) -> i32`; all resource-rep imports share `(i32) -> i32`.
Fix
Collect candidate keys → sort → pick `.first()`. Deterministic tie-breaking:
Picks may still be semantically wrong if multiple distinct resources share a prefix (Step 6 alias propagation is the right structural mitigation), but the output is now reproducible across runs.
Tests (2 new)
rebuilds the MergedModule across 64 iterations (each with fresh HashMap
hash seed) and asserts a single observed value.
for the primary path.
Tier-5 gate
Touches `merger.rs` and `resolver.rs` (both Tier-5). Mythos pass evidence
in a comment below.
Test plan
Refs
🤖 Generated with Claude Code