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

Skip to content

feat: P3 async lowering — foundation + stream<T> e2e (partial #94)#124

Merged
avrabe merged 1 commit into
mainfrom
feat/issue-94-p3-async-foundation
Apr 29, 2026
Merged

feat: P3 async lowering — foundation + stream<T> e2e (partial #94)#124
avrabe merged 1 commit into
mainfrom
feat/issue-94-p3-async-foundation

Conversation

@avrabe

@avrabe avrabe commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

Foundation layer for P3 async lowering (issue #94). Establishes the stable host-intrinsic ABI contract that subsequent lowering work builds against, plus an end-to-end detection test covering stream<u8>.

Closes partial of #94 — the parent stays open until follow-up sub-issues #120 / #121 / #122 land.

Summary

In-scope (this PR)

  1. Detection layer: parser already collected p3_async_features: Vec<String>; this PR makes it queryable structurally via HostIntrinsic + P3AsyncFeatures.
  2. ABI documentation: rustdoc table in p3_async.rs plus stable HOST_INTRINSIC_MODULE / per-verb constants.
  3. stream<T> e2e parse + detect.
  4. Regression guard: pure-P2 components produce empty features; existing 73-test runtime suite stays green.

Out of scope (deferred — see ADR-1)

Test plan

  • cargo test -p meld-core — 197 lib + 73 wit_bindgen_runtime + 5 new p3_async_lowering tests = green.
  • cargo clippy -p meld-core --all-targets -- -D warnings — clean.
  • cargo fmt -p meld-core --check — clean (pre-commit hook passed).
  • Fuser::p3_async_summary() returns empty for all 73 existing P2 fixtures (verified via pure_p2_component_has_no_p3_features).

Why "foundation"?

Issue #94 is major-version-class scope (5k+ LOC across merger, component_wrap, adapter, resolver). Landing it in one PR would couple unrelated decisions (callback trampoline shape, ring-buffer layout, error encoding) into one review and require cross-repo runtime work in kiln. This PR ships the stable API contract the rest of the work builds on — once merged, the lowering pass and runtime implementation can land independently and in parallel, sharing only the pulseengine:async ABI.

🤖 Generated with Claude Code

…2e (partial #94)

Establishes the foundation layer for P3 async lowering: a documented
`pulseengine:async` host-intrinsic ABI surface, a structured detection
API on `Fuser`, and an end-to-end test covering `stream<u8>` parsing
through detection.

Lowering pass (rewriting `(canon stream.*)` to `pulseengine:async/*`
imports), `future<T>` e2e, async-export callback alignment, and
formal error/backpressure conventions are deferred to follow-up
sub-issues #120 / #121 / #122 — see ADR-1 for the full breakdown.

73-test `wit_bindgen_runtime` suite stays green; 6 new unit tests +
5 new integration tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@avrabe avrabe marked this pull request as ready for review April 29, 2026 05:24
@avrabe avrabe merged commit c1e05bc into main Apr 29, 2026
4 of 8 checks passed
@avrabe avrabe deleted the feat/issue-94-p3-async-foundation branch April 29, 2026 05:55
@avrabe avrabe mentioned this pull request Apr 29, 2026
6 tasks
avrabe added a commit that referenced this pull request Apr 30, 2026
closes #120) (#129)

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]>
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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant