aontu 0.56.0 → 0.58.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 (138) 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 +5 -2
  7. package/dist/aontu.js +11 -3
  8. package/dist/aontu.js.map +1 -1
  9. package/dist/cli.d.ts +8 -2
  10. package/dist/cli.js +564 -21
  11. package/dist/cli.js.map +1 -1
  12. package/dist/ctx.d.ts +2 -0
  13. package/dist/ctx.js +1 -0
  14. package/dist/ctx.js.map +1 -1
  15. package/dist/escape.d.ts +5 -0
  16. package/dist/escape.js +455 -0
  17. package/dist/escape.js.map +1 -0
  18. package/dist/format.d.ts +9 -0
  19. package/dist/format.js +550 -55
  20. package/dist/format.js.map +1 -1
  21. package/dist/hints.js +74 -9
  22. package/dist/hints.js.map +1 -1
  23. package/dist/lang.js +374 -58
  24. package/dist/lang.js.map +1 -1
  25. package/dist/lower.d.ts +20 -0
  26. package/dist/lower.js +575 -0
  27. package/dist/lower.js.map +1 -0
  28. package/dist/lsp.d.ts +1 -1
  29. package/dist/lsp.js +4 -4
  30. package/dist/lsp.js.map +1 -1
  31. package/dist/mcp-server.js +2 -2
  32. package/dist/mcp-server.js.map +1 -1
  33. package/dist/mcp.d.ts +1 -0
  34. package/dist/mcp.js +40 -3
  35. package/dist/mcp.js.map +1 -1
  36. package/dist/mod-tool.js +8 -7
  37. package/dist/mod-tool.js.map +1 -1
  38. package/dist/mod.js +6 -6
  39. package/dist/mod.js.map +1 -1
  40. package/dist/render.d.ts +53 -0
  41. package/dist/render.js +542 -0
  42. package/dist/render.js.map +1 -0
  43. package/dist/sigdecl.js +1 -1
  44. package/dist/sigdecl.js.map +1 -1
  45. package/dist/std.d.ts +2 -0
  46. package/dist/std.js +498 -2
  47. package/dist/std.js.map +1 -1
  48. package/dist/template.d.ts +5 -0
  49. package/dist/template.js +257 -0
  50. package/dist/template.js.map +1 -0
  51. package/dist/tsconfig.tsbuildinfo +1 -1
  52. package/dist/unify.js +43 -0
  53. package/dist/unify.js.map +1 -1
  54. package/dist/val/AggFuncVal.d.ts +1 -1
  55. package/dist/val/AggFuncVal.js +10 -21
  56. package/dist/val/AggFuncVal.js.map +1 -1
  57. package/dist/val/BagVal.js +1 -1
  58. package/dist/val/BagVal.js.map +1 -1
  59. package/dist/val/ConstraintVal.js +1 -1
  60. package/dist/val/EachFuncVal.d.ts +1 -1
  61. package/dist/val/EachFuncVal.js +9 -15
  62. package/dist/val/EachFuncVal.js.map +1 -1
  63. package/dist/val/EmitFuncVal.d.ts +42 -0
  64. package/dist/val/EmitFuncVal.js +531 -0
  65. package/dist/val/EmitFuncVal.js.map +1 -0
  66. package/dist/val/FilterFuncVal.js +9 -6
  67. package/dist/val/FilterFuncVal.js.map +1 -1
  68. package/dist/val/FormFuncVal.d.ts +14 -0
  69. package/dist/val/FormFuncVal.js +55 -0
  70. package/dist/val/FormFuncVal.js.map +1 -0
  71. package/dist/val/FuncBaseVal.d.ts +1 -0
  72. package/dist/val/FuncBaseVal.js +16 -0
  73. package/dist/val/FuncBaseVal.js.map +1 -1
  74. package/dist/val/MapVal.d.ts +2 -1
  75. package/dist/val/MapVal.js +2 -1
  76. package/dist/val/MapVal.js.map +1 -1
  77. package/dist/val/PackFuncVal.d.ts +1 -1
  78. package/dist/val/PackFuncVal.js +23 -20
  79. package/dist/val/PackFuncVal.js.map +1 -1
  80. package/dist/val/PlaceVal.d.ts +3 -1
  81. package/dist/val/PlaceVal.js +9 -6
  82. package/dist/val/PlaceVal.js.map +1 -1
  83. package/dist/val/RefVal.d.ts +3 -0
  84. package/dist/val/RefVal.js +156 -17
  85. package/dist/val/RefVal.js.map +1 -1
  86. package/dist/val/StrFuncVal.d.ts +32 -0
  87. package/dist/val/StrFuncVal.js +292 -0
  88. package/dist/val/StrFuncVal.js.map +1 -0
  89. package/dist/val/Val.d.ts +7 -1
  90. package/dist/val/Val.js +12 -1
  91. package/dist/val/Val.js.map +1 -1
  92. package/dist/val/members.d.ts +9 -0
  93. package/dist/val/members.js +52 -0
  94. package/dist/val/members.js.map +1 -0
  95. package/grammar/aontu.abnf +4 -3
  96. package/grammar/aontu.gbnf +4 -3
  97. package/grammar/aontu.lark +4 -3
  98. package/grammar/aontu.tmLanguage.json +1 -1
  99. package/package.json +1 -1
  100. package/skill/SKILL.md +4 -4
  101. package/skill/error-codes.md +1 -1
  102. package/skill/examples.md +1 -1
  103. package/skill/grammar-card.md +1 -1
  104. package/src/agentsmd.ts +1 -1
  105. package/src/alias.ts +112 -0
  106. package/src/aontu.ts +20 -2
  107. package/src/cli.ts +630 -23
  108. package/src/ctx.ts +13 -0
  109. package/src/escape.ts +371 -0
  110. package/src/format.ts +648 -56
  111. package/src/hints.ts +94 -9
  112. package/src/lang.ts +430 -63
  113. package/src/lower.ts +636 -0
  114. package/src/lsp.ts +4 -4
  115. package/src/mcp-server.ts +3 -2
  116. package/src/mcp.ts +43 -4
  117. package/src/mod-tool.ts +9 -8
  118. package/src/mod.ts +6 -6
  119. package/src/render.ts +727 -0
  120. package/src/sigdecl.ts +1 -1
  121. package/src/std.ts +506 -1
  122. package/src/template.ts +291 -0
  123. package/src/unify.ts +47 -0
  124. package/src/val/AggFuncVal.ts +10 -21
  125. package/src/val/BagVal.ts +1 -1
  126. package/src/val/ConstraintVal.ts +1 -1
  127. package/src/val/EachFuncVal.ts +9 -19
  128. package/src/val/EmitFuncVal.ts +738 -0
  129. package/src/val/FilterFuncVal.ts +12 -7
  130. package/src/val/FormFuncVal.ts +119 -0
  131. package/src/val/FuncBaseVal.ts +18 -0
  132. package/src/val/MapVal.ts +3 -2
  133. package/src/val/PackFuncVal.ts +24 -22
  134. package/src/val/PlaceVal.ts +9 -6
  135. package/src/val/RefVal.ts +167 -18
  136. package/src/val/StrFuncVal.ts +334 -0
  137. package/src/val/Val.ts +42 -1
  138. package/src/val/members.ts +86 -0
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.',
@@ -222,11 +231,41 @@ const hints: Record<string, string> = {
222
231
 
223
232
  match_none: 'No pattern matched, and there is no default. `match` tries each\npattern in the order written and takes the first the value unifies\nwith; the value {value} unified with none of {tried}. Add a trailing\ndefault — the argument after the last pair — if the rest was meant\nto be allowed.\n \nExamples:\n match(1, integer, ok) -> "ok" # The first pattern matches;\n match(x, integer, ok, other) -> "other" # ... or the default does;\n match(x, integer, ok) -> nil # ... but nothing here does.',
224
233
 
234
+ emit_data: 'The first argument to emit() is not a bag. `emit` visits the\nchildren of its SELECTION, so the selection has to have children: a\nlist of nodes, or a map whose values are the nodes.\n \nExamples:\n emit([{k:1}], {match:{k:1},body:[a]}) -> [..] # A list of nodes;\n emit({x:{k:1}}, {match:{k:1},body:[a]}) -> [..] # ... or a map of them;\n emit(1, {match:{k:1},body:[a]}) -> nil # ... but not a scalar.',
235
+
236
+ emit_table: 'The second argument to emit() is not a rule table. A table is a\nLIST of templates, tried in order; a single template may be written\nas the map itself, which is that list of one.\n \nExamples:\n emit($.n, [{match:integer,body:[a]}]) -> [..] # A table of rules;\n emit($.n, {match:integer,body:[a]}) -> [..] # ... or one rule alone;\n emit($.n, integer) -> nil # ... but not a value.',
237
+
238
+ emit_template: 'A template in an emit() table is not a rule. Every rule is a map\nnaming both a `match` — the pattern the node is tried against — and a\n`body`, the pieces to emit. A rule with no pattern would claim every\nnode by accident; one with no body would claim a node and emit\nnothing.\n \nExamples:\n {match: {kind: sqs}, body: [a]} # A rule;\n {match: {kind: sqs}} # ... but a pattern is not one;\n {body: [a]} # ... nor is a body alone.',
239
+
240
+ emit_body: 'A template body in an emit() table is not a list. A body is the\nSEQUENCE of pieces the matched node emits, so it is written as a\nlist even when it holds one piece — which is what lets bodies\ncompose, since a body element that is itself a list splices.\n \nExamples:\n {match: integer, body: [a]} -> [..] # One piece;\n {match: integer, body: [a,b]} -> [..] # ... or several;\n {match: integer, body: a} -> nil # ... but not a bare value.',
241
+
242
+ emit_ref: 'A template body names {ref}, and the node it matched cannot\nanswer it. Inside a body a relative reference is a field of the\nMATCHED NODE — `.pin` is that node\'s `pin` — so the node has to have\nthe field; the node was {value}. An absolute reference (`$.x`) reads\nthe document root instead, and is untouched.\n \nExamples:\n {match:{pin:string}, body:[.pin]} -> [..] # A field of the node;\n {match:{pin:string}, body:[$.z]} -> [..] # ... or the root;\n {match:{pin:string}, body:[.port]} -> nil # ... but not a field it\n # has not got.',
243
+
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.',
245
+
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.',
255
+
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.',
257
+
258
+ rep_pattern: 'The pattern given to rep() is outside the portable subset. It is\nthe same subset re() takes — RE2-compatible, no backreferences, no\nlookaround — so one document has one regexp language rather than two,\nand so a generator running a pattern over model data cannot take\nexponential time doing it.\n \nExamples:\n rep(s, "[:,]", " ") -> ... # A class;\n rep(s, "(a)(b)", "$2$1") -> ... # ... a group;\n rep(s, "(?=a)", "x") -> nil # ... but not a lookahead.',
259
+
260
+ rep_sub: 'The substitution given to rep() names something the pattern has\nnot got. `$1` to `$9` are the numbered groups, `$&` is the whole match\nand `$$` is a literal `$`; a `$` naming anything else, or a group\nnumber the pattern does not have, is refused rather than expanded to\nnothing — a generator that writes a file with a hole in it and says\nnothing is the failure this refusal exists to close.\n \nExamples:\n rep(s, "(a)", "[$1]") -> ... # A group the pattern has;\n rep(s, "a", "$$") -> ... # ... a literal dollar;\n rep(s, "a", "$1") -> nil # ... but not a group it has not.',
261
+
262
+ split_sep: 'The separator given to split() is neither a string nor a pattern.\nA plain string is a LITERAL and an `re(…)` argument is a pattern — the\nasymmetry with rep() is deliberate, since splitting is usually on a\nliteral, and it removes the trap where `split(v, ".")` silently cuts\nbetween every character.\n \nExamples:\n split("a,b", ",") -> [..] # A literal separator;\n split("a1b", re("[0-9]")) -> [..] # ... or a pattern;\n split("a,b", 1) -> nil # ... but not a number.',
263
+
225
264
  place_pair: 'Two placeholders met, and neither has a value to fill the other.\n`_` is a HOLE: it is filled by whatever the call is unified with, so\na call holding one needs a peer that does not. Give one side a\nvalue.\n \nExamples:\n upper(_) & hello -> "HELLO" # The peer fills the hole;\n _ + 2 & 1 -> 3 # ... whatever the call is;\n upper(_) & lower(_) -> nil # ... but two holes fill nothing.',
226
265
 
227
266
 
228
267
  module_path: 'A module import is domain-shaped and carries a major, but its\npath cannot be a directory on every platform the toolchain runs on --\nso it is refused before anything is built from it. An element may not\nbe empty, may not begin or end with `.` (which is what forbids `..`),\nand may not be a reserved device name. These are Go\'s module-path\nrules, for Go\'s reason: a module path becomes a real directory.\n \nExamples:\n @"corp.example/s@1" -> {..} # An ordinary path is fine;\n @"corp.example/../s@1" -> nil # ... `..` would escape the store;\n @"corp.example/nul@1" -> nil # ... and Windows has no such file.',
229
- module_missing: 'A module import names a module that is not in this project. A\nmodule is resolved from LOCAL stores only -- `aon_vendor/` beside the\nproject\'s mod.aon, then the user cache -- because evaluation never\ntouches the network. Fetching is a separate step, and the message\nnames it.\n \nExamples:\n @"corp.example/s@1" -> nil # Not fetched: run aontu mod get;\n @"./local.aon" -> {..} # ... a local path is not a module;\n @"corp.example/s@1#aon1-…" -> {..} # ... and a pin does not fetch it either.',
268
+ module_missing: 'A module import names a module that is not in this project. A\nmodule is resolved from LOCAL stores only -- `aontu_meta/vendor/` beside the\nproject\'s mod.aon, then the user cache -- because evaluation never\ntouches the network. Fetching is a separate step, and the message\nnames it.\n \nExamples:\n @"corp.example/s@1" -> nil # Not fetched: run aontu mod get;\n @"./local.aon" -> {..} # ... a local path is not a module;\n @"corp.example/s@1#aon1-…" -> {..} # ... and a pin does not fetch it either.',
230
269
 
231
270
  module_integrity: 'A module resolved locally does not have the MEANING it was pinned\nto. The pin is a canon-hash -- the hash of the module unified\nstandalone -- so it survives comments, formatting and refactoring and\nbreaks on any semantic change in the module\'s transitive closure.\nVerification is always local: the registry\'s annotation is advisory.\n \nExamples:\n @"corp.example/s@1" -> {..} # No pin, no check;\n @"corp.example/s@1#aon1-x" -> nil # ... a pin that disagrees refuses;\n aontu hash <file> # ... and this is what it should be.',
232
271
 
@@ -245,7 +284,7 @@ const hints: Record<string, string> = {
245
284
  'This exact decimal exceeds the exactness budget: at most 4096\n' +
246
285
  'coefficient digits and an absolute scale of at most 4096. The\n' +
247
286
  'budget applies to computed results as well as to literals.\n' +
248
- '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' +
249
288
  'rather than approximated.' +
250
289
  '\n \nExamples:\n' +
251
290
  ' 0d1e1000000000 -> nil # Scale far beyond the budget;\n' +
@@ -255,7 +294,7 @@ const hints: Record<string, string> = {
255
294
  lossy_integer_literal:
256
295
  'This integer literal, {src}, is not exactly representable in\n' +
257
296
  'binary64, so storing it would silently round it to a DIFFERENT\n' +
258
- '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' +
259
298
  'literal to get the exact integer.\n' +
260
299
  'The rule is exactness, not magnitude -- a literal far outside the\n' +
261
300
  'int64 window is still a value when it lands exactly on a binary64.' +
@@ -267,7 +306,7 @@ const hints: Record<string, string> = {
267
306
  ' 100000000000000000000 -> 1e20 # 10^20 is huge and exact.',
268
307
 
269
308
  exact_float_mix:
270
- 'Aontu cannot mix an exact number with a binary float.\n' +
309
+ 'aontu cannot mix an exact number with a binary float.\n' +
271
310
  'Here the operands are {left} and {right}, in that order.\n' +
272
311
  'A big type never silently becomes a binary float, in either\n' +
273
312
  'operand order -- binary64 cannot hold every exact value, so the\n' +
@@ -332,7 +371,7 @@ const hints: Record<string, string> = {
332
371
 
333
372
  divide_by_zero:
334
373
  'Division by zero. `div`, `mod` and `rem` refuse a zero divisor in\n' +
335
- 'every numeric leaf, including binary floats: Aontu is a JSON\n' +
374
+ 'every numeric leaf, including binary floats: aontu is a JSON\n' +
336
375
  'superset with no notation for an infinity, so there is no value\n' +
337
376
  'the operation could answer with. A definition that divides by zero\n' +
338
377
  'is wrong, and this says so where it is written rather than\n' +
@@ -358,7 +397,7 @@ const hints: Record<string, string> = {
358
397
 
359
398
  float_overflow:
360
399
  'This result is not a finite binary64 number, so it is not a value\n' +
361
- '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' +
362
401
  'a JSON superset, and no JSON a generator could emit for one, so\n' +
363
402
  'the operation is refused where it is written rather than escaping\n' +
364
403
  'as an internal error or an unserialisable value.\n' +
@@ -373,7 +412,7 @@ const hints: Record<string, string> = {
373
412
  'The `integer` leaf holds a value only when it is integral, within\n' +
374
413
  'the int64 range, and exactly representable in binary64. This\n' +
375
414
  'result is not: {sum}.\n' +
376
- 'Aontu computes integers exactly and refuses to store a rounded\n' +
415
+ 'aontu computes integers exactly and refuses to store a rounded\n' +
377
416
  'answer -- write `0d<digits>` for an exact integer beyond that\n' +
378
417
  'window.' +
379
418
  '\n \nExamples:\n' +
@@ -515,6 +554,15 @@ const codeClasses: Record<string, string> = {
515
554
  view_profile_unknown: 'reference',
516
555
  view_style_profile: 'reference',
517
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',
518
566
  // The formatter's self-check (docs/design/FMT.0.md): a report-layer
519
567
  // code, class internal -- the formatter, not the document, is wrong.
520
568
  format_check: 'internal',
@@ -549,6 +597,41 @@ const codeClasses: Record<string, string> = {
549
597
  filter_data: 'parse',
550
598
  match_none: 'conflict',
551
599
 
600
+ // G9 phase 6 -- the string builtins. All five are class `parse`:
601
+ // what is wrong is the CALL as written -- a variant that names no
602
+ // convention, a pattern outside the subset, a substitution naming a
603
+ // group that does not exist, a separator that is neither string nor
604
+ // pattern. `usc_malformed` is the odd one and still `parse`: the
605
+ // TEXT the call was given has no inverse, which is a fact about the
606
+ // argument rather than about any meet.
607
+ esc_variant: 'parse',
608
+ usc_malformed: 'parse',
609
+ rep_pattern: 'parse',
610
+ rep_sub: 'parse',
611
+ split_sep: 'parse',
612
+
613
+ // G9 phase 6 -- apply-templates. The four shape codes are class
614
+ // `parse`: what is wrong is the CALL as written -- a selection with
615
+ // no children, a table that is not one, a rule missing a half.
616
+ // `emit_none` is class `conflict` for `match_none`'s reason: the
617
+ // node and every pattern written for it disagreed.
618
+ emit_data: 'parse',
619
+ emit_table: 'parse',
620
+ emit_template: 'parse',
621
+ emit_body: 'parse',
622
+ emit_none: 'conflict',
623
+ emit_ref: 'conflict',
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
+
552
635
  // G8 phase 3 -- the placeholder. Class `conflict`: two values met
553
636
  // and neither could answer for the other, which is what every
554
637
  // conflict is.
@@ -580,6 +663,8 @@ const codeClasses: Record<string, string> = {
580
663
  pref_implicit_bag: 'parse',
581
664
  alias_not_toplevel: 'parse',
582
665
  alias_in_path: 'parse',
666
+ alias_colon: 'parse',
667
+ bare_punct: 'parse',
583
668
  not_number: 'parse',
584
669
  negative: 'parse',
585
670
  decimal_syntax: 'parse',