Skip to content

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

SliceTitleAudience
33J3-polishHighlight declaration names in the docs grammarFrontend / website developer
33J4Benchmark pageFrontend / website developer
33J5Blog shell + first launch postFrontend + writer
33J6Grammar drift-gate testRust developer
33J7-prereqcorvid-browser crate — WASM-compatible typecheckerRust developer (BLOCKS 33J7)
33J7WASM playgroundFrontend + Rust developer
33LLaunch materials (video + announcement drafts + review)Dev-rel / marketing
33MBeta program (20 external developers + feedback triage)Dev-rel / community

After all six close, Phase 33 closes, v1.0 launches.

The repos

  1. Corvid language repo — source of truth for code and docs.
  2. Corvid website repo — landing page + docs site.

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.

  1. 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.
  2. Pre-phase chat before code. Confirm scope with the maintainer before writing code. Mid-slice scope changes are the failure mode this prevents.
  3. One slice per commit boundary. A slice is not done until its commit is on main of the relevant repo and the next slice has not yet started.
  4. Update learnings.md with each user-visible slice. No drift between shipped behavior and the learnings record.
  5. No editing auto-generated files. docs/reference/core-semantics.md is regenerated by corvid contract regen-doc. Treat it as read-only.
  6. 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_refund in agent 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 build or 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 uses clauses (separate polish slice).
  • Highlighting agent annotation names like @budget, @retry (separate polish slice; would need a meta.annotation.corvid scope).
  • LSP-style features (out of scope for the docs site; see docs/guides/editor-and-lsp.md).

Reference


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

  1. A page at https://corvid-lang.org/benchmarks that:

    • 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_bot in 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.md source 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 the ratios.json archive.
  2. A /benchmarks/methodology page 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.).
  3. A nav link to /benchmarks from the main landing’s nav and from the docs site header.

Acceptance criteria

  • Visiting corvid-lang.org/benchmarks shows the headline numbers from each benches/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/archives shows ≥20 dated sessions sourced from benches/results/*/ratios.json.
  • /benchmarks/methodology exists and links from /benchmarks.
  • Updating a RESULTS.md in 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.md or ratios.json files in the main repo. The runners produce them; the page renders them.
  • If a RESULTS.md carries a “draft” or “investigation” tag in the filename or front matter (the ones under benches/results/*-investigation/ or *-session/ patterns), do not surface them on the public page — those are in-progress archives. Surface only sessions whose ratios.json is marked published: true or, lacking that flag, sessions whose directory name does not contain investigation or session qualifiers. 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

  1. A /blog index page listing every published post with title, date, author, and reading time.
  2. 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.
  3. RSS feed at /blog/rss.xml.
  4. 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):

  1. 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.”

  2. 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.

  3. 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.

  4. What’s in the language (3 paragraphs). Effects, approve, Grounded<T>, agents, prompts. Link each to its chapter in The Corvid Book.

  5. 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.md and the benchmarks page.

  6. How to try it in 5 minutes (1 paragraph + code). curl ... | sh, corvid new, corvid run. Link to docs/book/02-quickstart.md.

  7. 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).

  8. Discuss / contribute (1 paragraph + links). Beta program signup, GitHub issues, Discord/Slack invite if one exists.

Acceptance criteria

  • /blog index renders with the launch post visible.
  • /blog/<slug> renders the launch post with code highlighting and cross-links resolving.
  • RSS feed at /blog/rss.xml validates 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.md as 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.md or benches/results/*/ratios.json and 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 as KwXyz in the TokKind enum).

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.rs

Two 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

  1. The two #[test] functions above, landed in crates/corvid-syntax/src/parser/tests.rs.
  2. Each test has a docstring explaining what it pins and what drift mode it catches.
  3. 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).
  4. CI workflow at .github/workflows/ci.yml must run these tests on every push (they will run automatically via cargo test --workspace; verify the workflow includes that step).

Acceptance criteria

  • cargo test -p corvid-syntax --lib grammar_md_keyword_list_matches_token_kind passes against the current grammar.md and token.rs.
  • cargo test -p corvid-syntax --lib grammar_md_production_names_have_parser_functions passes 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.md updated 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 (the every_enforced_guarantee_id_is_wired_to_workspace_source test) for the canonical shape. Match its style.
  • Hardcode the path docs/reference/grammar.md as 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/main and finding the compiler binary cannot be compiled to wasm32-unknown-unknown as 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:

  1. crates/corvid-cli/Cargo.toml declares only [[bin]], no [lib] with crate-type = ["cdylib"]. To produce a WASM module callable from JavaScript, we need either a cdylib library target or a new wrapper crate.

  2. corvid-cli’s dependency graph pulls in wasm- incompatible crates:

    • tokio with rt-multi-thread — does not compile to wasm32-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-cli directly 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.

  3. crates/corvid-codegen-wasm exists, 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.md

