aontu 0.62.0 → 0.64.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 (373) hide show
  1. package/README.md +7 -7
  2. package/dist/agentsmd.js +0 -27
  3. package/dist/agentsmd.js.map +1 -1
  4. package/dist/alias.js.map +1 -1
  5. package/dist/allow.js +0 -92
  6. package/dist/allow.js.map +1 -1
  7. package/dist/aontu.d.ts +3 -3
  8. package/dist/aontu.js +4 -84
  9. package/dist/aontu.js.map +1 -1
  10. package/dist/aontumodel.d.ts +4 -0
  11. package/dist/aontumodel.js +27 -0
  12. package/dist/aontumodel.js.map +1 -0
  13. package/dist/casing.d.ts +5 -0
  14. package/dist/casing.js +90 -0
  15. package/dist/casing.js.map +1 -0
  16. package/dist/cli.d.ts +2 -2
  17. package/dist/cli.js +228 -935
  18. package/dist/cli.js.map +1 -1
  19. package/dist/ctx.js +0 -48
  20. package/dist/ctx.js.map +1 -1
  21. package/dist/diff.js +0 -32
  22. package/dist/diff.js.map +1 -1
  23. package/dist/err.js +0 -40
  24. package/dist/err.js.map +1 -1
  25. package/dist/escape.js +0 -45
  26. package/dist/escape.js.map +1 -1
  27. package/dist/exactjson.d.ts +0 -35
  28. package/dist/exactjson.js +0 -131
  29. package/dist/exactjson.js.map +1 -1
  30. package/dist/format.js +13 -203
  31. package/dist/format.js.map +1 -1
  32. package/dist/grammar.d.ts +9 -0
  33. package/dist/grammar.js +54 -0
  34. package/dist/grammar.js.map +1 -0
  35. package/dist/graph.js +0 -26
  36. package/dist/graph.js.map +1 -1
  37. package/dist/hcanon.js +0 -82
  38. package/dist/hcanon.js.map +1 -1
  39. package/dist/helpdoc.js +2 -2
  40. package/dist/helpdoc.js.map +1 -1
  41. package/dist/hints.d.ts +0 -6
  42. package/dist/hints.js +57 -55
  43. package/dist/hints.js.map +1 -1
  44. package/dist/jsonschema.js +0 -114
  45. package/dist/jsonschema.js.map +1 -1
  46. package/dist/keyorder.d.ts +0 -7
  47. package/dist/keyorder.js +0 -41
  48. package/dist/keyorder.js.map +1 -1
  49. package/dist/lang.js +17 -915
  50. package/dist/lang.js.map +1 -1
  51. package/dist/lsp-server.js +0 -16
  52. package/dist/lsp-server.js.map +1 -1
  53. package/dist/lsp.d.ts +1 -1
  54. package/dist/lsp.js +12 -159
  55. package/dist/lsp.js.map +1 -1
  56. package/dist/mcp-server.js +0 -26
  57. package/dist/mcp-server.js.map +1 -1
  58. package/dist/mcp.js +0 -149
  59. package/dist/mcp.js.map +1 -1
  60. package/dist/mod-tool.js +16 -131
  61. package/dist/mod-tool.js.map +1 -1
  62. package/dist/mod.js +0 -162
  63. package/dist/mod.js.map +1 -1
  64. package/dist/patch.js +0 -217
  65. package/dist/patch.js.map +1 -1
  66. package/dist/profile.d.ts +9 -0
  67. package/dist/profile.js +28 -0
  68. package/dist/profile.js.map +1 -0
  69. package/dist/provenance.js +0 -140
  70. package/dist/provenance.js.map +1 -1
  71. package/dist/query.js +0 -75
  72. package/dist/query.js.map +1 -1
  73. package/dist/reach.js +0 -43
  74. package/dist/reach.js.map +1 -1
  75. package/dist/relation.js +0 -61
  76. package/dist/relation.js.map +1 -1
  77. package/dist/report-sarif.d.ts +0 -11
  78. package/dist/report-sarif.js +0 -28
  79. package/dist/report-sarif.js.map +1 -1
  80. package/dist/sig.js +0 -35
  81. package/dist/sig.js.map +1 -1
  82. package/dist/sigdecl.js +1 -1
  83. package/dist/sigdecl.js.map +1 -1
  84. package/dist/siggate.js +0 -4
  85. package/dist/siggate.js.map +1 -1
  86. package/dist/site.js +3 -29
  87. package/dist/site.js.map +1 -1
  88. package/dist/subsume.d.ts +0 -10
  89. package/dist/subsume.js +0 -137
  90. package/dist/subsume.js.map +1 -1
  91. package/dist/template.d.ts +2 -1
  92. package/dist/template.js +58 -138
  93. package/dist/template.js.map +1 -1
  94. package/dist/trace.d.ts +21 -0
  95. package/dist/trace.js +107 -0
  96. package/dist/trace.js.map +1 -0
  97. package/dist/trim.js +0 -41
  98. package/dist/trim.js.map +1 -1
  99. package/dist/tsconfig.tsbuildinfo +1 -1
  100. package/dist/type.js.map +1 -1
  101. package/dist/unify.js +13 -248
  102. package/dist/unify.js.map +1 -1
  103. package/dist/utility.js +0 -22
  104. package/dist/utility.js.map +1 -1
  105. package/dist/val/AbnfFuncVal.d.ts +18 -0
  106. package/dist/val/AbnfFuncVal.js +132 -0
  107. package/dist/val/AbnfFuncVal.js.map +1 -0
  108. package/dist/val/AbsentVal.d.ts +11 -0
  109. package/dist/val/AbsentVal.js +30 -0
  110. package/dist/val/AbsentVal.js.map +1 -0
  111. package/dist/val/AggFuncVal.d.ts +10 -1
  112. package/dist/val/AggFuncVal.js +104 -116
  113. package/dist/val/AggFuncVal.js.map +1 -1
  114. package/dist/val/ArithFuncVal.js +0 -12
  115. package/dist/val/ArithFuncVal.js.map +1 -1
  116. package/dist/val/BagVal.js +1 -78
  117. package/dist/val/BagVal.js.map +1 -1
  118. package/dist/val/BigDecimalVal.js +0 -16
  119. package/dist/val/BigDecimalVal.js.map +1 -1
  120. package/dist/val/BigIntegerVal.js +0 -16
  121. package/dist/val/BigIntegerVal.js.map +1 -1
  122. package/dist/val/CloseFuncVal.js +0 -9
  123. package/dist/val/CloseFuncVal.js.map +1 -1
  124. package/dist/val/CmpFuncVal.d.ts +2 -0
  125. package/dist/val/CmpFuncVal.js +49 -72
  126. package/dist/val/CmpFuncVal.js.map +1 -1
  127. package/dist/val/ConjunctVal.js +0 -29
  128. package/dist/val/ConjunctVal.js.map +1 -1
  129. package/dist/val/ConstraintVal.js +0 -500
  130. package/dist/val/ConstraintVal.js.map +1 -1
  131. package/dist/val/ContainerKindVal.js +0 -2
  132. package/dist/val/ContainerKindVal.js.map +1 -1
  133. package/dist/val/CopyFuncVal.js +0 -3
  134. package/dist/val/CopyFuncVal.js.map +1 -1
  135. package/dist/val/Decimal.js +0 -179
  136. package/dist/val/Decimal.js.map +1 -1
  137. package/dist/val/DeprecateFuncVal.js.map +1 -1
  138. package/dist/val/DisjunctVal.js +0 -152
  139. package/dist/val/DisjunctVal.js.map +1 -1
  140. package/dist/val/EachFuncVal.js +0 -3
  141. package/dist/val/EachFuncVal.js.map +1 -1
  142. package/dist/val/EmitFuncVal.d.ts +1 -1
  143. package/dist/val/EmitFuncVal.js +6 -119
  144. package/dist/val/EmitFuncVal.js.map +1 -1
  145. package/dist/val/ExpectVal.js +0 -62
  146. package/dist/val/ExpectVal.js.map +1 -1
  147. package/dist/val/FilterFuncVal.js +0 -25
  148. package/dist/val/FilterFuncVal.js.map +1 -1
  149. package/dist/val/FuncBaseVal.d.ts +1 -0
  150. package/dist/val/FuncBaseVal.js +7 -127
  151. package/dist/val/FuncBaseVal.js.map +1 -1
  152. package/dist/val/GraphAtomVal.js +0 -15
  153. package/dist/val/GraphAtomVal.js.map +1 -1
  154. package/dist/val/HideFuncVal.js +0 -13
  155. package/dist/val/HideFuncVal.js.map +1 -1
  156. package/dist/val/IntegerVal.js +0 -61
  157. package/dist/val/IntegerVal.js.map +1 -1
  158. package/dist/val/JunctionVal.js +0 -20
  159. package/dist/val/JunctionVal.js.map +1 -1
  160. package/dist/val/KeyFuncVal.js +0 -46
  161. package/dist/val/KeyFuncVal.js.map +1 -1
  162. package/dist/val/ListVal.js +0 -57
  163. package/dist/val/ListVal.js.map +1 -1
  164. package/dist/val/LowerFuncVal.js +0 -11
  165. package/dist/val/LowerFuncVal.js.map +1 -1
  166. package/dist/val/MapVal.js +0 -151
  167. package/dist/val/MapVal.js.map +1 -1
  168. package/dist/val/MatchFuncVal.js +0 -27
  169. package/dist/val/MatchFuncVal.js.map +1 -1
  170. package/dist/val/{FormFuncVal.d.ts → MaybeFuncVal.d.ts} +5 -5
  171. package/dist/val/MaybeFuncVal.js +50 -0
  172. package/dist/val/MaybeFuncVal.js.map +1 -0
  173. package/dist/val/MoveFuncVal.js +0 -18
  174. package/dist/val/MoveFuncVal.js.map +1 -1
  175. package/dist/val/NilVal.js +0 -60
  176. package/dist/val/NilVal.js.map +1 -1
  177. package/dist/val/NomFuncVal.js +18 -54
  178. package/dist/val/NomFuncVal.js.map +1 -1
  179. package/dist/val/NumberVal.js +0 -15
  180. package/dist/val/NumberVal.js.map +1 -1
  181. package/dist/val/OpBaseVal.d.ts +1 -0
  182. package/dist/val/OpBaseVal.js +3 -15
  183. package/dist/val/OpBaseVal.js.map +1 -1
  184. package/dist/val/PackFuncVal.js +0 -34
  185. package/dist/val/PackFuncVal.js.map +1 -1
  186. package/dist/val/PathFuncVal.js +0 -6
  187. package/dist/val/PathFuncVal.js.map +1 -1
  188. package/dist/val/PathVal.js +0 -41
  189. package/dist/val/PathVal.js.map +1 -1
  190. package/dist/val/PlaceVal.js +0 -25
  191. package/dist/val/PlaceVal.js.map +1 -1
  192. package/dist/val/PlusOpVal.d.ts +1 -7
  193. package/dist/val/PlusOpVal.js +13 -74
  194. package/dist/val/PlusOpVal.js.map +1 -1
  195. package/dist/val/PrefFuncVal.js +0 -1
  196. package/dist/val/PrefFuncVal.js.map +1 -1
  197. package/dist/val/PrefVal.js +0 -167
  198. package/dist/val/PrefVal.js.map +1 -1
  199. package/dist/val/RecurseVal.js +0 -55
  200. package/dist/val/RecurseVal.js.map +1 -1
  201. package/dist/val/RefVal.js +0 -282
  202. package/dist/val/RefVal.js.map +1 -1
  203. package/dist/val/ReferFuncVal.js +3 -232
  204. package/dist/val/ReferFuncVal.js.map +1 -1
  205. package/dist/val/ScalarKindVal.js +0 -49
  206. package/dist/val/ScalarKindVal.js.map +1 -1
  207. package/dist/val/ScalarVal.js +0 -11
  208. package/dist/val/ScalarVal.js.map +1 -1
  209. package/dist/val/StrFuncVal.js +0 -18
  210. package/dist/val/StrFuncVal.js.map +1 -1
  211. package/dist/val/SuperFuncVal.js +0 -32
  212. package/dist/val/SuperFuncVal.js.map +1 -1
  213. package/dist/val/TopVal.js +0 -1
  214. package/dist/val/TopVal.js.map +1 -1
  215. package/dist/val/TranslateFuncVal.js +1 -3
  216. package/dist/val/TranslateFuncVal.js.map +1 -1
  217. package/dist/val/UpperFuncVal.js +0 -11
  218. package/dist/val/UpperFuncVal.js.map +1 -1
  219. package/dist/val/Val.d.ts +1 -0
  220. package/dist/val/Val.js +2 -133
  221. package/dist/val/Val.js.map +1 -1
  222. package/dist/val/VarVal.js +0 -12
  223. package/dist/val/VarVal.js.map +1 -1
  224. package/dist/val/arith.js +0 -37
  225. package/dist/val/arith.js.map +1 -1
  226. package/dist/val/caserange.js +0 -61
  227. package/dist/val/caserange.js.map +1 -1
  228. package/dist/val/members.js +0 -6
  229. package/dist/val/members.js.map +1 -1
  230. package/dist/val/numcmp.js +0 -11
  231. package/dist/val/numcmp.js.map +1 -1
  232. package/dist/val/numkind.js +0 -145
  233. package/dist/val/numkind.js.map +1 -1
  234. package/dist/val/valutil.js +0 -16
  235. package/dist/val/valutil.js.map +1 -1
  236. package/dist/vet.js +0 -461
  237. package/dist/vet.js.map +1 -1
  238. package/dist/view.js +0 -414
  239. package/dist/view.js.map +1 -1
  240. package/dist/walk.js +0 -41
  241. package/dist/walk.js.map +1 -1
  242. package/grammar/aontu.abnf +8 -6
  243. package/grammar/aontu.gbnf +4 -4
  244. package/grammar/aontu.lark +4 -4
  245. package/grammar/aontu.tmLanguage.json +1 -1
  246. package/package.json +4 -2
  247. package/skill/tasks.md +9 -7
  248. package/src/agentsmd.ts +0 -35
  249. package/src/alias.ts +0 -39
  250. package/src/allow.ts +1 -96
  251. package/src/aontu.ts +4 -116
  252. package/src/aontumodel.ts +26 -0
  253. package/src/casing.ts +95 -0
  254. package/src/cli.ts +258 -1024
  255. package/src/ctx.ts +0 -103
  256. package/src/diff.ts +0 -40
  257. package/src/err.ts +0 -40
  258. package/src/escape.ts +0 -46
  259. package/src/exactjson.ts +0 -131
  260. package/src/format.ts +14 -257
  261. package/src/grammar.ts +72 -0
  262. package/src/graph.ts +0 -61
  263. package/src/hcanon.ts +0 -82
  264. package/src/helpdoc.ts +2 -2
  265. package/src/hints.ts +69 -57
  266. package/src/jsonschema.ts +0 -123
  267. package/src/keyorder.ts +0 -42
  268. package/src/lang.ts +19 -931
  269. package/src/lsp-server.ts +0 -16
  270. package/src/lsp.ts +12 -180
  271. package/src/mcp-server.ts +0 -31
  272. package/src/mcp.ts +0 -169
  273. package/src/mod-tool.ts +18 -159
  274. package/src/mod.ts +0 -178
  275. package/src/patch.ts +0 -232
  276. package/src/profile.ts +42 -0
  277. package/src/provenance.ts +0 -183
  278. package/src/query.ts +0 -84
  279. package/src/reach.ts +0 -53
  280. package/src/relation.ts +0 -84
  281. package/src/report-sarif.ts +0 -48
  282. package/src/sig.ts +0 -35
  283. package/src/sigdecl.ts +1 -1
  284. package/src/siggate.ts +0 -30
  285. package/src/site.ts +3 -29
  286. package/src/subsume.ts +1 -161
  287. package/src/template.ts +69 -140
  288. package/src/trace.ts +157 -0
  289. package/src/trim.ts +0 -53
  290. package/src/type.ts +2 -45
  291. package/src/unify.ts +14 -257
  292. package/src/utility.ts +0 -31
  293. package/src/val/AbnfFuncVal.ts +181 -0
  294. package/src/val/AbsentVal.ts +54 -0
  295. package/src/val/AggFuncVal.ts +152 -188
  296. package/src/val/ArithFuncVal.ts +0 -20
  297. package/src/val/BagVal.ts +1 -78
  298. package/src/val/BigDecimalVal.ts +0 -16
  299. package/src/val/BigIntegerVal.ts +0 -16
  300. package/src/val/CloseFuncVal.ts +0 -9
  301. package/src/val/CmpFuncVal.ts +68 -184
  302. package/src/val/ConjunctVal.ts +0 -33
  303. package/src/val/ConstraintVal.ts +2 -537
  304. package/src/val/ContainerKindVal.ts +0 -18
  305. package/src/val/CopyFuncVal.ts +0 -5
  306. package/src/val/Decimal.ts +1 -185
  307. package/src/val/DeprecateFuncVal.ts +0 -10
  308. package/src/val/DisjunctVal.ts +0 -157
  309. package/src/val/EachFuncVal.ts +0 -40
  310. package/src/val/EmitFuncVal.ts +8 -208
  311. package/src/val/ExpectVal.ts +0 -62
  312. package/src/val/FilterFuncVal.ts +0 -55
  313. package/src/val/FuncBaseVal.ts +9 -130
  314. package/src/val/GraphAtomVal.ts +0 -42
  315. package/src/val/HideFuncVal.ts +0 -15
  316. package/src/val/IntegerVal.ts +0 -61
  317. package/src/val/JunctionVal.ts +0 -20
  318. package/src/val/KeyFuncVal.ts +0 -48
  319. package/src/val/ListVal.ts +0 -59
  320. package/src/val/LowerFuncVal.ts +0 -12
  321. package/src/val/MapVal.ts +0 -151
  322. package/src/val/MatchFuncVal.ts +0 -59
  323. package/src/val/MaybeFuncVal.ts +86 -0
  324. package/src/val/MoveFuncVal.ts +0 -20
  325. package/src/val/NilVal.ts +0 -60
  326. package/src/val/NomFuncVal.ts +10 -99
  327. package/src/val/NumberVal.ts +0 -16
  328. package/src/val/OpBaseVal.ts +4 -17
  329. package/src/val/PackFuncVal.ts +0 -63
  330. package/src/val/PathFuncVal.ts +0 -32
  331. package/src/val/PathVal.ts +0 -66
  332. package/src/val/PlaceVal.ts +0 -45
  333. package/src/val/PlusOpVal.ts +18 -75
  334. package/src/val/PrefFuncVal.ts +0 -1
  335. package/src/val/PrefVal.ts +0 -179
  336. package/src/val/RecurseVal.ts +0 -81
  337. package/src/val/RefVal.ts +1 -285
  338. package/src/val/ReferFuncVal.ts +4 -255
  339. package/src/val/ScalarKindVal.ts +0 -50
  340. package/src/val/ScalarVal.ts +0 -12
  341. package/src/val/StrFuncVal.ts +0 -44
  342. package/src/val/SuperFuncVal.ts +0 -42
  343. package/src/val/TopVal.ts +0 -1
  344. package/src/val/TranslateFuncVal.ts +1 -51
  345. package/src/val/UpperFuncVal.ts +0 -12
  346. package/src/val/Val.ts +3 -192
  347. package/src/val/VarVal.ts +0 -15
  348. package/src/val/arith.ts +0 -92
  349. package/src/val/caserange.ts +0 -62
  350. package/src/val/members.ts +0 -23
  351. package/src/val/numcmp.ts +1 -27
  352. package/src/val/numkind.ts +0 -149
  353. package/src/val/valutil.ts +0 -16
  354. package/src/vet.ts +1 -582
  355. package/src/view.ts +0 -507
  356. package/src/walk.ts +0 -41
  357. package/dist/lower.d.ts +0 -23
  358. package/dist/lower.js +0 -578
  359. package/dist/lower.js.map +0 -1
  360. package/dist/render.d.ts +0 -53
  361. package/dist/render.js +0 -547
  362. package/dist/render.js.map +0 -1
  363. package/dist/std.d.ts +0 -3
  364. package/dist/std.js +0 -672
  365. package/dist/std.js.map +0 -1
  366. package/dist/val/FormFuncVal.js +0 -55
  367. package/dist/val/FormFuncVal.js.map +0 -1
  368. package/dist/val/NamerFuncVal.d.ts +0 -12
  369. package/dist/val/NamerFuncVal.js +0 -176
  370. package/dist/val/NamerFuncVal.js.map +0 -1
  371. package/src/lower.ts +0 -636
  372. package/src/render.ts +0 -732
  373. package/src/std.ts +0 -683
