Handoff prompt — finish Phase 33 (33J3-polish + 33J4–J7 + 33J7-prereq + 33L + 33M)
This brief covers the remaining slices in Phase 33 (the launch phase). It is a single document because the slices share context, but each slice is independently scoped and can be executed by a different person or coding agent. Read the shared header, then jump to the slice you are working on.
What is shipped
- 33J1 — Marketing landing page at https://corvid-lang.org (single-page hero / problem / demo / effect-algebra / inventions / examples / community / CTA, ~1,100 lines of HTML).
- 33J2 — Diataxis-style docs tree in the main repo
(
docs/book/,docs/guides/,docs/recipes/,docs/reference/,docs/migration/,docs/operations/,docs/security/,docs/internals/,docs/help/,docs/meta/,docs/phases/). - 33J3 — Docs site live at https://corvid-lang.org/docs rendering all 11 sections with syntax highlighting and search.
What remains
| Slice | Title | Audience |
|---|---|---|
| 33J3-polish | Highlight declaration names in the docs grammar | Frontend / website developer |
| 33J4 | Benchmark page | Frontend / website developer |
| 33J5 | Blog shell + first launch post | Frontend + writer |
| 33J6 | Grammar drift-gate test | Rust developer |
| 33J7-prereq | corvid-browser crate — WASM-compatible typechecker | Rust developer (BLOCKS 33J7) |
| 33J7 | WASM playground | Frontend + Rust developer |
| 33L | Launch materials (video + announcement drafts + review) | Dev-rel / marketing |
| 33M | Beta program (20 external developers + feedback triage) | Dev-rel / community |
After all six close, Phase 33 closes, v1.0 launches.
The repos
- Corvid language repo — source of truth for code and docs.
- URL: https://github.com/Micrurus-Ai/Corvid-lang
- Docs live at
docs/; benchmarks live atbenches/. - Most slices below should not edit this repo. Slice 33J6 (Rust test) is the only one that lands code here.
- Corvid website repo — landing page + docs site.
- URL: https://github.com/Micrurus-Ai/corvid-website
- Most website-side slices (33J4, 33J5, 33J7) land here.
What Corvid is (one paragraph for context)
Corvid is a programming language where dangerous AI actions
either compile with a proof or do not compile at all. The
compiler reads approve, Grounded<T>, effect rows, and budget
annotations the way other compilers read types. You do not need
to learn the language to do any slice below — you need to render
already-written content (33J4, J5), wire test infrastructure
(33J6), expose the compiler in a browser (33J7), or produce
launch artifacts about it (33L, 33M).
No-shortcut rules (apply to every slice)
These are the project’s hardest rules. Honor them.
- No optimistic ticking. A slice ticks only when its acceptance criteria are observably met. Do not tick a checkbox because “most of it” is done.
- Pre-phase chat before code. Confirm scope with the maintainer before writing code. Mid-slice scope changes are the failure mode this prevents.
- One slice per commit boundary. A slice is not done until
its commit is on
mainof the relevant repo and the next slice has not yet started. - Update
learnings.mdwith each user-visible slice. No drift between shipped behavior and the learnings record. - No editing auto-generated files.
docs/reference/core-semantics.mdis regenerated bycorvid contract regen-doc. Treat it as read-only. - Truth in launch wording. Phase 35V spent multiple verification slices tightening aspirational launch wording. Do not re-introduce claims wider than what ships.
Slice 33J3-polish — Highlight declaration names in the docs grammar
Goal
Fix a real gap in the deployed Corvid TextMate grammar at
docs-site/src/grammars/corvid.tmLanguage.json (in the
Micrurus-Ai/corvid-website repo): declaration names (the
identifier after agent, tool, prompt, fn, effect,
struct, type, server) are not highlighted. Only function
calls (identifier before () get entity.name.function.corvid.
So in agent refund_bot(...), the word refund_bot falls
through to plain identifier color instead of the function-name
color visible on call sites.
Surfaced during a structural review of the deployed grammar after slice 33J3 shipped at https://corvid-lang.org/docs.
Audience
Frontend / website developer working in
Micrurus-Ai/corvid-website.
Concrete deliverable
A single edit to
docs-site/src/grammars/corvid.tmLanguage.json adding two
rules of roughly this shape, placed before the generic
keyword and identifier rules so they match first:
{ "match": "\\b(agent|tool|prompt|fn)\\s+([a-z_][A-Za-z0-9_]*)", "captures": { "1": { "name": "keyword.declaration.corvid" }, "2": { "name": "entity.name.function.corvid" } }},{ "match": "\\b(effect|struct|type|server)\\s+([a-z_][A-Za-z0-9_]*)", "captures": { "1": { "name": "keyword.declaration.corvid" }, "2": { "name": "entity.name.type.corvid" } }}Acceptance criteria
- Visiting
https://corvid-lang.org/docs/book/03-tutorial-refund-agent
shows declaration names (e.g.
handle_refundinagent handle_refund(...)) rendered in the same color as call sites later on the same page. - Same fix verified on at least three pages:
book/03-tutorial-refund-agent,book/02-quickstart,recipes. - No regression on existing scopes: keywords still
highlight,
approve <Action>still highlights its action name, types still highlight,#:doc comments still gray. - Build is reproducible (
pnpm buildor whatever the website’s build command is) and the new grammar lands in the deployed bundle.
Constraints
- The grammar file is the source of truth for highlighting on every Corvid code block on the docs site. Test locally before merging — render at least the three pages above.
- Do not change Shiki theme or Expressive Code config in this slice; this is a grammar-only fix.
- Match the existing coding style in
corvid.tmLanguage.json(scope naming, regex format, ordering).
Out of scope
- Rewriting the grammar wholesale (this is a one-rule addition).
- Highlighting effect-row member names inside
usesclauses (separate polish slice). - Highlighting agent annotation names like
@budget,@retry(separate polish slice; would need ameta.annotation.corvidscope). - LSP-style features (out of scope for the docs site; see
docs/guides/editor-and-lsp.md).
Reference
- The grammar file: https://github.com/Micrurus-Ai/corvid-website/blob/main/docs-site/src/grammars/corvid.tmLanguage.json
- The deployed docs page to verify against: https://corvid-lang.org/docs/book/03-tutorial-refund-agent
- TextMate grammar reference: https://macromates.com/manual/en/language_grammars
- Shiki / Expressive Code grammar loading: https://expressive-code.com/key-features/syntax-highlighting/
Slice 33J4 — Benchmark page
Goal
A /benchmarks page on the website that renders the moat
benchmarks honestly: the headline numbers, the methodology, the
“honest slower” framing, and links to the reproducibility
archives.
Inputs (in the main repo)
The benchmarks live under benches/:
benches/├── moat/│ ├── README.md ← moat-benchmark overview│ ├── compile_time_rejection/│ │ ├── README.md│ │ ├── RESULTS.md ← auto-generated│ │ └── runner/ ← Python runner that produces RESULTS.md│ ├── governance_lines/│ │ ├── README.md│ │ ├── RESULTS.md ← per-app line counts vs Python/TS│ │ └── runner/│ ├── provenance_preservation/│ │ ├── README.md│ │ ├── RESULTS.md│ │ └── runner/│ ├── replay_determinism/│ │ └── ... (same shape)│ └── time_to_audit/│ └── ... (same shape)└── results/ ├── 2026-04-16-clean-run/ │ ├── ratios.json ← machine-readable archive │ └── README.md ├── 2026-04-17-marketable-session/ │ └── ratios.json └── ... (40+ dated archive sessions)Each RESULTS.md has a “Headline numbers” section near the top.
Each ratios.json carries per-benchmark ratio + ratio_basis
fields.
Concrete deliverables
-
A page at
https://corvid-lang.org/benchmarksthat:- Renders the moat headline numbers: compile-time-
rejection rate over 50 bug-class cases, governance line
count for
refund_bot/rag_qa_bot/support_escalation_botin Corvid vs. Python vs. TS, replay-determinism numbers, time-to-audit numbers. - Renders the honest orchestration-overhead numbers from Phase 17: ~25–36× slower than Python LangChain and 1.7– 2.6× slower than TypeScript on the canonical reference apps. Frame them as “honest slower” with the rationale — Corvid optimizes correctness, not raw throughput.
- Links each headline number to its
RESULTS.mdsource on GitHub and to a reproducibility command (corvid bench compare python|js). - Shows the published-archive list (
benches/results/*) filterable by date, with each row linking to theratios.jsonarchive.
- Renders the moat headline numbers: compile-time-
rejection rate over 50 bug-class cases, governance line
count for
-
A
/benchmarks/methodologypage that explains:- What “ratio” means (Corvid-to-Python ratio, with model-latency separated from orchestration overhead).
- How a benchmark is reproduced (
corvid bench compare, deterministic runners, drift gates). - The non-promise list: what we do NOT measure (model quality, end-user latency including network, etc.).
-
A nav link to
/benchmarksfrom the main landing’s nav and from the docs site header.
Acceptance criteria
- Visiting
corvid-lang.org/benchmarksshows the headline numbers from eachbenches/moat/<name>/RESULTS.md. - Every quoted number on the page links to the line in the
source
RESULTS.md(anchor link to the heading). - The page renders the “honest slower” framing in a paragraph that links to the Phase 17 numbers.
- The archive list at
/benchmarks/archivesshows ≥20 dated sessions sourced frombenches/results/*/ratios.json. -
/benchmarks/methodologyexists and links from/benchmarks. - Updating a
RESULTS.mdin the main repo triggers a website rebuild (same deploy hook as the docs site). - Mobile breakpoints are usable at <768px.
Constraints
- Do not edit any
RESULTS.mdorratios.jsonfiles in the main repo. The runners produce them; the page renders them. - If a
RESULTS.mdcarries a “draft” or “investigation” tag in the filename or front matter (the ones underbenches/results/*-investigation/or*-session/patterns), do not surface them on the public page — those are in-progress archives. Surface only sessions whoseratios.jsonis markedpublished: trueor, lacking that flag, sessions whose directory name does not containinvestigationorsessionqualifiers. Confirm the filter with the maintainer before shipping.
Out of scope
- A live benchmark runner in the browser (post-v1.0).
- A diff view between archives (post-v1.0).
- AI-generated benchmark commentary (post-v1.0).
Slice 33J5 — Blog shell + launch post
Goal
A blog section on the website at /blog with a working post
template, an index page, and one launch post: “Corvid v1.0:
compile-time AI safety, shipped.”
Concrete deliverables
- A
/blogindex page listing every published post with title, date, author, and reading time. - A per-post template at
/blog/<slug>with:- Title, date, author, reading time, hero image (optional).
- The post body in MDX or markdown.
- Code blocks with Corvid syntax highlighting (same highlighter as the docs site).
- Cross-links to docs pages and the GitHub repo.
- A “Discuss on HN / Reddit / Twitter” footer that opens the respective share dialog with the post’s URL prefilled.
- RSS feed at
/blog/rss.xml. - The launch post itself (see “Launch post outline” below).
Launch post outline (suggested structure)
The post is the canonical Corvid story for HN/Reddit/Twitter readers. Target audience: an experienced engineer who has not heard of Corvid and is skimming on a phone. Hook fast, prove fast, link fast.
Suggested structure (~1,500 words):
-
The hook (1 paragraph). “Your AI agent issued two refunds for the same customer last week. The Python library you trusted to prevent that quietly failed a runtime check in 20% of code paths. Corvid is a programming language where a refund call without an explicit approval does not compile. We just shipped v1.0.”
-
The five things every AI team is rebuilding (1 paragraph). Pull from
docs/book/00-why-corvid.md— the approval-before-dangerous-tool, the model-vs-source provenance, the budget, the replay, the model-upgrade-diff. -
The five-line demo (code block). Copy the compile-refusal snippet from
docs/book/02-quickstart.md. Show the error message verbatim. The image is louder than prose. -
What’s in the language (3 paragraphs). Effects,
approve,Grounded<T>, agents, prompts. Link each to its chapter in The Corvid Book. -
What’s NOT in v1.0 (1 paragraph). Honesty about orchestration overhead (~25–36× slower than Python LangChain on the canonical apps); about formal mechanized proofs of the type system being post-v1.0; about the second-implementation TCB shrinkage being post-v1.0. Link to
docs/security/model.mdand the benchmarks page. -
How to try it in 5 minutes (1 paragraph + code).
curl ... | sh,corvid new,corvid run. Link todocs/book/02-quickstart.md. -
The roadmap from here (1 paragraph). Phase 37+ (the production-backend track, mostly already shipped), post-v1.0 research agenda (formal proofs, second- implementation TCB).
-
Discuss / contribute (1 paragraph + links). Beta program signup, GitHub issues, Discord/Slack invite if one exists.
Acceptance criteria
-
/blogindex renders with the launch post visible. -
/blog/<slug>renders the launch post with code highlighting and cross-links resolving. - RSS feed at
/blog/rss.xmlvalidates against a generic RSS validator (e.g.validator.w3.org/feed/). - Launch post is ≤1,800 words.
- Launch post passes the no-shortcut wording audit: every
claim links to a runnable command, a test, or a
committed example. Use
docs/meta/launch-claim-audit.mdas the checklist. - Reading-time estimate appears on the post (~5–7 min target).
- Share-button footer opens HN, Reddit, Twitter share dialogs.
Constraints
- The launch post is the load-bearing wording artifact. Run the wording-audit before shipping: every claim must trace to a runnable command or a checked-in example. Phase 35V T1-H/T1-K spent slices tightening aspirational wording out of README and security-model.md; do not re-introduce it here.
- Do not invent benchmark numbers. Pull every number from
benches/moat/*/RESULTS.mdorbenches/results/*/ratios.jsonand link to the source.
Out of scope
- Comments / replies (post-v1.0; HN/Reddit are the comment surface).
- Multi-author bylines (one author is fine for v1.0).
- A newsletter signup (post-v1.0).
Slice 33J6 — Grammar drift gate
Goal
A Rust test in the workspace that fails when
docs/reference/grammar.md drifts from what the parser
actually accepts. The grammar doc is the load-bearing public
spec; without a drift gate, it silently rots.
Audience
This slice lands in the main Corvid repo, not the website repo. Audience is a Rust developer who knows the workspace conventions.
Inputs
- Grammar source:
docs/reference/grammar.md(289 lines, EBNF with 16 section headings). - Parser source:
crates/corvid-syntax/src/parser/with 20+ files (decl/mod.rs,decl/*.rs,expr.rs,stmt.rs,types.rs,prompt.rs, etc.). - Parser tests:
crates/corvid-syntax/src/parser/tests.rs(3,128 lines of integration tests covering accepted and rejected inputs). - Token enumeration:
crates/corvid-syntax/src/token.rs(every keyword variant asKwXyzin theTokKindenum).
Approach (recommended)
A full machine-checked grammar↔parser equivalence is research work. A drift gate does not need that. It needs to catch the recurring drift modes cheaply. Pin two orthogonal checks:
Check 1 — keyword list parity. Every keyword listed in
docs/reference/grammar.md’s “Lexical tokens” section must
appear as a Kw<Name> variant in corvid_syntax::TokKind,
and vice versa. Parse the grammar.md keyword list with a
simple regex, parse TokKind variants from token.rs source,
compare as sets.
Check 2 — production-name parity. Every production name
defined in grammar.md (the left-hand side of each ::=) must
have a corresponding fn parse_<name> (or parse_<name>_*)
in the parser source under crates/corvid-syntax/src/parser/.
This catches “we documented a production but the parser
doesn’t have it” and “we renamed a parser function but the
grammar still uses the old name.”
Both checks are textual / structural, not semantic. They will
not catch “we accept x but the grammar says we accept y.”
That kind of drift is what the parser tests
(parser/tests.rs) already catch through accepted/rejected
example inputs. The drift gate is the layer above:
keyword-list and production-name surface integrity.
File layout
Add the drift gate as a permanent sentinel test in the existing parser-tests file:
crates/corvid-syntax/src/parser/tests.rsTwo new #[test] functions, both #[cfg(test)]:
#[test]fn grammar_md_keyword_list_matches_token_kind() { // 1. Read docs/reference/grammar.md (use include_str!). // 2. Find the "## Lexical tokens" section. // 3. Extract keyword tokens from the bullet list. // 4. Read corvid-syntax/src/token.rs. // 5. Extract `Kw<Name>` variants from the TokKind enum. // 6. Convert grammar keywords (e.g. "agent") to expected // variants (e.g. "KwAgent") via a simple PascalCase rule. // 7. Assert set equality. On mismatch, print which side // has the extra entries.}
#[test]fn grammar_md_production_names_have_parser_functions() { // 1. Read docs/reference/grammar.md. // 2. Find every `<name> ::= ...` production left-hand side. // 3. Walk crates/corvid-syntax/src/parser/ for `.rs` files. // 4. Extract every `fn parse_<name>` declaration. // 5. For each production name, assert at least one // matching parser function exists (with name-mangling // rules documented in code — e.g. snake_case identity, // or `parse_<name>` / `parse_<name>_expr` / etc.). // 6. On mismatch, print which productions lack parsers.}Both tests use include_str! for the grammar.md content and
walk the workspace via std::fs::read_dir (same shape as the
every_enforced_guarantee_id_is_wired_to_workspace_source
sentinel in crates/corvid-guarantees/src/lib.rs).
Concrete deliverables
- The two
#[test]functions above, landed incrates/corvid-syntax/src/parser/tests.rs. - Each test has a docstring explaining what it pins and what drift mode it catches.
- Add the test names to the canonical sentinel list in
crates/corvid-guarantees/src/lib.rs’s “permanent sentinels” comment block (the 7 + 18 anchor list from Phase 35V). - CI workflow at
.github/workflows/ci.ymlmust run these tests on every push (they will run automatically viacargo test --workspace; verify the workflow includes that step).
Acceptance criteria
-
cargo test -p corvid-syntax --lib grammar_md_keyword_list_matches_token_kindpasses against the current grammar.md and token.rs. -
cargo test -p corvid-syntax --lib grammar_md_production_names_have_parser_functionspasses against the current grammar.md and parser/. - Inducing drift confirms the gate fires: - Add a fake keyword to grammar.md → test fails with a diagnostic naming the keyword. - Remove a parser function listed in grammar.md → test fails with a diagnostic naming the missing production.
- Test docstrings reference the grammar.md path and the parser path; a future move surfaces immediately (the Phase 33J2 cross-component-coupling lesson).
-
learnings.mdupdated with the entry: drift-gate pattern applied to the grammar surface.
Constraints
- Read the existing Phase 35V T1-Drift sentinel in
crates/corvid-guarantees/src/lib.rs(theevery_enforced_guarantee_id_is_wired_to_workspace_sourcetest) for the canonical shape. Match its style. - Hardcode the path
docs/reference/grammar.mdas a string in the diagnostic message so a future docs reorg surfaces immediately. - Do not attempt full semantic equivalence between grammar and parser. That is research work. Surface integrity is enough for v1.0.
Out of scope
- A full machine-checked EBNF → parser equivalence (post-v1.0).
- Auto-generating grammar.md from the parser (post-v1.0).
- A CI-side renderer that publishes a railroad diagram from grammar.md (nice-to-have, post-v1.0).
Slice 33J7-prereq — corvid-browser crate (WASM-compatible typechecker)
Status: BLOCKING. The 33J7 playground cannot proceed on the website side until this lands. Filed by the website team on 2026-05-11 after probing
Corvid-lang/mainand finding the compiler binary cannot be compiled towasm32-unknown-unknownas it stands.
Audience
Rust developer with workspace knowledge of
Micrurus-Ai/Corvid-lang. Lands in the main repo, not the
website repo.
Why this exists
The website team is building a browser-based cloud IDE for
Corvid as part of slice 33J7. The IDE compiles user-written
.cor source in the browser via a WASM module and renders the
resulting diagnostics with guarantee_id badges that link to
/docs/reference/guarantees#<id>.
A probe of Micrurus-Ai/Corvid-lang/main on 2026-05-11 found
three concrete blockers:
-
crates/corvid-cli/Cargo.tomldeclares only[[bin]], no[lib]withcrate-type = ["cdylib"]. To produce a WASM module callable from JavaScript, we need either acdyliblibrary target or a new wrapper crate. -
corvid-cli’s dependency graph pulls in wasm- incompatible crates:tokiowithrt-multi-thread— does not compile towasm32-unknown-unknown.rayon— same problem.libloading— needs dlopen, no browser equivalent.tempfile— needs filesystem.tar— fine on its own but ties into filesystem workflows.
Pulling
corvid-clidirectly into a WASM build will fail at compile time. We need a crate that depends only on the typechecking surface, not on the orchestration runtime. -
crates/corvid-codegen-wasmexists, but it’s the wrong direction. That crate emits WASM as a target for compiled Corvid programs (Corvid source → WASM binary). What we need is the compiler frontend to run in the browser as a WASM module so end-users can paste Corvid source into a textarea and get back diagnostics. There is no precedent crate for that direction yet.
The crate does not need to run programs — only check them.
Compile-refusal (the moat demo) is a typecheck-time signal, not
a runtime signal. Running agents and calling LLM providers is
explicitly out of scope for the WASM build; that happens
locally after curl install.
Concrete deliverable
A new crate, suggested name corvid-browser (rename to taste
— corvid-wasm-check, corvid-playground-wasm, etc.):
crates/corvid-browser/├── Cargo.toml # cdylib, dep set below├── src/│ └── lib.rs # exposes pub fn check(source: &str) -> CheckResult└── README.mdCargo.toml depends only on the typechecking surface —
concretely (subject to audit):
corvid-syntax(parser, lexer)corvid-astcorvid-resolvecorvid-types(effect calculus)corvid-guaranteesserde+serde_jsonfor diagnostic serializationwasm-bindgenfor the JS binding layer
Critical: before adding a dep here, check that its
transitive graph compiles to wasm32-unknown-unknown. The
typechecker may have tokio woven through it in ways that aren’t
visible from API names — audit and either gate problematic
features with cfg(target_arch = "wasm32") or extract pure-
Rust subsets.
src/lib.rs exposes a single entry point:
use serde::Serialize;use wasm_bindgen::prelude::*;
#[derive(Serialize)]pub struct Diagnostic { pub guarantee_id: String, // e.g. "approval.dangerous_call_requires_token" pub severity: String, // "error" | "warning" | "info" pub message: String, // primary message pub span: Span, // location pub help: Option<String>, // suggested fix, if any}
#[derive(Serialize)]pub struct Span { pub start_line: u32, // 1-indexed pub start_col: u32, // 1-indexed pub end_line: u32, pub end_col: u32,}
#[derive(Serialize)]pub struct CheckResult { pub diagnostics: Vec<Diagnostic>, pub ok: bool, // true if no errors (warnings OK)}
#[wasm_bindgen]pub fn check(source: &str) -> JsValue { let result: CheckResult = run_typecheck(source); serde_wasm_bindgen::to_value(&result).unwrap_or(JsValue::NULL)}The exact serialization shape is negotiable — propose
something cleaner if you see one. The key requirement: the
website renderer can map each diagnostic to a guarantee_id
for the docs link, a message for inline display, and a span for
editor squiggles.
Suggested approach
-
Audit the typechecker’s dep graph first. Run
cargo tree -p corvid-types,corvid-resolve,corvid-guarantees, etc. Identify any tokio / rayon / filesystem pulls. For each:cfg(not(target_arch = "wasm32"))gate, refactor, or pull the offending sub-feature into a different crate. -
Stand up the empty
corvid-browsercrate with a stubcheck()that returns an empty diagnostics array. Verify it builds clean:Terminal window cargo build -p corvid-browser --target wasm32-unknown-unknown --releaseThis proves the dep graph is clean before any real logic lands.
-
Wire the real typecheck path. From
check(source), call into the same pipelinecorvid check src/main.coruses for typechecking, but stop before code generation, runtime, connectors. The typecheck pipeline exists and is well- tested; this slice exposes it through a thin browser- targeting wrapper. -
Map internal diagnostic types to the
Diagnosticshape. Existing internal diagnostics carry richer info (multi-span notes, fix-it suggestions). For v1 of the playground, flatten to: one primary span, one message, optional help. Future versions can extend. -
Run-size budget: WASM module ≤8 MB gzipped on the wire (per the 33J7 brief). After the first build, run
wasm-bindgen --out-dir target/wasm-pack target/wasm32-unknown-unknown/release/corvid_browser.wasmand check gzipped size. If over budget:wasm-opt -Oz(binaryen) — usually 20–40% reduction.- Strip unused codegen backends (the browser-check use case does not need the Python or Cranelift code generators).
- Audit dep graph for surprise pull-ins.
-
Hook into CI. Add a build step in the Corvid-lang workflow that compiles the WASM artifact on every push to
main. Publish it as a release asset, or trigger arepository_dispatchtoMicrurus-Ai/corvid-websiteso the website CI re-pulls and re-deploys. The website-side dispatch listenercorvid-lang-wasm-changedwill be added by the website team once the crate ships.
Acceptance criteria
-
cargo build -p corvid-browser --target wasm32-unknown-unknown --releasecompletes with no errors. -
wasm-bindgenpostprocessing produces a JS-importable module plus a.wasmartifact. - Gzipped wire size of the
.wasmartifact is ≤8 MB. - Calling
check("agent foo(t: Ticket) -> Decision uses bar: return baz()")(a compile-refusal example) from JS returns aCheckResultwhosediagnostics[0].guarantee_idmatches what the native compiler reports for the same source. - Calling
check("# valid corvid")(a trivial valid program) returns{ ok: true, diagnostics: [] }. - At least one accepted-input and one rejected-input test
under
crates/corvid-browser/tests/. - CI workflow at
.github/workflows/build-wasm.yml(or added to existing CI) produces the artifact on every push tomain.
Constraints
- Match the workspace conventions documented in
CLAUDE.md(file-responsibility rubric, invention shipping contract, pre-phase chat before code). - This is a code-touching slice. Phase 35V’s pattern 5
(“cross-component coupling discovered at verification time”)
applies: any time you split a workspace boundary, validators
on the other side (registry coverage, signed-claim coverage,
contract-list output) may need alignment. Run
cargo test --workspacebefore opening the PR. - The diagnostic schema is load-bearing — once the website consumes it, schema changes require a coordinated rollout. Document it clearly in the crate README.
Out of scope (explicit non-promises for this slice)
- Runtime execution. No
corvid run, no agent execution. Typecheck only. - LLM provider calls. Not even via a stub. The playground’s user-supplied API key path runs directly from the browser to the provider; the WASM never sees a key.
- Connector OAuth flows (Gmail, Slack, MS365). Out of scope.
- Multi-file resolution across an entire
corvid.tomlproject. v1 of the playground supports single-file typechecking. Multi-file is a Phase 2 enhancement; we’ll spec it separately if there’s demand. - Code generation. The WASM module does not need to invoke Cranelift, the Python codegen, or any backend. Reject programs at typecheck if they reference things the typecheck-only build can’t see.
- A formal proof that
corvid-browsermatchescorvid checkbyte-for-byte. Best-effort parity is fine; surface differences as issues.
Estimated effort
- Best case: 2 weeks if the typechecker is already cleanly separable from runtime concerns.
- Typical case: 3–4 weeks if the dep audit reveals tokio / runtime entanglements that need refactoring.
- Hard case: 6+ weeks if the typechecker uses runtime primitives we didn’t anticipate.
Coordination
When the artifact builds:
- Comment on the tracking issue (or PR) with the WASM module
size and a sample
CheckResultJSON for the compile-refusal example. The website team uses that to wire the renderer. - The website team adds the
corvid-lang-wasm-changedrepository_dispatchlistener on their side, plus the CI step that clones Corvid-lang and fetches the artifact. - Either side can iterate on the diagnostic schema — propose changes via PR comments on the tracking issue.
Related
- Slice 33J7 below (the consumer of this crate).
- Original WASM target work: phase 20n-B in
docs/phases/phase-20n-open-gap-implementation.md(thecorvid-codegen-wasmcrate — the wrong direction for this slice, but useful context). - Effect spec:
docs/internals/effect-spec/. - Diagnostic format reference:
docs/reference/guarantees.md.
Slice 33J7 — WASM playground
Hard dependency on 33J7-prereq above. The website-side work below cannot proceed until the
corvid-browsercrate ships awasm32-unknown-unknownartifact with the documented diagnostic schema.
Goal
A browser-based code editor at corvid-lang.org/playground
that compiles Corvid source in the browser via the WASM target
and shows results inline (success output, type errors with
guarantee_ids, compile-refusal messages).
This is the “wow” demo. A visitor who has never installed
Corvid should be able to paste an agent, remove the approve,
hit Compile, and see the compiler refuse — in their browser,
in <2 seconds.
Audience
Frontend developer comfortable with WASM module loading and a code-editor library, working alongside a Rust developer who understands the cdylib/WASM target shape (Phase 20n-B, 20n-C).
Architecture
┌─────────────────────────────────────────────────────────────┐│ Browser ││ ││ ┌─────────────────┐ ┌────────────────────────────────┐ ││ │ CodeMirror / │ │ Corvid compiler (WASM module) │ ││ │ Monaco editor │───>│ (compiled from corvid-cli) │ ││ │ + Corvid syntax │ │ │ ││ │ highlighter │ │ exports: │ ││ └─────────────────┘ │ compile(src: string) │ ││ ↑ │ -> {ok, diagnostics, ir} │ ││ │ │ run(src: string) │ ││ │ │ -> {output, diagnostics} │ ││ │ └────────────────────────────────┘ ││ │ ↓ ││ │ ┌────────────────────────────────┐ ││ └──────────────│ Diagnostics renderer │ ││ │ (squiggles + error panel + │ ││ │ guarantee-id badge + claim │ ││ │ --explain link to docs) │ ││ └────────────────────────────────┘ │└─────────────────────────────────────────────────────────────┘Inputs
- Existing WASM target:
corvid build --target=wasmshipped in Phase 20n-B. The bare(ptr, len)UTF-8 ABI + multi-value returns are documented indocs/internals/wasm-abi.mdanddocs/phases/phase-20n-open-gap-implementation.md. - Corvid syntax-highlighter grammar: the same one the docs site uses (slice 33J3 landed it; ask the docs-site author for the Shiki/Prism grammar JSON).
- Canonical first-program examples in
docs/book/02-quickstart.mdanddocs/book/03-tutorial-refund-agent.md.
Concrete deliverables
-
A WASM module exposing the compiler.
- Built from
corvid-cliwith--target=wasmplus a thin extern “C” wrapper (pub extern "c" fn compile(...),pub extern "c" fn run(...)). - Compiled with
wasm-packorcargo build --target wasm32-unknown-unknown+ manual postprocessing. - Hosted as a static asset at
corvid-lang.org/playground/corvid.wasm.
- Built from
-
An editor UI at
/playground:- Code editor (CodeMirror 6 or Monaco; CodeMirror is lighter for a static site).
- Corvid syntax highlighting (same grammar as the docs site).
- Two buttons: Check (typecheck only, fast) and Run (compile + execute via the in-WASM runtime).
- Output panel showing stdout for successful runs, diagnostics for failures.
- Diagnostic squiggles in the editor at error locations.
- Each error’s
guarantee_idbadge links tocorvid-lang.org/docs/reference/guarantees#<id>for in-context explanation.
-
Canonical examples in a left-side dropdown:
- Hello, Corvid (a 5-line prompt+agent).
- Compile-refusal demo (the refund-without-approve from the quickstart).
- Grounded provenance demo.
- Budget-exceeded demo.
- Approve-in-wrong-scope demo.
- The full refund-agent tutorial (read-only mode).
-
A “share this code” button that encodes the editor’s contents into the URL fragment (
#code=<base64>). Loading a URL with#code=...restores the editor state. -
A “fork to local” button that downloads the editor’s contents as
playground.corplus acorvid.toml.
Build pipeline
The WASM module is the load-bearing artifact. Build it as part of the website’s CI:
# In a CI step before the website build:git clone --depth=1 https://github.com/Micrurus-Ai/Corvid-langcd Corvid-langcargo build -p corvid-cli --target wasm32-unknown-unknown --release# Postprocess: extract the cdylib, generate JS bindings, copy# into the website's static assets.wasm-bindgen target/wasm32-unknown-unknown/release/corvid.wasm \ --out-dir ../corvid-website/public/playground(The exact wasm-bindgen invocation depends on whether the
runtime is bundled. Confirm with the Rust developer.)
Acceptance criteria
- Visiting
corvid-lang.org/playgroundshows the editor with a Hello-Corvid example pre-loaded. - Clicking Check typechecks the current source and
reports diagnostics with
guarantee_ids inline. - Clicking Run executes a sandboxed run and shows stdout.
- Removing the
approvefrom the Compile-Refusal example shows theapproval.dangerous_call_requires_tokendiagnostic in <2 seconds total round trip. - Each diagnostic’s
guarantee_idis a clickable link tocorvid-lang.org/docs/reference/guarantees#<id>. - The canonical-examples dropdown lists at least 5 examples; switching between them updates the editor.
- The “share this code” button encodes the editor state in the URL fragment; loading a shared URL restores state.
- WASM module size on the wire is ≤8 MB gzipped.
- Page is usable on mobile (editor is read-only on narrow-screen if needed; full editor on tablet+).
Constraints
- The playground has no access to LLM providers, no filesystem, no network. Prompts that try to call out fail with a diagnostic explaining “playground runs in a sandbox; install Corvid locally to call providers.”
- Do not bundle a mock LLM provider that returns canned responses. That would teach the wrong mental model. Fail honestly with the sandbox-limitation diagnostic.
- WASM module must be the same compiler that ships on the native target. Do not ship a stripped-down “playground compiler” that accepts different syntax than the real one.
- Replay quarantine applies in the playground the same way it applies in production. A connector call refuses in real-mode in the sandbox.
Out of scope
- Saving examples to a server-side persistence layer (use the URL fragment encoding).
- User accounts, sign-in, collaborative editing (post-v1.0).
- A “compare this run to another model” surface (post-v1.0).
- VS Code’s full Monaco feature set — basic editor, error squiggles, syntax highlighting is enough.
Slice 33L — Launch materials
Goal
Three launch artifacts ready to share with the world: a 2-minute video showing Corvid’s moat, drafted announcements for HN / Reddit / ProductHunt, and external-reader review of all three.
Audience
Dev-rel / marketing + an engineer who can record the demo sessions.
Concrete deliverables
1. The 2-minute video (or animated GIF)
A single-take screencast (or animated GIF if file size matters more) showing:
Scene 1 (0:00–0:25) — The compile-time refusal.
- Open
examples/refund_bot/src/main.corin an editor. - Remove the
approveline. - Run
corvid check. - The compile-refusal diagnostic appears with the
guarantee_id. Camera holds for 3 seconds. - Add the
approveback. Re-runcorvid check. Passes.
Scene 2 (0:25–0:50) — The grounded provenance type.
- Open a snippet that pass a model-only string where a
Grounded<String>is expected. - Run
corvid check. Type-mismatch error fires with thegrounded.no_silent_unwrapguarantee_id. - Show how
unwrap_with_citation()fixes it.
Scene 3 (0:50–1:20) — The replay surface.
- Run an agent:
corvid run src/main.cor. - Run
corvid trace list, point at the captured trace. - Run
corvid replay <id>. The output is byte-identical; wall-clock is 50× faster. - Run
corvid eval --swap-model gpt-5 .... Show the diff.
Scene 4 (1:20–1:50) — The compile-time budget.
- Open an agent annotated
@budget($0.10). - Add a prompt with
cost: $0.50in its effect row. - Run
corvid check. Budget violation fires at compile time. - Camera holds.
Scene 5 (1:50–2:00) — One-line install + CTA.
- Terminal pane shows
curl -fsSL corvid-lang.org/install.sh | sh. - Caption: “Try it: corvid-lang.org”.
Format: 1920×1080, 60fps, ≤30 MB compressed (so it can embed in HN/Reddit/Twitter without re-encoding). Animated GIF fallback at 800×450, ≤5 MB.
Tooling suggestions:
- Recording: OBS Studio (free, cross-platform).
- Editing: DaVinci Resolve (free) for cuts and captions.
- GIF conversion:
ffmpegwith a 2-pass palette.
2. The HN announcement draft
A Show HN post:
- Title: ≤80 chars. Suggested:
"Show HN: Corvid – a language where unauthorized AI tool calls don't compile". - Body: ≤500 words. Structure:
- Hook (1 sentence).
- The five things every AI team is rebuilding (1 paragraph).
- The compile-refusal example (code block).
- What’s NOT in v1.0 (honest list).
- Install line + docs link + repo link.
- Tone: technical, terse, links over prose.
- Attach: the animated GIF as a top-level link.
Reference for the tone: https://news.ycombinator.com/highest — read 10 recent top-voted Show HN posts; match the rhythm.
3. The Reddit announcement drafts
Three subreddits, three drafts (subreddit conventions differ):
r/ProgrammingLanguages: technical depth, the effect-algebra hook, link to the spec.r/programming: the moat in plain English, the GIF up top.r/rust: emphasis on the Rust-backed implementation, the cdylib/WASM ABI, the Cranelift backend.
Each is ≤400 words. Each includes a clear self-disclosure that the poster is the author/team.
4. The ProductHunt draft
Standard PH listing:
- Tagline: ≤60 chars. Suggested:
"AI-safe programming. Refunds without approval don't compile." - Topics: AI, Developer Tools, Open Source.
- Description: ≤260 chars.
- Gallery: hero image + 4 feature screenshots.
- Maker comment: 1 paragraph, link-rich.
5. External-reader review
Get three external readers (not on the project) to read all three drafts before publication. Their feedback closes either as edits to the drafts or as filed issues in the website repo (out-of-scope-for-launch items).
Acceptance criteria
- Video file under
Micrurus-Ai/corvid-websiteatpublic/launch/corvid-2min.mp4and.gif; embedded on the landing page below the hero. - Three HN/Reddit/PH drafts committed to a private gist or
a
drafts/directory in the website repo (not on the public site). Each draft has a “ready to ship” header with the planned post date. - Three external-reader review feedback rounds completed; each round’s comments either landed in the draft or filed as a website-repo issue.
-
docs/meta/launch-claim-audit.mdupdated to confirm every claim in the drafts maps to a runnable command, a test, or a committed example. - Animated-GIF fallback (≤5 MB) is also committed.
Constraints
- Truth in launch wording. Same rule as 33J5: every claim traces to a runnable command, test, or committed example.
- The video must use real Corvid, not a re-typed mockup. The compile-refusal diagnostic shown on screen must match the real compiler’s output byte-for-byte. A user who runs the same command should get the same screen.
- Do not post any draft live until external-reader review is complete.
- Embargo: HN / Reddit / PH posts go live within a 24-hour window so the launch surface is coherent. Schedule before posting.
Out of scope
- Twitter / X / LinkedIn drafts (post-launch — they should link to whichever of HN/Reddit/PH gets the most engagement).
- Paid placement / ads (post-launch).
- A press release (post-launch).
Slice 33M — Beta program
Goal
20 external developers build something real in Corvid before v1.0 ships publicly. Their feedback either lands as code/docs/tests, or is filed as explicit non-scope. The beta gates the final v1.0 cut.
Audience
Dev-rel / community + triage engineer.
Concrete deliverables
1. A signup mechanism
A /beta page on the website with:
- 1-paragraph “what is the beta” framing.
- A signup form: name, email, what you’d build, prior language experience.
- A confirmation page + automated email with onboarding instructions.
Tooling: a static-form-handler service (Formspree, Netlify Forms, or a custom serverless function). Persist responses to a private spreadsheet or Notion DB.
2. An outreach plan
20 developers means active outreach. Sources:
- Personal network (DM 10 developers we know who work on AI systems).
- The
r/ProgrammingLanguagesdiscord/slack channels. - HN comment replies in adjacent threads (LangChain critiques, AI-safety threads).
- The Effect-Spec adversarial-taxonomy bounty page —
docs/internals/effect-spec/bounty.md— already describes the bypass-attempt invitation. Reuse it.
Target: 30 signups, of which 20 build something real.
3. An onboarding doc
A docs/meta/beta-program.md already exists; extend it (or
mirror it on the website) with:
- The expected time commitment (~5 hours over 2 weeks).
- The feedback mechanism (a GitHub issue with the
beta-programlabel, plus an optional weekly call). - The “build something real” scope: any agent ≥50 lines of Corvid. Examples include refund-bot variants, RAG agents, ticket-triage agents.
- The “what we promise to do with your feedback” commitment: every filed issue gets a response within 48 hours and is either landed as a code/docs/tests change before v1.0 cut OR filed as explicit post-v1.0 non-scope with a written reason.
4. The feedback triage process
Set up:
- A GitHub label
beta-programon the main repo. - A pinned issue or project board listing all beta-filed issues with their state (open / under review / landed / non-scope).
- A weekly triage ritual: every Wednesday, walk the open beta-filed issues, decide land-or-non-scope, write the decision.
- A “this is what changed” digest emailed to beta participants every Friday.
5. The final-cut gate
v1.0 ships only after:
- 20 developers have filed ≥1 issue each (or explicitly confirmed they have nothing to file).
- Every filed issue is either closed-by-landing or closed-by-non-scope-with-reason.
- The triage backlog is empty.
Acceptance criteria
-
/betasignup page is live; signups persist. - ≥30 signups recorded; ≥20 developers have completed onboarding (received the welcome email, joined the issue tracker).
- ≥20 beta-filed issues exist with the
beta-programlabel. - Every beta-filed issue has a response within 48 hours.
- Every beta-filed issue is closed (either landed or non-scope-with-reason) before the v1.0 cut.
- Weekly Friday digest goes out for at least 2 weeks of the beta window.
-
docs/meta/beta-program.mdreflects the final state of the program (what shipped, what didn’t).
Constraints
- Time is the budget. Beta is calendar-bound; allocate 2–4 weeks of beta window before v1.0 cut. Past that, ship.
- Do not promise things in the beta-program doc that you haven’t shipped. The “what we promise” line is load-bearing trust; over-promise once and the beta loses credibility.
- Every “non-scope” closure carries a written reason. “We won’t do this” is fine; “we won’t do this because [reason]” is the no-shortcut version.
Out of scope
- A paid beta or any monetization at this stage.
- A NDA or contributor-license agreement (the repo’s MIT/ Apache-2.0 dual license is enough).
- A formal advisory board (post-launch).
Shared appendix: where to start
If you are starting any of the slices above, do these three things first, in order:
- Read this entire brief. The slices reference each other; skipping ahead loses context.
- Read the Corvid Book’s first three chapters at
https://corvid-lang.org/docs/book/00-why-corvid,
/docs/book/01-install,/docs/book/02-quickstart. You do not need to learn the language. You need to know what the language promises. - Open a pre-phase chat issue on the main repo with the slice number in the title (e.g. “33J7 pre-phase chat — playground architecture confirm”). Wait for sign-off before writing code or content.
Then start your slice.
Closing the slice
A slice is done when:
- Its acceptance criteria are all observably met.
- Its PR has landed on the relevant repo’s
main. - The corresponding ROADMAP checkbox is ticked in a follow-up commit (or the same commit if it’s a docs slice).
learnings.mdhas an entry for the user-visible slice.- The next slice has not yet started.
Per the project’s “commit at slice boundaries” rule, do not batch multiple slices into one commit.
Reference reading
- The full Corvid Book: https://corvid-lang.org/docs/book.
- The CLI reference: https://corvid-lang.org/docs/reference/cli.
- The grammar: https://corvid-lang.org/docs/reference/grammar.
- The benchmarks: https://github.com/Micrurus-Ai/Corvid-lang/tree/main/benches.
- The launch-claim audit: https://github.com/Micrurus-Ai/Corvid-lang/blob/main/docs/meta/launch-claim-audit.md.
- The project’s hardest rules: https://github.com/Micrurus-Ai/Corvid-lang/blob/main/CLAUDE.md.
- ROADMAP (find your slice’s full context): https://github.com/Micrurus-Ai/Corvid-lang/blob/main/ROADMAP.md.
Good luck. Ship six honest things, not six aspirational ones.