Cargo.toml depends only on the typechecking surface — concretely (subject to audit):

  • corvid-syntax (parser, lexer)
  • corvid-ast
  • corvid-resolve
  • corvid-types (effect calculus)
  • corvid-guarantees
  • serde + serde_json for diagnostic serialization
  • wasm-bindgen for 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

  1. 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.

  2. Stand up the empty corvid-browser crate with a stub check() that returns an empty diagnostics array. Verify it builds clean:

    Terminal window
    cargo build -p corvid-browser --target wasm32-unknown-unknown --release

    This proves the dep graph is clean before any real logic lands.

  3. Wire the real typecheck path. From check(source), call into the same pipeline corvid check src/main.cor uses 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.

  4. Map internal diagnostic types to the Diagnostic shape. 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.

  5. 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.wasm and 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.
  6. 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 a repository_dispatch to Micrurus-Ai/corvid-website so the website CI re-pulls and re-deploys. The website-side dispatch listener corvid-lang-wasm-changed will be added by the website team once the crate ships.

Acceptance criteria

  • cargo build -p corvid-browser --target wasm32-unknown-unknown --release completes with no errors.
  • wasm-bindgen postprocessing produces a JS-importable module plus a .wasm artifact.
  • Gzipped wire size of the .wasm artifact is ≤8 MB.
  • Calling check("agent foo(t: Ticket) -> Decision uses bar: return baz()") (a compile-refusal example) from JS returns a CheckResult whose diagnostics[0].guarantee_id matches 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 to main.

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 --workspace before 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.toml project. 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-browser matches corvid check byte-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:

  1. Comment on the tracking issue (or PR) with the WASM module size and a sample CheckResult JSON for the compile-refusal example. The website team uses that to wire the renderer.
  2. The website team adds the corvid-lang-wasm-changed repository_dispatch listener on their side, plus the CI step that clones Corvid-lang and fetches the artifact.
  3. Either side can iterate on the diagnostic schema — propose changes via PR comments on the tracking issue.
  • Slice 33J7 below (the consumer of this crate).
  • Original WASM target work: phase 20n-B in docs/phases/phase-20n-open-gap-implementation.md (the corvid-codegen-wasm crate — 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-browser crate ships a wasm32-unknown-unknown artifact 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=wasm shipped in Phase 20n-B. The bare (ptr, len) UTF-8 ABI + multi-value returns are documented in docs/internals/wasm-abi.md and docs/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.md and docs/book/03-tutorial-refund-agent.md.

Concrete deliverables

  1. A WASM module exposing the compiler.

    • Built from corvid-cli with --target=wasm plus a thin extern “C” wrapper (pub extern "c" fn compile(...), pub extern "c" fn run(...)).
    • Compiled with wasm-pack or cargo build --target wasm32-unknown-unknown + manual postprocessing.
    • Hosted as a static asset at corvid-lang.org/playground/corvid.wasm.
  2. 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_id badge links to corvid-lang.org/docs/reference/guarantees#<id> for in-context explanation.
  3. 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).
  4. 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.

  5. A “fork to local” button that downloads the editor’s contents as playground.cor plus a corvid.toml.

Build pipeline

The WASM module is the load-bearing artifact. Build it as part of the website’s CI:

Terminal window
# In a CI step before the website build:
git clone --depth=1 https://github.com/Micrurus-Ai/Corvid-lang
cd Corvid-lang
cargo 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/playground shows 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 approve from the Compile-Refusal example shows the approval.dangerous_call_requires_token diagnostic in <2 seconds total round trip.
  • Each diagnostic’s guarantee_id is a clickable link to corvid-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.cor in an editor.
  • Remove the approve line.
  • Run corvid check.
  • The compile-refusal diagnostic appears with the guarantee_id. Camera holds for 3 seconds.
  • Add the approve back. Re-run corvid 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 the grounded.no_silent_unwrap guarantee_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.50 in 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: ffmpeg with 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-website at public/launch/corvid-2min.mp4 and .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.md updated 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/ProgrammingLanguages discord/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-program label, 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-program on 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

  • /beta signup 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-program label.
  • 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.md reflects 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:

  1. Read this entire brief. The slices reference each other; skipping ahead loses context.
  2. 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.
  3. 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:

  1. Its acceptance criteria are all observably met.
  2. Its PR has landed on the relevant repo’s main.
  3. The corresponding ROADMAP checkbox is ticked in a follow-up commit (or the same commit if it’s a docs slice).
  4. learnings.md has an entry for the user-visible slice.
  5. 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

Good luck. Ship six honest things, not six aspirational ones.