docs(adr): ADR-0018 — the creator toolchain and the escape hatch at the grammar IR - #326
Merged
Merged
Conversation
…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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 (
Programderives serde;ir.rssays so as settled architecture). A creator may compute aProgramby any means at authoring time provided theProgramis 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
javaon 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_skinis not ported. Skipping skins was declined — a missing skin isDW0309deliberately ("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 forcheck-versions.shto keep in lockstep. Exposing it fromdelvecwas 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
delvecgains the IR loader thatgrammar.mdalready claims exists — an unbound documented claim, and the reasonbell/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.