Skip to content

docs(adr): ADR-0018 — the creator toolchain and the escape hatch at the grammar IR - #326

Merged
stellarfeline merged 4 commits into
mainfrom
docs/adr-0018-creator-toolchain
Aug 7, 2026
Merged

docs(adr): ADR-0018 — the creator toolchain and the escape hatch at the grammar IR#326
stellarfeline merged 4 commits into
mainfrom
docs/adr-0018-creator-toolchain

Conversation

@stellarfeline

Copy link
Copy Markdown
Owner

Records the owner decisions of 2026-08-06/07. Owner-review PR: the key decisions were surfaced in chat and confirmed there.

§1 The hatch is the grammar IR. The two-layer picture (DSL above, engine Rust below) was wrong — the stack has a middle layer that is already data (Program derives serde; ir.rs says so as settled architecture). A creator may compute a Program by any means at authoring time provided the Program is checked in. That is the same position the LLM already occupies, with the same safety property, so ADR-0006 is untouched. Native creator Rust inside the compiler is rejected (Rust has no capability system; now()/env/HashMap order are all safe code). bell/ moves to the content repo as an ordinary crate — the ruling that opened this ADR is satisfied without an exception.

§2 cargo is a declared prerequisite; creator-facing tooling is Rust. Locating a JVM was declined because it cannot be tested — a launcher-private JRE is not java on PATH, and a discovery ladder is branch logic no CI job here can exercise. Rust also removes a defect: a Java authoring API would be a hand-written mirror of the IR types, which is the capability-duplication defect at a language boundary.

§3 Python is a prerequisite too; delve_skin is not ported. Skipping skins was declined — a missing skin is DW0309 deliberately ("not a silent skip"), and a degraded path is another unexercised branch.

§4 The authoring surface folds into delvewright-dsl; crates.io stays at two packages. Publishing grammar as a third was declined for a concrete reason: it adds a fourth version line for check-versions.sh to keep in lockstep. Exposing it from delvec was declined because a lib target makes creators pull the whole compiler tree, and it welds the authoring API to the engine version line that ADR-0017 §2 separated on purpose.

§5 delvec gains the IR loader that grammar.md already claims exists — an unbound documented claim, and the reason bell/ had to be Rust.

§6 Explicitly not decided: the campaign-semantics half. Beneath the DSL there is mcfunction, and ADR-0001 forbids reaching it. That half has no hatch and this ADR does not give it one; conflating the two halves is what made the argument unresolvable. Trigger recorded.

What CI proves

Nothing behavioural — ADR text plus its index row.

…he grammar IR

Records the 2026-08-06/07 owner decisions: the hatch is the grammar Program
IR (already data, above the determinism boundary, the same position the LLM
already occupies), not creator code inside the compiler; cargo and Python 3
are declared creator prerequisites rather than discovered; the authoring
surface folds into the already-published delvewright-dsl so crates.io stays
at two packages and ADR-0016 gains no fourth version line; delvec gains the
IR loader grammar.md already claims exists.

Explicitly does NOT decide the campaign-semantics half, which has no data
layer beneath the DSL and therefore no hatch — recorded with its trigger.
…sioned on-disk surface

External audit found two gaps, both real.

§6: letting a creator keep the generator that produced a Program creates a
generator/artifact mirror, and this ADR's own anti-mirror argument (used to
reject a hand-written Java API) applies to it verbatim. Named rather than
smoothed: the data is normative, a checked-in generator is an ordinary
authoring script. Requiring checked-in generators to be reproducible was
rejected — it re-imports onto creator code the determinism requirement §1
declined to impose. prefab<->Program IS bound by program_hash;
generator<->Program cannot be, and the ADR accepts that undetectable drift
instead of pretending a re-run-diff could gate it.

§7: once the Program JSON is the authoring form and a published crate's type,
it is a long-lived on-disk format — and the crate's semver covers the Rust API,
not the document. The IR has no version field and no deny_unknown_fields today,
so an older delvec meeting a newer Program silently ignores what it cannot
understand. This repo already paid for that failure in prefab metadata and fixed
it with deny_unknown_fields + DW0346. Required version, refusing loader,
deny_unknown_fields, per-construct fences — decided before the first Program is
checked in, when it is free.
… pin does not make it deterministic

Owner question exposed a gap: §6 said a checked-in generator has no special
standing, which reads as advice not to keep one. The reason to keep it is
review — a diff of generated IR is not human-readable and a diff of its source
is. Written down.

Also records, because the assumption is natural and wrong, that pinning
delvewright-dsl pins the LIBRARY and not the creator's own code: HashMap
iteration order, now(), env::var, read_dir order and rand are all safe Rust.
Determinism of a particular generator is empirical and per-generator, never
implied by a version pin. And a normative source would be a fiction regardless:
a build either re-runs creator code (refused by §1, breaks reproduce-from-pin)
or reads the checked-in Program, which makes the Program normative whatever a
document calls it.

Three non-gating strengthenings: provenance records the pinned library version
(undetectable drift becomes investigable); an advisory re-generate-and-diff in a
varied environment that reports and never gates; an opt-in per-generator
determinism claim established by observation and recorded.
@stellarfeline
stellarfeline merged commit b46d147 into main Aug 7, 2026
12 checks passed
@stellarfeline
stellarfeline deleted the docs/adr-0018-creator-toolchain branch August 7, 2026 21:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant