feat: P3 async lowering pass — canon stream/future → pulseengine:async (closes #120)#129
Merged
Merged
Conversation
closes #120) Implements the lowering pass deferred from PR #124 (the v0.5 P3 async foundation). The canonical built-ins `(canon stream.*)` and `(canon future.*)` (14 verbs total) are now rewritten into core-module imports against the documented `pulseengine:async` ABI surface (`HostIntrinsic::import()`). Mapping is one-to-one: canon stream.new → pulseengine:async/stream_new canon stream.read → pulseengine:async/stream_read canon stream.write → pulseengine:async/stream_write canon stream.cancel-read → pulseengine:async/stream_cancel_read canon stream.cancel-write → pulseengine:async/stream_cancel_write canon stream.drop-readable → pulseengine:async/stream_drop_readable canon stream.drop-writable → pulseengine:async/stream_drop_writable (same seven verbs for future) The existing `stream<u8>` fixture in tests/p3_async_lowering.rs gains an end-to-end assertion: after Fuser::fuse(), the fused module's import section contains exactly the imports under module `pulseengine:async` matching `p3_async_summary()`. New fuse-only test covers the symmetric `future<T>` case. ADR-1 updated to mark the lowering pass shipped. 73-test wit_bindgen_runtime suite stays green. Sub-#94. The remaining P3 async follow-ups (error/backpressure conventions #121, async-export callback alignment #122) ship in parallel PRs. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This was referenced May 12, 2026
Closed
avrabe
added a commit
that referenced
this pull request
May 13, 2026
First phase of the two-mode P3 async lifting work tracked under #94. This PR lands the host-intrinsic ABI surface a stackful lift needs; the actual trampoline emitter in adapter/fact.rs lands in the follow-up, mirroring the #124 -> #129 split that worked for the data-plane intrinsics. What lands: - 4 new HostIntrinsic variants (ThreadNew, ThreadSwitchTo, ThreadYield, ThreadExit) with pinned signatures and a thread::* name module - uses_stackful_lift() derived helper on P3AsyncFeatures (async lift without callback option => stackful mode per Component Model spec) - Two new tests: stackful_intrinsic_signatures_pinned (4 names + sigs + pulseengine:async module) and stackful_lift_is_async_without_callback (4-case truth table) - ADR-1 addendum documenting the two-mode policy side-by-side - SR-32 flipped planned -> in-progress in safety-requirements.yaml and traceability.yaml updated to point at the new code + tests - CHANGELOG [Unreleased] entry Emitter behavior is unchanged in this PR: a component requesting stackful lift still hits the existing clear error path. Phase 2 wires the trampoline. Refs: #94 (P3 async umbrella), SR-32 (stackful lifting requirement) Milestone: v0.8.0 Co-authored-by: Claude Opus 4.7 <[email protected]>
avrabe
added a commit
that referenced
this pull request
May 20, 2026
…173) * feat(p3): cross-component stream<T> pairing detection (#141, ADR-3) Foundation for the in-module cross-component stream adapter — sub-A of the P3 async umbrella #94. Today meld lowers every component's stream operations to host imports under `pulseengine:async` (ADR-1). When two fused components share a `stream<T>` end-to-end — one holds the writable end, one the readable end — both sides still route every chunk through the host even though both ends now live in the merged module. This PR ships the *detection* half (ADR-3, Path N): everything that can be proven correct with unit tests and no wasm runtime. The adapter *emitter* (ring buffer for same-memory, stream_read→copy→ stream_write chain for cross-memory) is a deliberately separate, runtime-verified follow-up — cross-component stream codegen is data-plane wasm that is only correct once executed on kiln/wasmtime, and landing unverified codegen into the merged module is the H-1/H-3 hazard class meld's Mythos and LS-N gates exist to prevent. The repo shipped P3 lowering in exactly this staged shape (#124 foundation, #129 full pass). What lands: - `safety/adr/ADR-3-cross-component-stream-adapter.md` — design doc. Design paths: N (detection-now/emitter-next, chosen), O (full emitter in one PR, rejected — unverifiable), P (keep host routing, rejected — defeats fusion). Documents the two emitter shapes the follow-up implements and the foundation's precision boundary. - `meld-core/src/p3_stream.rs` — new module, sibling to p3_async.rs. `StreamElement` (element type parsed from the `stream<...>` descriptor), `StreamRole` (Producer/Consumer from StreamWrite/ StreamRead canonical entries), `StreamPair`, `StreamPairGraph`, and a pure `build_stream_pair_graph(components, resolved_imports, mode)`. The pairing logic is a pure function unit-tested without any ParsedComponent construction. - `DependencyGraph` gains a `stream_pair_graph` field, populated by the resolver right after the resource graph (both key off `resolved_imports`). Memory mode follows `MemoryStrategy`. Detection is conservative. A `StreamPair` is a *candidate*, recorded only when two fusion-connected components have complementary roles on a stream of the **same element type**. It does not prove the two endpoints carry the same runtime handle (unknowable at build time). Pairing only on matching element type — never any producer with any consumer — keeps the foundation from manufacturing hallucinated cross-type pairs ("hallucinations are more expensive than silence"). `meld-core/src/p3_stream.rs` added to the Mythos Tier-5 path lists in mythos-gate.yml and mythos-auto.yml, per the documented drift-review process for new fusion-correctness files. Tests: 9 unit tests in p3_stream.rs including the 4 ADR-3 gating fixtures. Full meld-core lib suite 239 → 247 passing. Clippy clean. Refs: #141, #94 (umbrella), ADR-3, SR-33 (detection half). Co-Authored-By: Claude Opus 4.7 <[email protected]> * fix(ci): drop Tier-5 path-list change from this PR claude-code-action self-validates that the workflow invoking it has content identical to the version on `main` — a security measure that stops a PR from altering the workflow to exfiltrate secrets. PR #173 modified `mythos-auto.yml` (adding `p3_stream.rs` to the Tier-5 path list), so the action refused to run with: Action failed with error: Workflow validation failed. The workflow file must exist and have identical content to the version on the repository's default branch. Reverts the `mythos-gate.yml` / `mythos-auto.yml` path-list edits so `mythos-auto.yml` on this branch matches `main` and the auto-runner can actually scan the Tier-5 source this PR touches (`resolver.rs`, `merger.rs`). Registering `p3_stream.rs` in the Tier-5 lists moves to a separate follow-up PR that touches no Tier-5 *source* — its `detect` job sees no Tier-5 source change, sets `any=false`, and the scan (hence the self-validation) never runs. Co-Authored-By: Claude Opus 4.7 <[email protected]> --------- Co-authored-by: Claude Opus 4.7 <[email protected]>
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.
Summary
Implements the P3 async lowering pass — the actual rewrite from canonical built-ins (
(canon stream.*),(canon future.*)) to core-module imports against thepulseengine:asyncABI shipped in v0.5.0.The mapping is one-to-one (per
HostIntrinsic::import()frommeld_core::p3_async):canon stream.newpulseengine:async/stream_newcanon stream.readpulseengine:async/stream_readcanon stream.writepulseengine:async/stream_writecanon stream.cancel-readpulseengine:async/stream_cancel_readcanon stream.cancel-writepulseengine:async/stream_cancel_writecanon stream.drop-readablepulseengine:async/stream_drop_readablecanon stream.drop-writablepulseengine:async/stream_drop_writablefuture)pulseengine:async/future_*Test plan
wit_bindgen_runtimesuite green (no regressions)stream<u8>fixture: import-section matchesp3_async_summary()future<T>symmetric caseWhat's left
ADR-1 updated to mark this lowering pass shipped. The remaining P3 async items (#121 error/backpressure conventions, #122 async-export callback alignment) are filed as separate PRs.
Closes #120 (sub-#94).