aontu 0.57.0 → 0.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/README.md +2 -2
  2. package/dist/agentsmd.js +1 -1
  3. package/dist/alias.d.ts +3 -0
  4. package/dist/alias.js +59 -0
  5. package/dist/alias.js.map +1 -0
  6. package/dist/aontu.d.ts +4 -2
  7. package/dist/aontu.js +12 -3
  8. package/dist/aontu.js.map +1 -1
  9. package/dist/cli.d.ts +3 -1
  10. package/dist/cli.js +486 -4
  11. package/dist/cli.js.map +1 -1
  12. package/dist/ctx.d.ts +4 -0
  13. package/dist/ctx.js +3 -0
  14. package/dist/ctx.js.map +1 -1
  15. package/dist/err.js +6 -3
  16. package/dist/err.js.map +1 -1
  17. package/dist/format.js +8 -2
  18. package/dist/format.js.map +1 -1
  19. package/dist/hints.js +40 -9
  20. package/dist/hints.js.map +1 -1
  21. package/dist/lang.js +409 -58
  22. package/dist/lang.js.map +1 -1
  23. package/dist/lower.d.ts +20 -0
  24. package/dist/lower.js +575 -0
  25. package/dist/lower.js.map +1 -0
  26. package/dist/lsp.d.ts +1 -1
  27. package/dist/lsp.js +1 -1
  28. package/dist/lsp.js.map +1 -1
  29. package/dist/mcp-server.js +1 -1
  30. package/dist/mcp.d.ts +1 -0
  31. package/dist/mcp.js +40 -3
  32. package/dist/mcp.js.map +1 -1
  33. package/dist/render.d.ts +53 -0
  34. package/dist/render.js +542 -0
  35. package/dist/render.js.map +1 -0
  36. package/dist/sigdecl.js +1 -1
  37. package/dist/sigdecl.js.map +1 -1
  38. package/dist/std.d.ts +2 -0
  39. package/dist/std.js +498 -2
  40. package/dist/std.js.map +1 -1
  41. package/dist/template.d.ts +5 -0
  42. package/dist/template.js +257 -0
  43. package/dist/template.js.map +1 -0
  44. package/dist/tsconfig.tsbuildinfo +1 -1
  45. package/dist/type.d.ts +2 -0
  46. package/dist/type.js.map +1 -1
  47. package/dist/unify.js +43 -0
  48. package/dist/unify.js.map +1 -1
  49. package/dist/val/AggFuncVal.d.ts +1 -1
  50. package/dist/val/AggFuncVal.js +10 -21
  51. package/dist/val/AggFuncVal.js.map +1 -1
  52. package/dist/val/BagVal.js +1 -1
  53. package/dist/val/BagVal.js.map +1 -1
  54. package/dist/val/ConstraintVal.js +1 -1
  55. package/dist/val/DisjunctVal.js +33 -2
  56. package/dist/val/DisjunctVal.js.map +1 -1
  57. package/dist/val/EachFuncVal.d.ts +1 -1
  58. package/dist/val/EachFuncVal.js +8 -13
  59. package/dist/val/EachFuncVal.js.map +1 -1
  60. package/dist/val/EmitFuncVal.d.ts +23 -4
  61. package/dist/val/EmitFuncVal.js +298 -28
  62. package/dist/val/EmitFuncVal.js.map +1 -1
  63. package/dist/val/FilterFuncVal.js +8 -4
  64. package/dist/val/FilterFuncVal.js.map +1 -1
  65. package/dist/val/FormFuncVal.d.ts +14 -0
  66. package/dist/val/FormFuncVal.js +55 -0
  67. package/dist/val/FormFuncVal.js.map +1 -0
  68. package/dist/val/FuncBaseVal.js +36 -13
  69. package/dist/val/FuncBaseVal.js.map +1 -1
  70. package/dist/val/ListVal.js +9 -1
  71. package/dist/val/ListVal.js.map +1 -1
  72. package/dist/val/MapVal.d.ts +2 -1
  73. package/dist/val/MapVal.js +2 -1
  74. package/dist/val/MapVal.js.map +1 -1
  75. package/dist/val/PackFuncVal.d.ts +1 -1
  76. package/dist/val/PackFuncVal.js +22 -18
  77. package/dist/val/PackFuncVal.js.map +1 -1
  78. package/dist/val/PlaceVal.js +7 -2
  79. package/dist/val/PlaceVal.js.map +1 -1
  80. package/dist/val/RefVal.d.ts +3 -0
  81. package/dist/val/RefVal.js +181 -18
  82. package/dist/val/RefVal.js.map +1 -1
  83. package/dist/val/Val.d.ts +8 -1
  84. package/dist/val/Val.js +39 -1
  85. package/dist/val/Val.js.map +1 -1
  86. package/dist/val/members.d.ts +9 -0
  87. package/dist/val/members.js +52 -0
  88. package/dist/val/members.js.map +1 -0
  89. package/grammar/aontu.abnf +1 -1
  90. package/grammar/aontu.gbnf +1 -1
  91. package/grammar/aontu.lark +1 -1
  92. package/grammar/aontu.tmLanguage.json +1 -1
  93. package/package.json +1 -1
  94. package/skill/SKILL.md +4 -4
  95. package/skill/error-codes.md +1 -1
  96. package/skill/examples.md +1 -1
  97. package/skill/grammar-card.md +1 -1
  98. package/src/agentsmd.ts +1 -1
  99. package/src/alias.ts +112 -0
  100. package/src/aontu.ts +20 -2
  101. package/src/cli.ts +528 -4
  102. package/src/ctx.ts +18 -0
  103. package/src/err.ts +6 -3
  104. package/src/format.ts +12 -2
  105. package/src/hints.ts +47 -9
  106. package/src/lang.ts +453 -63
  107. package/src/lower.ts +636 -0
  108. package/src/lsp.ts +1 -1
  109. package/src/mcp-server.ts +1 -1
  110. package/src/mcp.ts +43 -4
  111. package/src/render.ts +727 -0
  112. package/src/sigdecl.ts +1 -1
  113. package/src/std.ts +506 -1
  114. package/src/template.ts +291 -0
  115. package/src/type.ts +10 -1
  116. package/src/unify.ts +47 -0
  117. package/src/val/AggFuncVal.ts +10 -21
  118. package/src/val/BagVal.ts +1 -1
  119. package/src/val/ConstraintVal.ts +1 -1
  120. package/src/val/DisjunctVal.ts +33 -2
  121. package/src/val/EachFuncVal.ts +8 -16
  122. package/src/val/EmitFuncVal.ts +376 -39
  123. package/src/val/FilterFuncVal.ts +11 -4
  124. package/src/val/FormFuncVal.ts +119 -0
  125. package/src/val/FuncBaseVal.ts +36 -13
  126. package/src/val/ListVal.ts +9 -1
  127. package/src/val/MapVal.ts +3 -2
  128. package/src/val/PackFuncVal.ts +23 -19
  129. package/src/val/PlaceVal.ts +7 -2
  130. package/src/val/RefVal.ts +193 -20
  131. package/src/val/Val.ts +75 -4
  132. package/src/val/members.ts +86 -0
