aontu 0.52.1 → 0.54.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 (310) hide show
  1. package/README.md +88 -0
  2. package/bin/aontu-mcp.js +4 -0
  3. package/dist/agentsmd.d.ts +16 -0
  4. package/dist/agentsmd.js +107 -0
  5. package/dist/agentsmd.js.map +1 -0
  6. package/dist/aontu.d.ts +15 -3
  7. package/dist/aontu.js +126 -5
  8. package/dist/aontu.js.map +1 -1
  9. package/dist/cli.d.ts +45 -1
  10. package/dist/cli.js +2845 -69
  11. package/dist/cli.js.map +1 -1
  12. package/dist/ctx.d.ts +18 -0
  13. package/dist/ctx.js +44 -0
  14. package/dist/ctx.js.map +1 -1
  15. package/dist/diff.d.ts +22 -0
  16. package/dist/diff.js +141 -0
  17. package/dist/diff.js.map +1 -0
  18. package/dist/err.d.ts +3 -1
  19. package/dist/err.js +45 -8
  20. package/dist/err.js.map +1 -1
  21. package/dist/graph.d.ts +13 -0
  22. package/dist/graph.js +110 -0
  23. package/dist/graph.js.map +1 -0
  24. package/dist/hcanon.d.ts +3 -0
  25. package/dist/hcanon.js +145 -0
  26. package/dist/hcanon.js.map +1 -0
  27. package/dist/hints.js +235 -8
  28. package/dist/hints.js.map +1 -1
  29. package/dist/jsonschema.d.ts +20 -0
  30. package/dist/jsonschema.js +425 -0
  31. package/dist/jsonschema.js.map +1 -0
  32. package/dist/lang.js +955 -110
  33. package/dist/lang.js.map +1 -1
  34. package/dist/lsp.d.ts +9 -2
  35. package/dist/lsp.js +343 -48
  36. package/dist/lsp.js.map +1 -1
  37. package/dist/mcp-server.d.ts +20 -0
  38. package/dist/mcp-server.js +147 -0
  39. package/dist/mcp-server.js.map +1 -0
  40. package/dist/mcp.d.ts +42 -0
  41. package/dist/mcp.js +941 -0
  42. package/dist/mcp.js.map +1 -0
  43. package/dist/mod-tool.d.ts +58 -0
  44. package/dist/mod-tool.js +532 -0
  45. package/dist/mod-tool.js.map +1 -0
  46. package/dist/mod.d.ts +35 -0
  47. package/dist/mod.js +345 -0
  48. package/dist/mod.js.map +1 -0
  49. package/dist/patch.d.ts +49 -0
  50. package/dist/patch.js +506 -0
  51. package/dist/patch.js.map +1 -0
  52. package/dist/provenance.d.ts +41 -0
  53. package/dist/provenance.js +336 -0
  54. package/dist/provenance.js.map +1 -0
  55. package/dist/query.d.ts +27 -0
  56. package/dist/query.js +294 -0
  57. package/dist/query.js.map +1 -0
  58. package/dist/reach.d.ts +15 -0
  59. package/dist/reach.js +168 -0
  60. package/dist/reach.js.map +1 -0
  61. package/dist/relation.d.ts +23 -0
  62. package/dist/relation.js +230 -0
  63. package/dist/relation.js.map +1 -0
  64. package/dist/report-sarif.d.ts +14 -0
  65. package/dist/report-sarif.js +102 -0
  66. package/dist/report-sarif.js.map +1 -0
  67. package/dist/sig.d.ts +25 -0
  68. package/dist/sig.js +277 -0
  69. package/dist/sig.js.map +1 -0
  70. package/dist/sigdecl.d.ts +2 -0
  71. package/dist/sigdecl.js +11 -0
  72. package/dist/sigdecl.js.map +1 -0
  73. package/dist/siggate.d.ts +4 -0
  74. package/dist/siggate.js +90 -0
  75. package/dist/siggate.js.map +1 -0
  76. package/dist/site.d.ts +4 -0
  77. package/dist/site.js +31 -0
  78. package/dist/site.js.map +1 -1
  79. package/dist/std.d.ts +1 -0
  80. package/dist/std.js +129 -0
  81. package/dist/std.js.map +1 -0
  82. package/dist/subsume.d.ts +39 -0
  83. package/dist/subsume.js +573 -0
  84. package/dist/subsume.js.map +1 -0
  85. package/dist/trim.d.ts +19 -0
  86. package/dist/trim.js +155 -0
  87. package/dist/trim.js.map +1 -0
  88. package/dist/tsconfig.tsbuildinfo +1 -1
  89. package/dist/type.d.ts +17 -1
  90. package/dist/type.js.map +1 -1
  91. package/dist/unify.d.ts +2 -1
  92. package/dist/unify.js +234 -38
  93. package/dist/unify.js.map +1 -1
  94. package/dist/utility.d.ts +8 -1
  95. package/dist/utility.js +68 -1
  96. package/dist/utility.js.map +1 -1
  97. package/dist/val/AggFuncVal.d.ts +44 -0
  98. package/dist/val/AggFuncVal.js +364 -0
  99. package/dist/val/AggFuncVal.js.map +1 -0
  100. package/dist/val/ArithFuncVal.d.ts +31 -0
  101. package/dist/val/ArithFuncVal.js +62 -0
  102. package/dist/val/ArithFuncVal.js.map +1 -0
  103. package/dist/val/BagVal.d.ts +7 -0
  104. package/dist/val/BagVal.js +150 -11
  105. package/dist/val/BagVal.js.map +1 -1
  106. package/dist/val/CloseFuncVal.js +9 -1
  107. package/dist/val/CloseFuncVal.js.map +1 -1
  108. package/dist/val/ConjunctVal.d.ts +1 -1
  109. package/dist/val/ConjunctVal.js +19 -0
  110. package/dist/val/ConjunctVal.js.map +1 -1
  111. package/dist/val/ConstraintVal.d.ts +7 -1
  112. package/dist/val/ConstraintVal.js +523 -45
  113. package/dist/val/ConstraintVal.js.map +1 -1
  114. package/dist/val/ContainerKindVal.d.ts +35 -0
  115. package/dist/val/ContainerKindVal.js +99 -0
  116. package/dist/val/ContainerKindVal.js.map +1 -0
  117. package/dist/val/CopyFuncVal.d.ts +1 -2
  118. package/dist/val/CopyFuncVal.js.map +1 -1
  119. package/dist/val/Decimal.d.ts +1 -0
  120. package/dist/val/Decimal.js +13 -0
  121. package/dist/val/Decimal.js.map +1 -1
  122. package/dist/val/DeprecateFuncVal.d.ts +11 -0
  123. package/dist/val/DeprecateFuncVal.js +47 -0
  124. package/dist/val/DeprecateFuncVal.js.map +1 -0
  125. package/dist/val/DisjunctVal.d.ts +1 -2
  126. package/dist/val/DisjunctVal.js +269 -53
  127. package/dist/val/DisjunctVal.js.map +1 -1
  128. package/dist/val/EachFuncVal.d.ts +15 -0
  129. package/dist/val/EachFuncVal.js +75 -0
  130. package/dist/val/EachFuncVal.js.map +1 -0
  131. package/dist/val/ExpectVal.js +62 -4
  132. package/dist/val/ExpectVal.js.map +1 -1
  133. package/dist/val/FeatureVal.js +1 -1
  134. package/dist/val/FeatureVal.js.map +1 -1
  135. package/dist/val/FilterFuncVal.d.ts +15 -0
  136. package/dist/val/FilterFuncVal.js +91 -0
  137. package/dist/val/FilterFuncVal.js.map +1 -0
  138. package/dist/val/FuncBaseVal.d.ts +7 -1
  139. package/dist/val/FuncBaseVal.js +183 -2
  140. package/dist/val/FuncBaseVal.js.map +1 -1
  141. package/dist/val/GraphAtomVal.d.ts +39 -0
  142. package/dist/val/GraphAtomVal.js +184 -0
  143. package/dist/val/GraphAtomVal.js.map +1 -0
  144. package/dist/val/HideFuncVal.js.map +1 -1
  145. package/dist/val/JunctionVal.js +24 -1
  146. package/dist/val/JunctionVal.js.map +1 -1
  147. package/dist/val/KeyFuncVal.d.ts +1 -1
  148. package/dist/val/KeyFuncVal.js +38 -30
  149. package/dist/val/KeyFuncVal.js.map +1 -1
  150. package/dist/val/ListVal.js +94 -14
  151. package/dist/val/ListVal.js.map +1 -1
  152. package/dist/val/LowerFuncVal.js.map +1 -1
  153. package/dist/val/MapVal.d.ts +1 -0
  154. package/dist/val/MapVal.js +146 -14
  155. package/dist/val/MapVal.js.map +1 -1
  156. package/dist/val/MatchFuncVal.d.ts +15 -0
  157. package/dist/val/MatchFuncVal.js +107 -0
  158. package/dist/val/MatchFuncVal.js.map +1 -0
  159. package/dist/val/MoveFuncVal.js.map +1 -1
  160. package/dist/val/NilVal.js +24 -0
  161. package/dist/val/NilVal.js.map +1 -1
  162. package/dist/val/OpBaseVal.d.ts +1 -1
  163. package/dist/val/OpBaseVal.js +19 -1
  164. package/dist/val/OpBaseVal.js.map +1 -1
  165. package/dist/val/OpenFuncVal.js +4 -1
  166. package/dist/val/OpenFuncVal.js.map +1 -1
  167. package/dist/val/PackFuncVal.d.ts +15 -0
  168. package/dist/val/PackFuncVal.js +108 -0
  169. package/dist/val/PackFuncVal.js.map +1 -0
  170. package/dist/val/PathFuncVal.d.ts +2 -2
  171. package/dist/val/PathFuncVal.js +75 -16
  172. package/dist/val/PathFuncVal.js.map +1 -1
  173. package/dist/val/PathVal.d.ts +25 -0
  174. package/dist/val/PathVal.js +150 -0
  175. package/dist/val/PathVal.js.map +1 -0
  176. package/dist/val/PlaceVal.d.ts +13 -0
  177. package/dist/val/PlaceVal.js +131 -0
  178. package/dist/val/PlaceVal.js.map +1 -0
  179. package/dist/val/PlusOpVal.d.ts +2 -1
  180. package/dist/val/PlusOpVal.js +61 -37
  181. package/dist/val/PlusOpVal.js.map +1 -1
  182. package/dist/val/PrefFuncVal.js.map +1 -1
  183. package/dist/val/PrefVal.d.ts +4 -2
  184. package/dist/val/PrefVal.js +223 -41
  185. package/dist/val/PrefVal.js.map +1 -1
  186. package/dist/val/RecurseVal.d.ts +19 -0
  187. package/dist/val/RecurseVal.js +217 -0
  188. package/dist/val/RecurseVal.js.map +1 -0
  189. package/dist/val/RefVal.d.ts +3 -2
  190. package/dist/val/RefVal.js +181 -66
  191. package/dist/val/RefVal.js.map +1 -1
  192. package/dist/val/ReferFuncVal.d.ts +59 -0
  193. package/dist/val/ReferFuncVal.js +604 -0
  194. package/dist/val/ReferFuncVal.js.map +1 -0
  195. package/dist/val/ScalarKindVal.d.ts +4 -3
  196. package/dist/val/ScalarKindVal.js +12 -12
  197. package/dist/val/ScalarKindVal.js.map +1 -1
  198. package/dist/val/SuperFuncVal.d.ts +4 -2
  199. package/dist/val/SuperFuncVal.js +118 -14
  200. package/dist/val/SuperFuncVal.js.map +1 -1
  201. package/dist/val/TopVal.d.ts +1 -1
  202. package/dist/val/TopVal.js.map +1 -1
  203. package/dist/val/TypeFuncVal.js.map +1 -1
  204. package/dist/val/UpperFuncVal.js.map +1 -1
  205. package/dist/val/Val.d.ts +7 -1
  206. package/dist/val/Val.js +170 -2
  207. package/dist/val/Val.js.map +1 -1
  208. package/dist/val/VarVal.js.map +1 -1
  209. package/dist/val/arith.d.ts +6 -0
  210. package/dist/val/arith.js +173 -0
  211. package/dist/val/arith.js.map +1 -0
  212. package/dist/vet.d.ts +45 -0
  213. package/dist/vet.js +802 -0
  214. package/dist/vet.js.map +1 -0
  215. package/dist/view.d.ts +85 -0
  216. package/dist/view.js +1948 -0
  217. package/dist/view.js.map +1 -0
  218. package/dist/walk.d.ts +2 -0
  219. package/dist/walk.js +91 -0
  220. package/dist/walk.js.map +1 -0
  221. package/grammar/aontu.gbnf +138 -0
  222. package/grammar/aontu.lark +118 -0
  223. package/grammar/aontu.tmLanguage.json +184 -0
  224. package/package.json +30 -8
  225. package/skill/SKILL.md +37 -0
  226. package/skill/error-codes.md +62 -0
  227. package/skill/examples.md +99 -0
  228. package/skill/grammar-card.md +56 -0
  229. package/src/agentsmd.ts +135 -0
  230. package/src/aontu.ts +166 -5
  231. package/src/cli.ts +3324 -72
  232. package/src/ctx.ts +93 -1
  233. package/src/diff.ts +198 -0
  234. package/src/err.ts +50 -8
  235. package/src/graph.ts +185 -0
  236. package/src/hcanon.ts +167 -0
  237. package/src/hints.ts +291 -8
  238. package/src/jsonschema.ts +552 -0
  239. package/src/lang.ts +1049 -110
  240. package/src/lsp.ts +351 -49
  241. package/src/mcp-server.ts +187 -0
  242. package/src/mcp.ts +1130 -0
  243. package/src/mod-tool.ts +718 -0
  244. package/src/mod.ts +453 -0
  245. package/src/patch.ts +628 -0
  246. package/src/provenance.ts +437 -0
  247. package/src/query.ts +381 -0
  248. package/src/reach.ts +213 -0
  249. package/src/relation.ts +298 -0
  250. package/src/report-sarif.ts +137 -0
  251. package/src/sig.ts +345 -0
  252. package/src/sigdecl.ts +11 -0
  253. package/src/siggate.ts +144 -0
  254. package/src/site.ts +36 -1
  255. package/src/std.ts +131 -0
  256. package/src/subsume.ts +739 -0
  257. package/src/trim.ts +195 -0
  258. package/src/tsconfig.json +10 -4
  259. package/src/type.ts +51 -2
  260. package/src/unify.ts +253 -38
  261. package/src/utility.ts +79 -1
  262. package/src/val/AggFuncVal.ts +546 -0
  263. package/src/val/ArithFuncVal.ts +108 -0
  264. package/src/val/BagVal.ts +158 -12
  265. package/src/val/CloseFuncVal.ts +9 -1
  266. package/src/val/ConjunctVal.ts +20 -0
  267. package/src/val/ConstraintVal.ts +576 -48
  268. package/src/val/ContainerKindVal.ts +158 -0
  269. package/src/val/CopyFuncVal.ts +0 -1
  270. package/src/val/Decimal.ts +15 -0
  271. package/src/val/DeprecateFuncVal.ts +84 -0
  272. package/src/val/DisjunctVal.ts +282 -59
  273. package/src/val/EachFuncVal.ts +133 -0
  274. package/src/val/ExpectVal.ts +65 -8
  275. package/src/val/FeatureVal.ts +1 -1
  276. package/src/val/FilterFuncVal.ts +154 -0
  277. package/src/val/FuncBaseVal.ts +206 -2
  278. package/src/val/GraphAtomVal.ts +264 -0
  279. package/src/val/HideFuncVal.ts +0 -2
  280. package/src/val/JunctionVal.ts +24 -1
  281. package/src/val/KeyFuncVal.ts +39 -35
  282. package/src/val/ListVal.ts +101 -15
  283. package/src/val/LowerFuncVal.ts +0 -1
  284. package/src/val/MapVal.ts +153 -14
  285. package/src/val/MatchFuncVal.ts +176 -0
  286. package/src/val/MoveFuncVal.ts +0 -2
  287. package/src/val/NilVal.ts +25 -0
  288. package/src/val/OpBaseVal.ts +20 -1
  289. package/src/val/OpenFuncVal.ts +4 -2
  290. package/src/val/PackFuncVal.ts +175 -0
  291. package/src/val/PathFuncVal.ts +107 -20
  292. package/src/val/PathVal.ts +221 -0
  293. package/src/val/PlaceVal.ts +193 -0
  294. package/src/val/PlusOpVal.ts +67 -39
  295. package/src/val/PrefFuncVal.ts +0 -1
  296. package/src/val/PrefVal.ts +251 -60
  297. package/src/val/RecurseVal.ts +285 -0
  298. package/src/val/RefVal.ts +183 -78
  299. package/src/val/ReferFuncVal.ts +732 -0
  300. package/src/val/ScalarKindVal.ts +12 -13
  301. package/src/val/SuperFuncVal.ts +137 -13
  302. package/src/val/TopVal.ts +1 -2
  303. package/src/val/TypeFuncVal.ts +0 -2
  304. package/src/val/UpperFuncVal.ts +0 -1
  305. package/src/val/Val.ts +216 -4
  306. package/src/val/VarVal.ts +0 -1
  307. package/src/val/arith.ts +319 -0
  308. package/src/vet.ts +1025 -0
  309. package/src/view.ts +2563 -0
  310. package/src/walk.ts +99 -0
