When are two specs the same spec?
The industry spent 2025 agreeing that the spec — not the prompt, not the code — is the source of truth. That argument is over, and it was never the hard part. Rename a variable and the diff lights up though nothing changed. Weaken an acceptance criterion and the diff is one line among forty. A spec whose meaning is a canonical graph has a name you can derive, and then did the meaning change is a string comparison a machine can run. Nothing on this domain does that yet, and the section that says why is on this page rather than in a footnote.
Specs won. We are not here to reargue it.
By mid-2026 every major coding agent ships some flavour of spec-driven development and the phrase of the year is the spec is the prompt. Good. That consensus is the starting condition, not the product — because every one of those specs is prose. Structured Markdown, held together by convention and good intentions, reviewed by a person. The tools disagree about format and lifecycle and agree completely about substance.
Which leaves the two hardest questions untouched: when are two specs the same spec, and what shows a run obeyed one? A review meeting answers the first. A passing suite is a sample, not a record of what happened, and that is the second. We think both deserve arithmetic.
Identity, not diff review.
A spec canonicalizes to a graph; the graph derives a name. Reformat the document, reorder the clauses, rename freely — the name holds. Change what the spec claims and the name moves. The figure below is that property drawn out, using the one identity this stack has actually measured.
Reordering is free; the name holds. Weakening a constraint is not; the name moves, and a machine notices without being told what to look at. That is the design, and the top two rows are the only part of it anything has actually run — sem-8ae91fe9cbc5fd08 was derived on arch/linux · build workstation and again on t&r · freebsd 15 guest, engine v0.7.0-alpha.5, on 2026-08-09. Two operating systems, one implementation: a portability result, not a semantics result. The third row is a drawing of a compiler nobody has written.
Three things exist here, at three different rungs, so they are not in one list.
A single status for this domain would be false in one direction or the other. One artifact answers on a deployed host, one is a pair of parsers with test suites, one is a document. The rung chip on each says which.
The SPEC.md toolchain
live_deployedParser, validator, linter, differ, a CLI and eight MCP tools for the prose SPEC.md format. It is real, it is running, and it is the design this page argues past — built for the world where a spec is a document a person reviews.
Witness: GET / returns 200 and renders a registry page naming its own MCP endpoint. POST /mcp returns 406 without an event-stream Accept header and a JSON-RPC error envelope with one. Measured 2026-08-17.
Two reference parsers
in_treeThe same format parsed twice, in Elixir and in TypeScript, so that the format is a format rather than one program's habits. This is the strongest thing in the repository and it is still one team's work.
Witness: Both suites run in under a second on a laptop and the counts on this page are re-run by the build, not typed into it.
The SPEC.md specification
specThe format document: frontmatter fields, the eight canonical sections, a PEG grammar, normative validation rules, and the interoperability section that says what a second implementation has to agree about.
Witness: A document. Nothing in it runs, and the section this page leans on hardest — the join from Markdown to a canonical graph — describes a compiler that has never been written.
The compiler that would join the two halves of this page does not exist.
The machinery derives identities from canonical graphs. The front end parses Markdown (§3) and speaks MCP (§4.2). Nothing turns one into the other, so today a SpecPrompt spec is a validated document and not a checksummed one. Stated first, at full size, because it is the thing a reader would otherwise assume works.
The Markdown to WRL compiler
specThe join between the two halves of this domain. The machinery derives identities from canonical graphs; the front end parses Markdown; nothing turns one into the other. Until it exists, a SpecPrompt spec is a validated document and not a checksummed one.
Diff by identity
specThe whole point of a derivable name: reformat a spec and the string holds, weaken an acceptance criterion and it moves, so CI can answer did the meaning change with a string comparison instead of a review meeting.
A second independent implementation
specSame identity on two machines currently means one codebase agreeing with itself. Two operating systems is a portability result, not a semantics result, and this page has never claimed otherwise.
Whether anyone wants this
specWhether working engineers will accept a graph with a checksum over prose they can skim is untested with anyone but us. The Markdown front end exists precisely because we suspect the answer is no.
Drift detection at more than demo size
specCatching spec-versus-implementation drift by identity has run against exactly one world. Every claim about how it scales is extrapolated from a sample of one.
Every count below was produced by running the suite, not typed onto this page.
This build shells out to mix test and to vitest, parses what they print, and refuses to emit the page if either number disagrees with the frozen record beside it. A count cannot be hand-written onto this site; the only way to move one is to change what the tests do.
| Suite | Ran | Failed | Excluded | Provenance |
|---|---|---|---|---|
| Elixir · mix test | 71 tests | 0 failing | 0 excluded | re-run by this build |
| TypeScript · vitest | 22 tests | 0 failing | 0 excluded | re-run by this build |
| Both suites | 93 tests | 0 failing | 0 excluded | the frozen record and the run agree |
Each row was produced by executing the suite named in it and parsing what the runner printed — mix test against the Elixir toolchain in lib/, and npx vitest run against the TypeScript parser in npm/. Two parsers of one format (§4.8) is the strongest claim in this repository and it is still one team’s work. The counts are re-derived on every build; the frozen record beside them is what they are checked against, never their source.
And the rows that are a name rather than a thing.
Same table shape, honest column. built · superseded is used where something is deployed and running but replaced by the argument above — taking neither credit for it nor pretending it was never there.
| Piece | What it is | Status — measured or admitted |
|---|---|---|
| WRL | the spec language — meaning as a canonical graph | real · upstream |
| TRVM | the term-rewrite runtime that reduces it | in the T&R image |
| trvs / TRAAVIIS | seals a run into a replayable film | alpha · v0.7.0-alpha.5 |
| Identity check | the same sem- id derived on two operating systems | measured · once |
| SPEC.md toolchain | parser, validator, linter, differ, a CLI and eight MCP tools, live on its own host | built · superseded |
| Spec registry | publish and browse specs — deployed, and without films | built · superseded |
| Markdown → WRL compiler | prose in, identity out — the join between the two halves of this page | not built |
| Diff by identity | “did the meaning change?” as a string comparison | not built |
| Second implementation | independent derivation of the same identities | not built |
Where this stands, and what would move it.
- Status
- live_deployed — The SPEC.md toolchain is deployed and answering. app.specprompt.com returns 200, its health-bearing MCP endpoint at POST /mcp returns a well-formed JSON-RPC error rather than a web-server error, and the two reference parsers this repository ships agree with their own suites.
- Last verified
- 2026-08-17
- Source
- Four measurements on 2026-08-17. (1) mix test in specprompt.com — 71 tests, 0 failures. (2) npx vitest run in specprompt.com/npm — 22 tests, 0 failures. (3) curl https://app.specprompt.com/ — 200. (4) curl -X POST https://app.specprompt.com/mcp with a JSON-RPC tools/list body — 406 without an event-stream Accept header, and with one a JSON-RPC envelope carrying code -32600, which is the MCP server refusing an uninitialised session rather than a page failing to serve.
- Limit
- This establishes that the prior toolchain runs on this domain and that two parsers agree with the tests written for them. It does not establish the claim this page is built on — that a spec has a derivable identity — because no compiler joins the Markdown front end to WRL. It does not establish that the deployed MCP server does anything useful past refusing an uninitialised call; no tool was invoked end to end. And the one identity measured across two operating systems was derived by a single implementation twice, which is not two implementations agreeing.
- Next rung
- external — A second implementation, written by someone who is not us, that derives the same sem- identity from the same canonical graph — or a spec whose identity this one gets wrong. Either moves the semantics off self-report. Nothing else will, and shipping the compiler will not: it would make the claim testable, not tested.
- Specs on this domain with a derivable identity
- 0. The deployed toolchain validates prose. The compiler that would give a validated document a content-addressed name is not built, so nothing served here has one — including this page's own claims.
- Implementations of the semantics that are not ours
- 0. One codebase derived the demo world's identity on two operating systems. That is the same program run twice. A second implementation is what would turn a portability result into a semantics result.
Retraction — two things this page used to say
It claimed a layer. The previous hero eyebrow read The specification layer of the ComputeDriven stack. ampersand-nav files this domain as a specification in that world rather than a layer of it, and this page embeds that nav one element below the band — so the page was contradicting, on screen, the component rendered immediately beneath it. The band now says what the nav says. If the placement is wrong, the fix is in the nav, which this repository does not own.
It published an email address. hello@computedriven.com stood in the footer of the page this replaces. Corrections now go through the form above, which posts to the endpoint the parent site uses, and through this repository’s issues. No mailto: and no address in the markup — the gate refuses both.
And the retraction the earlier page made, which stands. An earlier specprompt.com carried a quarterly roadmap whose dates passed without the format they promised, and an ecosystem diagram of a pipeline its products had never run end to end. The dates were removed rather than refreshed to a later quarter. What is left is measured, linked to something you can run, or marked not built — and where a thing is deployed but replaced by the argument on this page, it says built · superseded rather than taking credit or pretending it was never there.
Three rungs, three lists. Nothing asks you to use what is not built.
lib/ and the TypeScript parser in npm/ — one format read by two programs, which is the only reason to believe it is a format.Run the testsmix test and npx vitest run. Both finish in about a second. The counts in the table above are what your machine should print.If a number on this page is wrong, that is the message we most want.
This page is generated from a record and gated, which catches a value that drifted from its witness. It cannot catch a witness that was wrong to begin with. If you maintain specs for agents and did the meaning change costs your team meetings, that is also worth hearing — it shapes what the compiler would have to accept.
Or file it in public: github.com/c-u-l8er/specprompt.com/issues. Both reach the same people.