Sunday, late afternoon. I tagged verbose v0.3.0 three days ago and spent most of yesterday writing about the thing I was most proud of — the generator pipeline, the hold-out runs, what authorship even means when the model writes the formal source. Three articles in one day. I’d thought that was the release post. It isn’t.

The thing I keep coming back to is smaller and weirder. I have one .verbose file open in my editor. I can compile it to a 1.2 KB ELF binary that opens a TCP socket and answers HTTP. I can compile the same file — same characters, same line breaks — to a WASM module that runs in a browser tab, in wasmtime, in a Cloudflare Worker if I cared to push it there. The CPU instructions are different. The runtime model is different. The output is, by every measure that matters at the byte level, two unrelated programs. The source is the same source.

That’s what v0.3.0 is, more than anything else. The WASM back end caught up enough — through milestones I’d been calling W1 through W4 in commit messages nobody reads — that the second target became a real surface. Not a demo. A real second machine I can target from prose I wrote once.

What jumped

Five days, four milestones. I’m not going to walk through each — the changelog has them. The shape is: numeric primitives (abs, min, max), then text foundations (literals, the I/O ABI), then a bump allocator and concat and itoa so text could actually be built at runtime, then six text primitives (length, parse_int, starts_with, ends_with, contains, json_escape), and finally Result(T, E) and match_result at the rule body’s top level. By the end, the WASM emitter could compile every shape my native back end already handled, give or take the obvious gaps (no socket, no fetch, no fork — these aren’t things WASM offers, and I’m not pretending it does).

I’d been describing the WASM target for a year as a roadmap line. It moved into the present tense this week.

What surprised me

Honestly, the part that didn’t surprise me was that it worked. The compiler architecture had been pointing here from the start — verifier in front, three back ends already on the other side (interpreter, native x86-64, Rust transpiler). Adding a fourth was always going to be a matter of writing it. The bet of the language is that the verifier holds the floor and the back ends are downstream of the verified IR. That bet keeps paying.

The part that surprised me was the silence. Adding a back end didn’t require touching the verifier. Didn’t require touching the parser. Didn’t require touching the IR. The Result(text, text) work, the match_result work, the text composition work — every single piece of that landed once in the front half of the compiler, and the WASM emitter inherited it for free, the same way the native emitter had. The same source compiles to two different machines because the source describes what the program does, not how the metal does it. I knew that was the design. Watching it actually behave that way was a different thing.

There’s a moment — and I’m going to keep noticing this kind of moment because they’re the ones I forget about a week later — where you watch a piece of architecture you committed to two years ago do exactly what you said it would do, and the surprise isn’t the result, it’s the quietness of the result. No drama. Just the next compile target showing up where the architecture had always said it would.

A small thing about composability

I want to mention match_result separately because it’s the part of the release I underestimated.

match_result is rule composition with pattern matching. Rule A returns a Result(number, text). Rule B calls Rule A, matches on the outcome, branches. Cross-concept (the callee’s input fields are a subset of the caller’s) and nested (A calls B calls C, no stack explosion). The verifier still proves termination, still tracks reads, still rejects anything that doesn’t add up.

The reason I underestimated it is that “rules can call rules” sounds like a compiler feature you’d expect to already have. Of course rules compose. What’s actually new — and what I keep noticing as I write more .verbose — is that the failure path composes too. The error from rule C surfaces in rule A surfaces in rule B, with the verifier checking each step, and the binary still doing only what every step declared. Whatever the AI Act calls “explainability of an automated decision,” whatever a regulated audit calls “trace this Err back to its source,” that’s the shape it’s growing into. Not because I added explainability. Because the failure path is just data, and the verifier verifies it the same way it verifies everything else.

The shape of the release

I want to be careful here, because this post is the kind that drifts into “look how far it’s come” if I’m not watching. v0.3.0 isn’t a finished thing. The WASM back end has gaps. The generator pipeline is good on a small hold-out and I have no idea how it behaves at scale. The verifier still has corners I haven’t tested. There’s no LSP integration, no debugger, no ecosystem — and I’m not building those, because that’s not what verbose is for.

What v0.3.0 is, honestly, is a moment where the language stopped being a single-target thing. It now has two real machines downstream of it. The author writes one source, the auditor reads one source, and the deployment chooses where the bytes go. I don’t yet know which use cases push for which target — embedded asks for native, edge functions ask for WASM, a regulated decision rule probably asks for both depending on where it runs — but the question “which target” is now a deployment question, not an authoring question. The author’s job stayed the same.

That’s the part I’m going to remember about this release a year from now. Not the milestone count. Not the byte sizes. The way one source file looked, sitting in my editor, while two completely different binaries were emitted from it without any of the work upstream knowing about either machine.

The compiler did exactly what its architecture said it would do. Nothing dramatic. Just a Sunday afternoon, two cargo run invocations, two emitted artifacts, the same source unchanged between them. The proof was in the unchanged.