@@ -127,10 +127,20 @@ captured linears. |S1 |pt1 #240 + pt2 return-escape + `&mut` surface +
127127pt3 Slice A NLL last-use DONE (Refs #177); residual = Slices B–D
128128(flow-sensitive escape, origin variables, quantity integration) —
129129issue #177
130- |CORE-02 |Effect-handler dispatch on WasmGC (currently `UnsupportedFeature`;
131- EH proposal or CPS). The #225 CPS line closes the async slice. |S2 |partial
132- (#225 line CLOSED PR1..PR3d+PR4; #234 generalises the recogniser —
133- ADR-016 ACCEPTED, side-table typecheck→codegen, staged S1..S4; S1 done)
130+ |CORE-02 |Effect-handler dispatch on WasmGC (was `UnsupportedFeature`;
131+ the chosen path is CPS over the EH proposal). The #225 CPS line closed
132+ the async slice; #234 generalised the boundary recogniser from a
133+ hardcoded name set to "any call whose effect row ⊇ `Async`". |S2
134+ |*CLOSED 2026-05-19* — #225 line CLOSED PR1..PR3d+PR4; #234 ADR-016
135+ delivered end-to-end (S1 #270 ADR; S2a #275 shared call-site
136+ numbering `lib/effect_sites.ml`; S2b #276 typecheck builds the
137+ ordinal→effect side-table; S3 #277 pipeline threads it + codegen
138+ boundary predicate switched + user-defined-`Async` e2e
139+ `tests/codegen/effect_async_boundary.affine`; S4 #278 hardcoded
140+ `async_primitives` set retired — boundary is now exactly
141+ `Effect_sites.is_async_call`). Issue #234 closed completed. Table-miss
142+ fallback (`Effect_sites.is_async_call` = false ⇒ no transform) remains
143+ as the sound table-empty / count-mismatch path.
134144|CORE-03 |ADR-014: module-qualified type/effect path. Decision settled
135145(both `.`/`::` accepted, `Pkg::Type` canonical, `.`→`::` for free via the
136146`::`-fold). Was the estate's dominant parse blocker (525/1177 .affine).
@@ -183,6 +193,19 @@ round-trips + Deno codegen __cell-shape assertion) |S3 |DONE
183193(`lib/interp.ml`, `lib/js_codegen.ml`, `lib/codegen_deno.ml`); sibling
184194`panic` is wired and `error` should mirror it (divergent `T`) |S3 |open
185195— issue #329
196+ |STDLIB-04c |`string_concat` extern — *REMOVED* (Refs #330): the
197+ canonical surface is the `++` operator (lowered in `Value.binop_string`
198+ and `__as_concat`); the extern was declared but never wired in any
199+ backend nor called from any stdlib/test/fixture — dead surface. The
200+ contract is now operator-only and one-source-of-truth. |S3 |DONE
201+ 2026-05-24 (Refs #330)
202+ |STDLIB-04b |Throws extern `error<T>` — *LANDED* (Refs #329): mirrors
203+ `panic`'s divergent semantics with a polymorphic return (`<T>` unifies
204+ with the call-site expectation, unobservable at runtime). Wired in
205+ interp (`RuntimeError`), Deno codegen (`throw new Error`), resolve
206+ seed, and typecheck as a scheme (`poly1` so each call instantiates a
207+ fresh tyvar). 3 hermetic tests in "E2E STDLIB-04b error #329". |S3
208+ |DONE 2026-05-24 (Refs #329)
186209|STDLIB-04c |`string_concat` extern — no direct wiring found; `++`
187210operator independently lowered. Decide: remove (operator-only) or wire
188211to mirror `++` |S3 |open — issue #330
@@ -195,9 +218,13 @@ prelude. `read_line` is interactive and intentionally out of scope (the
195218TEA-bridge tests already exercise the redirected-stdin path). No impl
196219change; was test-debt, not impl-debt. |S3 |DONE 2026-05-24 (Refs #331)
197220|STDLIB-04e |Pure externs (`int_to_string`/`string_to_int`/
198- `string_length`) — real + tested (`lib/interp.ml:615-633`,
199- `lib/codegen_deno.ml:263-272`); bookkeeping to mark DONE |S3 |open —
200- issue #332
221+ `string_length`) — *DONE* (Refs #332): `int_to_string` +
222+ `string_length` were already real-wired; `string_to_int` was unwired
223+ dead surface (re-audit caught the gap the initial sweep missed — same
224+ trap STDLIB-04c removed). Now the typed-alias of `parse_int` in interp
225+ + Deno codegen + resolve/typecheck seeds. 4 hermetic tests in "E2E
226+ STDLIB-04e Pure #332" lock the round-trip semantics. |S3 |DONE
227+ 2026-05-24 (Refs #332)
201228|===
202229
203230== Section D — INT (ecosystem integration)
@@ -230,16 +257,33 @@ follow-up
230257multi-ns import object, ownership accessor); 14 unit tests via pinned
231258`deno task test` + `tests/modules/loader-bridge/` e2e on real
232259compiler-emitted xmod wasm (closes INT-01↔INT-02). Unblocks INT-05/08/11
233- |INT-03 |WASI preview2 / host I/O |S1→S4b |#180 ADR-015 (full
260+ |INT-03 |WASI preview2 / host I/O |S1→S6a |#180 ADR-015 (full
234261Component-Model re-target, S1..S6); S2 toolchain #251 closed;
235- S3 componentize done; ** S4a (clock) + S4b (env_count, arg_count)
262+ S3 componentize done; S4a (clock) + S4b (env_count, arg_count)
236263DONE — on-demand preview1 imports via Effect_sites pre-scan,
237264canonical-order indexing through `ctx.wasi_func_indices`; combo
238265regression proves no collision. String accessors (env_at/arg_at)
239266gated on byte-level wasm IR (I32Load8U/I32Store8 absent today) —
240- tracked next slice. Real-host main-invoke = S6 (WIT export
241- lifting). Next S5
242- (native clocks/env/argv)**
267+ tracked next slice. **S6a (WIT export lifting) DONE:
268+ `lib/codegen.ml` auto-emits a `_start : () -> ()` shim whenever
269+ a parameter-less `fn main()` is present (additive, no regression
270+ on reactor consumers); `tools/componentize.sh --command` wraps
271+ with the fetch-pinned command adapter (sha256
272+ 8ff2ea78… / wasmtime v44.0.1, provisioned alongside the reactor
273+ adapter); `tests/componentize/command_smoke.sh` gates the
274+ contract end-to-end — `wasi:cli/run` lifted, ownership section
275+ survives, `wasmtime run` exits 0. Real-host main-invoke now
276+ works via `wasmtime run <component>`.** Remaining S6
277+ sub-slices: S5 (native clocks/env/argv), S6b (`wasi:sockets`),
278+ S6c (flip the default wasm target from preview1 → component)
279+ regression proves no collision. **S5 (env_at/arg_at) DONE — wasm
280+ IR extended with the byte-level load/store family
281+ (I32Load8U/I32Store8 and siblings); accessors lower to on-demand
282+ `environ_get`/`args_get` imports paired with the existing
283+ `*_sizes_get` (dedup keeps each WASI import exactly once even when
284+ both `*_count` and `*_at` are used in the same unit); guest
285+ allocates a length-prefixed AS string and byte-copies from the
286+ WASI buffer.** Real-host main-invoke = S6 (WIT export lifting)
243287|INT-04 |Publish to JSR/npm |S2 |#181 packaging READY (dry-run green,
244288manual workflow); compiler-binary distribution decided = **ADR-019**
245289(#260, Releases + thin Deno/JSR shim, staged S1..S4) — S1/S2/S3
@@ -292,7 +336,9 @@ Proven + locked (see INT-02)
292336|CONV-01 |Estate-wide re-validation of the #199/#205 closure ABI (static →
293337real wasm engine) |S2 |open #235
294338|CONV-02 |Effect-threaded async-boundary detection (generalise the
295- structural-conservative recogniser) |S2 |open #234
339+ structural-conservative recogniser) |S2 |*CLOSED 2026-05-19* — #234
340+ DELIVERED end-to-end (ADR-016 S1..S4; PRs #270/#275/#276/#277/#278).
341+ See CORE-02 above for the resolution narrative.
296342|CONV-03 |#225/#160 convergence ABI matured to "shared with Ephapax" |S1
297343|partial (PR3a/b/c merged)
298344|CONV-04 |Widen emitted-wasm enforcement beyond L7+L10 toward L1–6/L13–16 |S2
0 commit comments