aontu 0.61.0 → 0.63.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 (371) hide show
  1. package/README.md +4 -4
  2. package/dist/agentsmd.d.ts +1 -0
  3. package/dist/agentsmd.js +7 -28
  4. package/dist/agentsmd.js.map +1 -1
  5. package/dist/alias.js.map +1 -1
  6. package/dist/allow.d.ts +23 -0
  7. package/dist/allow.js +138 -0
  8. package/dist/allow.js.map +1 -0
  9. package/dist/aontu.d.ts +4 -2
  10. package/dist/aontu.js +4 -80
  11. package/dist/aontu.js.map +1 -1
  12. package/dist/aontumodel.d.ts +4 -0
  13. package/dist/aontumodel.js +33 -0
  14. package/dist/aontumodel.js.map +1 -0
  15. package/dist/cli.d.ts +10 -1
  16. package/dist/cli.js +877 -479
  17. package/dist/cli.js.map +1 -1
  18. package/dist/ctx.js +0 -48
  19. package/dist/ctx.js.map +1 -1
  20. package/dist/diff.js +0 -32
  21. package/dist/diff.js.map +1 -1
  22. package/dist/err.js +0 -40
  23. package/dist/err.js.map +1 -1
  24. package/dist/escape.js +0 -45
  25. package/dist/escape.js.map +1 -1
  26. package/dist/exactjson.d.ts +0 -35
  27. package/dist/exactjson.js +0 -131
  28. package/dist/exactjson.js.map +1 -1
  29. package/dist/format.js +55 -189
  30. package/dist/format.js.map +1 -1
  31. package/dist/grammar.d.ts +9 -0
  32. package/dist/grammar.js +54 -0
  33. package/dist/grammar.js.map +1 -0
  34. package/dist/graph.js +0 -26
  35. package/dist/graph.js.map +1 -1
  36. package/dist/hcanon.js +0 -82
  37. package/dist/hcanon.js.map +1 -1
  38. package/dist/helpdoc.d.ts +16 -0
  39. package/dist/helpdoc.js +59 -0
  40. package/dist/helpdoc.js.map +1 -0
  41. package/dist/hints.d.ts +0 -6
  42. package/dist/hints.js +59 -47
  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 +32 -877
  50. package/dist/lang.js.map +1 -1
  51. package/dist/lower.d.ts +3 -0
  52. package/dist/lower.js +14 -61
  53. package/dist/lower.js.map +1 -1
  54. package/dist/lsp-server.js +0 -16
  55. package/dist/lsp-server.js.map +1 -1
  56. package/dist/lsp.d.ts +1 -1
  57. package/dist/lsp.js +12 -159
  58. package/dist/lsp.js.map +1 -1
  59. package/dist/mcp-server.js +0 -26
  60. package/dist/mcp-server.js.map +1 -1
  61. package/dist/mcp.js +0 -113
  62. package/dist/mcp.js.map +1 -1
  63. package/dist/mod-tool.js +0 -130
  64. package/dist/mod-tool.js.map +1 -1
  65. package/dist/mod.js +0 -162
  66. package/dist/mod.js.map +1 -1
  67. package/dist/patch.js +0 -217
  68. package/dist/patch.js.map +1 -1
  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.d.ts +2 -0
  76. package/dist/relation.js +3 -58
  77. package/dist/relation.js.map +1 -1
  78. package/dist/render.js +33 -143
  79. package/dist/render.js.map +1 -1
  80. package/dist/report-sarif.d.ts +0 -11
  81. package/dist/report-sarif.js +0 -28
  82. package/dist/report-sarif.js.map +1 -1
  83. package/dist/sig.js +0 -35
  84. package/dist/sig.js.map +1 -1
  85. package/dist/sigdecl.js +1 -1
  86. package/dist/sigdecl.js.map +1 -1
  87. package/dist/siggate.js +0 -4
  88. package/dist/siggate.js.map +1 -1
  89. package/dist/site.js +3 -29
  90. package/dist/site.js.map +1 -1
  91. package/dist/subsume.d.ts +0 -10
  92. package/dist/subsume.js +0 -137
  93. package/dist/subsume.js.map +1 -1
  94. package/dist/template.d.ts +2 -1
  95. package/dist/template.js +58 -138
  96. package/dist/template.js.map +1 -1
  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 +12 -242
  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 +20 -0
  125. package/dist/val/CmpFuncVal.js +188 -0
  126. package/dist/val/CmpFuncVal.js.map +1 -0
  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.d.ts +1 -2
  141. package/dist/val/EachFuncVal.js +12 -29
  142. package/dist/val/EachFuncVal.js.map +1 -1
  143. package/dist/val/EmitFuncVal.d.ts +1 -1
  144. package/dist/val/EmitFuncVal.js +6 -119
  145. package/dist/val/EmitFuncVal.js.map +1 -1
  146. package/dist/val/ExpectVal.js +0 -62
  147. package/dist/val/ExpectVal.js.map +1 -1
  148. package/dist/val/FilterFuncVal.js +0 -25
  149. package/dist/val/FilterFuncVal.js.map +1 -1
  150. package/dist/val/FuncBaseVal.d.ts +1 -0
  151. package/dist/val/FuncBaseVal.js +7 -127
  152. package/dist/val/FuncBaseVal.js.map +1 -1
  153. package/dist/val/GraphAtomVal.js +0 -15
  154. package/dist/val/GraphAtomVal.js.map +1 -1
  155. package/dist/val/HideFuncVal.js +0 -13
  156. package/dist/val/HideFuncVal.js.map +1 -1
  157. package/dist/val/IntegerVal.js +0 -61
  158. package/dist/val/IntegerVal.js.map +1 -1
  159. package/dist/val/JunctionVal.js +0 -20
  160. package/dist/val/JunctionVal.js.map +1 -1
  161. package/dist/val/KeyFuncVal.js +0 -46
  162. package/dist/val/KeyFuncVal.js.map +1 -1
  163. package/dist/val/ListVal.js +0 -57
  164. package/dist/val/ListVal.js.map +1 -1
  165. package/dist/val/LowerFuncVal.js +11 -6
  166. package/dist/val/LowerFuncVal.js.map +1 -1
  167. package/dist/val/MapVal.js +0 -151
  168. package/dist/val/MapVal.js.map +1 -1
  169. package/dist/val/MatchFuncVal.js +0 -27
  170. package/dist/val/MatchFuncVal.js.map +1 -1
  171. package/dist/val/{FormFuncVal.d.ts → MaybeFuncVal.d.ts} +5 -5
  172. package/dist/val/MaybeFuncVal.js +50 -0
  173. package/dist/val/MaybeFuncVal.js.map +1 -0
  174. package/dist/val/MoveFuncVal.js +0 -18
  175. package/dist/val/MoveFuncVal.js.map +1 -1
  176. package/dist/val/NilVal.js +2 -36
  177. package/dist/val/NilVal.js.map +1 -1
  178. package/dist/val/NomFuncVal.d.ts +12 -0
  179. package/dist/val/NomFuncVal.js +153 -0
  180. package/dist/val/NomFuncVal.js.map +1 -0
  181. package/dist/val/NumberVal.js +0 -15
  182. package/dist/val/NumberVal.js.map +1 -1
  183. package/dist/val/OpBaseVal.d.ts +1 -0
  184. package/dist/val/OpBaseVal.js +3 -15
  185. package/dist/val/OpBaseVal.js.map +1 -1
  186. package/dist/val/PackFuncVal.js +0 -34
  187. package/dist/val/PackFuncVal.js.map +1 -1
  188. package/dist/val/PathFuncVal.js +0 -6
  189. package/dist/val/PathFuncVal.js.map +1 -1
  190. package/dist/val/PathVal.js +0 -41
  191. package/dist/val/PathVal.js.map +1 -1
  192. package/dist/val/PlaceVal.js +0 -25
  193. package/dist/val/PlaceVal.js.map +1 -1
  194. package/dist/val/PlusOpVal.d.ts +1 -7
  195. package/dist/val/PlusOpVal.js +13 -74
  196. package/dist/val/PlusOpVal.js.map +1 -1
  197. package/dist/val/PrefFuncVal.js +0 -1
  198. package/dist/val/PrefFuncVal.js.map +1 -1
  199. package/dist/val/PrefVal.js +0 -167
  200. package/dist/val/PrefVal.js.map +1 -1
  201. package/dist/val/RecurseVal.js +0 -55
  202. package/dist/val/RecurseVal.js.map +1 -1
  203. package/dist/val/RefVal.js +0 -282
  204. package/dist/val/RefVal.js.map +1 -1
  205. package/dist/val/ReferFuncVal.js +0 -232
  206. package/dist/val/ReferFuncVal.js.map +1 -1
  207. package/dist/val/ScalarKindVal.js +0 -49
  208. package/dist/val/ScalarKindVal.js.map +1 -1
  209. package/dist/val/ScalarVal.js +0 -11
  210. package/dist/val/ScalarVal.js.map +1 -1
  211. package/dist/val/StrFuncVal.js +0 -18
  212. package/dist/val/StrFuncVal.js.map +1 -1
  213. package/dist/val/SuperFuncVal.js +0 -32
  214. package/dist/val/SuperFuncVal.js.map +1 -1
  215. package/dist/val/TopVal.js +0 -1
  216. package/dist/val/TopVal.js.map +1 -1
  217. package/dist/val/TranslateFuncVal.d.ts +12 -0
  218. package/dist/val/TranslateFuncVal.js +99 -0
  219. package/dist/val/TranslateFuncVal.js.map +1 -0
  220. package/dist/val/UpperFuncVal.js +11 -6
  221. package/dist/val/UpperFuncVal.js.map +1 -1
  222. package/dist/val/Val.d.ts +1 -0
  223. package/dist/val/Val.js +2 -133
  224. package/dist/val/Val.js.map +1 -1
  225. package/dist/val/VarVal.js +0 -12
  226. package/dist/val/VarVal.js.map +1 -1
  227. package/dist/val/arith.js +0 -37
  228. package/dist/val/arith.js.map +1 -1
  229. package/dist/val/caserange.d.ts +3 -0
  230. package/dist/val/caserange.js +49 -0
  231. package/dist/val/caserange.js.map +1 -0
  232. package/dist/val/members.js +0 -6
  233. package/dist/val/members.js.map +1 -1
  234. package/dist/val/numcmp.js +0 -11
  235. package/dist/val/numcmp.js.map +1 -1
  236. package/dist/val/numkind.js +0 -145
  237. package/dist/val/numkind.js.map +1 -1
  238. package/dist/val/valutil.js +0 -16
  239. package/dist/val/valutil.js.map +1 -1
  240. package/dist/vet.d.ts +12 -0
  241. package/dist/vet.js +159 -412
  242. package/dist/vet.js.map +1 -1
  243. package/dist/view.js +0 -414
  244. package/dist/view.js.map +1 -1
  245. package/dist/walk.js +0 -41
  246. package/dist/walk.js.map +1 -1
  247. package/grammar/aontu.abnf +9 -7
  248. package/grammar/aontu.gbnf +5 -5
  249. package/grammar/aontu.lark +5 -5
  250. package/grammar/aontu.tmLanguage.json +1 -1
  251. package/package.json +4 -2
  252. package/skill/SKILL.md +8 -0
  253. package/skill/init/check.sh +28 -0
  254. package/skill/init/data.aon +12 -0
  255. package/skill/init/model.aon +19 -0
  256. package/skill/tasks.md +151 -0
  257. package/src/agentsmd.ts +8 -32
  258. package/src/alias.ts +0 -39
  259. package/src/allow.ts +221 -0
  260. package/src/aontu.ts +10 -108
  261. package/src/aontumodel.ts +32 -0
  262. package/src/cli.ts +1009 -540
  263. package/src/ctx.ts +0 -103
  264. package/src/diff.ts +0 -40
  265. package/src/err.ts +0 -40
  266. package/src/escape.ts +0 -46
  267. package/src/exactjson.ts +0 -131
  268. package/src/format.ts +63 -234
  269. package/src/grammar.ts +72 -0
  270. package/src/graph.ts +0 -61
  271. package/src/hcanon.ts +0 -82
  272. package/src/helpdoc.ts +77 -0
  273. package/src/hints.ts +72 -49
  274. package/src/jsonschema.ts +0 -123
  275. package/src/keyorder.ts +0 -42
  276. package/src/lang.ts +39 -895
  277. package/src/lower.ts +15 -65
  278. package/src/lsp-server.ts +0 -16
  279. package/src/lsp.ts +12 -180
  280. package/src/mcp-server.ts +0 -31
  281. package/src/mcp.ts +0 -130
  282. package/src/mod-tool.ts +0 -158
  283. package/src/mod.ts +0 -178
  284. package/src/patch.ts +0 -232
  285. package/src/provenance.ts +0 -183
  286. package/src/query.ts +0 -84
  287. package/src/reach.ts +0 -53
  288. package/src/relation.ts +7 -71
  289. package/src/render.ts +33 -180
  290. package/src/report-sarif.ts +0 -48
  291. package/src/sig.ts +0 -35
  292. package/src/sigdecl.ts +1 -1
  293. package/src/siggate.ts +0 -30
  294. package/src/site.ts +3 -29
  295. package/src/subsume.ts +1 -161
  296. package/src/template.ts +69 -140
  297. package/src/trim.ts +0 -53
  298. package/src/type.ts +2 -45
  299. package/src/unify.ts +13 -251
  300. package/src/utility.ts +0 -31
  301. package/src/val/AbnfFuncVal.ts +181 -0
  302. package/src/val/AbsentVal.ts +54 -0
  303. package/src/val/AggFuncVal.ts +152 -188
  304. package/src/val/ArithFuncVal.ts +0 -20
  305. package/src/val/BagVal.ts +1 -78
  306. package/src/val/BigDecimalVal.ts +0 -16
  307. package/src/val/BigIntegerVal.ts +0 -16
  308. package/src/val/CloseFuncVal.ts +0 -9
  309. package/src/val/CmpFuncVal.ts +249 -0
  310. package/src/val/ConjunctVal.ts +0 -33
  311. package/src/val/ConstraintVal.ts +2 -537
  312. package/src/val/ContainerKindVal.ts +0 -18
  313. package/src/val/CopyFuncVal.ts +0 -5
  314. package/src/val/Decimal.ts +1 -185
  315. package/src/val/DeprecateFuncVal.ts +0 -10
  316. package/src/val/DisjunctVal.ts +0 -157
  317. package/src/val/EachFuncVal.ts +12 -53
  318. package/src/val/EmitFuncVal.ts +8 -208
  319. package/src/val/ExpectVal.ts +0 -62
  320. package/src/val/FilterFuncVal.ts +0 -55
  321. package/src/val/FuncBaseVal.ts +9 -130
  322. package/src/val/GraphAtomVal.ts +0 -42
  323. package/src/val/HideFuncVal.ts +0 -15
  324. package/src/val/IntegerVal.ts +0 -61
  325. package/src/val/JunctionVal.ts +0 -20
  326. package/src/val/KeyFuncVal.ts +0 -48
  327. package/src/val/ListVal.ts +0 -59
  328. package/src/val/LowerFuncVal.ts +12 -7
  329. package/src/val/MapVal.ts +0 -151
  330. package/src/val/MatchFuncVal.ts +0 -59
  331. package/src/val/MaybeFuncVal.ts +86 -0
  332. package/src/val/MoveFuncVal.ts +0 -20
  333. package/src/val/NilVal.ts +2 -36
  334. package/src/val/NomFuncVal.ts +200 -0
  335. package/src/val/NumberVal.ts +0 -16
  336. package/src/val/OpBaseVal.ts +4 -17
  337. package/src/val/PackFuncVal.ts +0 -63
  338. package/src/val/PathFuncVal.ts +0 -32
  339. package/src/val/PathVal.ts +0 -66
  340. package/src/val/PlaceVal.ts +0 -45
  341. package/src/val/PlusOpVal.ts +18 -75
  342. package/src/val/PrefFuncVal.ts +0 -1
  343. package/src/val/PrefVal.ts +0 -179
  344. package/src/val/RecurseVal.ts +0 -81
  345. package/src/val/RefVal.ts +1 -285
  346. package/src/val/ReferFuncVal.ts +0 -255
  347. package/src/val/ScalarKindVal.ts +0 -50
  348. package/src/val/ScalarVal.ts +0 -12
  349. package/src/val/StrFuncVal.ts +0 -44
  350. package/src/val/SuperFuncVal.ts +0 -42
  351. package/src/val/TopVal.ts +0 -1
  352. package/src/val/TranslateFuncVal.ts +132 -0
  353. package/src/val/UpperFuncVal.ts +12 -7
  354. package/src/val/Val.ts +3 -192
  355. package/src/val/VarVal.ts +0 -15
  356. package/src/val/arith.ts +0 -92
  357. package/src/val/caserange.ts +53 -0
  358. package/src/val/members.ts +0 -23
  359. package/src/val/numcmp.ts +1 -27
  360. package/src/val/numkind.ts +0 -149
  361. package/src/val/valutil.ts +0 -16
  362. package/src/vet.ts +209 -504
  363. package/src/view.ts +0 -507
  364. package/src/walk.ts +0 -41
  365. package/dist/std.d.ts +0 -3
  366. package/dist/std.js +0 -637
  367. package/dist/std.js.map +0 -1
  368. package/dist/val/FormFuncVal.js +0 -55
  369. package/dist/val/FormFuncVal.js.map +0 -1
  370. package/src/std.ts +0 -648
  371. package/src/val/FormFuncVal.ts +0 -119
