0018. A valid but unimplemented tag is a build error
0018. A valid but unimplemented tag is a build error
Status
Accepted
Date
2026-10-04
Deciders
roadmap author; the lead may overrule
Context
The 26 tag contracts on main (merged in PR #1; PR #2 only adopted an MX option) describe the whole resource-file vocabulary: relationships, policies, calculations, aggregates and more (roadmap, section 0 and M1). A contract tells MX, the separate project that parses .mx files, which tags and attributes a file may contain. The compiler will implement that vocabulary over several milestones, so for a long time a file can be valid for MX and still use something Mesh does not handle. A policies block that is silently ignored would look like protection and give none.
Decision
The roadmap author decided this in plan revision 2: “A tag or attribute that is valid but not implemented is a build error. PR #1’s contracts already accept the whole vocabulary; the compiler grows into it milestone by milestone. Silently ignoring a policies block would be the worst kind of fallback” (plan revision 2 (superseded), section 8, D5). The roadmap states the rule in M1: such a tag or attribute is “a build error naming it and the milestone that will” implement it. The M1 list is relationships, belongs-to, has-many, change, validate, filter, sort, policies, policy, authorize-if, calculations, calculate, value, aggregates, count. It follows the vocabulary alignment that opens M1, which renames tags to follow Ash’s DSL (ADR-0034), so the names will change with it. public is not on the list: it is recorded in the model and nothing in v1 reads it (roadmap, M1; ADR-0035, Proposed, on what it means). The rule follows the principle “No silent fallback” (roadmap, section 2, item 2; research synthesis, section 8, “Silent fallbacks”). Nothing in the rulings file overrules it.
Options considered
Option A: Build error naming the milestone (chosen)
| Dimension | Assessment |
|---|---|
| Complexity | Low: a list per milestone, shrinking |
| Cost | Low; every milestone must delete entries from the list |
| Safety | A project cannot appear to work while ignoring a rule |
| Reversibility | Easy: remove the check |
Pros: a stated rule is either honoured or reported; authors and agents see which milestone brings the feature.
Cons: the example post.mx cannot build in full until M8 (M1 test 5; M8 test 6); users cannot try a later feature early; the list must stay current.
Option B: Warning, then ignore
| Dimension | Assessment |
|---|---|
| Complexity | Low |
| Cost | Lowest |
| Safety | Poor: warnings are missed; Ash turns verifier errors into warnings and had to build a test helper to recover the signal (research synthesis, section 8, “Do differently”) |
| Reversibility | Easy, but behaviour changes silently when implemented |
Pros: the full example file builds from M1.
Cons: an ignored policies block, or an ignored filter, produces working but wrong software.
Option C: Shrink the contracts to what is implemented
| Dimension | Assessment |
|---|---|
| Complexity | Medium: contracts change in every milestone |
| Cost | Higher; each milestone edits contracts and their negative fixtures |
| Safety | MX itself rejects the tag |
| Reversibility | Easy, but churn |
Pros: the error comes from MX, with no Mesh rule.
Cons: discards the full fixture and the contracts’ coverage of the vocabulary, and the mapping to Ash’s DSL (ADR-0034) is done against the whole vocabulary, so contracts would be edited twice.
Trade-off analysis
The three options differ in where the error comes from and whether the file stays valid. A keeps the file valid and the error honest, at the cost of a maintained list.
Consequences
Easier: staged delivery with no hidden gaps. Harder: every milestone must remove its entries and the user docs must say what is not yet available. Revisit the list after the vocabulary alignment at the start of M1.
Action items
- M1: implement the list and the error with file, line and milestone.
- M3 to M8: remove entries as tags land.
- M8: no entries remain; the full example builds.