ADR013 ExecutableLayer
Title: Executable layer
- Status: Accepted
- Decided: D2026-03
- Recorded: D2026-09-07
- Followed by: ADR014
Literals - Affects:
Parser,Prose
Context
sprig did not start out descriptive. The early language was closer to something executable, or to something that could generate code in an existing language, than to a field guide.
Prose arrived in December 2025, out of a conversation about wanting the UI to read like a story. That produced the descriptive layer — the thing that turned out to be the point. But the executable ambition did not go away alongside it. It got a name: scene.
A scene was meant to be the executable part of a universe. It described, in
structured language, what happens — and the shapes of things, which in
practice was a type schema. It was built, and it got a long way. What is now
archive/scenes is nineteen files and roughly forty-nine hundred lines: a
scene compiler, a SceneRuntime, a SceneInstance, a PortalHandle, an
attestation model with computed statuses, and a projection-expectation system.
The type schema had string and integer constraints with real syntax:
minLength { 1 }
maxLength { 64 }
So the question was not whether a limited executable layer could be built. It was built, more than once. The question was whether sprig should have one.
The answer came from using it. The scene language was so specific that by the time a use case was narrow enough for scenes to handle, it was easier to write that use case in code. And across every attempt at executable prose, the same thing fell out: code was never the hard part. Code is not especially hard to write or hard to read. The hard part is almost always author intention — why a thing exists, what it is for, how it sits against everything else — and non-executable prose already did that well, even when the only place the intention lived was prose.
The executable layer was therefore spending complexity to compete where code was already strong, and buying nothing where prose was already strong.
Decision
There is no executable layer in sprig and prose. Scenes are removed.
If an executable layer ever exists, it is a different language paired with sprig — "sprig and something else" — not prose.
Consequences
The line this draws. Prose describes a world. It does not run it. That is why the output is a graph and not a program, and it is the sentence every later refusal in this directory inherits.
What has no home in prose. Anything that only means something in an executing system: types, cardinality, conditions, arithmetic, time as a value. When a later record refuses one of those, this is the record it is applying.
The principle underneath it. Prose earns its place only where it beats code, and the place it beats code is stated intention. A feature that makes prose better at execution is spending the one advantage prose has. That test — does this make prose better at intention, or better at running things — is worth applying to any proposal that feels like it is adding power.
What this does not do. It does not stop consumers from acting on a universe. Sprig's whole premise is systems responding to a described world; the CLI, the field guide, and the receipt scanner all read the manifest programmatically. "Not executable" is a statement about prose the language, not about tools. The refusal is that prose itself never carries behaviour.
Cost. Roughly forty-nine hundred lines are archived rather than deleted, including a working runtime and a type schema that took real effort. Keeping them readable is deliberate: it is the only remaining evidence that the alternative was tried rather than dismissed.
A word is now free, and it is not free of history. The scene language used
expects for projection expectations. Prose has since proposed an expects
block (011) that is a different idea, and the
difference is exactly the line this record draws — the scene version was a
schema, the prose version states author intent. The two cannot meet in one
grammar, because one of them was removed by this decision.
Alternatives considered
Keep the limited executable layer. This is what was built, so it was not rejected on paper. It was rejected by use: the narrower the language got, the more often writing the thing in code was simply easier, and the value it was supposed to add turned out to be value prose was already delivering.
Keep the shapes half, drop the "what happens" half. Retain the type schema
as a description of structure and abandon execution. Rejected. A schema with
nothing to execute against is a schema for its own sake, and dimensions
already say what a thing is. Note that this is not the ancestor of the
proposed expects block; that block is about intention, not structure, and
011 records the distinction.
Scenes as a separate file type or package inside sprig. Rejected. The confusion was that a project held two languages doing two different jobs, and a file extension does not fix that. It relocates it.
Code generation from prose rather than execution inside it. This was the earlier shape of the project rather than a considered alternative, and it was already behind sprig by the time scenes existed. It is recorded here because a future reader will propose it, and the answer is the same: it makes prose better at producing code, which is not the axis prose wins on.
Evidence
archive/scenes is the primary evidence, and it is deliberately still
readable. src/api/SceneRuntime.js and src/api/SceneInstance.js mean scenes
ran. src/attestations/compute_status.js means they were checked.
test/string-constraints.test.js and test/integer-constraints.test.js mean
the type schema had real value constraints — minLength, maxLength, min,
max, step, of — expressed in the same keyword { value } block shape
prose uses. That is what prose with literals would have looked like, and it is
why 014 follows from this record rather than standing on
its own.
This was also not a single decision. Executable prose was attempted more than once, in more than one shape, and every attempt landed the same way. A record that described only the last attempt would make the conclusion look like a preference.