@@ -1,31 +1,5 @@
1
1
  /* Copyright (c) 2025 Richard Rodger, MIT License */
2
2
 
3
- // THE RECURSIVE RESIDUAL (docs/design/RECURSION.0.md): where RefVal's
4
- // prefix test used to answer `path_cycle` for a self-reference --
5
- // `$.Node` written anywhere inside `Node` -- it now answers this
6
- // value: a deferred reference carrying the target path, exactly as a
7
- // constraint atom carries its bound. No new syntax: the reference the
8
- // author wrote simply MEANS the fixpoint.
9
- //
10
- // The three moments of every residual:
11
- //
12
- // - At unification, EXPAND ONE LEVEL PER MEET WITH STRUCTURE: met by
13
- // a map, list, or scalar, the residual clones the schema body one
14
- // level -- per destination, under ADR-005's clone discipline -- and
15
- // unifies the clone with the peer. The clone's own self-reference
16
- // is again this residual, so each expansion consumes one level of
17
- // concrete data; data is finite, so expansion terminates
18
- // (structural descent), with the depth budget as the backstop
19
- // (recursion_budget).
20
- // - In canon and the aon1- hash, SYMBOLIC: the residual prints as the
21
- // reference the author wrote, so a recursive schema's canon is
22
- // finite and round-trips, and the hash pins the mu-form rather than
23
- // any unrolling.
24
- // - At generation, an unexpanded residual REFUSES with
25
- // recursion_unexpanded. Guardedness is therefore EMERGENT: under
26
- // `next?:` the refusal is isolated and the optional key drops;
27
- // under `*null | $.Node` the preference generates; a REQUIRED
28
- // recursive field with no data refuses at the instance.
29
3
 
