feat(wasi): --world server — verified HTTP handlers as wasi:http components — v0.0.195 - #850
Conversation
…onents — v0.0.195 vera compile --target wasi-p2 --world server packages the same contract-checked handle(Request -> Response) program vera serve hosts natively as a wasi:http/incoming-handler@0.2.0 component that stock wasmtime serve runs unmodified (live-tested: routing, handler headers, 1 MiB body byte-identical under GC stress, trap -> 500, @0.2.3 links). Headers work without a host: the String-keyed Map ops are implemented in guest WAT with exact host-semantics parity, pinned by a host-vs- served differential battery. The server-world surface is explicit — IO print/stderr only; stdin/filesystem/env ops rejected with diagnostics (negative-probed: they do not link under the proxy world); bodies buffered; cli-world emission byte-identical (pinned). vera run rejects server artifacts with a pointer to wasmtime serve. Design live-validated before implementation; five mutation kills. Spec §13.7; WASI.md check-7 loose ends closed. Co-Authored-By: Claude <noreply@anthropic.invalid>
|
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 (4)
🔗 Linked repositories identifiedCodeRabbit considers these linked repositories for cross-repo context during reviews:
📝 WalkthroughWalkthroughThis PR adds ChangesServer-world compiler and CLI feature
SKILL.md allowlist re-keying
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant CLI as vera/cli.py
participant Emitter as emit_wasi_component
participant ServerPipeline as _emit_server_component
participant Wasmtime as wasmtime serve
User->>CLI: vera compile --target wasi-p2 --world server file.vera
CLI->>Emitter: emit_wasi_component(result, world="server")
Emitter->>ServerPipeline: validate, gate, and assemble server component
ServerPipeline-->>Emitter: wasi:http/incoming-handler component
Emitter-->>CLI: compiled component
CLI-->>User: server component output
User->>Wasmtime: wasmtime serve component.wasm
Wasmtime->>Wasmtime: invoke handle(Request -> Response)
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 #850 +/- ##
==========================================
+ Coverage 92.00% 92.01% +0.01%
==========================================
Files 95 95
Lines 28363 28677 +314
Branches 332 332
==========================================
+ Hits 26095 26387 +292
- Misses 2260 2282 +22
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:
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 `@TESTING.md`:
- Line 9: The test overview counts are inconsistent in the Tests row, so update
the summary in TESTING.md to make the total match the breakdown. Reconcile the
values shown for passed, stress, and skipped tests against the total, and adjust
either the total or one of the subcounts so the numbers add up consistently in
the overview table.
In `@vera/cli.py`:
- Around line 404-425: Move the pure CLI flag validation in cli.py so the
world/target compatibility check runs before _load_and_parse and
codegen_compile, since it only depends on world and target and not on result.
Keep the wasi-p2 emit gating that uses result in place, but hoist the existing
world != "cli" and target != "wasi-p2" guard to return the error immediately for
invalid flag combinations, both in normal and as_json paths.
In `@vera/codegen/wasi.py`:
- Around line 2668-2674: Add a wasmtime serve smoke test that exercises the
server-side IO surface exposed by _SERVER_IO_OPS in vera/codegen/wasi.py. Extend
tests/test_wasi_target.py with a round-trip test that actually runs under
wasmtime serve and calls IO.time, IO.sleep, and Random.random_* instead of only
verifying the component loads. Use the existing
test_time_sleep_random_handler_parses_as_component and the server-world wiring
around time/sleep/random_* as the entry point so the new test catches
proxy-world drift in the clock/random adapters.
🪄 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: cfb5d2d5-7457-4073-b430-bd0031f19a33
⛔ 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 (17)
CHANGELOG.mdCLAUDE.mdHISTORY.mdREADME.mdROADMAP.mdSKILL.mdTESTING.mdTOOLCHAIN.mdWASI.mdpyproject.tomlscripts/check_skill_examples.pyspec/13-wasi.mdtests/test_wasi_target.pyvera/__init__.pyvera/cli.pyvera/codegen/wasi.pyvera/runtime/server.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
aallan/vera-bench(manual)
…ion, teardown kill fallback - vera run --world server with the DEFAULT target now gives the same usage error cmd_compile gives instead of a message implying the user asked for wasi-p2; the previously-untested default-target path gets a test. - CHANGELOG @0.2.3 phrasing corrected (imports are pinned @0.2.0; wasmtime's semver-compatible lookup links them — the design study probed @0.2.3 acceptance separately). - Spec §13.7 server-world surface now lists IO.time / IO.sleep / Random (implementation accepted them; prose understated). - The serve-smoke context manager force-kills on SIGTERM timeout instead of leaking the process. Co-Authored-By: Claude <noreply@anthropic.invalid>
Review round 1 — pr-review-toolkit code-reviewerEmpirical review of Confirmed by execution: family-gate completeness — shim emitted ⟺ dispatch slot populated (both derive from the same Four low-severity nits, all fixed in the follow-up commit:
|
…clock/random smoke - The pure --world/--target flag validation now fires before any parse/compile work in both cmd_compile and cmd_run (an incompatible combo no longer costs a compile round-trip to discover). - TESTING.md overview breakdown reconciled (5,742 + 26 + 40 = 5,808). - New serve-smoke test executes IO.time / IO.sleep / Random.random_int through a real request under stock wasmtime serve (the surface was previously parse-tested only) — time bracketed against the host clock with the established cross-clock slack, random range-checked. Co-Authored-By: Claude <noreply@anthropic.invalid>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
README.md (1)
185-185: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMention the
--world/--targetgating rule.The paragraph documents
--world serveras the deployment path but doesn't note that it's only valid with--target wasi-p2(enforced bycmd_compile/cmd_run, per this PR's cli.py changes). As per path instructions forREADME.md, the wasi-p2 description should "explicitly mention ... that server-world behavior is enforced by the target/world gating rules."🤖 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` at line 185, The README wording for the wasi-p2 section omits the target/world gating rule, so update the `vera compile --target wasi-p2` and `--world server` description to explicitly state that server-world behavior is only allowed with `--target wasi-p2` and is enforced by the `cmd_compile`/`cmd_run` checks. Keep the focus on the `--target wasi-p2` and `--world server` contract so readers understand the server deployment path is gated by those options, not available independently.Source: Path instructions
♻️ Duplicate comments (2)
TESTING.md (1)
9-9: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winOverview "Tests" breakdown still doesn't add up.
5,735 passed + 26 stress + 40 skipped = 5,801, not5,807. This exact inconsistency was flagged in a previous review round (then the total was5,806, off by 5) and remains unresolved — it's now off by 6 since this PR bumps the total by 1 (the newtest_run_world_without_wasi_p2_is_a_usage_errortest) without updating the passed sub-count.🤖 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` at line 9, The Tests summary in TESTING.md is inconsistent because the total count does not match the sub-counts. Update the breakdown near the Tests table so the total in the row matches the sum of passed, stress, and skipped tests, and make sure the passed count reflects the newly added test_run_world_without_wasi_p2_is_a_usage_error. Use the Tests row in TESTING.md as the source of truth and adjust the numbers so they add up exactly.vera/cli.py (1)
404-425: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valuePure flag-validation still runs after a full compile (now in two places).
world != "cli" and target != "wasi-p2"depends only on the CLI flags, yet bothcmd_compile(404-425) and the newcmd_runcopy (763-782) check it only after_load_and_parse/codegen_compilesucceeds. A user who passes--world serveron a program that also fails to compile burns a full compile cycle before learning the flags were wrong. This was already raised as non-blocking/optional in a prior review round forcmd_compile; it's now duplicated verbatim incmd_run.Also applies to: 763-782
🤖 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/cli.py` around lines 404 - 425, Move the pure flag check for `world != "cli" and target != "wasi-p2"` in `cmd_compile` and the duplicated `cmd_run` logic so it runs before `_load_and_parse` or `codegen_compile` starts. Keep the existing error formatting and JSON/stderr handling, but validate the CLI flags first using the same `world`, `target`, `as_json`, and `msg` logic so invalid combinations fail fast without doing a full compile.
🤖 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.
Outside diff comments:
In `@README.md`:
- Line 185: The README wording for the wasi-p2 section omits the target/world
gating rule, so update the `vera compile --target wasi-p2` and `--world server`
description to explicitly state that server-world behavior is only allowed with
`--target wasi-p2` and is enforced by the `cmd_compile`/`cmd_run` checks. Keep
the focus on the `--target wasi-p2` and `--world server` contract so readers
understand the server deployment path is gated by those options, not available
independently.
---
Duplicate comments:
In `@TESTING.md`:
- Line 9: The Tests summary in TESTING.md is inconsistent because the total
count does not match the sub-counts. Update the breakdown near the Tests table
so the total in the row matches the sum of passed, stress, and skipped tests,
and make sure the passed count reflects the newly added
test_run_world_without_wasi_p2_is_a_usage_error. Use the Tests row in TESTING.md
as the source of truth and adjust the numbers so they add up exactly.
In `@vera/cli.py`:
- Around line 404-425: Move the pure flag check for `world != "cli" and target
!= "wasi-p2"` in `cmd_compile` and the duplicated `cmd_run` logic so it runs
before `_load_and_parse` or `codegen_compile` starts. Keep the existing error
formatting and JSON/stderr handling, but validate the CLI flags first using the
same `world`, `target`, `as_json`, and `msg` logic so invalid combinations fail
fast without doing a full compile.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: aeec6706-b0a7-4220-b02d-4b999ac162a1
📒 Files selected for processing (8)
CHANGELOG.mdHISTORY.mdREADME.mdROADMAP.mdTESTING.mdspec/13-wasi.mdtests/test_wasi_target.pyvera/cli.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
aallan/vera-bench(manual)
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
vera/cli.py (2)
1616-1620: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winDiagnostic dict is missing the
locationfield carried by every other envelope in this file.All other JSON diagnostics in
cmd_compile/cmd_run(and the file-not-found / trap paths) include"location": {"line": 0, "column": 0}. A consumer that readsdiag["location"]willKeyErroronly on this invalid---worldpath. Given the JSON CLI output is a documented stability contract, keep the shape uniform.🔧 Proposed fix
if use_json: print(json.dumps({"ok": False, "file": "", "diagnostics": [{"severity": "error", - "description": msg}]}, + "description": msg, + "location": {"line": 0, "column": 0}}]}, indent=2))As per path instructions: "JSON CLI output fields are a stability contract".
🤖 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/cli.py` around lines 1616 - 1620, The JSON envelope in the invalid-`--world` branch is missing the standard `location` field, unlike the other diagnostic payloads in `cmd_compile`, `cmd_run`, and the file-not-found/trap paths. Update the `use_json` branch in this CLI handler to emit the same diagnostic shape by adding a `location` object with line and column set to 0 inside the `diagnostics` entry, keeping the JSON output consistent with the rest of the file.Source: Path instructions
775-799: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winOptional: this server-world refusal never touches
result, so it can hoist above the compile.The
world == "server"branch depends only onworld(and by the Line 618 gate,targetis already guaranteed to bewasi-p2when we get here). As placed,vera run --world server --target wasi-p2on a program that also fails to compile shows the compile error first; the user fixes it, recompiles, and only then learnsvera runcannot host the component — the same two-round-trip pattern that motivated hoisting the pure flag check earlier in this PR. Moving this block just below the Line 631 validation gives immediate, program-independent feedback and skips a discarded compile. Non-blocking.🤖 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/cli.py` around lines 775 - 799, The `world == "server"` refusal in `vera.cli.run` is independent of compilation and only depends on the already-validated `world`/`target` state, so it should be checked earlier. Hoist this branch to immediately after the existing `target`/world validation in `run` so `vera run --world server --target wasi-p2` fails fast with the hosting error instead of first reporting unrelated compile failures; keep the same `msg`, JSON error path, and stderr behavior.
🤖 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.
Outside diff comments:
In `@vera/cli.py`:
- Around line 1616-1620: The JSON envelope in the invalid-`--world` branch is
missing the standard `location` field, unlike the other diagnostic payloads in
`cmd_compile`, `cmd_run`, and the file-not-found/trap paths. Update the
`use_json` branch in this CLI handler to emit the same diagnostic shape by
adding a `location` object with line and column set to 0 inside the
`diagnostics` entry, keeping the JSON output consistent with the rest of the
file.
- Around line 775-799: The `world == "server"` refusal in `vera.cli.run` is
independent of compilation and only depends on the already-validated
`world`/`target` state, so it should be checked earlier. Hoist this branch to
immediately after the existing `target`/world validation in `run` so `vera run
--world server --target wasi-p2` fails fast with the hosting error instead of
first reporting unrelated compile failures; keep the same `msg`, JSON error
path, and stderr behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 6e413643-446f-4ac3-b7bd-4636fb8049aa
📒 Files selected for processing (6)
HISTORY.mdREADME.mdROADMAP.mdTESTING.mdtests/test_wasi_target.pyvera/cli.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
aallan/vera-bench(manual)
… fields, README gating clause - The world==server run-refusal now fires before any parse/compile work in cmd_run, matching the hoisted flag validation (the message, JSON shape, and stderr behavior are unchanged). - main()'s --target and --world invalid-value JSON envelopes gain the standard location field (JSON CLI output fields are a stability contract; the --target gap was pre-existing and identical). - README's wasi-p2 paragraph states the gating rule explicitly: --world server is only valid with --target wasi-p2. Skip-changelog: CLI diagnostic-shape polish + README clause within the v0.0.195 feature already described in this PR's CHANGELOG section Co-Authored-By: Claude <noreply@anthropic.invalid>
…side the guarded class The new test_time_sleep_random_execute_under_serve was appended after TestCliServerWorld rather than inside the skipif-guarded TestWasmtimeServeSmoke class, so every CI test job at 32aea1c failed with FileNotFoundError: 'wasmtime' (runners lack the CLI; it passed locally where wasmtime exists). The test now carries its own skipif with a docstring note on why. Skip-changelog: test-only guard fix within this PR's feature Co-Authored-By: Claude <noreply@anthropic.invalid>
|
@coderabbitai Outside-diff findings, all resolved:
Separately: the all-red CI at 32aea1c was my test-placement error — the new clock/random serve smoke sat outside the skipif-guarded class and hit |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -e
git fetch origin pull/850/head:pr850 2>&1 | tail -5
git checkout pr850 2>&1 | tail -5
echo "---README.md gating clause---"
grep -n "world server" README.md | head -20
echo "---TESTING.md tests row---"
grep -n "5,742\|5,808\|5,768" TESTING.md
echo "---cli.py world/target validation hoist---"
rg -n "def cmd_compile|def cmd_run" vera/cli.py
echo "---cmd_run body head---"
sed -n '/def cmd_run/,/^def /p' vera/cli.py | head -60
echo "---location field in json envelopes---"
rg -n "location" vera/cli.py | head -30Length of output: 6102 All confirmed — the fixes match your summary exactly: README.md's gating clause is in place (Line 185), TESTING.md's Tests row correctly reads 5,742 passed + 26 stress + 40 skipped = 5,808 (Line 9), and |
What
--world server— verified HTTP handlers as portable wasi:http components and release v0.0.195. Stage D of the server-effects sprint (WASI.md); builds on the v0.0.194 WASI Preview 2 target (#237) and the v0.0.193<HttpServer>effect (#305). Refs #237, #305 (both closed; lineage only).vera compile --target wasi-p2 --world server examples/http_server.vera wasmtime serve examples/http_server.wasm # stock CLI, no flagsOne contract-verified
handle(@Request -> @Response)program, two deployment paths: the nativevera servedriver (#305, unchanged) and now awasi:http/incoming-handler@0.2.0component any wasi:http host can run. Live-tested under stockwasmtime serve46.0.1: routing, handler-set headers, a 1 MiB body byte-identical under GC stress, guest trap → host 500,@0.2.3semver linking.Design (live-validated before implementation, per the Stage-C pattern)
$Libctwo-module realloc dodge proved unnecessary — recorded inWASI.md); the serve wrapper lives in the adapter, importing the wasi:http lowers directly plus MAIN'shandle/alloc/GC globals; dispatch table 16→32 slots. Every request-half import spelling and flattening was proven by wasmtime-py parse and a served round-trip before the emitter was written.Request/Responseheaders areMap<String, String>, whose operations are host imports on the core target. A Vera Map is two plain guest-heap blocks, so the server world implements the String-keyed Map ops in guest WAT with the host's exact semantics (position-preserving update, later-insert-wins, power-of-two capacity, entry shadow-pushes), pinned by a host-vs-served differential battery (mixed-case / absent / duplicate / 41-header matrix, insertion-order agreement). Non-String instantiations and all other collection families stay gated.$serve_handlereads method / path-with-query / headers / body into the GC-exempt arena, copies out into the guest-heapRequestADT from the compilation's ownadt_layouts(WAT-level shadow-stack rooting throughout), callshandle, decodesResponse, and drives the outgoing-response sequence (borrow-before-transfer, child-stream-drop-before-finish, 4096-byte chunks). Status u16 pre-check and forbidden-header errors answer 500 gracefully instead of trapping the server (live-tested with status 70000).IO.print/IO.stderrroute to the serve console;read_line/read_char/read_file/write_file/get_env/args/exitare rejected — negative-probed: those imports do not link under the wasi:http proxy world. Bodies buffered (streaming is future work); request headers share the ~63 KiB arena..pycfalse green; purged and confirmed RED).vera runrejects server-world artifacts with a pointer towasmtime serve(wasmtime-py's built-in host has no wasi:http and no resource-definition API — verified).Tests (RED-first; 5 mutation kills)
33 new emitter tests + 5 CLI tests in
tests/test_wasi_target.py: server-world parse battery, family-gate diagnostics (8), cli-world byte-pin (3), layout tripwires, and a 9-test livewasmtime servesmoke (skipif no CLI) — example round-trips, the header-matrix differential, map-order differential,IO.printconsole routing, trap→500 withrequirestext, graceful-500 paths, 1 MiB + 50-header GC stress, plus an in-suite eager-GC shadow-push mutation-validation test that performs its own surgery deterministically. CLI: server component parse,--watexport check,vera runrejection,--world-requires-wasi-p2, missing-handler diagnostic.Mutations killed: later-wins→first-wins (header differential RED), map update→append (order differential RED), Request-build shadow-push dropped (500 vs 200), server table size leaked into cli emission (pin RED after
.pycpurge), family-gate line removed (exactly its test RED).Docs + release v0.0.195
Spec §13.7 (server world) with conformance renumbered §13.8; TOOLCHAIN/README/SKILL/CLAUDE command surfaces;
WASI.mdcheck-7 loose ends closed ($Libcandincoming-body.finishsuperseded, with the design-study evidence); CHANGELOG v0.0.195 + link refs; version sync (6 sites); HISTORY Stage-16 row + By-the-numbers trailing column refreshed to v0.0.195; doc counts (5,806 tests).Verification
ruff check(+--select S) clean without--fixexamples/http_server.veraserved by stockwasmtime serve, no flags🤖 Generated with Claude Code
Summary by CodeRabbit
serverworld forwasi:httpcomponents, runnable withwasmtime serve(including adapter behaviour) and supported viavera serve.--worldoption forvera compile/vera runto select CLI vs server component modes (withvera runrejecting server-world hosting).letbindings.wasmtime serverequest/response parity.CHANGELOG,HISTORY,README,TOOLCHAIN,SKILL,WASI,ROADMAP, andspecto document--world serverworkflows and the v0.0.195 release.