package/src/unify.ts CHANGED
@@ -29,36 +29,6 @@ import {
29
29
  } from './val/top'
30
30
 
31
31
 
32
- // The evaluation budgets live on the context (ctx.budget: passes,
33
- // revisits, depth), defaulted there to the shared spec-visible
34
- // constants test/spec/budget.tsv pins in both ports (9 / 999 / 1000)
35
- // and configurable through the trust profile (G5, docs/trust.md) —
36
- // deterministically: a budget is an integer count of engine events,
37
- // never wall-clock.
38
- //
39
- // Why the revisit default is 999: how many times one (Val, path) pair
40
- // may be re-unified within a single fixpoint pass before the evaluator
41
- // calls it non-convergence (`unify_cycle`). The old false positive here
42
- // -- a legal model with many sibling conjunct terms at one path, each
43
- // re-running the TOP self-unify -- is fixed by the per-pass memo below
44
- // (_tcc/_tpi); test/spec/budget.tsv drives 1200 sibling terms through
45
- // both engines as the regression guard.
46
- //
47
- // Why the depth default is 1000: the whole shared suite peaks at 603
48
- // (the deliberately extreme 1200-sibling-term fixture; ordinary
49
- // documents are two orders below), and V8 exhausts its call stack
50
- // somewhere past depth ~1500 in this evaluator. 1000 sits above every
51
- // real document and below the host limit, so the budget -- not the
52
- // host -- decides the verdict.
53
-
54
- // Charge a DIRECT `Val.unify` recursion to the same depth budget that
55
- // `unite` enforces. Function and operator arguments evaluate through
56
- // `arg.unify(top(), ...)` rather than through the dispatcher, so without
57
- // this the counter stays flat while the JavaScript stack keeps growing:
58
- // a 1500-deep `upper(upper(...))` resolved in TypeScript while Go — which
59
- // routes its arguments through the counted dispatcher — reported
60
- // `unify_cycle`. Returns the budget nil instead of running when the
61
- // budget is spent.
62
32
  const withDepth = (
63
33
  ctx: AontuContext, a: any, b: any, run: () => any
64
34
  ): any => {
@@ -78,27 +48,10 @@ const withDepth = (
78
48
  // Vals should only have to unify downwards (in .unify) over Vals they understand.
79
49
  // and for complex Vals, TOP, which means self unify if not yet done
80
50
  const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
81
- // Fast paths that don't recurse and so don't need cycle-detection:
82
- // short-circuit before the saw-key build and seen-map lookup (which
83
- // together cost ~2.5µs per call). Only return early when the result
84
- // is already `done` — a non-done result would need the trailing
85
- // top() unify below.
86
- //
87
- // A6a: same ref, already done
88
- // A6b: different ref but same id + both done
89
- // P1: exact-equal scalars that are already done (14% of calls
90
- // in foo-sdk, ~100% with a.done=true)
91
51
  if (a !== undefined && a !== null) {
92
52
  if (a === b) {
93
53
  if (a.done) return a
94
54
  }
95
- // ... and NOT on an instrumented run (G7 provenance). Both arms
96
- // below answer with one operand and never reach the recorder at
97
- // the tail, so an equal pair — two positions of one entity that
98
- // agree, a clone meeting its source — contributed silently and
99
- // `why` named one site where the Go port, whose recorder wraps the
100
- // whole dispatcher, named both. Instrumented runs pay the slow
101
- // path knowingly; uninstrumented ones pay one undefined check.
102
55
  else if (b !== undefined && b !== null && undefined === ctx.prov) {
103
56
  if (a.done && b.done) {
104
57
  if (a.id === b.id) {
@@ -113,19 +66,8 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
113
66
  && !a.isMap && !a.isList
114
67
  && !a.isConjunct && !a.isDisjunct
115
68
  && !a.isRef && !a.isPref && !a.isFunc && !a.isExpect
116
- // NOT two TOPs: every top has the same (absent) peg, so
117
- // this path would treat any two as the same value and
118
- // return one of them whole — dropping a rider the other
119
- // carries. The slow path answers the same thing for two
120
- // plain tops, so nothing is lost by declining the shortcut.
121
69
  && !a.isTop && !b.isTop
122
- // NOT two rel residuals (RELATIONS P1) for the same
123
- // reason: a settled rel is DONE with an absent peg, so
124
- // any two matched here — dropping one side's type and
125
- // held constraints. RelVal.unify merges them instead.
126
- // NOT two graph atoms (P2) either: acyclic() and
127
- // inverse(x) share a constructor and an absent peg
128
- // without being the same declaration.
70
+ && !a.isRefer
129
71
  && !a.isRel && !a.isGraphAtom && !a.isRecurse) {
130
72
  // The deprecation record survives the fast path too (G3):
131
73
  // `deprecate(5) & 5` short-circuits here.
@@ -138,6 +80,17 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
138
80
  }
139
81
  }
140
82
 
83
+ // ABSENCE IS THE UNIT OF THE MEET (ADR-034). The dispatch below is
84
+ // the LEFT operand's, so `&` commutes only if it is answered here.
85
+ if (null != a && null != b) {
86
+ if (true === a.isAbsent) {
87
+ return a.unify(b, ctx)
88
+ }
89
+ if (true === b.isAbsent) {
90
+ return b.unify(a, ctx)
91
+ }
92
+ }
93
+
141
94
  const te = ctx.explain && explainOpen(ctx, ctx.explain, 'unite', a, b)
142
95
 
143
96
  let out = a
@@ -155,16 +108,9 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
155
108
  // See for example PrefVal peg.id equality inspection.
156
109
  const sawCount = ctx.seen[saw] ?? 0
157
110
  if (ctx.budget.depth <= ctx._depth.n) {
158
- // Structural recursion budget. Without it, deep nesting exhausts the
159
- // V8 call stack and the catch-all below reports a RangeError as
160
- // `internal` — a verdict that depends on the host's stack size
161
- // rather than on the document, which is exactly what the
162
- // determinism clause forbids (docs/trust.md). Tripping here instead
163
- // makes it a stated budget error, like the pass budget.
164
111
  out = makeNilErr(ctx, 'unify_cycle', a, b)
165
112
  }
166
113
  else if (ctx.budget.revisits < sawCount) {
167
- // console.log('SAW', sawCount, saw, a?.id, a?.canon, b?.id, b?.canon, ctx.cc)
168
114
  out = makeNilErr(ctx, 'unify_cycle', a, b)
169
115
  }
170
116
  else {
@@ -174,18 +120,6 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
174
120
  try {
175
121
  let unified = false
176
122
 
177
- // Dispatch ladder. Structure note:
178
- // - `a == null` is degenerate (shouldn't happen in practice:
179
- // the top-level call seeds with a real Val). Kept for safety.
180
- // - TOP is the unit element: unifying with it returns the
181
- // other side. Handle both sides.
182
- // - Otherwise route by Val type. Complex Vals (Conjunct,
183
- // Disjunct, Ref, Pref, Func, Expect) have their own unify
184
- // that knows how to absorb the peer; prefer `a.unify` when
185
- // `a` is complex, else `b.unify` when `b` is complex. If
186
- // neither is complex and it's not a plain-scalar match, fall
187
- // through to the generic `a.unify` (concrete Val classes
188
- // each handle their own peer case).
189
123
  if (a == null) {
190
124
  out = b
191
125
  why = 'b'
@@ -219,18 +153,9 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
219
153
  || b.isVar
220
154
  || b.isFunc
221
155
  || b.isExpect
222
- // The refer residual (G4 phase 2) DRIVES, like the other
223
- // residuals here: its peer is a plain string, which knows
224
- // nothing about entity addresses, so letting the string drive
225
- // dropped the address and left the constraint standing.
226
156
  || b.isRefer
227
- // An operator holding a HOLE (G8 phase 3) drives for the same
228
- // reason: its peer is what FILLS it, and a scalar asked to
229
- // unify with `_ + 2` sees an operator rather than a hole and
230
- // refuses it on kind. Narrow to placeheld operators on
231
- // purpose -- every other operator meets its peer the way it
232
- // always has, through the conjunct fold that drives it.
233
- || (b.isOp && hasPlace(b))
157
+ // An op DRIVES while an operand has not decided (ADR-037).
158
+ || (b.isOp && (hasPlace(b) || b.holdsStaged))
234
159
  // A graph atom DRIVES (RELATIONS P2): its peer is the value
235
160
  // it rides beside -- a container, a rel, a scalar -- and none
236
161
  // of them know the atom; the atom knows to residuate.
@@ -243,10 +168,6 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
243
168
  unified = true
244
169
  why = 'bv'
245
170
  }
246
- // Exactly equal scalars (not caught by early fast-path — e.g.
247
- // because a or b isn't .done yet). Rel residuals are excluded
248
- // exactly as in the fast path: their pegs are equally absent
249
- // without the values being the same relation.
250
171
  else if (a.constructor === b.constructor && a.peg === b.peg
251
172
  && !a.isRel && !a.isGraphAtom && !a.isRecurse) {
252
173
  out = update(a, b)
@@ -263,18 +184,7 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
263
184
  why += 'N'
264
185
  }
265
186
 
266
- // Any non-done top-level result self-unifies with TOP to ensure
267
- // its children finish converging. Skipped when `unified` is true
268
- // because the branch that set `out = X.unify(Y, ctx)` already
269
- // ran that Val's own unify logic.
270
187
  if (!out.done && !unified) {
271
- // Once per pass per (Val, path): within a single fixpoint pass
272
- // nothing external to the subtree changes, so repeating the TOP
273
- // self-unify — which conjunct folds otherwise trigger once per
274
- // fold term — is pure re-work, and on large models (hundreds of
275
- // sibling terms) the repeats trip the MAXCYCLE guard as a false
276
- // positive. The path is part of the key: a shared Val can
277
- // resolve path-dependent content differently per location.
278
188
  if (undefined !== ctx.cc
279
189
  && (out as any)._tcc === ctx.cc && (out as any)._tpi === ctx.pathidx) {
280
190
  why += 't'
@@ -290,12 +200,6 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
290
200
  }
291
201
  }
292
202
  catch (err: any) {
293
- // This catch-all converts an unexpected exception into an 'internal'
294
- // Nil so one bad node doesn't crash a whole unify. To avoid fully
295
- // masking regressions, preserve the original error message (and a
296
- // RangeError flag — i.e. stack overflow from runaway recursion) on
297
- // the Nil's details so it surfaces in the formatted error rather
298
- // than vanishing. See err.ts (descErr) for how details render.
299
203
  out = makeNilErr(ctx, 'internal', a, b, undefined, {
300
204
  error: String(err?.message ?? err),
301
205
  ...(err instanceof RangeError ? { overflow: true } : {}),
@@ -308,20 +212,10 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
308
212
 
309
213
  ctx.explain && explainClose(te, out)
310
214
 
311
- // The provenance record (G7 phase 3), at the one place every meet
312
- // passes through — the same reason the deprecation rider below lives
313
- // here. Off by default: an uninstrumented run pays this one property
314
- // load, and an instrumented one pays site materialisation knowingly.
315
215
  if (undefined !== ctx.prov) {
316
216
  ctx.prov.record(ctx.path, a, b, out)
317
217
  }
318
218
 
319
- // The deprecation record survives EVERY meet (G3 phase 4): the
320
- // boolean marks have their own sweeps (ConjunctVal, the bag walks),
321
- // but a record lost in one meet shape is a use the tooling never
322
- // warns about, so it rides here, at the one place all meets pass
323
- // through. First record wins; TOP and nil stay clean (TOP is the
324
- // unit, and an error needs no deprecation).
325
219
  if (null != out && true === (out as any).isVal &&
326
220
  !out.isTop && !out.isNil && null == out.deprecation) {
327
221
  const dep = (null != a ? a.deprecation : undefined) ??
@@ -331,12 +225,6 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
331
225
  }
332
226
  }
333
227
 
334
- // THE RENDER RIDERS SURVIVE EVERY MEET (RENDER.0.md P7), and here
335
- // for the deprecation record's reason: a reference resolves by
336
- // MEETING its target with the peer at the referring position, and an
337
- // emitted piece meets the vocabulary's alternative before the fold
338
- // ever sees it, so a record lost in one meet shape is a line the
339
- // trace cannot name. Both are absent unless the run is instrumented.
340
228
  if (undefined !== ctx.reads &&
341
229
  null != out && true === (out as any).isVal && !out.isTop && !out.isNil) {
342
230
  riders(a, b, out)
@@ -346,18 +234,6 @@ const unite = (ctx: AontuContext, a: any, b: any, whence: string) => {
346
234
  }
347
235
 
348
236
 
349
- // The two P7 riders, carried from the operands to the result: the read
350
- // address a value was found at, and the dispatch that emitted it.
351
- // First record wins, as the deprecation record's does. Reached only
352
- // from an instrumented run (AontuContext.reads), so an ordinary meet
353
- // pays the one property load its call site makes and nothing else.
354
- //
355
- // AN OPERAND MAY BE ABSENT and reading through it is not a decision:
356
- // `unite` is called with no peer wherever a bag holds a key its peer
357
- // does not, and `Object(undefined)` is an empty object, so both riders
358
- // are read the same way whether the operand is there or not. Written
359
- // with a test first, that test had an arm no instrumented document
360
- // reached -- true of the reading, not of the engine.
361
237
  function riders(a: any, b: any, to: any): void {
362
238
  const av = Object(a)
363
239
  const bv = Object(b)
@@ -367,17 +243,10 @@ function riders(a: any, b: any, to: any): void {
367
243
  to.origin = org
368
244
  }
369
245
  }
370
- if (null == to.emitted) {
371
- const emt = av.emitted ?? bv.emitted
372
- if (null != emt) {
373
- to.emitted = emt
374
- }
375
- }
376
246
  }
377
247
 
378
248
 
379
249
  function update(x: Val, _y: Val) {
380
- // TODO: update x with y.site
381
250
  return x
382
251
  }
383
252
 
@@ -406,26 +275,6 @@ function residuePaths(v: Val, max: number): string[] {
406
275
  }
407
276
 
408
277
 
409
- // THE TYPE FLOW, APPLIED (G4 phase 2). `refer(t)` unifies `t` INTO the
410
- // node it addresses, which is a write at a position the meet is not
411
- // currently at -- the one non-local effect in the evaluator.
412
- //
413
- // It cannot be only a write made during the pass. A pass BUILDS a new
414
- // tree from the old one, and `ctx.root` during pass N is pass N-1's
415
- // result; a subtree rebuilt by pass N (which is exactly what happens
416
- // when the link sits inside its own target, or when two nodes link at
417
- // each other) drops a write made into the previous one. So each flow is
418
- // also RECORDED, keyed by the target's path, and re-applied to the
419
- // pass's own result here.
420
- //
421
- // Keyed by PATH, so there is no registry of names to collide in
422
- // (ADR-014) -- the key is the position the address resolved to, and
423
- // re-uniting the same type at the same position is idempotent, which is
424
- // what makes replaying every recorded flow every pass correct rather
425
- // than merely cheap.
426
- //
427
- // The pass loop is its only caller; it is EXPORTED for the test that
428
- // pins the unresolved-path guard below (see there).
429
278
  function applyFlows(ctx: AontuContext, root: Val): Val {
430
279
  const flows: Map<string, Val> | undefined = (ctx as any).referflows
431
280
  // NOTHING TO APPLY is the common case -- a document with no links
@@ -433,32 +282,8 @@ function applyFlows(ctx: AontuContext, root: Val): Val {
433
282
  if (null == flows || 0 === flows.size) {
434
283
  return root
435
284
  }
436
- // Sorted, so two flows landing at overlapping positions arrive in the
437
- // same order in both ports.
438
285
  for (const key of [...flows.keys()].sort()) {
439
286
  const path = key.split('\x00')
440
- // The SHARED resolver, the one `refer` itself uses: a second
441
- // descent written here would be a second answer to "what does this
442
- // path name", and the two would drift (the Go twin calls the same
443
- // findAt, arm for arm -- ADR-001).
444
- //
445
- // A RECORDED PATH THAT NO LONGER RESOLVES is skipped rather than
446
- // refused: the record outliving its position is a question about
447
- // the tree, and the link that named it answers it
448
- // (test/spec/refer.tsv, `flow-target-moved-away`).
449
- //
450
- // NO DOCUMENT REACHES IT: a record is written only for a path that
451
- // HAD resolved, and unification never takes a node back out of the
452
- // tree — `move` copies and hides its source rather than removing
453
- // it, which is the one rearrangement that looked like it would
454
- // (probed in both ports: the flow still resolves on every pass,
455
- // `flow-lands-then-its-parent-moves`). The guard is the contract
456
- // for a rearrangement that does, and it is pinned by a direct call
457
- // (`apply-flows-skips-a-record-that-stops-resolving` in
458
- // ts/test/coverage3.test.ts) rather than by an ignore marker: node's
459
- // `coverage ignore` drops LINES, and the gate reads BRANCH records,
460
- // which survive it. The Go twin in go/unify.go can use the marker
461
- // because that gate counts statements.
462
287
  const found = findAt(root, path)
463
288
  if (undefined === found) {
464
289
  continue
@@ -517,8 +342,6 @@ class Unify {
517
342
  })
518
343
  }
519
344
 
520
- // TODO: messy
521
- // uctx.seterr(this.err)
522
345
  uctx.err = this.err
523
346
  uctx.explain = this.explain
524
347
 
@@ -526,12 +349,6 @@ class Unify {
526
349
  // keyed by ref canon + source site, shared across all passes.
527
350
  ; (uctx as any).snapmap = new Map()
528
351
 
529
- // The RECORDED TYPE FLOWS (G4 phase 2): target path -> the type
530
- // `refer(t)` unified into it, replayed onto each pass's result by
531
- // applyFlows. Seeded HERE, on the unify root, for the reason the
532
- // snapshot map above is: a descended context is Object.create'd
533
- // from its parent, so a `??=` in the descendant would make its
534
- // OWN map and the root would never see what was recorded.
535
352
  ; (uctx as any).referflows = new Map()
536
353
 
537
354
  // The re-entrancy guard for those flows: the set of target paths
@@ -547,71 +364,23 @@ class Unify {
547
364
  let lastCanon: string | undefined = undefined
548
365
  let settle = false
549
366
  for (; this.cc < maxcc && DONE !== res.dc; this.cc++) {
550
- // console.log('CC', this.cc, res.canon)
551
367
  uctx.cc = this.cc
552
368
  uctx.seen = {}
553
369
 
554
- // THE STAGING RULE (G8 phase 0,
555
- // docs/capability-review/g8-generation.md), stated once, here,
556
- // for every value whose answer depends on WHERE IT IS. Such a
557
- // value residuates while the model is still moving and fires on
558
- // the first pass whose input is IDENTICAL to the previous
559
- // pass's input: nothing moved, so nothing will move it again,
560
- // and the position it reports is the position it ends at.
561
- //
562
- // Why the whole model and not the value's own path. A spread, a
563
- // reference or a `move` can place a value under a path it has
564
- // already been driven at and THEN change what encloses it --
565
- // `move` hides its source one pass AFTER it copies it, and a
566
- // `key()` that answered on the strength of its path alone would
567
- // answer for the ghost. Stability of the model is the only
568
- // signal that says every such rearrangement is finished.
569
370
  uctx.settle = settle
570
371
 
571
- // Snapshot BEFORE the final pass (the loop condition has
572
- // already established the tree is not done), so exhaustion can
573
- // tell "still refining" from "stable residue" below. Taken at
574
- // the final pass's ENTRY rather than the previous pass's exit
575
- // — the same value when the budget allows two passes, and the
576
- // only possible value when the trust profile sets passes to 1,
577
- // where the old placement (cc === maxcc - 2, never true) made
578
- // exhaustion silent, exactly the truncation docs/trust.md
579
- // forbids. `lastCanon` IS that entry canon whenever a previous
580
- // pass rendered one, so this costs nothing extra.
581
372
  if (this.cc === maxcc - 1) {
582
373
  prevCanon = lastCanon ?? res.canon
583
374
  }
584
375
 
585
376
  res = unite(te ? uctx.clone({ explain: ec(te, 'run') }) : uctx, res, top(), 'unify')
586
377
 
587
- // MULTI-ERROR COLLECTION (G2 phase 6): the pass loop CONTINUES
588
- // past an erroring pass, so independent failures a later pass
589
- // would reach are collected in the same run — the break that
590
- // stood here made every multi-error report truncated at the
591
- // first erroring pass.
592
- //
593
- // What controls the cascade the design feared: a nil is
594
- // ABSORBING (unite's isNil arms return the existing nil, no new
595
- // error), so one failure stays ONE NilVal however many later
596
- // meets touch it — a reference resolving to a failed target
597
- // takes the same nil identity, which is exactly what lets the
598
- // report layer dedup by identity. The probes that established
599
- // this (fan-in refs, spread templates, disjunct trials, nested
600
- // conjuncts) are pinned as vet.tsv's multi-* rows in both
601
- // ports.
602
378
 
603
379
  // The recorded type flows, re-applied to the tree THIS pass
604
380
  // built: a pass rebuilds subtrees, and a flow written into the
605
381
  // previous pass's tree does not survive that.
606
382
  res = applyFlows(uctx, res)
607
383
 
608
- // The staging signal for the NEXT pass, rendered here rather
609
- // than at the top of the loop so a model that is FINISHED is
610
- // never rendered at all: canon walks references, and the only
611
- // trees that close a cycle are hand-built ones (the pass loop
612
- // is what a test drives them through), which converge in one
613
- // pass and must not be walked to decide a question that no
614
- // longer arises.
615
384
  if (DONE !== res.dc) {
616
385
  const nowCanon = res.canon
617
386
  settle = undefined !== lastCanon && lastCanon === nowCanon
@@ -621,16 +390,6 @@ class Unify {
621
390
  uctx = uctx.clone({ root: res })
622
391
  }
623
392
 
624
- // The pass budget is spent AND the final pass still made
625
- // progress: the model was cut off while converging, and no other
626
- // error explains why. Silent truncation would surface later as
627
- // ordinary incompleteness, so exhaustion is a semantic error of
628
- // its own (class budget, docs/trust.md clause 2) -- retrying with
629
- // a larger budget is a valid response to THIS code and useless
630
- // for path_cycle or no_path. A STABLE residue (the final pass
631
- // changed nothing -- e.g. a stuck `1+true`) is not a budget
632
- // failure: it is ordinary incompleteness and stays silent here,
633
- // surfacing at generate exactly as before.
634
393
  if (maxcc <= this.cc && DONE !== res.dc && 0 === uctx.err.length
635
394
  && undefined !== prevCanon && prevCanon !== res.canon) {
636
395
  makeNilErr(uctx, 'budget_passes', undefined, undefined, 'resolve', {
@@ -653,8 +412,6 @@ class Unify {
653
412
  } /* node:coverage ignore next 10 */
654
413
 
655
414
 
656
-
657
-
658
415
  export {
659
416
  Unify,
660
417
  unite,
package/src/utility.ts CHANGED
@@ -1,18 +1,9 @@
1
1
  /* Copyright (c) 2023-2025 Richard Rodger, MIT License */
2
2
 
3
3
 
4
-
5
4
  import type { AontuOptions, TrustOptions, Val } from './type'
6
5
 
7
6
 
8
- // THE INCLUDE OPTIONS AN ENGINE HANDS ITS Aontu INSTANCE. Every verb
9
- // engine builds one, and until there were two such options each did it
10
- // inline -- `null == options.trust ? undefined : { trust: options.trust }`,
11
- // written out twelve times. That is fine while there is one option and
12
- // a latent bug the moment there are two: `textExt` had to reach the
13
- // same twelve places, and the one it missed refused a `.md` include
14
- // under a flag the bare command honoured. One function now, so a third
15
- // include option is threaded once.
16
7
  type IncludeOptions = {
17
8
  trust?: TrustOptions
18
9
  textExt?: string[]
@@ -27,11 +18,6 @@ function includeOpts(options: IncludeOptions): Partial<AontuOptions> {
27
18
  }
28
19
 
29
20
 
30
- // Default walk() depth limit. High enough that real configs are never
31
- // silently truncated (the old default of 32 dropped marks on deeply
32
- // nested refs/funcs → wrong output), while still bounding runaway or
33
- // accidentally-cyclic walks (walk has no cycle detection). Pass null for
34
- // truly unbounded.
35
21
  const WALK_DEFAULT_MAXDEPTH = 9999
36
22
 
37
23
 
@@ -47,12 +33,6 @@ function propagateMarks(source: Val, target: Val): void {
47
33
  }
48
34
 
49
35
 
50
- // Collect every value in the tree carrying the deprecation record (G3
51
- // phase 4), with its path — the one walk behind vet's `deprecated`
52
- // warnings and the LSP's Deprecated tags. The record travels on meets
53
- // (the unite rider) and clones, so this sees the declaration and every
54
- // use resolving through it. The non-Val guard is for a bag's raw peg
55
- // entries, which degenerate parses can leave behind.
56
36
  function collectDeprecations(
57
37
  root: Val): Array<{ val: Val, path: string[] }> {
58
38
  const out: Array<{ val: Val, path: string[] }> = []
@@ -97,17 +77,6 @@ function deprecationMessage(d: Record<string, string>): string {
97
77
  }
98
78
 
99
79
 
100
- // The canonical form of a value, wrapped in the RIDER it carries —
101
- // the deprecation record (G3 phase 4) — reparseably, so
102
- // `deprecate(x, m)` survives canon. Bags render their children through
103
- // this (MapVal/ListVal canon), which is where a marked FIELD — the
104
- // realistic case — lives.
105
- //
106
- // The rider renders HERE and not in the value's own `canon` for the
107
- // same reason the guard at the MapVal call site tests the isVal flag:
108
- // a bag's canon recursion visits each child once, and a child that
109
- // wrapped itself as well would render its subtree twice per level —
110
- // 2^depth on a nested document.
111
80
  function canonRiders(v: Val): string {
112
81
  const c = v.canon
113
82
  const d = v.deprecation