fix(p3-async): mixed-mode stackful, type classification, stream-write over-count#153
Conversation
|
Mythos delta-pass evidence Tier-5 file touched: A fresh agent ran The agent also verified-and-rejected 3 priors (PAYLOAD_SHIFT docstring vs emitter, missing intrinsic variants, name typos) — those checks remain in the agent transcript and are NOT defects. Adjacent findings not in this PR:
|
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 |
7941f3e to
2977518
Compare
… over-count Three independent defects in meld-core/src/p3_async.rs surfaced by the post-v0.8.0 Mythos delta-pass on the file. 1. LS-A-12 — P3AsyncFeatures::uses_stackful_lift mis-classifies mixed-mode uses_stackful_lift() was derived as `uses_async_lift && !uses_callback_lift`, a conjunction of two component-wide existential flags. A component that declares one callback-mode async lift AND one stackful-mode async lift sets both flags to true, so the derived predicate returned false even though a stackful lift was present. Fix: new independent field `uses_stackful_lift_internal: bool` set per-lift in detect_features. uses_callback_lift remains "any lift has callback"; uses_stackful_lift_internal is "any lift is stackful". The dispatcher in adapter/fact.rs already routes per-site based on the merged module's [callback]<export> companion, so this never reached the emitter — but downstream consumers following the public API would misroute. Bug shipped in #146 / v0.8.0. 2. LS-A-13 — StreamWriteResult::decode folds over-count into Complete decode(ret, requested) classified any non-negative ret with `written >= requested` as Complete, including the out-of-contract `written > requested` case. A buggy or hostile runtime returning n > data_len would silently drive callers to advance their producer cursor past the source buffer. Fix: split into three explicit arms — `==` => Complete, `<` => Partial, `>` => Unknown(ret). 3. LS-A-14 — detect_features substring matching misclassifies future<stream<...>> detect_features classified P3Async types via desc.contains("stream") / desc.contains("future"). A nested type future<stream<u8>> matched "stream" first and landed in stream_types instead of future_types. Fix: classify on the root constructor of the description (the prefix up to the first '<'), not on substring containment. Tests (4 new): - stackful_lift_is_existential_over_lifts (replaces single-lift test) - ls_a_12_mixed_mode_component_reports_stackful - ls_a_13_stream_write_over_count_is_unknown_not_complete - ls_a_14_future_of_stream_classifies_as_future LS-A-12 / LS-A-13 / LS-A-14 added to safety/stpa/loss-scenarios.yaml. Discovered by the post-v0.8.0 Mythos delta-pass sweep (gate from #151). Refs: LS-A-12, LS-A-13, LS-A-14 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2977518 to
ccf485b
Compare
Cuts v0.8.1 carrying the post-v0.8.0 Mythos delta-pass sweep on the 8 Tier-5 files unscanned at v0.8.0 cut time (per #151 gate scope). Ten loss scenarios closed across 6 fix PRs, all of them silent (no host trap, no validator rejection — wrong-by-construction outputs): - LS-A-11 (#152) — extended-const init/offset truncation in segments and global initializers. Folds (i32.const x)(i32.const y) i32.add instead of dropping operands after the first. - LS-A-12/13/14 (#153) — p3-async detection bugs: mixed-mode stackful mis-classification, stream-write over-count silently classified as Complete, future<stream<...>> mis-routed to stream_types via substring match. - LS-A-15 (#154) — HashMap.iter().find non-determinism at three sites; realloc and resource-rep/-new fallbacks now sort candidate keys. - LS-A-16 (#159) — wrapper dropped source canonical options for lifts; every export silently received the first lift's string encoding. - LS-A-17/18/19 (#156) — resource_graph definer purge and terminal- exporter pass ignored the iface dimension; merger dedup used ends_with(rn) where exact match was required (float / bigfloat suffix collision). - LS-A-20 (#157) — flags<N> canonical ABI silently modeled as Record<N x Bool>; new ComponentValType::Flags variant with explicit arms in every canonical-ABI helper. Also under Added: the Mythos delta-pass CI gate workflow (#151) that made this sweep observable at PR time, and the stackful async-lift cross-memory (ptr, len) return path that v0.8.0 had errored out on. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Summary
Second fix from the post-v0.8.0 Mythos delta-pass sweep. Three independent
defects in `meld-core/src/p3_async.rs`, all silent (no trap, no validator
catch).
The bugs
Fixes
LS-A-12 — New independent field `uses_stackful_lift_internal: bool`
set per-lift in `detect_features`. `uses_callback_lift` (any lift has
callback) and `uses_stackful_lift_internal` (any lift is stackful) are
now independent. The dispatcher in `adapter/fact.rs` already routes
per-site based on the merged module's `[callback]` companion,
so this never reached the emitter — but downstream consumers following
the public API would misroute. Bug shipped in feat(p3-async): stackful lifting ABI foundation (#140 phase 1) #146 / v0.8.0.
LS-A-13 — Split `>=` check into three explicit arms:
`==` → `Complete`, `<` → `Partial`, `>` → `Unknown(ret)`.
LS-A-14 — Classify on the root constructor (prefix up to first `<`),
not on substring containment.
Tests (4 new)
single-lift truth-table test; covers the mixed-mode case
`detect_features` with both lift kinds
Tier-5 gate
This PR touches `p3_async.rs` (Tier-5). The Mythos gate will fire and
request the `mythos-pass-done` label. The pass IS the work in this PR.
Test plan
Note on overlap with #152
This PR is independent of #152 (extended-const fix). Both add entries
to `safety/stpa/loss-scenarios.yaml` and `CHANGELOG.md` Fixed section.
Whichever merges first wins; the other will need a small textual rebase
(additive only, no real semantic conflict).
Refs
🤖 Generated with Claude Code