30
4
  import type {
31
5
  Val,
@@ -78,12 +52,6 @@ class RecurseVal extends FeatureVal {
78
52
  return out
79
53
  }
80
54
 
81
- // The schema body the target names, from the ROOT: the fixpoint is
82
- // over the finished definition, and the definition's own residual
83
- // keeps it finite. When the root does not contain the target -- the
84
- // residual was LIFTED out of its defining tree, as vet's anchored
85
- // meet does -- fall back to ctx._fixroot, the settled tree the
86
- // lifter kept for exactly this walk.
87
55
  private body(ctx: AontuContext): Val | undefined {
88
56
  return walkTarget(ctx.root, this.target)
89
57
  ?? walkTarget((ctx as any)._fixroot, this.target)
@@ -92,9 +60,6 @@ class RecurseVal extends FeatureVal {
92
60
  unify(peer: Val, ctx: AontuContext): Val {
93
61
  const p: any = peer
94
62
 
95
- // The self-drive: nothing to advance -- the residual waits for
96
- // structure. (A null/nil peer never arrives; unite's ladder
97
- // absorbs both.)
98
63
  if (null == peer || true === p.isTop) {
99
64
  return this
100
65
  }
@@ -105,9 +70,6 @@ class RecurseVal extends FeatureVal {
105
70
  && this.target.every((s, i) => s === p.target[i])) {
106
71
  return this
107
72
  }
108
- // Different targets -- mutual recursion meeting -- are BOTH
109
- // held: each expands as data arrives, through the fold that
110
- // keeps a conjunct's members separate.
111
73
  const out = new ConjunctVal({ peg: [this, peer] }, ctx)
112
74
  propagateMarks(this, out)
113
75
  out.path = this.path
@@ -129,25 +91,6 @@ class RecurseVal extends FeatureVal {
129
91
  out.path = this.path
130
92
  return out
131
93
  }
132
- // ADR-005's clone discipline: the expansion is a per-destination
133
- // instantiation, so the definition itself is never written
134
- // into. The clone's type/hide marks are CLEARED at every depth,
135
- // exactly as a plain reference copy clears them (concreteFlow's
136
- // rule): the schema is hidden, the instances it expands into
137
- // are the output.
138
- // The clone is REBASED to the DRIVE path explicitly (spec.path;
139
- // the Go twin passes cp(r.path), whose stored paths its clone
140
- // arms keep clean): the default rebase slices the definition's
141
- // path by the destination's length, which leaks definition
142
- // segments into instance paths whenever the destination is
143
- // shallower -- a residual carried inside a copied definition
144
- // body (`chain: $.spec.Step` inside Policy, copied to a slot
145
- // shallower than the definition) reported
146
- // `$.payments_policy.Policy.chain.then.approver` for the
147
- // finding Go placed at `$.payments_policy.chain.then.approver`.
148
- // The drive path is also right under vet's anchored meet, which
149
- // drives AT the anchor's own path (see vet.ts), so anchored
150
- // findings land in the schema's namespace in both ports.
151
94
  const level: any = body.clone(ctx, {
152
95
  dup: true, path: [...ctx.path],
153
96
  } as any)
@@ -173,9 +116,6 @@ class RecurseVal extends FeatureVal {
173
116
  }
174
117
 
175
118
  gen(ctx: AontuContext) {
176
- // An unexpanded residual in a demanded position refuses;
177
- // guardedness is emergent -- under an optional key the bag's
178
- // isolated context swallows this and drops the key.
179
119
  makeNilErr(ctx, 'recursion_unexpanded', this, undefined, 'recurse',
180
120
  { target: '$.' + this.target.join('.') })
181
121
  return undefined
@@ -204,13 +144,6 @@ function bumpRecurse(v: any, xc: number): void {
204
144
  v.xc = Math.max(v.xc, xc)
205
145
  return
206
146
  }
207
- // A RAW REFERENCE TO A RECURSIVE TARGET IS THE RECURSION, minted or
208
- // not -- the same reading containsRecurseOf already takes, and the
209
- // reason bound 2 was inert. A freshly cloned level holds the
210
- // definition's references UNRESOLVED, so this walk found no
211
- // residual to stamp and `xc` read 0 at every expansion, in the
212
- // healthy form too. The seed rides on the reference and the
213
- // residual minted from it starts there (ts/src/val/RefVal.ts).
214
147
  if (true === v.isRef) {
215
148
  v.rxc = Math.max(v.rxc ?? 0, xc)
216
149
  return
@@ -237,12 +170,6 @@ function bumpRecurse(v: any, xc: number): void {
237
170
  }
238
171
 
239
172
 
240
- // containsRecurseOf answers whether a definition holds a residual of
241
- // the given target -- i.e. the definition is (transitively) the
242
- // fixpoint that target names. A reference RESOLVING to such a
243
- // definition must itself answer the residual: cloned instead, every
244
- // reparse of a canon unrolled the schema one more level and canon
245
- // never converged.
246
173
  function containsRecurseOf(v: any, target: string[], depth?: number): boolean {
247
174
  const d = depth ?? 0
248
175
  if (null == v || true !== v.isVal || 8 < d) {
@@ -252,14 +179,6 @@ function containsRecurseOf(v: any, target: string[], depth?: number): boolean {
252
179
  return v.target.length === target.length
253
180
  && v.target.every((s: string, i: number) => s === target[i])
254
181
  }
255
- // A RAW REFERENCE to the target IS the recursion, minted or not:
256
- // the answer must not depend on whether the definition's own
257
- // prefix position has been visited yet. Without this arm the
258
- // answer was ORDER-DEPENDENT -- reparsing a generated canon puts
259
- // the instance before the definition, its trailing `$.spec.Step`
260
- // leaves resolved before `Step.then` had minted, and each resolve
261
- // cloned one more unrolled level until the unify depth guard
262
- // (unify_cycle) killed the document.
263
182
  if (true === v.isRef && Array.isArray(v.peg)) {
264
183
  if (v.peg.length === target.length
265
184
  && v.peg.every((s: any, i: number) => s === target[i])) {
package/src/val/RefVal.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  /* Copyright (c) 2021-2025 Richard Rodger, MIT License */
2
2
 
3
3
 
4
-
5
4
  import {
6
5
  walk,
7
6
  explainOpen,
@@ -42,22 +41,12 @@ import { BigIntegerVal } from './BigIntegerVal'
42
41
  import { BigDecimalVal } from './BigDecimalVal'
43
42
 
44
43
 
45
-
46
44
  // A path segment no spelling can produce, used when append meets a Val
47
45
  // class it has no rule for. A key cannot contain a NUL, so this can never
48
46
  // match, which turns a silent path-shortening bug into a visible miss.
49
47
  const UNSPELLABLE_SEGMENT = '\u0000unspellable'
50
48
 
51
49
 
52
- // Is this value an unresolved type()/hide() call — or a conjunct still
53
- // carrying one? A reference that lands on one must defer rather than
54
- // clone it (see the call site in `find`): the marks such a call will
55
- // stamp belong to the field it was WRITTEN at, and a clone resolving
56
- // at the reference's site re-applies them after the reference's
57
- // mark-clearing walk has already run. Only the two mark wrappers
58
- // qualify — every other pending call resolves to an unmarked value,
59
- // and the existing early-clone behaviour for those is pinned
60
- // (move()/copy() ghost rows, hole-filling conjuncts).
61
50
  function pendingMarkWrapper(v: any): boolean {
62
51
  if (true === v.isTypeFunc || true === v.isHideFunc) {
63
52
  return !v.done
@@ -108,13 +97,6 @@ class RefVal extends FeatureVal {
108
97
  // a rendering of the settled tree, never a parse-time property.
109
98
  expansion: Val | undefined = undefined
110
99
 
111
- // THE RECURSION SEED (use-cases/BUGS.md §57). A reference that names
112
- // a recursive definition IS the fixpoint reference; it mints a
113
- // RecurseVal when it resolves. bumpRecurse stamps the expansion
114
- // depth here, because a freshly cloned level holds the definition's
115
- // references UNRESOLVED and so has no residual to stamp -- which is
116
- // why the design's second termination bound read 0 at every
117
- // expansion. The minted residual starts from this.
118
100
  rxc: number = 0
119
101
  prefix: boolean = false
120
102
 
@@ -139,14 +121,12 @@ class RefVal extends FeatureVal {
139
121
  this.append(spec.peg[pI])
140
122
  }
141
123
 
142
- //console.log('RefVal', this.id, this.peg)
143
124
  }
144
125
 
145
126
 
146
127
  append(part: any) {
147
128
  let partval
148
129
 
149
- // console.log('APPEND', part)
150
130
 
151
131
  if ('string' === typeof part) {
152
132
  partval = part
@@ -159,33 +139,16 @@ class RefVal extends FeatureVal {
159
139
  }
160
140
 
161
141
  else if (part instanceof IntegerVal) {
162
- // partval = '' + part.peg
163
142
  partval = part.src
164
143
  this.peg.push(partval)
165
144
  }
166
145
 
167
- // TODO: this is a bit of a hack, review
168
- // Seems like a fundamental ambiguity?
169
- // Resolved by path function
170
146
  else if (part instanceof NumberVal) {
171
- // let partvals: string[] = part.peg.toFixed(11).replace(/(\.0)?0+$/, '$1').split('.')
172
147
  let partvals: string[] = part.src.split('.')
173
148
  this.peg.push(...partvals)
174
149
  }
175
150
 
176
- // THE EXACT LEAVES ARE PATH TEXT LIKE ANY OTHER SPELLING. `0d1` as a
177
- // segment addresses the key literally spelled `0d1` -- the same key
178
- // `a:{0d1:7}` creates -- and is NOT the number 1, so it neither
179
- // indexes a list nor reaches a key spelled `1`.
180
- //
181
- // Without these branches the part fell off the end of the chain and
182
- // was SILENTLY DROPPED, so `$.a.0d0` resolved to `$.a` and handed back
183
- // the CONTAINER. That is a wrong value, not a miss -- strictly worse
184
- // than an error -- and it made `$.a.0d0` and `$.a.0d1` denote the same
185
- // location.
186
151
  else if (part instanceof BigIntegerVal || part instanceof BigDecimalVal) {
187
- // A bigdecimal splits on its point exactly as a float does, so
188
- // `$.x.0d1.5` addresses two levels.
189
152
  this.peg.push(...part.src.split('.'))
190
153
  }
191
154
 
@@ -219,12 +182,6 @@ class RefVal extends FeatureVal {
219
182
  this.peg.push(...part.peg)
220
183
  }
221
184
 
222
- // A closed chain, deliberately. Every branch above ends in a push, so
223
- // an unhandled Val class used to fall through in SILENCE and shorten
224
- // the path by one segment -- which is how the two exact leaves, added
225
- // by the number tower, made references resolve to their own container.
226
- // A segment that cannot be spelled is pushed as one that cannot match,
227
- // so the reference misses loudly instead of succeeding wrongly.
228
185
  else {
229
186
  this.peg.push(UNSPELLABLE_SEGMENT)
230
187
  }
@@ -239,9 +196,6 @@ class RefVal extends FeatureVal {
239
196
 
240
197
  if (this.id !== peer.id) {
241
198
 
242
- // TODO: not resolved when all Vals in path are done is an error
243
- // as path cannot be found
244
- // let resolved: Val | undefined = null == ctx ? this : ctx.find(this)
245
199
  let found: Val | undefined = this.find(ctx)
246
200
 
247
201
  // `?? this` makes resolved non-nullish, so an unresolved reference
@@ -275,21 +229,12 @@ class RefVal extends FeatureVal {
275
229
  out.dc = DONE === out.dc ? DONE : this.dc + 1
276
230
  }
277
231
 
278
- // console.log('REFVAL-UNIFY-OUT', ctx.cc, this.id, this.canon, this.done, 'P=', peer.id, peer.canon, peer.done, '->', out.id, out.canon, out.done)
279
232
 
280
233
  explainClose(te, out)
281
234
  return out
282
235
  }
283
236
 
284
237
 
285
- // `snap` is set by snapshotRefSpread (MapVal): a SPREAD snapshot
286
- // wants the target's pre-resolution STRUCTURE — key()/path() still
287
- // unresolved, to be re-resolved per destination — so the
288
- // pending-mark-wrapper defer below must not apply to it. Deferring
289
- // there made the snapshot wait until the target's own key() had
290
- // resolved at the target, and the literal leaked into every
291
- // destination (the exact failure the snapshot exists to prevent —
292
- // test/spec/spread-type.tsv, spread-type-key-ref).
293
238
  find(ctx: AontuContext, snap?: boolean) {
294
239
  let out: Val | undefined = undefined
295
240
 
@@ -315,16 +260,8 @@ class RefVal extends FeatureVal {
315
260
 
316
261
  let refpath: string[] = []
317
262
  let pI = 0
318
- // let descent = ''
319
263
 
320
264
  if (isprefixpath) {
321
- // THE DETECTOR'S ANSWER IS A RESIDUAL (RECURSION.0.md): a
322
- // self-reference under a guarded shape is the fixpoint the
323
- // author wrote, so the prefix hit mints the recursive residual
324
- // instead of refusing -- except the degenerate all-empty
325
- // spelling (path("")), which names nothing and keeps its
326
- // path_cycle. Only all-string paths recurse; anything else
327
- // keeps the conservative refusal.
328
265
  let degenerate = 0 === this.path.length
329
266
  let target: string[] = []
330
267
  for (let i = 0; i < this.peg.length && !degenerate; i++) {
@@ -350,44 +287,16 @@ class RefVal extends FeatureVal {
350
287
 
351
288
  for (let pI = 0; pI < this.peg.length; pI++) {
352
289
  let part = this.peg[pI]
353
- // An unspellable segment MISSES BEFORE ANY LOOKUP. The marker
354
- // is NUL-prefixed because no spelling produces one, but a
355
- // document can still hold a key spelled with an escaped NUL
356
- // (`a:{"unspellable":7}`), and matching it would turn the
357
- // silent path-shortening this marker exists to prevent into a
358
- // different silent wrong value. The marker is a marker, never a
359
- // lookup key.
360
290
  if (UNSPELLABLE_SEGMENT === part) {
361
291
  return makeNilErr(ctx, 'no_path', this)
362
292
  }
363
293
  if (part instanceof VarVal) {
364
- // EVERY `$name` IN A PATH IS AN ORDINARY VARIABLE. `$KEY`,
365
- // `$SELF` and `$PARENT` used to be intercepted here by name;
366
- // they are gone (ADR-009). `key()` is the replacement for
367
- // `$KEY` and answers where a value LANDS rather than where it
368
- // was written, `$SELF.x` was only ever `$.x`, and `$PARENT.x`
369
- // was only ever `.x`.
370
294
  {
371
295
  part = (part as VarVal).unify(top(), ctx)
372
296
  if (part.isNil) {
373
- // TODO: var not found, so can't find path
374
297
  return
375
298
  }
376
299
  else {
377
- // The resolved variable IS a path segment: $seg.r with
378
- // seg="x" reads ...x.r (previously the coerced value was
379
- // dropped, silently reading the path without it).
380
- //
381
- // Integer kind renders its EXACT digits -- the FOURTH site
382
- // to get this wrong (see integerDigits and #21). `'' + peg`
383
- // on a JS number gives the shortest round-tripping form, so
384
- // a variable bound to 2^60 addressed the key
385
- // "1152921504606847000" and missed the real one. Go's
386
- // ref.go dispatches on kind here and was already correct.
387
- //
388
- // Every other kind is already right under `'' +`: a bigint
389
- // and a Decimal stringify to exact digits, and a float must
390
- // keep JS parity.
391
300
  parts.push(part.isInteger ?
392
301
  integerDigits(part.peg as number) : '' + part.peg)
393
302
  }
@@ -419,9 +328,7 @@ class RefVal extends FeatureVal {
419
328
  if (null != node) {
420
329
  for (; pI < refpath.length; pI++) {
421
330
  let part = refpath[pI]
422
- // console.log('PART', pI, part, node)
423
331
 
424
- // descent += (' | ' + pI + '=' + node.canon) // Util.inspect(node))
425
332
 
426
333
  if (node.isMap) {
427
334
  node = node.peg[part]
@@ -429,15 +336,6 @@ class RefVal extends FeatureVal {
429
336
  else if (node.isList) {
430
337
  node = node.peg[part]
431
338
  }
432
- // A PENDING MARK WRAPPER IS TRANSPARENT TO THE WALK: hide()
433
- // and type() only mark, and their argument is the structure
434
- // the path names. Without this, two sibling schemas in one
435
- // hide() bag deadlock -- the wrapper waits for its argument,
436
- // the argument's members wait for references that walk into
437
- // the unresolved wrapper (BUGS.md §53's family; the
438
- // recursive Policy/Step pair found it again). The found node
439
- // is cloned and mark-cleared exactly as any reference target
440
- // is, and the wrapper still marks its own field.
441
339
  else if (true === (node as any).isFunc
442
340
  && ((node as any).isHideFunc || (node as any).isTypeFunc)
443
341
  && (true === (node as any).peg?.[0]?.isMap
@@ -445,26 +343,6 @@ class RefVal extends FeatureVal {
445
343
  node = (node as any).peg[0].peg[part]
446
344
  }
447
345
 
448
- // AND SO IS A CONJUNCT THAT STILL CARRIES ONE (issue #164).
449
- // Two statements for one key meet, so a key written as
450
- // `T: type({...})` twice is a CONJUNCT of two wrappers -- and
451
- // one written once beside a plain `T: {...}` is a conjunct
452
- // too. The arm above sees a wrapper only when it is the whole
453
- // node, so a reference into such a key walked into the
454
- // conjunct and stopped: the wrapper waited for its argument,
455
- // the argument waited for the reference, and neither moved.
456
- // The first referring child of every consumer stayed
457
- // unresolved and generation reported mapval_no_gen at a path
458
- // that names none of this, which is how a five-file schema
459
- // spent its evening being bisected.
460
- //
461
- // The answer at a segment is the MEET of what each term
462
- // supplies, so terms that have no such member are skipped and
463
- // the rest are conjoined -- one term answers as itself, and
464
- // the ordinary map arm answers once the fold has happened.
465
- // Restricted to a conjunct that still holds a pending
466
- // wrapper: every other conjunct folds on its own, and this
467
- // walk exists only to break the wrapper's deadlock.
468
346
  else if (true === (node as any).isConjunct
469
347
  && Array.isArray((node as any).peg)
470
348
  && pendingMarkWrapper(node)) {
@@ -499,16 +377,6 @@ class RefVal extends FeatureVal {
499
377
  }
500
378
  }
501
379
 
502
- // THE ANCHORED-MEET FALLBACK (vet --at): an absolute reference
503
- // inside a lifted subtree names the SCHEMA's namespace, and the
504
- // meet's root does not contain it. The settled schema root the
505
- // lifter kept (AontuContext._fixroot; see RecurseVal.body) is
506
- // the tree such a reference means. Without this, a recursion
507
- // re-entering through a list spread died as no_path at the
508
- // first element under vet --at, while the map-tail form (whose
509
- // residual was minted during schema settling) worked; the Go
510
- // port answers the anchored meet from settled structures and
511
- // never sees the gap.
512
380
  const fixroot: any = (ctx as any)._fixroot
513
381
  if (this.absolute && null != fixroot
514
382
  && (nopath || pI !== refpath.length)) {
@@ -541,14 +409,6 @@ class RefVal extends FeatureVal {
541
409
  else if (pI === refpath.length) {
542
410
  out = node
543
411
 
544
- // THE READ IS RECORDED, AND THE VALUE STAMPED WITH WHERE IT
545
- // WAS FOUND (RENDER.0.md P7). A resolved reference clones its
546
- // target into the referring position, so without the stamp a
547
- // value that arrived by reference knows only where it came to
548
- // rest -- and `render --coverage` has nothing to measure the
549
- // model against. Off unless the run is instrumented; the first
550
- // address wins, and every reference to one node names the same
551
- // address anyway.
552
412
  if (undefined !== ctx.reads && null != node) {
553
413
  // The root's own address is `$`, as the coverage walk spells
554
414
  // it: a dot with nothing after it would match no path there.
@@ -566,58 +426,18 @@ class RefVal extends FeatureVal {
566
426
  }
567
427
  }
568
428
 
569
- // A reference landing on another reference -- or on a FUNCTION,
570
- // whose arguments the chase now follows (issue #35) -- may be a
571
- // PROVEN mutual cycle (a: $.b, b: $.a; a: $.b, b: upper($.a)).
572
- // Follow the chain and, if it returns to a node still open above
573
- // it, report path_cycle now instead of deferring every pass and
574
- // dying later as a spent budget. No proof (the chain leaves plain
575
- // refs and calls, or ends) defers as before.
576
429
  if (null != out && ((out as any).isRef || (out as any).isFunc) &&
577
430
  this.detectRefCycle(ctx)) {
578
431
  out = makeNilErr(ctx, 'path_cycle', this)
579
432
  }
580
- // A PENDING MARK WRAPPER IS NOT YET A VALUE TO COPY (ADR-005).
581
- // A type()/hide() call still waiting for its argument — an
582
- // alias reference inside a type() body, a generator inside a
583
- // hide() — would be cloned here as the CALL, and the clone
584
- // then resolves at the REFERENCE's site, stamping marks that
585
- // the mark-clearing walk below has already run too early to
586
- // clear. That is how a type-marked alias silently suppressed
587
- // the referring field's emission (use-cases/BUGS.md §12), how
588
- // `hide(pack(...))` leaked its mark onto downstream packs
589
- // (§11), and how hide() around a computed field swallowed the
590
- // value into a silent [] (§35b). Defer instead: the reference
591
- // residuates until the wrapper has resolved at its OWN field,
592
- // and the ordinary marked-value path below then clears the
593
- // marks on the clone as documented. The move() reference
594
- // (`_hide_found`) is exempt: a move TRANSPLANTS the pending
595
- // call, and the ghost rows (test/spec/func.tsv) pin that its
596
- // innards resolve at the destination.
597
433
  else if (null != out && !snap && !this.mark._hide_found &&
598
434
  pendingMarkWrapper(out)) {
599
435
  out = undefined
600
436
  }
601
- // A STAGED ARGUMENT SNAPSHOTS A SETTLED SOURCE (the argsnap
602
- // flag, set by driveStagedArgs). A generator's data argument is
603
- // a copy OUTSIDE the tree, so anything in the target that still
604
- // resolves against its own tree location — a spread-injected
605
- // relative reference, a pending template — must finish there
606
- // BEFORE the copy is taken: cloned earlier, the copy's rebased
607
- // relative refs dangle under the generator and the model dies
608
- // as *_no_gen with the generator never firing. Deferring here
609
- // is exactly the documented staging rule: the generator waits
610
- // for the source, then snapshots it whole.
611
437
  else if (null != out && !snap && true === (ctx as any).argsnap &&
612
438
  !out.done) {
613
439
  out = undefined
614
440
  }
615
- // A REFERENCE TO A RECURSIVE DEFINITION IS THE FIXPOINT
616
- // REFERENCE (RECURSION.0.md): resolving it to a clone
617
- // unrolled the schema one level, and every reparse of a
618
- // canon then unrolled one more -- canon never converged. The
619
- // residual is the resolved form, exactly as at the prefix
620
- // positions inside the definition.
621
441
  else if (null != out && !snap && containsRecurseOf(out, this.peg as any)) {
622
442
  const rec: any = new RecurseVal(
623
443
  { target: [...this.peg], xc: this.rxc } as any, ctx)
@@ -628,83 +448,31 @@ class RefVal extends FeatureVal {
628
448
  // Types and hidden values are cloned and made concrete
629
449
  else if (null != out) { // && (out.mark.type || out.mark.hide)) {
630
450
 
631
- // console.log('FOUND-A', out)
632
451
 
633
452
  if (this.mark.type || this.mark.hide) {
634
453
  out.mark.type = this.mark.type
635
454
  out.mark.hide = this.mark.hide
636
455
 
637
- // walk(out, (_key: string | number | undefined, val: Val) => {
638
- // val.mark.type = this.mark.type
639
- // val.mark.hide = this.mark.hide
640
- // return val
641
- // })
642
456
  }
643
457
 
644
458
  if (this.mark._hide_found) {
645
459
  out.mark.hide = true
646
460
  }
647
461
 
648
- // console.log('FOUND-B', out)
649
-
650
- // A REFERENCE LIFTS: the copy is concrete, its type and hide
651
- // marks cleared to the leaves -- a marked target is what the
652
- // author hid or typed, and a reference to it is the author
653
- // asking for it in the open. EXCEPT the snapshot a staged
654
- // verb takes of its data (`argsnap`: each, emit, filter,
655
- // pack, pick, join, the aggregates), when the target itself
656
- // is not marked: a member marked inside an unmarked bag was
657
- // hidden IN ITS OWN RIGHT, and the verb's enumeration
658
- // (ts/src/val/members.ts, BUGS.md §79) needs to see that
659
- // mark to leave the member out, as generation does. A marked
660
- // target lifts even there, or `each($.schema.entities, _)`
661
- // under `schema: hide({...})` would see every entity as
662
- // hidden, since hide() marks to the leaves.
462
+
663
463
  const lifted = true !== (ctx as any).argsnap
664
464
  || true === out.mark.type || true === out.mark.hide
665
465
 
666
- // A REFERENCE'S COPY OWNS ITS ARGUMENTS (ADR-025). The copy
667
- // is a per-destination instance exactly as a spread's or a
668
- // generator's is, so ADR-005's rule holds here too: nothing
669
- // path-dependent may be shared between two destinations, or
670
- // the first destination's resolution answers for them all.
671
- // The shallow clone shared a call's ARGUMENTS -- so
672
- // `items: [&: $.entities.User]` over a `close({...})` target
673
- // gave every element the one inner map, whose path each
674
- // element rebased in turn, and the constraint that failed at
675
- // element 2 reported element 0's path (use-cases GAP 8).
676
- //
677
- // A STAGED CALL IS THE EXCEPTION, because it has not decided
678
- // yet. Its arguments are still being driven AT ITS OWN SITE
679
- // (the staging rule, G8 phase 0), and a copy that owned them
680
- // would drive its own set at the referring position instead:
681
- // the relative `.side_effect` in a `match()` would read the
682
- // referring field's siblings (use-cases/09-agent-tools), and
683
- // an alias naming an `emit` rule table -- a template, which
684
- // is exactly a value copied before it resolves -- would read
685
- // its recursive `%w` as a self-reference. A staged call
686
- // ANYWHERE in the target counts: what is referenced is
687
- // usually the conjunct the call sits in, not the call.
688
- // The copy shares what the source is still settling, and
689
- // owns the rest.
690
466
  out = out.clone(ctx, { dup: !out.holdsStaged })
691
467
 
692
468
  if (lifted) {
693
469
  walk(out, (_key: string | number | undefined, val: Val) => {
694
470
  val.mark.type = false
695
471
  val.mark.hide = false
696
- // THE LINK IS NOT CLEARED (G4 phase 3): a link says what
697
- // a value POINTS AT, and a copy of a link points at the
698
- // same thing. An ABSOLUTE address still names the same
699
- // node from the copy; a RELATIVE one is read from the
700
- // copy's own position, which is what makes a referenced
701
- // model resolve its internal links inside the copy
702
- // (ADR-014).
703
472
  return val
704
473
  })
705
474
  }
706
475
 
707
- // onsole.log('FOUND-C', out)
708
476
  }
709
477
  }
710
478
  }
@@ -715,45 +483,7 @@ class RefVal extends FeatureVal {
715
483
  }
716
484
 
717
485
 
718
- // Follow the chain of plain references from this node; true iff the
719
- // chain revisits a node -- a PROVEN reference cycle, distinct from a
720
- // merely unresolved reference. Detection is only on the resolution
721
- // chain revisiting a node, never on syntactic shape: a chain that
722
- // passes through a variable segment, a conjunct or any other non-ref
723
- // value yields no proof and the ref defers as before.
724
- //
725
- // A FUNCTION is followed, through its arguments (issue #35). A
726
- // function resolves only once every argument does, so a chain that
727
- // reaches `b:upper($.a)` and out through `$.a` has proved the same
728
- // dependency a bare `b:$.a` proves -- `a:$.b b:upper($.a)` is a cycle
729
- // whichever link wears the call. Without this the shape exhausted the
730
- // depth budget instead: a `unify_cycle`, which under the G5 taxonomy
731
- // means "retry with more may help", where a proven structural cycle is
732
- // FIX THE MODEL. A conjunct and a disjunct stay unfollowed for reasons
733
- // that are not the same: a disjunct member may simply not be taken, so
734
- // reaching one proves nothing; a conjunct would be sound to follow, and
735
- // is left out only because nothing needs it yet.
736
- //
737
- // The Go port reaches the same verdict on this shape by a DIFFERENT
738
- // arm, and that difference outlives this method: its clonePath re-paths
739
- // a resolved clone to the referring site, so the inner `$.a` lands at
740
- // path [a] and the plain isprefixpath test proves the cycle before any
741
- // chase is needed. TypeScript's clone keeps the source paths. ADR-001
742
- // asks for arm-for-arm correspondence, so the clone-path difference is
743
- // worth closing on its own; it is wider than this issue and both ports
744
- // now agree on the verdict and the code either way.
745
486
  detectRefCycle(ctx: AontuContext): boolean {
746
- // Depth-first with an explicit ANCESTOR set, because a function may
747
- // carry several reference arguments and the cycle can run through
748
- // any one of them. The set holds the chain currently being walked,
749
- // not every node ever walked: revisiting a node reached down a
750
- // DIFFERENT branch is an ordinary shared reference (two keys reading
751
- // one third key), and only revisiting one that is still open above
752
- // us is a cycle.
753
- //
754
- // Identity is the RESOLVED PATH, not the RefVal instance: the same
755
- // target can be reached through distinct ref instances, and it is
756
- // returning to the same place that closes a loop.
757
487
  const chase = (ref: RefVal, ancestors: Set<string>): boolean => {
758
488
  const rp = ref.plainRefPath()
759
489
  if (null == rp) {
@@ -870,7 +600,6 @@ class RefVal extends FeatureVal {
870
600
  }
871
601
  return (this.absolute ? '$' : '') +
872
602
  (0 < this.peg.length ? '.' : '') +
873
- // this.peg.join(this.sep)
874
603
  this.peg.map((p: any) => '.' === p ? '' :
875
604
  (p.isVal ? p.canon : '' + p))
876
605
  .join('.')
@@ -878,18 +607,6 @@ class RefVal extends FeatureVal {
878
607
 
879
608
 
880
609
  get canon() {
881
- // AN ALIAS REFERENCE CANONS AS THE VALUE IT NAMES. A reference left
882
- // standing after unification is one inside a spread template
883
- // (`[&: %u]`, `{&: {a: %u}}`): the template applies to children
884
- // that have not arrived, so it is not resolved in place. Canon
885
- // erases the declaration (an alias is a name for a value, and
886
- // nothing more -- ALIASES.0.md §4), so the name alone would not
887
- // reparse, and the hash of `t: {&: %u}` would differ from the hash
888
- // of `t: {&: integer}`, which is the same document. The expansion
889
- // is attached by expandAliases (ts/src/alias.ts) once the tree has
890
- // settled; without one -- a parse-only tree, an unresolved name, or
891
- // the KNOT of a recursive alias inside its own template -- the
892
- // reference spells its name. Twin of RefVal.Canon in go/ref.go.
893
610
  if (undefined !== this.expansion) {
894
611
  return this.expansion.canon
895
612
  }
@@ -906,7 +623,6 @@ class RefVal extends FeatureVal {
906
623
  undefined,
907
624
  )
908
625
 
909
- // TODO: refactor to use Site pointer
910
626
  nil.path = this.path
911
627
  nil.site.url = this.site.url
912
628
  nil.site.row = this.site.row