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,16 +1,6 @@
1
1
  /* Copyright (c) 2021-2025 Richard Rodger, MIT License */
2
2
 
3
3
 
4
- // THE IMMEDIATE PARENT TYPE (docs/design/SUPER.0.md): super(x) answers
5
- // the type one step above its argument, structurally. The lattice
6
- // primitive Val.superior() stays what it always was -- the preference
7
- // override gate and query's kind lift -- and answers here only for the
8
- // forms it already served (scalars, kinds, top). Everything structural
9
- // is this file's walk: maps and lists lift child by child, preferences
10
- // unwrap, disjunctions distribute, constraints answer the kind they
11
- // constrain, and a recursion residual stays a symbolic call -- the
12
- // finite spelling of a lift that is itself recursive.
13
-
14
4
  import type {
15
5
  Val,
16
6
  ValSpec,
@@ -49,13 +39,6 @@ class SuperFuncVal extends FuncBaseVal {
49
39
  }
50
40
 
51
41
 
52
- // A DIRECT residual rides the residuate path rather than resolving:
53
- // the pending call IS the answer (SUPER.0.md, the phase boundary),
54
- // printing as written and refusing at generation exactly as an
55
- // unexpanded recursion does. Residuals met DURING descent are minted
56
- // as pending child calls by superOf below; only the top-level
57
- // argument needs the defer, or resolve would re-mint the same call
58
- // inside one pass forever.
59
42
  deferResolve(_ctx: AontuContext, args?: Val[]): boolean {
60
43
  return true === (args?.[0] as any)?.isRecurse
61
44
  }
@@ -75,22 +58,11 @@ class SuperFuncVal extends FuncBaseVal {
75
58
  // caller drives arguments before resolve fires, so pending forms --
76
59
  // held conjuncts, unresolved references, holes -- never arrive).
77
60
  function superOf(ctx: AontuContext, v: any): Val {
78
- // The residual's lift is itself recursive, so the finite answer is
79
- // the symbolic call (SUPER.0.md): a fresh pending super() holding a
80
- // clone of the residual, standing wherever the residual stood --
81
- // the `next?` slot of a lifted recursive body prints
82
- // `super($.Node)` and drops under an optional key at generation.
83
61
  if (true === v.isRecurse) {
84
62
  const call = new SuperFuncVal({ peg: [v.clone(ctx)] }, ctx)
85
63
  return v.place(call)
86
64
  }
87
65
 
88
- // Maps and lists lift child by child. Shape is carried, not lifted:
89
- // key optionality and closedness describe the container, and the
90
- // spread template lifts so the result admits at the lifted level
91
- // for future keys exactly as the original admitted at its own.
92
- // A fresh bag (ADR-005 instantiation): type/hide marks are not
93
- // copied -- the lift of a hidden definition is output.
94
66
  if (true === v.isMap) {
95
67
  const peg: Record<string, Val> = {}
96
68
  for (const k of Object.keys(v.peg)) {
@@ -115,9 +87,6 @@ function superOf(ctx: AontuContext, v: any): Val {
115
87
  return v.place(out)
116
88
  }
117
89
 
118
- // The parent TYPE of a soft value is the parent of the value --
119
- // softness does not survive typing. Deliberately NOT superpeg,
120
- // whose top-for-a-kind answer is override-gate semantics.
121
90
  if (true === v.isPref) {
122
91
  return superOf(ctx, v.peg)
123
92
  }
@@ -145,11 +114,6 @@ function superOf(ctx: AontuContext, v: any): Val {
145
114
  return v.place(new DisjunctVal({ peg: arms }, ctx))
146
115
  }
147
116
 
148
- // A constraint's parent is the kind it constrains: the absorbed
149
- // leaf kind when it has one (integer & min(3) -> integer), else the
150
- // domain its atoms compare in (min(3) -> number, min("a") ->
151
- // string). length() constrains strings, lists and maps alike, so
152
- // with neither it falls through to top.
153
117
  if (true === v.isConstraint) {
154
118
  if (null != v.kind) {
155
119
  return v.place(new ScalarKindVal({ peg: v.kind }))
@@ -163,12 +127,6 @@ function superOf(ctx: AontuContext, v: any): Val {
163
127
  return v.place(top())
164
128
  }
165
129
 
166
- // The lattice primitive answers for the forms it always served:
167
- // a concrete scalar lifts to its leaf kind, a kind to its parent,
168
- // top to itself, and a NIL to itself -- which is how a failed
169
- // argument stays the failure: `super(1 & 2)` reports the conflict
170
- // rather than typing it. Where it has no meaningful answer (superior()
171
- // defaults to top for features), top is the honest remainder.
172
130
  const sup = v.superior()
173
131
  if (null != sup && true !== (sup as any).isTop) {
174
132
  return sup
package/src/val/TopVal.ts CHANGED
@@ -38,7 +38,6 @@ class TopVal extends Val {
38
38
  }
39
39
 
40
40
  same(peer: Val): boolean {
41
- // return this === peer
42
41
  return peer.isTop
43
42
  }
44
43
 
@@ -0,0 +1,132 @@
1
+ /* Copyright (c) 2026 Richard Rodger, MIT License */
2
+
3
+
4
+ import type {
5
+ Val,
6
+ ValSpec,
7
+ } from '../type'
8
+
9
+ import {
10
+ AontuContext,
11
+ } from '../ctx'
12
+
13
+ import { makeNilErr } from '../err'
14
+
15
+ import { StringVal } from './StringVal'
16
+ import { FuncBaseVal } from './FuncBaseVal'
17
+
18
+
19
+ // A set with its ranges expanded, or undefined when a range descends.
20
+ // `-` first or last is a literal.
21
+ function expandSet(set: string): string[] | undefined {
22
+ const cps = Array.from(set)
23
+ const out: string[] = []
24
+
25
+ for (let i = 0; i < cps.length; i++) {
26
+ const c = cps[i]
27
+ const next = cps[i + 1]
28
+ const after = cps[i + 2]
29
+
30
+ if ('-' === next && undefined !== after && 0 < i + 2) {
31
+ const lo = c.codePointAt(0) as number
32
+ const hi = after.codePointAt(0) as number
33
+ if (hi < lo) {
34
+ return undefined
35
+ }
36
+ for (let cp = lo; cp <= hi; cp++) {
37
+ out.push(String.fromCodePoint(cp))
38
+ }
39
+ i += 2
40
+ continue
41
+ }
42
+
43
+ out.push(c)
44
+ }
45
+
46
+ return out
47
+ }
48
+
49
+
50
+ // The text a value carries, when it is a concrete string.
51
+ function textOf(v: Val | undefined): string | undefined {
52
+ const s: any = v
53
+ return (true === s?.isScalar && 'string' === typeof s.peg) ? s.peg : undefined
54
+ }
55
+
56
+
57
+ class TranslateFuncVal extends FuncBaseVal {
58
+ isTranslateFunc = true
59
+
60
+ constructor(spec: ValSpec, ctx?: AontuContext) {
61
+ super(spec, ctx)
62
+ }
63
+
64
+ make(_ctx: AontuContext, spec: ValSpec): Val {
65
+ return new TranslateFuncVal(spec)
66
+ }
67
+
68
+ funcname() {
69
+ return 'translate'
70
+ }
71
+
72
+
73
+ resolve(ctx: AontuContext, args: Val[]): Val {
74
+ // Arity is checked at parse (funcArity), so a body guard is dead.
75
+ const src = textOf(args[0])
76
+ if (undefined === src) {
77
+ return makeNilErr(ctx, 'invalid-arg', this, args[0], 'src')
78
+ }
79
+
80
+ const fromText = textOf(args[1])
81
+ if (undefined === fromText) {
82
+ return makeNilErr(ctx, 'invalid-arg', this, args[1], 'from')
83
+ }
84
+ const from = expandSet(fromText)
85
+ if (undefined === from) {
86
+ return makeNilErr(ctx, 'invalid-arg', this, args[1], 'from')
87
+ }
88
+
89
+ let to: string[] = []
90
+ if (3 === args.length) {
91
+ const toText = textOf(args[2])
92
+ if (undefined === toText) {
93
+ return makeNilErr(ctx, 'invalid-arg', this, args[2], 'to')
94
+ }
95
+ const expanded = expandSet(toText)
96
+ if (undefined === expanded) {
97
+ return makeNilErr(ctx, 'invalid-arg', this, args[2], 'to')
98
+ }
99
+ to = expanded
100
+ }
101
+
102
+ // The table, built left to right so a character named twice takes
103
+ // its last mapping. An empty `to` maps to nothing, which is the
104
+ // deletion: there is no last character to pad with.
105
+ const pad = 0 < to.length ? to[to.length - 1] : undefined
106
+ const table = new Map<string, string | undefined>()
107
+ for (let i = 0; i < from.length; i++) {
108
+ table.set(from[i], i < to.length ? to[i] : pad)
109
+ }
110
+
111
+ let out = ''
112
+ for (const c of Array.from(src)) {
113
+ if (table.has(c)) {
114
+ const sub = table.get(c)
115
+ if (undefined !== sub) {
116
+ out += sub
117
+ }
118
+ continue
119
+ }
120
+ out += c
121
+ }
122
+
123
+ return this.place(new StringVal({ peg: out }, ctx))
124
+ }
125
+
126
+ } /* node:coverage ignore next 6 */
127
+
128
+
129
+ export {
130
+ expandSet,
131
+ TranslateFuncVal,
132
+ }
@@ -16,7 +16,7 @@ import { makeNilErr } from '../err'
16
16
  import { ScalarKindVal } from '../val/ScalarKindVal'
17
17
  import { makeScalarLike } from '../val/valutil'
18
18
  import { Decimal } from '../val/Decimal'
19
-
19
+ import { caseRange, rangeArg } from './caserange'
20
20
 
21
21
 
22
22
  import { FuncBaseVal } from './FuncBaseVal'
@@ -49,13 +49,18 @@ class UpperFuncVal extends FuncBaseVal {
49
49
  // internal error.
50
50
  const arg = args?.[0]
51
51
  const oldpeg = arg?.peg
52
- const peg = 'string' === typeof oldpeg ? oldpeg.toUpperCase() :
52
+
53
+ const start = rangeArg(args?.[1])
54
+ const len = rangeArg(args?.[2])
55
+ const ranged = undefined !== start || undefined !== len
56
+ if (ranged &&
57
+ (Number.isNaN(start as number) || Number.isNaN(len as number) ||
58
+ 'string' !== typeof oldpeg)) {
59
+ return this.place(makeNilErr(ctx, 'invalid-arg', this, arg, 'range'))
60
+ }
61
+ const peg = 'string' === typeof oldpeg ?
62
+ caseRange(oldpeg, start ?? 0, len ?? -1, true) :
53
63
  'number' === typeof oldpeg ? Math.ceil(oldpeg) :
54
- // The exact leaves take an EXACT ceiling and keep their kind: a
55
- // biginteger is already integral so it is its own ceiling, and a
56
- // bigdecimal ceils by coefficient arithmetic. Math.ceil is not
57
- // an option for either — it would round the value into binary64
58
- // first, which is the loss the `0d` leaves exist to refuse.
59
64
  'bigint' === typeof oldpeg ? oldpeg :
60
65
  oldpeg instanceof Decimal ? oldpeg.ceil() :
61
66
  undefined
package/src/val/Val.ts CHANGED
@@ -34,22 +34,6 @@ type ValSpec = {
34
34
  mark?: Partial<ValMark>,
35
35
  kind?: any,
36
36
 
37
- // THE PER-DESTINATION INSTANTIATION FLAG (ADR-005). A generator's
38
- // template is cloned once per destination, and every clone must be
39
- // a full instance: nothing path-dependent may be shared between two
40
- // destinations, or the first destination's resolution answers for
41
- // them all. The default clone shares inner structure deliberately
42
- // (`peg: this.peg` below — the move()/copy() ghost rows in
43
- // test/spec/func.tsv pin that sharing), so instantiation asks for
44
- // depth explicitly: `dup: true` makes FuncBaseVal, PrefVal and
45
- // OpBaseVal clone their inner Vals too, and the bag/junction clones
46
- // carry the flag down. Set by pack/each template instantiation,
47
- // filter condition testing, spread application (MapVal/
48
- // ListVal.spreadClone), and REFERENCE RESOLUTION of a target that
49
- // holds no staged call, whose copy is a per-destination instance
50
- // too (ADR-025) — never by the residuation clone, whose sharing is
51
- // pinned behaviour, and never by a copy of something still being
52
- // settled at its own site, which is what keeps the ghost rows.
53
37
  dup?: boolean,
54
38
 
55
39
 
@@ -72,7 +56,6 @@ type ValSpec = {
72
56
  }
73
57
 
74
58
 
75
-
76
59
  const DONE = -1
77
60
 
78
61
  const SPREAD = Symbol('spread')
@@ -84,12 +67,6 @@ const SPREAD = Symbol('spread')
84
67
  const EMPTY_ERR: any[] = Object.freeze([]) as unknown as any[]
85
68
 
86
69
 
87
- // Process-global, monotonic Val id source. Correctness only requires ids
88
- // to be unique within a single unify run (fast-path identity checks,
89
- // `same()`), which holds. It is NOT reset between generate() calls, so in
90
- // a long-running host (e.g. the LSP) it grows for the process lifetime;
91
- // that is acceptable — an id is a small number and is never used as a
92
- // memory key. TODO: switch to the per-run ctx.vc counter (see ctx.ts).
93
70
  let ID = 1000
94
71
 
95
72
 
@@ -100,6 +77,7 @@ abstract class Val {
100
77
  declare isVal: boolean
101
78
 
102
79
  declare isTop: boolean
80
+ declare isAbsent: boolean
103
81
  declare isNil: boolean
104
82
  declare isNull: boolean
105
83
  declare isMap: boolean
@@ -164,39 +142,12 @@ abstract class Val {
164
142
  hide: false,
165
143
  }
166
144
 
167
- // The deprecation record (G3 phase 4, `deprecate(x, m)`): boolean
168
- // marks cannot hold a message, a replacement path and a version, so
169
- // the Val carries one optional record. Keys are the three the
170
- // builtin defines (msg, use, since), all optional, values strings;
171
- // `use` is a path spelled as a STRING — a live reference would
172
- // resolve and unify, which is not wanted. Propagated through meets
173
- // by propagateMarks and carried by clone, exactly as the boolean
174
- // marks are.
175
145
  deprecation?: Record<string, string>
176
146
 
177
- // The LINK (G4 phase 2/3): the tree address a `refer` resolved to,
178
- // stamped on the string it answers. The string IS the value — a
179
- // link, not an embedding — so nothing downstream could otherwise
180
- // tell a checked link from a literal that happens to look like one,
181
- // and the edge set (ts/src/graph.ts) is exactly the set of these.
182
147
  link?: string
183
148
 
184
- // THE READ ADDRESS (RENDER.0.md P7): the tree path a reference
185
- // resolved this value AT, stamped where it was found. A resolved
186
- // reference CLONES its target into the referring position, so a
187
- // value that arrived by reference otherwise knows only where it came
188
- // to rest -- and a trace saying a line came from `$.code.units.0`
189
- // names the output, not the model. Written only by an instrumented
190
- // run (AontuContext.reads), carried by clone and by the meet rider,
191
- // exactly as the deprecation record is.
192
149
  origin?: string
193
150
 
194
- // THE DISPATCH THAT PRODUCED THIS PIECE (RENDER.0.md D11, P7): the
195
- // node an `emit` matched and the rule it took, stamped on every
196
- // piece the dispatch instantiated. The INNERMOST dispatch wins: a
197
- // nested rule set splices its pieces into the outer result, and the
198
- // rule that wrote a line is the one that wrote it. Written only by
199
- // an instrumented run, and carried like `origin`.
200
151
  emitted?: EmitOrigin
201
152
 
202
153
  // The GRAPH of an evaluated document (G4 phase 3): the edge set,
@@ -222,7 +173,6 @@ abstract class Val {
222
173
  // functions whose branches no supported Node can execute.
223
174
  private _ctx: any
224
175
 
225
- // TODO: Site needed in ctor
226
176
  constructor(spec: ValSpec, ctx?: AontuContext) {
227
177
  this._ctx = ctx
228
178
 
@@ -239,14 +189,11 @@ abstract class Val {
239
189
  // ctx.clone just to carry it.
240
190
  this.path = spec?.path ?? ctx?.path ?? []
241
191
 
242
- // TODO: make this work
243
- // this.id = spec?.id ?? (ctx ? ++ctx.vc : ++ID)
244
192
  this.id = ++ID
245
193
 
246
194
  this.mark.type = !!spec.mark?.type
247
195
  this.mark.hide = !!spec.mark?.hide
248
196
 
249
- // console.log('BV', this.id, this.constructor.name, this.peg?.canon)
250
197
  }
251
198
 
252
199
 
@@ -295,26 +242,6 @@ abstract class Val {
295
242
  out.site.row = spec?.row ?? this.site.row
296
243
  out.site.col = spec?.col ?? this.site.col
297
244
  out.site.url = spec?.url ?? this.site.url
298
- // THE SPAN TRAVELS WITH THE POSITION. Copying row and col but not
299
- // the extent would leave a site that names a place and denies it has
300
- // any width — internally inconsistent, and it made the two ports
301
- // disagree on every derived value (the shared subsume rows caught
302
- // it). Safe because the span is VERIFIABLE: a consumer reads the
303
- // document at (row, col, len) and refuses when it does not match
304
- // `src`, so a span that has stopped describing its value is
305
- // detectable rather than believed. See ts/src/site.ts.
306
- //
307
- // Read from `this.site`, never from the spec: ValSpec.src is a
308
- // DIFFERENT field — ScalarVal's literal spelling, kept so `$.a.0x0`
309
- // addresses the key `0x0` — and reading it here would put a path
310
- // segment where a source span belongs.
311
- //
312
- // UNCONDITIONAL, as the Go twin is (clonePath, go/clone.go). A
313
- // guard dropping the span when the spec relocates the value was
314
- // written first and the coverage gate refused it as dead: nothing
315
- // clones to a new row or column. Should a relocating caller ever
316
- // appear it must drop both fields — an extent belongs to a place,
317
- // and the text at a new one is not this value's to claim.
318
245
  out.site.len = this.site.len
319
246
  out.site.src = this.site.src
320
247
 
@@ -332,11 +259,6 @@ abstract class Val {
332
259
  out.deprecation = this.deprecation
333
260
  }
334
261
 
335
- // THE RENDER RIDERS TRAVEL WITH THE CLONE (P7), for the reason the
336
- // deprecation record does: a clone of a value read at `$.schema`
337
- // was read at `$.schema`, and a clone of an emitted piece is still
338
- // that dispatch's. Both are absent unless the run is instrumented,
339
- // so this is two undefined reads otherwise.
340
262
  if (null != this.origin) {
341
263
  out.origin = this.origin
342
264
  }
@@ -344,17 +266,6 @@ abstract class Val {
344
266
  out.emitted = this.emitted
345
267
  }
346
268
 
347
- // THE APPLY-ONCE MARK TRAVELS WITH THE CLONE. `_spr` records which
348
- // spread template has already been merged into this value, and the
349
- // bag loops read it to keep a template from being applied twice
350
- // (MapVal.unify, ListVal.unify). A clone that dropped it looked
351
- // un-spread, so a REFERENCE resolving to a templated bag had the
352
- // template applied a second time -- over the value the first
353
- // application had already produced. With `n: key()` that meant
354
- // meeting the answered `"x"` as though it were a map and asking
355
- // `key()` again, which answered `"n"`: `$.a.b.f.x.n.n`, "n"
356
- // against "x" (use-cases/BUGS.md §50). The Go port carries it and
357
- // answered correctly; this is the canonical side catching up.
358
269
  if (null != (this as any)._spr) {
359
270
  ; (out as any)._spr = (this as any)._spr
360
271
  }
@@ -362,26 +273,9 @@ abstract class Val {
362
273
  ; (out as any)._sid = (this as any)._sid
363
274
  }
364
275
 
365
- // PROVENANCE TRAVELS WITH THE CLONE, exactly as the site does, and
366
- // for the same reason: a clone of a value the author wrote IS that
367
- // written value somewhere else, and it carries the author's site,
368
- // so it can be pointed at. Without this a default reaching a
369
- // `pack()`-generated child, or a shape carried by a `$ref`, was
370
- // invisible to `why` -- which answered "nothing met at this path"
371
- // over a value it had just printed (the review's finding E). See
372
- // WRITTEN in ts/src/provenance.ts; the mark is only ever set by an
373
- // instrumented run, so this is one undefined read otherwise.
374
276
  if (true === (this as any)[WRITTEN]) {
375
277
  (out as any)[WRITTEN] = true
376
278
  }
377
- // AND SO DOES BEING PART OF SOMETHING. A clone of a disjunction's
378
- // member is still that member of that written disjunction, and the
379
- // whole statement is what the author needs shown -- otherwise a
380
- // default reaching a generated child reports `*"info"` and
381
- // `string` as two contributions at two columns, where the author
382
- // wrote `*info | string` once. A number, deliberately: a Val
383
- // holding another Val as an own property is a cycle through the
384
- // tree. See INNER_OF in ts/src/provenance.ts.
385
279
  if (null != (this as any)[INNER_OF]) {
386
280
  (out as any)[INNER_OF] = (this as any)[INNER_OF]
387
281
  }
@@ -390,16 +284,6 @@ abstract class Val {
390
284
  }
391
285
 
392
286
 
393
- // Shallow clone for spread constraints: creates a new Val with the
394
- // correct path context but shares non-path-dependent children.
395
- // Override in MapVal/ListVal to avoid deep-cloning simple children.
396
- //
397
- // A FULL INSTANCE (`dup`, ADR-005): a spread constraint is applied
398
- // once per destination child, and each application must own its
399
- // path-dependent innards — a bare clone shared a call's arguments
400
- // and a preference's inner value across destinations, so a spread
401
- // like `&: {k: key(0)} & $.schema.C` resolved its one shared key()
402
- // at the first child it met (use-cases/BUGS.md §12's id_name form).
403
287
  spreadClone(ctx: AontuContext): Val {
404
288
  const out = this.clone(ctx, { dup: true })
405
289
  repathInstance(out, out.path)
@@ -407,12 +291,6 @@ abstract class Val {
407
291
  }
408
292
 
409
293
 
410
- // True if this Val's unification result depends on its own `path`
411
- // — i.e. the tree contains a RefVal, KeyFuncVal, PathFuncVal,
412
- // MoveFuncVal, or SuperFuncVal. Used by MapVal/ListVal.spreadClone
413
- // to share the spread constraint across keys when it's safe.
414
- // Lazy + cached: the answer is a function of the Val's immutable
415
- // structure, so we compute once per Val.
416
294
  _isPathDependent?: boolean
417
295
  get isPathDependent(): boolean {
418
296
  if (this._isPathDependent !== undefined) return this._isPathDependent
@@ -443,13 +321,6 @@ abstract class Val {
443
321
  }
444
322
 
445
323
 
446
- // A STAGED CALL STANDING ANYWHERE IN THIS VALUE (the `staged` flag,
447
- // G8 phase 0). Such a call has not decided: its arguments are still
448
- // being driven AT ITS OWN SITE, so a REFERENCE's copy shares it
449
- // rather than owning a set of arguments it would drive at the
450
- // referring position instead (RefVal.find, ADR-025). Not cached:
451
- // unlike isPathDependent this is a fact about the value's current
452
- // state, and the whole point is that it stops being true.
453
324
  get holdsStaged(): boolean {
454
325
  if (true === (this as any).staged) {
455
326
  return true
@@ -470,14 +341,6 @@ abstract class Val {
470
341
  }
471
342
 
472
343
 
473
- // PUT A MINTED VALUE WHERE THIS ONE STANDS: the site travels, and so
474
- // does provenance, because the two answer one question. A narrowed
475
- // disjunction, a lifted kind, a resolved reference -- each is a
476
- // value the engine built from a value the author wrote, standing
477
- // where that one stood. Carrying the site and withholding the mark
478
- // would let `why` print a value, know the line it came from, and
479
- // still answer "nothing met at this path" (the review's finding E).
480
- // See WRITTEN and INNER_OF in ts/src/provenance.ts.
481
344
  place(v: Val) {
482
345
  v.site.row = this.site.row
483
346
  v.site.col = this.site.col
@@ -493,25 +356,8 @@ abstract class Val {
493
356
  return v
494
357
  }
495
358
 
496
- // CONTRACT: implementations should treat `this` and `peer` as
497
- // immutable and return a new Val. KNOWN EXCEPTION: the MapVal/ListVal
498
- // fast-path for a TOP peer returns and refines `this` in place (an
499
- // intentional optimization for the fixpoint loop). The practical
500
- // consequence is that a parsed/unified tree is SINGLE-USE — do not
501
- // re-unify or re-generate the same Val, and do not share it across
502
- // threads. The public Aontu.unify/generate entry points re-parse per
503
- // call, so this only matters if you hold and reuse a Val yourself.
504
359
  unify(_peer: Val, _ctx: AontuContext): Val { return this }
505
360
 
506
- // TODO: indicate marks in some way that is ignored by reparse.
507
- // Need an annotation/taggins syntax? a:{}/type ?
508
- // ABSTRACT: every concrete Val renders its own canonical form. There
509
- // used to be an empty-string default here, and the one class relying
510
- // on it (ExpectVal) was rendering a key with no value -- `{"r":}`,
511
- // text that is not a document (issue #43). With that fixed, nothing
512
- // reached the default, so it is declared rather than defaulted: a new
513
- // Val that forgets `canon` is now a compile error instead of silently
514
- // canoning as nothing.
515
361
  abstract get canon(): string
516
362
 
517
363
 
@@ -550,7 +396,6 @@ abstract class Val {
550
396
  ...Object.entries(this.mark).filter(n => n[1]).map(n => n[0]).sort()
551
397
  ].filter(n => null != n).join(','))
552
398
 
553
- // let insp = this.inspection(inspect)
554
399
  let insp = this.inspection(1 + d)
555
400
  if (null != insp && '' != insp) {
556
401
  s.push('/' + insp)
@@ -587,16 +432,11 @@ abstract class Val {
587
432
  }
588
433
 
589
434
 
590
- // Prototype-level defaults for Val's type-discriminator flags.
591
- // Keeping these on the prototype (instead of per-instance class-field
592
- // initializers) removes ~35 property writes from every Val construction
593
- // and eliminates the corresponding hidden-class transitions. Subclasses
594
- // override only the flags that differ, via their own class-field
595
- // initializers (e.g. `MapVal.isMap = true`).
596
435
  Object.assign(Val.prototype, {
597
436
  isVal: true,
598
437
 
599
438
  isTop: false,
439
+ isAbsent: false,
600
440
  isNil: false,
601
441
  isNull: false,
602
442
  isMap: false,
@@ -639,22 +479,6 @@ Object.assign(Val.prototype, {
639
479
  })
640
480
 
641
481
 
642
- // THE INSTANCE PATH NORMALISATION (ADR-005), the TS mirror of the Go
643
- // port's setPaths (go/clone.go): assign every value in a freshly
644
- // instantiated template the path the PARSER would have given it at the
645
- // instance's destination. A deep instance clone (`dup`) copies values
646
- // whose stored parse paths are argument-shaped — a func argument has
647
- // no key of its own, a spread template lives under a '&' segment — and
648
- // Val.clone's ctx-cut cannot rebase those: it derives the child path
649
- // from the driving ctx alone and drops the segments in between, which
650
- // is how a nested list spread inside a close()d template lost its
651
- // parent key and every finding under it named the wrong path (the
652
- // 06-k8s use case's env findings). One canonical walk instead:
653
- // bag children descend by key (numeric for a list element, as the
654
- // parser records them), a spread constraint sits under '&' with its
655
- // content at the bag's own path, and junction members, operator
656
- // operands, function arguments and a preference's value all sit AT
657
- // their holder's path — exactly the parse-time shape.
658
482
  function repathInstance(v: any, path: string[]): void {
659
483
  if (true !== v?.isVal) {
660
484
  return
@@ -666,9 +490,6 @@ function repathInstance(v: any, path: string[]): void {
666
490
  if (true === v.isBag) {
667
491
  const spread = v.spread?.cj
668
492
  if (null != spread && true === spread.isVal) {
669
- // The spread's CONTENT is pathed at the bag (its fields land on
670
- // the bag's children); only its ROOT carries the '&' segment —
671
- // the same two steps as the Go twin's setPaths.
672
493
  repathInstance(spread, path)
673
494
  spread.path = [...path, '&']
674
495
  }
@@ -704,7 +525,7 @@ function inspectpeg(peg: any, d: number) {
704
525
  '\n' + indent + ']') :
705
526
  ('{' +
706
527
  Object.entries(peg).map((n: any) =>
707
- '\n ' + indent + n[0] + ': ' + // n[1].inspect(d)
528
+ '\n ' + indent + n[0] + ': ' +
708
529
  n[1].inspect(d)
709
530
  ).join(',') +
710
531
  '\n' + indent + '}')
@@ -720,16 +541,6 @@ function pretty(s: string) {
720
541
  }
721
542
 
722
543
 
723
- // THE STABLE IDENTITY OF A SPREAD TEMPLATE, across clones. Every Val
724
- // takes a fresh `id` when it is constructed, so the bag loops'
725
- // apply-once mark -- which records WHICH template has already been
726
- // merged into a value -- could never match after a clone: a reference
727
- // resolving to a templated bag clones the bag AND its template, and the
728
- // fresh template's id matched nothing, so the template was applied a
729
- // second time over the value the first application had produced
730
- // (use-cases/BUGS.md §50). The first call fixes the identity to the
731
- // original's own id; Val.clone carries `_sid`, so every clone of that
732
- // template answers with it.
733
544
  function spreadId(cj: any): number {
734
545
  return cj._sid ?? (cj._sid = cj.id)
735
546
  }