package/src/format.ts CHANGED
@@ -148,6 +148,10 @@ type Node = {
148
148
  // value; spread: the value.
149
149
  key?: string
150
150
  opt?: boolean
151
+ // pair: written with `=`, the alias declaration operator, rather than
152
+ // a colon. The spelling is the parse's -- a colon after an alias name
153
+ // is a refused document, and the formatter keeps it one.
154
+ alias?: boolean
151
155
  value?: Node
152
156
 
153
157
  // map, list: the entries, and the comment on the opener's line.
@@ -349,8 +353,9 @@ class Reader {
349
353
  if (this.atKey()) {
350
354
  const tok = this.T[this.i]
351
355
  const opt = '#QM' === this.name(1)
356
+ const alias = '=' === this.T[this.i + (opt ? 2 : 1)].src
352
357
  this.i += opt ? 3 : 2
353
- return { t: 'pair', key: keyText(tok), opt, value: this.value(), at }
358
+ return { t: 'pair', key: keyText(tok), opt, alias, value: this.value(), at }
354
359
  }
355
360
  return this.value()
356
361
  }
@@ -590,6 +595,11 @@ function width(s: string): number {
590
595
  }
591
596
 
592
597
  function pairHead(node: Node, tight: boolean): string {
598
+ // An alias declaration is `%name = value` at every width: the `=` is
599
+ // an operator, and operators are spaced (§3.2).
600
+ if (node.alias) {
601
+ return node.key! + ' = '
602
+ }
593
603
  return node.key! + (node.opt ? '?' : '') + (tight ? ':' : ': ')
594
604
  }
595
605
 
@@ -1104,7 +1114,7 @@ function mergeRuns(body: Node[]): Node[] {
1104
1114
  continue
1105
1115
  }
1106
1116
  out.push({
1107
- t: 'pair', key: first.key, opt: first.opt,
1117
+ t: 'pair', key: first.key, opt: first.opt, alias: first.alias,
1108
1118
  value: { t: 'map', body: mergeRuns(merged) }, orig: group,
1109
1119
  })
1110
1120
  i = j - carry.length
package/src/hints.ts CHANGED
@@ -122,7 +122,7 @@ const hints: Record<string, string> = {
122
122
  ' grouping (...) (?:...) alternation a|b\n' +
123
123
  ' anchors ^ $ \\A \\z \\b \\B\n' +
124
124
  ' \n' +
125
- 'Aontu DEFINES the abbreviations rather than inheriting either\n' +
125
+ 'aontu DEFINES the abbreviations rather than inheriting either\n' +
126
126
  'host regex engine, so they mean the same in both ports:\n' +
127
127
  ' \\d [0-9] \\w [0-9A-Za-z_] \\s [ \\t\\n\\r\\f\\v] . [^\\n]\n' +
128
128
  'Note \\s is these six ASCII characters only -- not U+00A0.\n' +
@@ -164,13 +164,17 @@ const hints: Record<string, string> = {
164
164
  merge_conflict: 'A version-control conflict marker was found in the source. The\nfile still holds an unresolved merge: resolve it and remove the\n`<<<<<<<`, `=======` and `>>>>>>>` lines before unifying.\n \nExamples:\n <<<<<<< HEAD -> nil # A conflict marker, not a `<` operation;\n ======= -> nil # ... nor a chain of `=` characters;\n >>>>>>> other -> nil # ... nor a `>` operation.',
165
165
 
166
166
  include_denied: 'An @"..." include was refused by the active trust profile\n(docs/trust.md). The document asked to read a source the evaluation\'s\ninclude capability does not allow: widen the capability if the read is\nintended, or remove the include if it is not.\n \nExamples:\n a:@"in-root.aon" -> {..} # Inside the confinement root: allowed;\n a:@"../secret.aon" -> nil # ... but escaping the root is denied;\n a:@"/etc/hostname" -> nil # ... and so is an absolute path outside it.',
167
- include_extension: 'An @\"...\" include named a file the engine does not read. THE\nEXTENSION DECIDES which of two things a file is: `.aon` and\n`.aontu` are Aontu source, with the whole language in them, and\n`.json`, `.jsonld`, `.jsonc`, `.json5`, `.jsonic`, `.jsc`, `.toml`,\n`.yaml`, `.yml` and `.ini` are configuration DATA, read by that\nformat\'s own parser. Anything else -- and a name with no extension\n-- is refused rather than guessed at: a guess produces a document\nthat looks right and is not.\n \nExamples:\n a:@\"model.aon\" -> {..} # Aontu source;\n a:@\"server.toml\" -> {..} # ... config data, read as TOML;\n a:@\"notes.txt\" -> nil # ... but text is not a document;\n a:@\"data\" -> nil # ... and neither is an unnamed kind.',
167
+ include_extension: 'An @\"...\" include named a file the engine does not read. THE\nEXTENSION DECIDES which of two things a file is: `.aon` and\n`.aontu` are aontu source, with the whole language in them, and\n`.json`, `.jsonld`, `.jsonc`, `.json5`, `.jsonic`, `.jsc`, `.toml`,\n`.yaml`, `.yml` and `.ini` are configuration DATA, read by that\nformat\'s own parser. Anything else -- and a name with no extension\n-- is refused rather than guessed at: a guess produces a document\nthat looks right and is not.\n \nExamples:\n a:@\"model.aon\" -> {..} # aontu source;\n a:@\"server.toml\" -> {..} # ... config data, read as TOML;\n a:@\"notes.txt\" -> nil # ... but text is not a document;\n a:@\"data\" -> nil # ... and neither is an unnamed kind.',
168
168
 
169
169
  func_arity: 'This function was called with the wrong number of arguments:\n{func} takes {want}, but was given {got}.\n \nExamples:\n upper(\"a\") -> \"A\" # One argument, which is what upper takes;\n upper(\"a\",\"b\") -> nil # ... so two is a mistake in the source;\n key() -> \"\" # key takes none, or one level count;\n neq(1,2,3) -> neq # ... and neq takes one or more exclusions.',
170
170
  func_arg: 'This argument does not fit the function\'s signature:\n \n {sig}\n argument {argn} (`{arg}`) was `{got}`.\n \nThe signature is the declared call surface (one line per builtin,\ntest/spec/signature.tsv); an argument slot admits a concrete value\nof its declared kind, `number` admitting every numeric leaf and\n`string` admitting a path.\n \nExamples:\n upper("a") -> "A" # A string fits upper(s: string|number);\n upper(1) -> 1 # ... and so does a number;\n upper(true) -> nil # ... but a boolean fits neither word;\n add([1],2) -> nil # ... and a list is no operand.',
171
171
 
172
172
  elided_value: 'A key or element was written with no value after the colon. An\nelided value is a mistake in the source rather than a null: write\n`null` if that is what was meant, or supply the value.\n \nExamples:\n a:null -> null # An explicit null, which is a value;\n a: -> nil # ... but nothing at all is not;\n a: b:1 -> {..} # A colon chain is not an elision;\n [1,] -> [1] # ... nor is a trailing comma.',
173
173
 
174
+ alias_colon: 'An alias is declared with `=`: write `%name = value`. Until 0.57.0\nthe declaration was spelled with a colon, `%name: value`, and that\nform is refused rather than read as an ordinary key -- a document\nwritten for the old spelling fails here, at the declaration, instead\nof gaining a key named `%name` and a use that resolves to nothing.\n \nExamples:\n %u8 = integer & min(0) -> {..} # Declares %u8, which a: %u8 uses;\n %u8: integer -> nil # The form before 0.58.0, refused;\n "%u8": 1 -> {..} # A quoted key is an ordinary key.',
175
+
176
+ bare_punct: 'A bare string holds letters, digits, `-` and `_`, and nothing else.\nThis one holds `{char}`, in `{text}`. Every other punctuation\ncharacter is either syntax or an error, never silently part of a\nstring: a value that needs one is written quoted, and a `>` or `<`\nthat was meant as a bound is written as min(x), max(x), above(x) or\nbelow(x).\n \nExamples:\n a: team-payments -> "team-payments" # `-` and `_` are text;\n a: 2026-09-05 -> "2026-09-05" # ... digits included;\n a: x=y -> nil # `=` is not;\n a: "x=y" -> "x=y" # ... so quote it;\n a: >10 -> nil # Not an operator: write above(10).',
177
+
174
178
 
175
179
 
176
180
 
@@ -191,6 +195,11 @@ const hints: Record<string, string> = {
191
195
 
192
196
  view_kind_unknown: 'The figure kind is not one the verb draws. The kinds are tree, matrix,\ngraph, layer, sets, layers, ladder and poset; the note lists them.',
193
197
 
198
+ render_path: 'A unit path is written below the output directory: relative, with no\n`..` segment, and no two units the same. Rename the unit.',
199
+ render_lang: 'A text escape carries verbatim syntax of ONE language, and it must be\nthe unit\'s: a text of another language in this unit would be written\nas if it were this one. Move it to a unit of its own language.',
200
+ render_profile: 'Only fragments and text escapes render without a lowering, under the\ntext profile. A record, enum, alias, const or func needs a profile\nwhose language has one (typescript, go): set the unit\'s lang, or\nwrite the declaration as a fragment.',
201
+ render_strict: 'Under strict, an opaque escape -- a text declaration or a raw piece,\nwhich the renderer cannot check -- is refused. Write it as lines, or\nrender without strict and read the loss report.',
202
+ render_unit: 'The unit asked for is not in the instance. The report names the\npath; the units are listed by `--format json`.',
194
203
  view_profile_unknown: 'The figure kind does not render into the profile asked for: there is no\ntext form of a node-link drawing and no Mermaid form of a matrix. The\nnote lists the profiles the kind declares; the first is its default.',
195
204
 
196
205
  format_check: 'The formatted text is not the same document, so nothing was written.\nThis is a formatter defect: please report it, with the source.',
@@ -234,7 +243,15 @@ const hints: Record<string, string> = {
234
243
 
235
244
  emit_none: 'No template matched a node, and there is no catch-all. `emit`\ntries each template in the order written and takes the first the\nnode unifies with; the node {value} unified with none of {tried}.\nAdd a template whose `match` is `any` — last, since the first match\nwins — if the rest of the selection was meant to be allowed.\n \nExamples:\n emit([1], [{match:integer,body:[a]}]) -> [..] # A pattern matches;\n emit([x], [{match:any,body:[a]}]) -> [..] # ... or a catch-all;\n emit([x], [{match:integer,body:[a]}]) -> nil # ... but nothing here.',
236
245
 
237
- esc_variant: 'esc() and usc() were given a variant that names no convention.\nA variant names a CONVENTION rather than a language, because several\nlanguages share one and one language has several. The names are `sq`,\n`sql`, `shell`, `xml`, `uri` and `regex`; written with no variant at\nall it is the C escape, JSON canonical, which covers the double-quoted\nliteral of every C-family language.\n \nExamples:\n esc(text) -> ... # C / JSON, the default;\n esc(text, sq) -> ... # ... single-quoted C-family;\n esc(text, pascal) -> nil # ... but that is not a convention.',
246
+ replace_overlap: "Two keys of a template's `replace` map overlap: {key} is inside\n{other}. A replacement is one left-to-right scan of the body's literal\ntext taking the longest key at each position, and a key inside\nanother is ambiguous whatever the order -- so it is refused on the\ntemplate, before any node is visited.\n \nExamples:\n replace: {PIN: .pin, MSG: .msg} # Two keys, neither inside the other;\n replace: {PIN: .pin} # ... or one alone;\n replace: {P: .p, PIN: .pin} # ... but P is inside PIN.",
247
+
248
+ replace_unused: 'A key of a template\'s `replace` map matches nothing: {key} appears\nin none of the body\'s literal lines. A replacement key is an exact\nstring the body already holds as ordinary target text, so a key the\nbody does not hold means the template drifted from its map -- refused\nbefore any node is visited, since the drift is the same for every\nnode.\n \nExamples:\n {replace: {PIN: .pin}, body: ["listen(PIN)"]} # The body holds PIN;\n {replace: {PIN: .pin}, body: ["pin: PIN"]} # ... anywhere in a line;\n {replace: {PIN: .pin}, body: ["listen(pin)"]} # ... but not here.',
249
+
250
+ replace_value: 'A replacement value is not text: the `replace` key {key} came to\n{value} at the node. A value reaches the body as a string -- a number\nor a boolean spells itself, as it does after `+` -- and it has to\nhave settled by the time the dispatch fires, so a map, a list, a\nnull or a value still unresolved is refused rather than written into\na file as something else.\n \nExamples:\n replace: {PIN: .pin} # A string field;\n replace: {PORT: .port} # ... or a number, as digits;\n replace: {ALL: _} # ... but the node itself is a map.',
251
+
252
+ form_data: 'The first argument to form() is not a bag. `form` makes one list\nelement per child of its DATA, so the data has to have children: a\nlist, or a map whose values are taken in sorted-key order.\n \nExamples:\n form([a,b], upper(_)) -> [..] # A list, in source order;\n form({b:2,a:1}, _) -> [..] # ... a map, in sorted-key order;\n form(1, _) -> nil # ... but a scalar has no children.',
253
+
254
+ esc_variant: 'esc(), usc() or a template\'s `esc:` key were given a variant that\nnames no convention.\nA variant names a CONVENTION rather than a language, because several\nlanguages share one and one language has several. The names are `sq`,\n`sql`, `shell`, `xml`, `uri` and `regex`; written with no variant at\nall it is the C escape, JSON canonical, which covers the double-quoted\nliteral of every C-family language.\n \nExamples:\n esc(text) -> ... # C / JSON, the default;\n esc(text, sq) -> ... # ... single-quoted C-family;\n esc(text, pascal) -> nil # ... but that is not a convention.',
238
255
 
239
256
  usc_malformed: 'usc() was given text the convention could not have produced,\nso there is nothing to read back out: a truncated code-point escape, an\nescape the convention does not define, or an escape character standing\nalone where the convention doubles it. `usc` is the LEFT inverse of\n`esc` and it is partial — every escaped value has an original, but not\nevery string is an escaped value.\n \nExamples:\n usc(esc(text)) -> ... # Whatever esc() wrote;\n usc(text, sql) -> ... # ... in the same convention;\n usc(text, shell) -> nil # ... but not in another one.',
240
257
 
@@ -267,7 +284,7 @@ const hints: Record<string, string> = {
267
284
  'This exact decimal exceeds the exactness budget: at most 4096\n' +
268
285
  'coefficient digits and an absolute scale of at most 4096. The\n' +
269
286
  'budget applies to computed results as well as to literals.\n' +
270
- 'Aontu never rounds, so a value beyond the budget is refused\n' +
287
+ 'aontu never rounds, so a value beyond the budget is refused\n' +
271
288
  'rather than approximated.' +
272
289
  '\n \nExamples:\n' +
273
290
  ' 0d1e1000000000 -> nil # Scale far beyond the budget;\n' +
@@ -277,7 +294,7 @@ const hints: Record<string, string> = {
277
294
  lossy_integer_literal:
278
295
  'This integer literal, {src}, is not exactly representable in\n' +
279
296
  'binary64, so storing it would silently round it to a DIFFERENT\n' +
280
- 'number. Aontu refuses rather than corrupts: write it as a `0d`\n' +
297
+ 'number. aontu refuses rather than corrupts: write it as a `0d`\n' +
281
298
  'literal to get the exact integer.\n' +
282
299
  'The rule is exactness, not magnitude -- a literal far outside the\n' +
283
300
  'int64 window is still a value when it lands exactly on a binary64.' +
@@ -289,7 +306,7 @@ const hints: Record<string, string> = {
289
306
  ' 100000000000000000000 -> 1e20 # 10^20 is huge and exact.',
290
307
 
291
308
  exact_float_mix:
292
- 'Aontu cannot mix an exact number with a binary float.\n' +
309
+ 'aontu cannot mix an exact number with a binary float.\n' +
293
310
  'Here the operands are {left} and {right}, in that order.\n' +
294
311
  'A big type never silently becomes a binary float, in either\n' +
295
312
  'operand order -- binary64 cannot hold every exact value, so the\n' +
@@ -354,7 +371,7 @@ const hints: Record<string, string> = {
354
371
 
355
372
  divide_by_zero:
356
373
  'Division by zero. `div`, `mod` and `rem` refuse a zero divisor in\n' +
357
- 'every numeric leaf, including binary floats: Aontu is a JSON\n' +
374
+ 'every numeric leaf, including binary floats: aontu is a JSON\n' +
358
375
  'superset with no notation for an infinity, so there is no value\n' +
359
376
  'the operation could answer with. A definition that divides by zero\n' +
360
377
  'is wrong, and this says so where it is written rather than\n' +
@@ -380,7 +397,7 @@ const hints: Record<string, string> = {
380
397
 
381
398
  float_overflow:
382
399
  'This result is not a finite binary64 number, so it is not a value\n' +
383
- 'Aontu can carry. There is no notation for an infinity or a NaN in\n' +
400
+ 'aontu can carry. There is no notation for an infinity or a NaN in\n' +
384
401
  'a JSON superset, and no JSON a generator could emit for one, so\n' +
385
402
  'the operation is refused where it is written rather than escaping\n' +
386
403
  'as an internal error or an unserialisable value.\n' +
@@ -395,7 +412,7 @@ const hints: Record<string, string> = {
395
412
  'The `integer` leaf holds a value only when it is integral, within\n' +
396
413
  'the int64 range, and exactly representable in binary64. This\n' +
397
414
  'result is not: {sum}.\n' +
398
- 'Aontu computes integers exactly and refuses to store a rounded\n' +
415
+ 'aontu computes integers exactly and refuses to store a rounded\n' +
399
416
  'answer -- write `0d<digits>` for an exact integer beyond that\n' +
400
417
  'window.' +
401
418
  '\n \nExamples:\n' +
@@ -537,6 +554,15 @@ const codeClasses: Record<string, string> = {
537
554
  view_profile_unknown: 'reference',
538
555
  view_style_profile: 'reference',
539
556
  view_style_unknown: 'reference',
557
+ // The renderer (docs/design/RENDER.0.md D7, D8): a unit path that is
558
+ // not a relative descent of its own, a text escape in the wrong
559
+ // language, a declaration with no lowering, an opaque escape under
560
+ // strict, a unit filter that names nothing.
561
+ render_path: 'parse',
562
+ render_lang: 'conflict',
563
+ render_profile: 'parse',
564
+ render_strict: 'conflict',
565
+ render_unit: 'reference',
540
566
  // The formatter's self-check (docs/design/FMT.0.md): a report-layer
541
567
  // code, class internal -- the formatter, not the document, is wrong.
542
568
  format_check: 'internal',
@@ -596,6 +622,16 @@ const codeClasses: Record<string, string> = {
596
622
  emit_none: 'conflict',
597
623
  emit_ref: 'conflict',
598
624
 
625
+ // RENDER P6 -- `replace` on a template, and `form`. The two
626
+ // template checks are class `parse`: what is wrong is the TEMPLATE
627
+ // as written, before any node. `replace_value` is class `conflict`:
628
+ // the node's value and the body that wanted text disagreed.
629
+ // `form_data` is `each_data`'s twin.
630
+ replace_overlap: 'parse',
631
+ replace_unused: 'parse',
632
+ replace_value: 'conflict',
633
+ form_data: 'parse',
634
+
599
635
  // G8 phase 3 -- the placeholder. Class `conflict`: two values met
600
636
  // and neither could answer for the other, which is what every
601
637
  // conflict is.
@@ -627,6 +663,8 @@ const codeClasses: Record<string, string> = {
627
663
  pref_implicit_bag: 'parse',
628
664
  alias_not_toplevel: 'parse',
629
665
  alias_in_path: 'parse',
666
+ alias_colon: 'parse',
667
+ bare_punct: 'parse',
630
668
  not_number: 'parse',
631
669
  negative: 'parse',
632
670
  decimal_syntax: 'parse',