feat(wasi): experimental WASI Preview 2 target — vera compile/run --target wasi-p2 — v0.0.194#849
Conversation
…arget wasi-p2 — v0.0.194 Emit a binary WebAssembly component whose vera.* IO + Random imports are implemented over WASI 0.2 interfaces (dispatch-table shim topology, GC-exempt cabi_realloc arena, adapter core module elem-planted before any lift), runnable by stock wasmtime with no flags and no Vera bindings. vera run --target wasi-p2 executes it under the built-in add_wasip2 host with the core-path ExecuteResult contract, including trap-kind classification recovered from the backtrace text and the WASI stderr channel. Unsupported host families are a diagnostic naming the family, never a silent fallback. Dual-target conformance differential: 71 of 88 run-level programs byte-identical across targets (rest family-gated, main-less, or wall-clock; loud skips). New spec chapter 13 documents the architecture and the inherent WASI 0.2 divergences (exit codes degrade to 0/1, no structured trap frames). Also: doc-shadowing scanner skips .claude/; IO.args GC-rooting bug found in passing filed as #847 with a KNOWN_ISSUES row. Refs #237 Co-Authored-By: Claude <[email protected]>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
🔗 Linked repositories identifiedCodeRabbit considers these linked repositories for cross-repo context during reviews:
📝 WalkthroughWalkthroughThis PR adds an experimental WASI Preview 2 target across code generation, runtime execution, CLI integration, tests, and documentation, and updates release/version metadata. It also renumbers SKILL.md fenced-example allowlist entries and skips ChangesWASI Preview 2 target implementation
Unrelated maintenance updates
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant VeraCLI
participant emit_wasi_component
participant execute_wasi_p2
participant Wasmtime
VeraCLI->>emit_wasi_component: compile --target wasi-p2
VeraCLI->>execute_wasi_p2: run --target wasi-p2
execute_wasi_p2->>emit_wasi_component: emit component from CompileResult
execute_wasi_p2->>Wasmtime: instantiate component with WasiConfig
Wasmtime-->>execute_wasi_p2: run main or wasi:cli/run
Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 7 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (7 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #849 +/- ##
==========================================
+ Coverage 91.90% 92.00% +0.09%
==========================================
Files 93 95 +2
Lines 27838 28363 +525
Branches 332 332
==========================================
+ Hits 25585 26095 +510
- Misses 2245 2260 +15
Partials 8 8
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Review round 1 — pr-review-toolkit code-reviewerEmpirical review of Confirmed by execution: family gate ordering ahead of the JSON success envelope; JSON envelope parity with the core path (incl. the documented exit-code degradation); Two low-severity observations, both considered and kept as-is:
No code changes from this round. |
… — windows-latest CI The core host reads stdin through Python's universal-newlines text layer, so read_line never returns a trailing \r on any platform; the adapter now strips a trailing \r alongside the \n (RED-first via an explicit CRLF-bytes stdin test that failed on every platform). A lone \r separator stays content — documented divergence, spec section 13.6. The LF stdin fixture now writes binary so its bytes are deterministic cross-platform. The time-bracket test gains 100 ms of cross-clock slack (wall-clock vs time.time() quantization overshot by 1 ms on windows-latest) — still catches unit errors, the test's real target. Co-Authored-By: Claude <[email protected]>
|
CI round 1 (
Counts rebumped (5,755 tests / |
…the sprint Carrying the row in this PR would only conflict with the #846 rebase that removes it (maintainer direction on the #849/#846 coordination). Issue #847 remains open and tracked; #846 closes it on merge. Skip-changelog: KNOWN_ISSUES-only edit; #847 tracking is on the issue and PR #846 Co-Authored-By: Claude <[email protected]>
There was a problem hiding this comment.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
TESTING.md (1)
11-13: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUpdate the conformance count everywhere in this file.
The overview now says 104 conformance programs, but the Conformance Suite prose later in this file still says 103. As per the count-sync guidance, replace the old literal everywhere.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@TESTING.md` around lines 11 - 13, The conformance program count is inconsistent across TESTING.md: the overview already uses the new total, but the Conformance Suite prose still has the old literal. Update every remaining 103 reference in that document to match the 104 count, using the existing “Conformance programs” and “Conformance Suite” wording as anchors so the totals stay in sync throughout the file.Source: Learnings
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@HISTORY.md`:
- Around line 430-449: The release metrics table in HISTORY.md has an incorrect
spec chapter count for v0.0.194. Update the "Spec chapters" value in the summary
table to match the documented coverage from spec/13-wasi.md, keeping it at 13
rather than 14, and ensure the v0.0.194 column remains consistent with the rest
of the release statistics.
In `@README.md`:
- Around line 222-224: The README summary counts are out of sync with the later
project-structure block, so update every stale literal in this file to match the
current totals. Use the existing status text near the top and the
project-structure section as the anchors, and make sure the examples count and
spec chapter count are consistent everywhere, including any references tied to
the spec chapters and examples.
In `@ROADMAP.md`:
- Line 11: The spec chapter total in the roadmap overview is incorrect and
should remain 13, not 14. Update the summary text that lists test, conformance,
example, and spec chapter counts so it matches the actual additions from
spec/13-wasi.md and keeps the chapter count aligned with chapter 13 only.
In `@scripts/check_skill_examples.py`:
- Around line 104-112: The inline note in the examples table is stale and
references a non-existent allowlist entry, which will confuse future
maintenance. Update the comment in check_skill_examples.py so it points to the
current bare-add example entry in the same block, using the surrounding keys
like the FRAGMENT entries for “Wrong: bare `@Int` + `@Int` without indices” and the
nearby “Correct” entries to confirm the right location.
In `@tests/test_wasi_target.py`:
- Around line 483-494: The `test_random_int_respects_inclusive_bounds` check
only samples `Random.random_int(1, 6)` and can miss a bug where the upper bound
is excluded, so strengthen it with a deterministic boundary case. Extend the
test in `tests/test_wasi_target.py` to also exercise the `Random.random_int`
path with equal lower/upper bounds (for example via a small `_compile_ok`
sample), and assert it returns that exact value so inclusive semantics are
verified without relying on chance.
In `@vera/codegen/wasi.py`:
- Around line 1249-1275: The _get_preopen helper is returning an owned preopen
descriptor from get-directories and the current callers only use it as a
borrowed handle for open-at, which causes component resource leaks on repeated
file operations. Update the preopen handling so the first descriptor is retained
for the process lifetime in the generated WASM, or explicitly drop the owned
descriptor on each file-operation path after open-at; use _get_preopen and the
related open-at call sites as the places to fix this behavior.
- Around line 724-732: The reserved-name validation in wasi.py is too broad
because it scans the entire WAT text for markers like "$wasi_tbl" and
"$__wasi_run", which incorrectly catches string literals and other data
payloads. Update the check in the code path that raises the ValueError so it
only inspects actual WAT identifiers, or explicitly skips data segments before
matching reserved names. Keep the logic centered around the existing reserved
marker loop and the same error message, but narrow the matching so literal
payload content is not treated as a reserved identifier collision.
- Around line 2418-2429: The lifted main export mapping in the wasi codegen path
only handles unit, i64, and f64 results, so i32 scalar mains are missed. Update
the main export logic in the lift/main generation block so `lay.main_results`
also recognizes the i32/bool scalar case and emits the corresponding lifted
`main` function/export, using the existing `lift_result`/`parts.append` flow to
keep the plain `main` export available.
In `@vera/runtime/wasi_host.py`:
- Around line 43-46: The wasi host module is importing WasmTrapError from the
wrong place; switch it to the canonical definition used by the CLI trap handler.
Update the imports in the wasi_host module so WasmTrapError comes from
vera.codegen.api, while keeping only _classify_trap imported from
vera.runtime.traps, and leave the rest of the runner logic unchanged.
---
Outside diff comments:
In `@TESTING.md`:
- Around line 11-13: The conformance program count is inconsistent across
TESTING.md: the overview already uses the new total, but the Conformance Suite
prose still has the old literal. Update every remaining 103 reference in that
document to match the 104 count, using the existing “Conformance programs” and
“Conformance Suite” wording as anchors so the totals stay in sync throughout the
file.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 48bfdf9a-323b-4e9c-b09f-f6cbc394a833
⛔ Files ignored due to path filters (6)
docs/SKILL.mdis excluded by!docs/**docs/index.htmlis excluded by!docs/**docs/index.mdis excluded by!docs/**docs/llms-full.txtis excluded by!docs/**docs/llms.txtis excluded by!docs/**uv.lockis excluded by!**/*.lock,!uv.lock
📒 Files selected for processing (20)
CHANGELOG.mdCLAUDE.mdHISTORY.mdKNOWN_ISSUES.mdREADME.mdROADMAP.mdSKILL.mdTESTING.mdTOOLCHAIN.mdWASI.mdpyproject.tomlscripts/check_doc_builtin_shadowing.pyscripts/check_skill_examples.pyspec/11-compilation.mdspec/13-wasi.mdtests/test_wasi_target.pyvera/__init__.pyvera/cli.pyvera/codegen/wasi.pyvera/runtime/wasi_host.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
aallan/vera-bench(manual)
… narrowing, doc sync - Cache the first preopen descriptor in a $preopen_fd global (sentinel -2): get-directories returns a fresh OWNED descriptor list per call, so the previous per-file-op fetch leaked one handle into the instance's resource table on every IO.read_file/write_file. Same process-lifetime pattern as the cached std stream handles; pinned structurally (single l_get_dirs call site) and behaviorally (60 recursive reads through one instance). - Narrow the reserved-identifier scan to non-data WAT lines: a program PRINTING "$wasi_tbl" is not a collision (regression pair pins both directions: literal accepted, real fn-name collision still rejected). - random_int equal-bounds test (low == high == 4 -> exactly 4) pins upper-bound inclusivity deterministically. - Import WasmTrapError from vera.codegen.api (the CLI's canonical import site; same class object). - Doc sync: README project-structure block (14 chapters / 36 examples), TESTING.md conformance prose (104), stale allowlist note in check_skill_examples.py re-anchored + entries reordered. Co-Authored-By: Claude <[email protected]>
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (3)
HISTORY.md (1)
438-449: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winKeep the release table at 13 spec chapters.
The v0.0.194 column still says 14 here; this should stay aligned with the rest of the release metrics.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@HISTORY.md` around lines 438 - 449, The release metrics table in HISTORY.md has an incorrect spec chapter count for the v0.0.194 column; update the “Spec chapters” value so it stays aligned with the other release metrics and matches the intended 13. Use the existing release table row and the v0.0.194 column as the target location.Source: Path instructions
README.md (1)
222-224: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winKeep the spec chapter total at 13.
This still says 14 chapters in both spots; the published total should remain 13 here.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@README.md` around lines 222 - 224, The README copy still advertises a 14-chapter specification, but the published total should remain 13. Update the wording in the affected prose so both mentions of the spec chapter count are changed to 13, keeping the rest of the Vera status text unchanged.Source: Path instructions
ROADMAP.md (1)
11-11: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winKeep the roadmap spec count at 13.
This status line still says 14 spec chapters.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ROADMAP.md` at line 11, The roadmap status line is reporting the wrong spec chapter count; update the count in the ROADMAP summary so it stays at 13 instead of 14. Find the line that mentions “spec chapters” in ROADMAP.md and change only that displayed number to match the intended total.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/test_wasi_target.py`:
- Around line 594-635: The new CRLF regression coverage in
test_read_line_strips_crlf_like_the_core_host only exercises \r\n, but the core
host’s universal-newlines behavior also normalizes bare \r endings. Extend this
test in tests/test_wasi_target.py (around the existing
test_read_line_strips_crlf_like_the_core_host and _run_component usage) with a
bare-\r input case, such as a tempfile written via NamedTemporaryFile and read
through IO.read_line, to verify the adapter strips lone \r and matches the core
path for old-Mac-style line endings too.
In `@vera/codegen/wasi.py`:
- Around line 1775-1781: The stdin trimming logic in the read path is stripping
a trailing carriage return even when the loop exits on EOF, which changes inputs
like a final CR-terminated byte sequence. Update the newline handling in the
relevant read routine so the `\r` removal is only performed when the terminator
captured by `$b` is `\n`, and leave a trailing `\r` intact when EOF was the stop
condition. Use the existing `$b` state in the `read_byte`/stdin loop to gate the
CR trim in the code around the current newline stripping logic.
---
Duplicate comments:
In `@HISTORY.md`:
- Around line 438-449: The release metrics table in HISTORY.md has an incorrect
spec chapter count for the v0.0.194 column; update the “Spec chapters” value so
it stays aligned with the other release metrics and matches the intended 13. Use
the existing release table row and the v0.0.194 column as the target location.
In `@README.md`:
- Around line 222-224: The README copy still advertises a 14-chapter
specification, but the published total should remain 13. Update the wording in
the affected prose so both mentions of the spec chapter count are changed to 13,
keeping the rest of the Vera status text unchanged.
In `@ROADMAP.md`:
- Line 11: The roadmap status line is reporting the wrong spec chapter count;
update the count in the ROADMAP summary so it stays at 13 instead of 14. Find
the line that mentions “spec chapters” in ROADMAP.md and change only that
displayed number to match the intended total.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 53d06427-f8b3-4857-8a72-417a6023243a
📒 Files selected for processing (8)
CHANGELOG.mdHISTORY.mdREADME.mdROADMAP.mdTESTING.mdspec/13-wasi.mdtests/test_wasi_target.pyvera/codegen/wasi.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
aallan/vera-bench(manual)
|
@coderabbitai The outside-diff TESTING.md finding is fixed in c2bd15b — the Conformance Suite prose now says 104 programs, matching the overview table and |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
git log --oneline -1 c2bd15b -- TESTING.md 2>/dev/null
grep -n "104 program" TESTING.md
grep -n "Conformance Suite" -A3 TESTING.mdLength of output: 2161
|
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
vera/codegen/wasi.py (1)
724-741: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winReserved-marker scan still over-matches by substring — trailing boundary missing.
The fix correctly excludes
(data ...)payloads now, but the match itself is still a plain substring check (marker in ident_lines) for$wasi_tbl,$wasi_arena_ptr,$cabi_realloc, and$__wasi_run. Since Vera function names compile directly to$<name>(confirmed bytest_identifier_collision_is_still_rejectedin the test file), a user fn named e.g.wasi_tblishorcabi_reallocationwould false-positive: its WAT identifier$wasi_tblishcontains$wasi_tblas a prefix and gets rejected as a "reserved identifier collision" even though it's a distinct name.$wasi_sig_is fine as-is since it's an intentional prefix family, but the other four markers are meant to be exact-identifier matches.🐛 Proposed fix — require a non-identifier char (or end-of-string) after the marker
for marker in ( - "$wasi_tbl", "$wasi_arena_ptr", "$cabi_realloc", - "$__wasi_run", "$wasi_sig_", + "$wasi_tbl", "$wasi_arena_ptr", "$cabi_realloc", "$__wasi_run", ): - if marker in ident_lines: + if re.search(re.escape(marker) + r"(?![A-Za-z0-9_])", ident_lines): raise ValueError( f"program defines the reserved identifier {marker!r}; " "--target wasi-p2 cannot compile it" ) + if "$wasi_sig_" in ident_lines: # intentional prefix family + raise ValueError( + "program defines an identifier reserved for wasi-p2 shim " + "signatures ('$wasi_sig_*'); --target wasi-p2 cannot " + "compile it" + )
reis already imported/used elsewhere in this module (e.g. themain_resultsregex a few lines below), so no new import is needed.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@vera/codegen/wasi.py` around lines 724 - 741, The reserved-identifier check in wasi.py is still using a raw substring match inside the marker scan, so exact reserved names like $wasi_tbl, $wasi_arena_ptr, $cabi_realloc, and $__wasi_run can falsely match longer user identifiers such as $wasi_tblish. Update the collision logic around the ident_lines loop to require a proper identifier boundary after those markers (or end-of-string), while keeping $wasi_sig_ as the intended prefix-family exception; use the existing regex support in this module rather than a plain “marker in ident_lines” check.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/test_wasi_target.py`:
- Around line 1158-1190: The reserved-identifier tests in TestReservedMarkerScan
only cover an exact match and a literal string case, so they miss the substring
false-positive where names like wasi_tblish are incorrectly rejected. Add a
regression test alongside test_identifier_collision_is_still_rejected that
defines an allowed identifier containing the reserved marker as a substring and
verifies emit_wasi_component does not raise ValueError, while keeping the exact
reserved name rejection test unchanged. This will lock in the boundary behavior
for the reserved-identifier check.
---
Outside diff comments:
In `@vera/codegen/wasi.py`:
- Around line 724-741: The reserved-identifier check in wasi.py is still using a
raw substring match inside the marker scan, so exact reserved names like
$wasi_tbl, $wasi_arena_ptr, $cabi_realloc, and $__wasi_run can falsely match
longer user identifiers such as $wasi_tblish. Update the collision logic around
the ident_lines loop to require a proper identifier boundary after those markers
(or end-of-string), while keeping $wasi_sig_ as the intended prefix-family
exception; use the existing regex support in this module rather than a plain
“marker in ident_lines” check.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 224ebe57-b4ae-4ca4-b0b7-36c3a28053bd
📒 Files selected for processing (8)
HISTORY.mdREADME.mdROADMAP.mdTESTING.mdscripts/check_skill_examples.pytests/test_wasi_target.pyvera/codegen/wasi.pyvera/runtime/wasi_host.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
aallan/vera-bench(manual)
|
CI round 2 at |
…n tail pins - The reserved-marker scan now requires an identifier boundary after each exact marker ($wasi_tblish is a different identifier, not a collision; $wasi_sig_ stays the deliberate prefix family) — pinned by an acceptance test that runs a fn named wasi_tblish end to end, mutation-validated RED with the boundary disabled. - Two stdin tail pins, each verified against the core host's universal-newlines behavior first: \r-at-EOF IS stripped (Python's text layer treats it as a line break — gating the strip on a \n terminator would diverge from the core path), and a lone \r separator stays content per the documented spec §13.6 divergence. Co-Authored-By: Claude <[email protected]>
|
@coderabbitai The outside-diff marker-scan finding is fixed in a49219f — exact reserved markers now require an identifier boundary ( |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
git log --oneline -1 a49219f 2>/dev/null
grep -n "wasi_sig_" vera/codegen/wasi.py | head -20
grep -n "lookahead\|re.escape" vera/codegen/wasi.py | head -20Length of output: 2186
The marker-scan fix in a49219f sounds correct: anchoring reserved-marker matches to an identifier boundary via Noted on the chapter-count resolution as well — with |
…-p2-target Conflict resolution: the #846/#848 [Unreleased] Fixed bullets ride the v0.0.194 section this PR cuts (the queued-entries convention); doc counts recomputed against the merged tree (5,768 tests); main's updated TESTING rows for test_codegen_gc_rooting / test_runtime_traps kept. #847 is closed by #846, so no KNOWN_ISSUES row returns. Co-Authored-By: Claude <[email protected]>
…being parked in await Server arrival is produced by the executor worker thread and says nothing about the main thread's position; interrupt_main() only sets a pending SIGINT flag, and firing it early let the flag materialize outside execute()'s protected region on slow runners (xdist worker crash on two macOS jobs, exit_code=None on ubuntu — 3/12 matrix jobs at PR #849's merge head). The interrupter now polls sys._current_frames() until the main thread's stack shows host_async_await -> Future.result before firing (bounded deadline so the test can never hang); the sub-second local runtimes prove the gate matches rather than falling through to the deadline. Analysis on the reopened #848. Co-Authored-By: Claude <[email protected]>
What
An experimental WASI Preview 2 target (IO + Random surface) —
vera compile/run --target wasi-p2(#237) — and release v0.0.194. Stage C of the server-effects sprint (WASI.md).The honesty bar from the plan: programs whose host-import surface is IO/Random emit pure wasip2 components runnable by stock wasmtime — and anything else is a diagnostic naming the family, never a silent fallback. This closes #237 as written (its listed ops are exactly the IO family); it is not a blanket "WASI 0.2 compliant" claim.
Design (validated live before implementation)
Every WASI import spelling and both entry lifts were proven by live
Component(engine, wat)parse andLinker.add_wasip2()instantiation before the emitter was written — parse-only validation missed a real bug (filesystemerror-codecase 6 isquota, notdisk-quota) that only instantiation caught.vera/codegen/wasi.py): the component wraps the unchanged core module — each(import "vera" "op")becomes a same-namedcall_indirectshim through a funcref table MAIN defines and exports; a generated adapter core module implements all 14 IO/Random ops (+contract_fail/overflow_trap) over canon-lowered WASI imports and elem-plants itself into the table at instantiation, strictly before any lifted export can run. The naive main↔adapter topology is an instantiation cycle (forbidden); the table is defined after the closure table so existingcall_indirectsites keep table 0.cabi_reallocbumps over a fixed 64 KiB region belowgc_heap_start(reset per op; 128-byte retptr slab), so the mark-sweep GC never scans it and a collection can never move a half-written host block (the Conway's Life at 12x30 still corrupts strings from gen 1 onwards (additional trigger beyond #588) #593/Map<K, T_heap> values stored in _map_store are invisible to conservative GC scan — post-walk reachability of JObject children #695 UAF class, host-side). Data crossing back into Vera is copied out under WAT-level shadow-stack rooting — pinned by a 500-arg GC-pressure stress with collections mid-copy-loop; oversized argv traps cleanly at the arena cap.i32.load8_u, noti32.load— slab reuse leaves garbage in the padding; found live as an EOFerr(closed)misread aslast-operation-failedwith a stale list length as a "handle" (unknown handle index 16).vera/runtime/wasi_host.py): always sets aWasiConfig(config-less wasip2 call = process SIGABRT, per the spike), captures stdout/stderr intoExecuteResult(+ the IO.print buffered until exit — animations and TUIs invisible #543 live tee with an incremental UTF-8 decoder — the 4096-byte write cap can split multibyte sequences), snapshotsos.environ, preopens the cwd, and classifies traps into the Runtime traps need Vera-native diagnostics, not raw wasmtime stack traces #516 kind taxonomy from the backtrace text + the WASI stderr channel (contract_violationkeeps the full violation text; structured frames don't cross the component boundary — spike check 5's documented degradation,framesis empty).wasi:cli/[email protected](what stockwasmtime runinvokes) + a plain liftedmainfor scalar returns; String/heap-returningmainruns viawasi:cli/runwith no value (documented).wasi:cli/exitcarries ok/err only, soIO.exit(n)degrades to 0/1 under every wasip2 host; no structured trap frames; launch-time env snapshot.Tests (RED-first; 8 mutations killed)
tests/test_wasi_target.py(139 tests):wasi:cli/rundrive, env hit/miss + 200-var scan, argv (argv[0] skip, 500-arg GC stress, >64 KiB trap), file round-trips +Err("no-entry")/no-preopen errno mapping, 64 KiB chunked read, stdin incl. UTF-8 multibyte + EOF parity, time bracketing, sleep, random bounds, exit, contract-violation text on WASI stderr, overflow.--target wasmWAT untouched.Componentparse — a core module fails it),--watcomponent text, family-gate diagnostics in text + JSON,vera runvalue/stdout/JSON envelopes, exit 0/1 degradation,--fnrejection, trap-kind classification through the component boundary.main-less, 1 wall-clock (all loud skips). The sweep caught a real bug:handle[Exn]components need the exceptions proposal enabled on the runner's engine (fixed; the two EH programs now pass the differential).wasmtimeCLI (skips where not installed).Found in passing
#847 — pre-existing core bug (no WASI involved):
IO.argselements were not GC-rooted against later allocations; out-of-bounds trap underVERA_EAGER_GC=1, latent otherwise. Localized by a host-parity differential (Python host and WASI adapter corrupt byte-identically → guest-side rooting, not the adapter). Filed as #847; the maintainer-driven PR #846 landed the pair-let rooting fix (that issue is handled there, so this PR carries no KNOWN_ISSUES row for it). Also fixed durably: the doc-builtin-shadowing scanner now skips.claude/(session worktrees carry repo copies that re-flagged every spec chapter).Also fixes #848 (round 2)
The #846 print-reorder de-flake proved insufficient at this PR's merge head: 3/12 matrix jobs failed with new modes (xdist worker crash ×2,
exit_code=None×1). Root cause: the interrupter fires on server arrival — produced by the executor worker thread regardless of the main thread's position — andinterrupt_main()only sets a pending SIGINT flag, which on slow runners can materialize outsideexecute()'s protected region. The interrupter now also pollssys._current_frames()until the main thread is verifiably parked inhost_async_await→Future.result(the interruptible wait the #595 machinery intercepts) before firing, with a bounded deadline so the test can never hang. Sub-second local runtimes (vs the 10 s deadline) prove the gate matches rather than falling through. Full analysis on the reopened #848.Docs
New
spec/13-wasi.md(architecture, arena, supported surface, entries, divergences, conformance evidence); spec §11.1 target pointer; README (commands + honest feature paragraph); SKILL.md §WASI Preview 2 compilation; TOOLCHAIN.md recipe; CLAUDE.md commands + chapter range; WASI.md loose-ends closed (spike keepers landed as this suite); allowlist re-anchors (3 fixer duplicate-key collisions resolved against real fence lines — the #606 pitfall, again).Release v0.0.194
Version sync (6 sites), CHANGELOG section + link refs, ROADMAP (#237 removed; #406 gate note updated), HISTORY Stage-16 row + By-the-numbers v0.0.194 "WASI 0.2 target" column appended (the lead sentence was also stale at "Six releases" for a 7-column table — now "Eight"/8; maintainer's call whether this column stays permanent like Inference/HttpServer or gets refreshed away by the next routine release), doc counts (5,754 tests / 90 files / 14 spec chapters).
Verification
ruff check(+--select S) clean without--fixvera compile --target wasi-p2artifact runs under stockwasmtime runwith no flagsCloses #237
Closes #848
🤖 Generated with Claude Code
Summary by CodeRabbit
wasi-p2command-line workflows and updated project guidance..claude/directories.