@@ -13,7 +13,8 @@ import {
13
13
 
14
14
  import { AontuContext } from '../ctx'
15
15
 
16
- import { makeNilErr } from '../err'
16
+ import { AontuError, descErr, makeNilErr } from '../err'
17
+ import { exactJSON } from '../exactjson'
17
18
  import { unite } from '../unify'
18
19
 
19
20
  import {
@@ -30,8 +31,8 @@ import {
30
31
  top
31
32
  } from './top'
32
33
 
33
- import { NilVal, TRIAL_NIL } from '../val/NilVal'
34
- import { PrefVal } from '../val/PrefVal'
34
+ import { TRIAL_NIL } from '../val/NilVal'
35
+ import { PrefVal, prefInnerPeg } from '../val/PrefVal'
35
36
  import { JunctionVal } from '../val/JunctionVal'
36
37
 
37
38
 
@@ -70,7 +71,12 @@ class DisjunctVal extends JunctionVal {
70
71
  const te = ctx.explain && explainOpen(ctx, ctx.explain, 'Disjunct', this, peer)
71
72
 
72
73
  if (!this.prefsRanked) {
73
- this.rankPrefs(ctx)
74
+ const ranked = this.rankPrefs(ctx)
75
+ // A clash between equal-rank defaults refuses for the whole
76
+ // disjunction (R2): the disagreement IS the answer.
77
+ if (null != ranked && ranked.isNil) {
78
+ return ranked
79
+ }
74
80
  }
75
81
 
76
82
  // // // console.log('DISJUNCT-unify-A', this.id, this.canon)
@@ -95,6 +101,16 @@ class DisjunctVal extends JunctionVal {
95
101
  // before return.
96
102
  const savedErr = ctx.err
97
103
  const savedTrialMode = ctx._trialMode
104
+ // A MEMBER'S TYPE FLOW IS PART OF THAT MEMBER. `refer(t)`/`rel(t)`
105
+ // assert `t` on ANOTHER node, and the assertion may only take
106
+ // effect if the member that makes it survives: committing every
107
+ // member's flow puts `t_A & t_B` on the target, which no reading
108
+ // of `A | B` licenses and which leaves the target MORE constrained
109
+ // than either alternative. The flow record is therefore staged per
110
+ // trial, like `ctx.err`, and only the survivors' records are
111
+ // merged into the real one below.
112
+ const savedFlows: Map<string, Val> | undefined = (ctx as any).referflows
113
+ const staged: (Map<string, Val> | undefined)[] = []
98
114
  // C1-inner: tell `makeNilErr` to return TRIAL_NIL in this scope
99
115
  // instead of allocating per-failure NilVals. Save/restore so
100
116
  // nested DisjunctVal trials (and the outer non-trial code) are
@@ -102,11 +118,16 @@ class DisjunctVal extends JunctionVal {
102
118
  // leaving ctx._trialMode=true would collapse every subsequent real
103
119
  // error in this ctx to the shared TRIAL_NIL sentinel.
104
120
  ctx._trialMode = true
121
+ let gate: number[] | undefined = undefined
105
122
  try {
106
123
  for (let vI = 0; vI < this.peg.length; vI++) {
107
124
  const v = this.peg[vI]
108
125
  const trialErr: any[] = []
109
126
  ctx.err = trialErr
127
+ if (undefined !== savedFlows) {
128
+ staged[vI] = new Map()
129
+ ;(ctx as any).referflows = staged[vI]
130
+ }
110
131
 
111
132
  oval[vI] = unite(te ? ctx.clone({ explain: ec(te, 'DIST:' + vI) }) : ctx, v, peer, 'dj-peer')
112
133
 
@@ -117,17 +138,96 @@ class DisjunctVal extends JunctionVal {
117
138
  // sentinel instead of allocating a fresh NilVal per trial.
118
139
  oval[vI] = TRIAL_NIL
119
140
  }
141
+ else if (v instanceof PrefVal &&
142
+ !(peer as any).isPref && !peer.isTop &&
143
+ true === (prefInnerPeg(v) as any).isScalar) {
144
+ // A candidate for the admission gate below: a non-pref,
145
+ // non-top peer met a scalar preference inside this
146
+ // disjunction.
147
+ ; (gate = gate ?? []).push(vI)
148
+ }
120
149
 
121
150
  done = done && DONE === oval[vI].dc
122
151
  }
152
+
153
+ // THE ADMISSION GATE (ADR-004). A peer that meets a preference
154
+ // INSIDE a disjunction must be admitted by the disjunction: by
155
+ // some sibling alternative (whose own trial above already
156
+ // answers that), or by the preferred value itself (the pref
157
+ // branch's own admitted set). The pref's kind gate alone used to
158
+ // decide, so a same-kind concrete peer replaced the default with
159
+ // the alternatives never consulted -- `k:*'auto'|'literal'|'data'`
160
+ // plus `k:'autoo'` answered "autoo", and `*8080|(integer&neq(80))`
161
+ // admitted 80 (use-cases/BUGS.md §1-2). An inadmissible override
162
+ // now fails the pref member's trial, and when every member is
163
+ // gone the meet is the existing `empty` refusal.
164
+ //
165
+ // SCALAR preferred values only, exactly the kind gate's own
166
+ // boundary (test/spec/pref.tsv, "THE GATE IS A SCALAR GATE"): a
167
+ // structural or kind-peg default stays ungated. A deliberately
168
+ // open default remains spellable as `*x|top` -- the top branch
169
+ // admits every override (the apidef machine-emitted idiom).
170
+ if (undefined !== gate) {
171
+ for (const gI of gate) {
172
+ let admitted = false
173
+ for (let kI = 0; kI < oval.length && !admitted; kI++) {
174
+ // Sibling alternatives only: a pref member cannot admit
175
+ // its own override (post-rankPrefs at most one pref
176
+ // stands at this level, so this is defensive).
177
+ admitted = kI !== gI && !oval[kI].isNil &&
178
+ !(this.peg[kI] as any).isPref
179
+ }
180
+ if (!admitted) {
181
+ const admitErr: any[] = []
182
+ ctx.err = admitErr
183
+ // The trial is against a CLONE: the preferred value must
184
+ // stay pristine for the surviving preference (the
185
+ // MatchFuncVal.resolve precedent).
186
+ const met = unite(ctx,
187
+ prefInnerPeg(this.peg[gI] as PrefVal).clone(ctx), peer,
188
+ 'dj-admit')
189
+ if (0 < admitErr.length || met.isNil) {
190
+ oval[gI] = TRIAL_NIL
191
+ }
192
+ }
193
+ }
194
+ }
123
195
  }
124
196
  finally {
125
197
  ctx._trialMode = savedTrialMode
126
198
  ctx.err = savedErr
199
+ ;(ctx as any).referflows = savedFlows
127
200
  }
128
201
 
129
202
  // // // console.log('DISJUNCT-unify-B', this.id, oval.map(v => v.canon))
130
203
 
204
+ // A PREFERENCE CONJOINED WITH A DISJUNCTION IS A PREFERENCE ON THE
205
+ // ALTERNATIVE IT NAMES: `(A|B) & *A` is `*A|B`, the same value the
206
+ // direct spelling `*A|B` denotes. Distribution carries the peer to
207
+ // each member, and a scalar preference meeting a concrete same-kind
208
+ // member is replaced BY that member (the kind gate) -- so the
209
+ // preference simply vanished, and `specversion: ("1.0"|"1.1") &
210
+ // *"1.0"`, the enum-with-default written the other way round, held
211
+ // no default at all. The old generation fold hid it by folding the
212
+ // members together; ADR-007 does not, and a disjunction that has
213
+ // lost its default is not the value the author wrote.
214
+ //
215
+ // A preference naming no alternative is dropped, as it is today: it
216
+ // has nothing to prefer, and the default-validity lint is what
217
+ // reports that shape.
218
+ if (true === (peer as any).isPref) {
219
+ const want: any = prefInnerPeg(peer as PrefVal)
220
+ for (let vI = 0; vI < oval.length; vI++) {
221
+ const got: any = oval[vI]
222
+ if (!got.isNil && true !== got.isPref && got.same(want)) {
223
+ const wrapped = new PrefVal({ peg: got }, ctx)
224
+ wrapped.rank = (peer as PrefVal).rank
225
+ ;(peer as PrefVal).place(wrapped)
226
+ oval[vI] = wrapped
227
+ }
228
+ }
229
+ }
230
+
131
231
  // Remove duplicates, and normalize
132
232
  if (1 < oval.length) {
133
233
  for (let vI = 0; vI < oval.length; vI++) {
@@ -145,25 +245,80 @@ class DisjunctVal extends JunctionVal {
145
245
  for (let kI = vI + 1; kI < oval.length; kI++) {
146
246
  if (oval[kI].same(oval[vI])) {
147
247
  oval[kI] = TRIAL_NIL
248
+ continue
249
+ }
250
+
251
+ // TWO PREFERENCES OVER ONE VALUE ARE ONE PREFERENCE, and
252
+ // the lower rank is the one that generates: `*1 | **1` is
253
+ // `*1`. Ranking folds EQUAL ranks (R2); this folds the rest,
254
+ // which R5 stopped discarding.
255
+ //
256
+ // A PLAIN arm holding that same value is NOT a duplicate of
257
+ // it and must not be folded away: it is the sibling that
258
+ // ADMITS an override under ADR-004's gate, which is the
259
+ // whole point of writing `*x | x`. Folding it turned that
260
+ // idiom's own default into a `pref_not_instance` finding,
261
+ // and `*top | top` is pinned as its control.
262
+ const a: any = oval[vI]
263
+ const b: any = oval[kI]
264
+ if (true === a.isPref && true === b.isPref
265
+ && prefInnerPeg(a).same(prefInnerPeg(b))) {
266
+ if ((a as PrefVal).rank <= (b as PrefVal).rank) {
267
+ oval[kI] = TRIAL_NIL
268
+ }
269
+ else {
270
+ oval[vI] = TRIAL_NIL
271
+ break
272
+ }
148
273
  }
149
274
  }
150
275
  }
151
276
 
152
277
  // // // console.log('DISJUNCT-unify-D', this.id, oval.map(v => v.canon))
278
+ }
153
279
 
154
- oval = oval.filter(v => !v.isNil)
280
+ // THE SURVIVORS' FLOWS, AND ONLY THEIRS. Members knocked out by
281
+ // the trial, by the admission gate or by the dedup above are all
282
+ // nil here, so this runs after every one of those and before the
283
+ // filter that drops them.
284
+ if (undefined !== savedFlows) {
285
+ for (let vI = 0; vI < staged.length; vI++) {
286
+ const st = staged[vI]
287
+ if (undefined === st || true === oval[vI]?.isNil) {
288
+ continue
289
+ }
290
+ for (const [k, fv] of st) {
291
+ const prev = savedFlows.get(k)
292
+ savedFlows.set(k, undefined === prev ? fv
293
+ : unite(ctx, prev, fv, 'refer-flow-record'))
294
+ }
295
+ }
155
296
  }
156
297
 
298
+ // Outside the 1<length block: a SINGLE-member disjunction (e.g. a
299
+ // rankPrefs collapse) whose one member fails the trial or the
300
+ // admission gate must reach the `empty` refusal below, not
301
+ // return the trial sentinel as if it were the answer.
302
+ oval = oval.filter(v => !v.isNil)
303
+
157
304
  let out: Val
158
305
 
159
306
  if (1 == oval.length) {
160
307
  out = oval[0]
161
308
  }
162
309
  else if (0 == oval.length) {
163
- return makeNilErr(ctx, '|:empty', this, peer)
310
+ return makeNilErr(ctx, 'empty', this, peer)
164
311
  }
165
312
  else {
166
313
  out = new DisjunctVal({ peg: oval }, ctx)
314
+ // A NARROWED DISJUNCTION IS STILL THAT DISJUNCTION. The meet mints
315
+ // a fresh value, which used to arrive unsited and file-less -- so
316
+ // every finding naming a disjunction that had met anything
317
+ // pointed at row -1 with no file, and an agent handed the report
318
+ // had nowhere to go (the review's finding F). `place` copies the
319
+ // whole site, position and url together, which is what tells the
320
+ // report which document it came from.
321
+ this.place(out)
167
322
  }
168
323
 
169
324
  out.dc = done ? DONE : this.dc + 1
@@ -177,48 +332,61 @@ class DisjunctVal extends JunctionVal {
177
332
  }
178
333
 
179
334
 
180
- rankPrefs(ctx: AontuContext) {
181
- let lastpref: PrefVal | undefined = undefined
182
- let lastprefI = -1
335
+ // RANK ORDERS THE SURVIVORS, IT DOES NOT DISCARD AT PARSE (ADR-011
336
+ // R5, docs/design/DEFAULTS.0.md). Every rank is KEPT here, and
337
+ // generation takes the lowest-rank preference still standing -- so
338
+ // eliminating the lower arm PROMOTES the next instead of taking the
339
+ // whole ladder with it. This ran once, before the member trials,
340
+ // and discarded every arm but the lowest: `*1 | **2` met by
341
+ // `neq(1)` lost the default entirely and refused, where the ladder
342
+ // exists precisely to answer 2. Rank is a preference order over
343
+ // WHAT SURVIVES, which is not knowable until the trials have run.
344
+ //
345
+ // Only EQUAL ranks fold, because two defaults at one rank are one
346
+ // decision: compatible pegs merge, and a disagreement is the
347
+ // `pref_rank_clash` refusal (R2), which belongs to the whole
348
+ // disjunction -- there is no alternative to fall back to.
349
+ //
350
+ // Answers the sole surviving preference when the disjunction holds
351
+ // exactly one -- which the RECURSIVE call below consumes to lift a
352
+ // nested disjunct's winner into this one -- or the clash refusal.
353
+ rankPrefs(ctx: AontuContext): Val | undefined {
354
+ // The kept index per rank, so an equal-rank twin folds into the
355
+ // arm already standing for that rank.
356
+ const atRank: Record<number, number> = {}
183
357
 
184
358
  // // // console.log('RP-A', this.peg.map((p: Val) => p.canon))
185
359
 
186
360
  for (let vI = 0; vI < this.peg.length; vI++) {
187
361
  const v = this.peg[vI]
362
+ let pref: PrefVal | undefined = undefined
363
+
188
364
  if (v instanceof PrefVal) {
189
- if (null != lastpref) {
190
- if (v.rank === lastpref.rank) {
191
- const pref = v.unify(lastpref, ctx) as PrefVal
192
- if (pref.isNil) {
193
- return pref
194
- }
195
- else {
196
- this.peg[lastprefI] = pref
197
- lastpref = pref
198
- this.peg[vI] = null
199
- }
200
- // return Nil.make(ctx, '|:prefs', lastpref, v, 'associate')
201
- }
202
- else if (v.rank < lastpref.rank) {
203
- this.peg[lastprefI] = null
204
- lastpref = v
205
- lastprefI = vI
206
- }
207
- else {
208
- this.peg[vI] = null
209
- }
210
- }
211
- else {
212
- lastpref = v
213
- lastprefI = vI
214
- }
365
+ pref = v
215
366
  }
216
367
  else if (v.isDisjunct) {
217
- let subrank: any = v.rankPrefs(ctx)
368
+ const subrank = (v as DisjunctVal).rankPrefs(ctx)
369
+ if (null != subrank && subrank.isNil) {
370
+ return subrank
371
+ }
218
372
  if (subrank instanceof PrefVal) {
219
373
  this.peg[vI] = subrank
220
- lastpref = subrank
221
- lastprefI = vI
374
+ pref = subrank
375
+ }
376
+ }
377
+
378
+ if (undefined !== pref) {
379
+ const at = atRank[pref.rank]
380
+ if (undefined === at) {
381
+ atRank[pref.rank] = vI
382
+ }
383
+ else {
384
+ const folded = pref.unify(this.peg[at], ctx)
385
+ if (folded.isNil) {
386
+ return folded
387
+ }
388
+ this.peg[at] = folded
389
+ this.peg[vI] = null
222
390
  }
223
391
  }
224
392
  }
@@ -231,6 +399,8 @@ class DisjunctVal extends JunctionVal {
231
399
  if (1 === this.peg.length && this.peg[0] instanceof PrefVal) {
232
400
  return this.peg[0]
233
401
  }
402
+
403
+ return undefined
234
404
  }
235
405
 
236
406
 
@@ -246,35 +416,88 @@ class DisjunctVal extends JunctionVal {
246
416
  }
247
417
 
248
418
 
419
+ // AN UNRESOLVED DISJUNCTION IS NOT A VALUE (ADR-007).
420
+ //
421
+ // Generation used to FOLD the surviving members together with unify
422
+ // and emit the result. That answer is in no branch of the
423
+ // disjunction: `({x:1}|{y:2}) & {z:3}` generated `{x:1,y:2,z:3}`, a
424
+ // map the model never admits, and `1|2` died as a scalar_value
425
+ // CONFLICT -- the conflict of the fold, not of anything the author
426
+ // wrote. The second half is what made vet decorative: vet's
427
+ // incompleteness check keeps incomplete-class findings, so a missing
428
+ // required enum field (`role: 'a'|'b'` with no data) arrived as a
429
+ // conflict, was filtered out, and vetted VALID with zero findings
430
+ // (use-cases/BUGS.md §13, the review's finding C).
431
+ //
432
+ // What remains after unification is what the model still admits, so
433
+ // more than one surviving alternative means the truth is not yet
434
+ // settled -- incomplete, the same class a bare `string` residue
435
+ // answers, and the same answer CUE gives for a non-concrete export.
436
+ // A preference resolves it (that is what `*` is for), and so does a
437
+ // single surviving member.
249
438
  gen(ctx: AontuContext) {
250
- // TODO: move this to main unify
251
-
252
- // console.log('DJ-GEN', this.peg.map((p: any) => p.canon), ctx.err)
253
-
254
439
  if (0 < this.peg.length) {
440
+ // Ranking may not have run when gen is reached without a prior
441
+ // unify (a library caller generating a freshly parsed tree), and
442
+ // it is what guarantees at most one preference stands here.
443
+ if (!this.prefsRanked) {
444
+ this.rankPrefs(ctx)
445
+ }
255
446
 
256
- let vals = this.peg.filter((v: Val) => v instanceof PrefVal)
257
- // // // console.log('DJ-GEN-VALS-A', vals.map((p: any) => p.canon))
447
+ const prefs = this.peg.filter((v: Val) => v instanceof PrefVal)
448
+
449
+ // ALTERNATIVES THAT GENERATE THE SAME VALUE ARE RESOLVED
450
+ // (ADR-007's rule, asked at the moment it matters): `[] | [&:
451
+ // T]` met by an empty list keeps both arms -- they differ as
452
+ // SCHEMAS, which is what stops the dedup collapsing the
453
+ // template away (BUGS.md §52 regime 4) -- but both generate
454
+ // the empty list, and one generated value is one value.
455
+ if (0 === prefs.length && 1 < this.peg.length) {
456
+ const gctx = ctx.clone({ err: [], collect: true })
457
+ let firstOut: any
458
+ let allSame = true
459
+ for (let gI = 0; gI < this.peg.length && allSame; gI++) {
460
+ const gout = this.peg[gI].gen(gctx)
461
+ if (0 < gctx.err.length || undefined === gout) {
462
+ allSame = false
463
+ }
464
+ else if (0 === gI) {
465
+ firstOut = gout
466
+ }
467
+ else {
468
+ allSame = exactJSON(gout) === exactJSON(firstOut)
469
+ }
470
+ }
471
+ if (allSame) {
472
+ return firstOut
473
+ }
474
+ }
258
475
 
259
- vals = 0 === vals.length ? this.peg : vals
476
+ if (0 === prefs.length && 1 < this.peg.length) {
477
+ const nerr = makeNilErr(ctx, 'disjunct_no_gen', this)
478
+ descErr(nerr, ctx)
479
+ ctx?.adderr(nerr)
260
480
 
261
- let val = vals[0]
481
+ if (null == ctx || !ctx.collect) {
482
+ throw new AontuError(nerr.msg, [nerr])
483
+ }
262
484
 
263
- // TODO: over unifies complex types like maps
264
- // ({x:1}|{y:2})&{z:3} should be {"x":1,"z":3}|{"y":2,"z":3} not { x:1, z:3, y:2 }
265
- for (let vI = 1; vI < vals.length; vI++) {
266
- // Index `vals`, not `this.peg`: when the pref members are not the
267
- // leading entries the two arrays differ, and folding against
268
- // this.peg[vI] would unify the wrong (or a repeated) member.
269
- let valnext = val.unify(vals[vI], ctx)
270
- // // // console.log('DJ-GEN-VALS-NEXT', valnext.canon)
271
- val = valnext
485
+ return undefined
272
486
  }
273
487
 
274
- // console.log('DJ-GEN-VALS-B', val.canon)
275
- const out = val.gen(ctx)
276
- // console.log('DJ-GEN-VALS-C', out)
277
- return out
488
+ // THE LOWEST-RANK SURVIVOR (R5). Ranking no longer discards the
489
+ // weaker arms, so the choice is made here, over what is left:
490
+ // `*1 | **2` answers 1, and answers 2 once `*1` is gone.
491
+ let best: any = this.peg[0]
492
+ if (0 < prefs.length) {
493
+ best = prefs[0]
494
+ for (const p of prefs) {
495
+ if ((p as PrefVal).rank < best.rank) {
496
+ best = p
497
+ }
498
+ }
499
+ }
500
+ return best.gen(ctx)
278
501
  }
279
502
 
280
503
  return super.gen(ctx)
@@ -0,0 +1,133 @@
1
+ /* Copyright (c) 2025 Richard Rodger, MIT License */
2
+
3
+ // GENERATION: `each(data, tmpl)` (G8 phase 1,
4
+ // docs/capability-review/g8-generation.md). One element of the result
5
+ // list per child of `data`, each of them that child met with `tmpl`.
6
+ // Written with one argument, `each(m)` is a map's children as a list.
7
+ //
8
+ // ports: {http: 80, https: 443}
9
+ // open: each($.ports, integer) -> [80, 443]
10
+ //
11
+ // ORDER IS FIXED, and fixed the way canon already fixes it: source
12
+ // order for a list, sorted-key order for a map (`cmpCodePoint`, the
13
+ // comparator `MapVal.canon` and the Go port's marshalling use). A
14
+ // generated list whose order depended on insertion history would differ
15
+ // between two runs of the same document, and between the two ports --
16
+ // the one thing the shared spec exists to prevent.
17
+ //
18
+ // The element is the source child CLONED, not shared: it is a second
19
+ // position holding that value, and a position is where path-dependent
20
+ // content resolves. What the clone keeps is the identity, if the child
21
+ // carries one (G4 phase 1) -- a listed entity is still that entity, and
22
+ // the merge that follows is the point.
23
+
24
+ import type {
25
+ Val,
26
+ ValSpec,
27
+ } from '../type'
28
+
29
+ import {
30
+ AontuContext,
31
+ } from '../ctx'
32
+
33
+ import { unite } from '../unify'
34
+ import { makeNilErr } from '../err'
35
+ import { ListVal } from './ListVal'
36
+ import { FuncBaseVal } from './FuncBaseVal'
37
+ import { repathInstance } from './Val'
38
+ import { fillPlace } from './PlaceVal'
39
+ import { cmpCodePoint } from '../keyorder'
40
+
41
+
42
+ // The children a data bag holds, in the order the result must carry
43
+ // them, or the code naming what is wrong with the argument.
44
+ function dataValues(data: Val | undefined): Val[] | string {
45
+ const d: any = data
46
+
47
+ if (true === d?.isMap) {
48
+ return Object.keys(d.peg).sort(cmpCodePoint).map((k: string) => d.peg[k])
49
+ }
50
+
51
+ if (true === d?.isList) {
52
+ return [...(d.peg as Val[])]
53
+ }
54
+
55
+ return 'each_data'
56
+ }
57
+
58
+
59
+ class EachFuncVal extends FuncBaseVal {
60
+ isEachFunc = true
61
+
62
+ // THE STAGING RULE, for the reason given in PackFuncVal.
63
+ staged = true
64
+
65
+ constructor(
66
+ spec: ValSpec,
67
+ ctx?: AontuContext
68
+ ) {
69
+ super(spec, ctx)
70
+ }
71
+
72
+
73
+
74
+ funcname() {
75
+ return 'each'
76
+ }
77
+
78
+
79
+ // The template is not an argument to drive (see PackFuncVal.prepare).
80
+ prepare(_ctx: AontuContext, _args: Val[]) {
81
+ return null
82
+ }
83
+
84
+
85
+ unify(peer: Val, ctx: AontuContext): Val {
86
+ // ONE argument is driven: the data. The template is not (see
87
+ // prepare above), and driveStagedArgs answers whether the data has
88
+ // settled -- the other half of "ready to fire".
89
+ const ready = this.driveStagedArgs(ctx, 1)
90
+
91
+ if (!ready || !ctx.settle) {
92
+ return this.residuate(peer, ctx)
93
+ }
94
+
95
+ return super.unify(peer, ctx)
96
+ }
97
+
98
+
99
+ resolve(ctx: AontuContext, args: Val[]) {
100
+ const vals = dataValues(args?.[0])
101
+ if ('string' === typeof vals) {
102
+ return makeNilErr(ctx, vals, this)
103
+ }
104
+
105
+ const tmpl: Val | undefined = args?.[1]
106
+ const peg: Val[] = []
107
+
108
+ for (let i = 0; i < vals.length; i++) {
109
+ const elctx = ctx.descend(String(i))
110
+ const el = vals[i].clone(elctx)
111
+ // The template is CLONED per element, never shared — a FULL
112
+ // instance to the leaves (`dup`, ADR-005): see PackFuncVal.resolve.
113
+ // `_` inside the template binds the source child (G8 phase 3),
114
+ // which for `each` is the element itself.
115
+ let inst: Val | undefined = undefined
116
+ if (undefined !== tmpl) {
117
+ inst = tmpl.clone(elctx, { dup: true })
118
+ repathInstance(inst, inst.path)
119
+ }
120
+ peg.push(undefined === inst ? el :
121
+ unite(elctx, el, fillPlace(inst, vals[i], elctx), 'each'))
122
+ }
123
+
124
+ return new ListVal({ peg }, ctx)
125
+ }
126
+
127
+ } /* node:coverage ignore next 7 */
128
+
129
+
130
+ export {
131
+ dataValues,
132
+ EachFuncVal,
133
+ }