Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(p3-bridge): cross-component stream-bridge emitter (#141, SR-33)#239

Merged
avrabe merged 6 commits into
mainfrom
feat/141-stream-emitter
Jun 11, 2026
Merged

feat(p3-bridge): cross-component stream-bridge emitter (#141, SR-33)#239
avrabe merged 6 commits into
mainfrom
feat/141-stream-emitter

Conversation

@avrabe

@avrabe avrabe commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

v0.29.0 scope — the emitter the SR-33 audit proved was never built (closes #141; design recorded on the issue, ADR-3 path-N follow-up).

What

meld-core/src/p3_bridge.rs (Tier-5, pre-registered in #238): when the fused module's StreamPairGraph is non-empty, meld emits a bridge memory (slot headers + 8×4096B rings), per-component shims for the five stream intrinsics with the component's memory index hardwired, and rewires intrinsic call sites to the shims. Dispatch on handle bit 31: locally-minted handles → in-module ring ops (no host crossing); foreign handles → the retained host imports; slot exhaustion → host stream_new fallback. ADR-2 contract preserved end-to-end (write returns accepted count, 0 = backpressure; read returns bytes, 0 = EOF only after writer-drop AND drain, −5 Pending; drop_writable half-closes).

Oracles (runtime, through the REAL pipeline)

Five fixtures fuse two hand-built components (which trigger the real pair detector — untyped stream canon entries + fusion connection via a linked core-module export) and execute under wasmtime with host stubs that trap on any tagged handle plus zero-call counters:

  • ls_st_1_round_trip_local_stream_never_crosses_host
  • cross_memory_chain_preserves_data_across_distinct_memories
  • backpressure_partial_write_then_drain_then_resume
  • ls_st_1_eof_only_after_writer_drop_and_drain
  • slot_exhaustion_falls_back_to_host_stream

All pass; workspace 537/0; clippy/fmt clean. LS-ST-1 approved; SR-33 → implemented (honest history note kept; ADR-3 "zero-copy" amended to "no host crossing, single copy").

Notes & limitations (documented in-module)

Emitter runs before adapter wiring (adapter indices bake in functions.len()); slots retire on drop_readable (no reuse — degrades to host, never loses data); cancel ops stay host-routed (bridged ops never block); module-wide stream_new takeover is the accepted static-pairing over-approximation; shared-memory mode is the same codegen with immediates 0 but has no dedicated runtime fixture.

Mythos clean-room pass to follow as comment + label before merge.

🤖 Generated with Claude Code

avrabe and others added 4 commits June 11, 2026 08:56
SyntheticKind::StreamBridge tags the stream-bridge dispatch shims the
#141 emitter appends to merged.functions, mirroring AdapterShim /
TaskReturnShim. AdapterRole::StreamBridge maps it to <meld-adapter>
line 10 (next free line; adapter_lines_are_distinct_and_nonzero pins
the contract witness consumes).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
The headline #141 deliverable: when the resolver's StreamPairGraph is
non-empty, the fuse pipeline (new step 2.6) emits the shim-dispatch
bridge designed in the issue's v0.29.0 design comment:

- one bridge memory (8 slots x 4096-byte power-of-two rings; 1 header
  page + 1 ring page, fixed 2 pages, compile-time layout asserts),
- per-component shims for stream_new/read/write/drop_readable/
  drop_writable with the component's merged memory index hardwired as
  an immediate (same-memory fusion = identical codegen, immediates 0),
- bit-31 LOCAL_TAG handle dispatch: tagged -> ring ops, untagged ->
  the retained pulseengine:async host import (foreign fallback);
  slot exhaustion falls back to host stream_new, never errors,
- ADR-2 contract preserved: write returns accepted count (0 =
  backpressure), read returns bytes (0 = EOF only after writer drop
  AND drain, -5 Pending while open+empty); u32 wrapping monotonic
  cursors, two-part wrapping memory.copy on both sides,
- call sites rewired via function_index_map + body re-extraction (the
  wire_adapter_indices mechanism).

Placement deviation from the prompt-level plan, recorded in the module
docs: the emitter runs BEFORE adapter generation/wiring because
adapters are encoded after merged.functions - appending shims after
wire_adapter_indices had baked functions.len()-derived adapter indices
into call sites would shift every adapter call off-target.

ADR-3 amendment recorded: 'zero-copy same-memory ring' drops to 'no
host crossing, single copy' (the ABI's caller-buffer contract requires
the copy; fusion removes the double host round-trip).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Fuses two hand-built components through the REAL pipeline (no test-only
entry point) and executes the fused core module under wasmtime with
pulseengine:async host stubs that TRAP on any bit-31-tagged handle —
proving bridged streams never cross the host:

- ls_st_1_round_trip_local_stream_never_crosses_host: [1,2,3,4]
  producer->consumer via a local stream, zero host calls (LS-ST-1 gate)
- cross_memory_chain_preserves_data_across_distinct_memories: 3
  memories (producer + consumer + bridge), 300-byte pattern intact
- backpressure_partial_write_then_drain_then_resume: write > RING_CAP
  returns 4096 accepted, 0 on full ring, remainder after drain,
  two-part ring-wrap copy exercised on write AND read
- ls_st_1_eof_only_after_writer_drop_and_drain: -5 Pending while
  open+empty; drop_writable -> drain -> sticky 0 EOF (LS-ST-1 gate)
- slot_exhaustion_falls_back_to_host_stream: 9th stream is host-minted
  (untagged) and its ops reach the host imports exactly once each

Pair-gating construction (documented in the test header): the detector
needs CanonicalEntry::StreamWrite/StreamRead plus a resolved_imports
connection. Components carry an UNTYPED stream type + canon
stream.write/stream.read (untyped avoids the validator's memory-option
requirement, which would force instantiating the module in-component
and internalise the host imports), and are fusion-connected by the
producer exporting its core module as "link" and the consumer
importing a core module "link". The sanctioned fallback (driving the
emitter with a constructed StreamPairGraph) was NOT needed.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
)

LS-ST-1 (approved, UCA-A-4, H-1/H-3/H-4): the bridge mis-routes a
stream op (local handle to host / foreign handle to ring) or corrupts
ring cursors — fix pins the four p3_bridge_runtime oracles plus the
host-fallback fixture, mirroring LS-D-3's structure.

SR-33 planned -> implemented (milestone v0.29.0), keeping the honest
history note: detection shipped v0.9.0 (#173), the emitter was MISSING
until v0.29.0 (the earlier 'implemented' status was a bulk-sync error
reverted in PR #221). Verification names the four runtime oracles and
records the ADR-3 'zero-copy' -> 'no host crossing, single copy'
amendment. rivet validate: 175 -> 174 pre-existing errors (this change
closes one gap, introduces none).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown

Mythos delta-pass required

This PR modifies one or more Tier-5 source files (per
scripts/mythos/rank.md):

meld-core/src/merger.rs
meld-core/src/p3_bridge.rs

Before merge, run the Mythos discover protocol on the
modified Tier-5 files:

  1. Follow scripts/mythos/discover.md
    — one fresh agent session per touched Tier-5 file.
  2. For each finding, the agent must produce both a Kani
    harness and a failing PoC test (per the protocol's
    "if you cannot produce both, do not report" rule).
  3. Attach a comment on this PR with either the findings
    (formatted per discover.md's output schema) or
    NO FINDINGS.
  4. Add the mythos-pass-done label to this PR.

Why this gate exists: LS-A-10
(CABI alignment padding in async-lift retptr writeback) was
found by the v0.8.0 pre-release Mythos pass — but it had
lived in the callback emitter since #128, across six
releases. A PR-time gate would have caught it at review
time instead of at the release boundary.

The gate check on this PR will pass once the label is
applied.

@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown

LS-N verification gate

⚠️ 43/45 verified — 2 missing regression tests

count
Passed (≥1 test, all green) 43
Failed (≥1 test failure) 0
Missing (no ls_*_NN_* test found) 2

Approved loss-scenarios.yaml entries are expected to have a
regression test named ls_<letter>_<num>_* (e.g. LS-A-11
ls_a_11_*). The gate runs each prefix via cargo test --lib --no-fail-fast and aggregates pass/fail/missing.

Failed LS entries

(none)

Missing regression tests
  • LS-R-13
  • LS-M-6

Updated automatically by tools/post_verification_comment.py.
Source of truth: safety/stpa/loss-scenarios.yaml.

S1: a zero-length read with data available returned 0 — the EOF
sentinel — so a status probe could close a live stream. Now returns
Pending (-5); 0 stays reserved for writer-dropped-and-drained.

S2: a write to a slot whose reader (or writer) end was dropped
silently filled the ring and returned the accepted count. Now
returns AbiError::Closed per ADR-2 ('subsequent writes return
Closed').

Both flagged by the clean-room pass as contract deviations not
provable as divergence against the in-repo host stubs (which share
the same idealization) — fixed defensively since the production
host semantics are the authority. All 5 runtime oracles still pass.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@avrabe

avrabe commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

Mythos clean-room delta-pass — Tier-5 files p3_bridge.rs (+ merger/dwarf/lib wiring)

VERDICT: NO PROVABLE FINDING on the raw-codegen risk surface, with the highest-value angles cleared by proof:

  1. Ring arithmetic — wrapping-cursor fill/avail/offset correct under u32 wraparound (RING_CAP power-of-two divides 2³², offset continuity holds past 4 GiB); two-part copy bounds never cross slots; exact-boundary write (off+n==RING_CAP) has no off-by-one; oracle (c) exercises both wrap halves.
  2. Memory immediates — bridge memory is provably the appended index (nothing appends after pipeline Step 2.6; the emitter-before-adapter-wiring ordering claim verified against lib.rs). The pass built a shared-memory + address-rebasing PoC — the configuration the runtime oracles never cover — and it validates and round-trips 300 bytes intact.
  3. Dispatch + slot state machine — tagged slots always in-range; no path resets state to FREE (no reuse, "lose optimization never data" holds); new_shim branch depths and i64 packing correct.

Three unverified suspicions (reproducers built and removed; not provable as fusion-vs-host divergence because the in-repo host stubs share the same idealization):

  • S1 zero-length read with data returned the EOF sentinel → fixed defensively in cec435e (now Pending).
  • S2 write to a dropped slot silently accepted → fixed defensively in cec435e (now AbiError::Closed per ADR-2).
  • S3 module-wide stream_new takeover: a stream intended for a non-bridged host consumer would carry a tagged handle the host can't interpret — the design's documented static-pairing over-approximation; carried as a known limitation in the module docs and SR-33, revisit if a real host-stream-consuming fixture appears.

All 5 runtime oracles green post-hardening; workspace suite green; clippy/fmt clean.

@avrabe avrabe added the mythos-pass-done Mythos delta-pass completed on Tier-5 file changes; findings (or NO FINDINGS) attached to PR label Jun 11, 2026
@avrabe avrabe enabled auto-merge (squash) June 11, 2026 07:19
@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown

Mythos delta-pass (auto)

1 finding(s) across 3 Tier-5 file(s)

File Verdict Hypothesis
`` ✅ NO FINDINGS
`` ✅ NO FINDINGS
meld-core/src/p3_bridge.rs ❌ FINDING emit_drop_shim decodes slot = handle & 0x7FFFFFFF and computes header_addr = slot * SLOT_HEADER_STRIDE without bounding slot against SLOT_COUNT; for the forged handle LOCAL_TAG | 4096, header_addr == RINGS_BASE (65536), so the unguarded i32.store writes new_state (4 bytes, in-bounds, no wasm trap) directly into slot 0's ring data, silently corrupting stream payload bytes.

Auto-run via anthropics/claude-code-action@v1
(SHA-pinned) on the touched Tier-5 files, using the
maintainer's Max-plan OAuth token. See
.github/workflows/mythos-auto.yml and
scripts/mythos/discover.md.

@avrabe avrabe merged commit 1694929 into main Jun 11, 2026
16 of 18 checks passed
@avrabe avrabe deleted the feat/141-stream-emitter branch June 11, 2026 08:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mythos-pass-done Mythos delta-pass completed on Tier-5 file changes; findings (or NO FINDINGS) attached to PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

P3 async — cross-component stream adapter (#94 sub-A)

1 participant