aontu 0.52.1 → 0.53.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 (272) 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 +14 -3
  7. package/dist/aontu.js +96 -4
  8. package/dist/aontu.js.map +1 -1
  9. package/dist/cli.d.ts +44 -1
  10. package/dist/cli.js +2401 -44
  11. package/dist/cli.js.map +1 -1
  12. package/dist/ctx.d.ts +13 -0
  13. package/dist/ctx.js +43 -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 +38 -7
  20. package/dist/err.js.map +1 -1
  21. package/dist/graph.d.ts +16 -0
  22. package/dist/graph.js +73 -0
  23. package/dist/graph.js.map +1 -0
  24. package/dist/hcanon.d.ts +3 -0
  25. package/dist/hcanon.js +146 -0
  26. package/dist/hcanon.js.map +1 -0
  27. package/dist/hints.js +167 -4
  28. package/dist/hints.js.map +1 -1
  29. package/dist/jsonschema.d.ts +20 -0
  30. package/dist/jsonschema.js +391 -0
  31. package/dist/jsonschema.js.map +1 -0
  32. package/dist/lang.js +512 -69
  33. package/dist/lang.js.map +1 -1
  34. package/dist/lsp.d.ts +9 -2
  35. package/dist/lsp.js +262 -47
  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 +814 -0
  42. package/dist/mcp.js.map +1 -0
  43. package/dist/mod-tool.d.ts +58 -0
  44. package/dist/mod-tool.js +498 -0
  45. package/dist/mod-tool.js.map +1 -0
  46. package/dist/mod.d.ts +31 -0
  47. package/dist/mod.js +250 -0
  48. package/dist/mod.js.map +1 -0
  49. package/dist/patch.d.ts +44 -0
  50. package/dist/patch.js +506 -0
  51. package/dist/patch.js.map +1 -0
  52. package/dist/provenance.d.ts +40 -0
  53. package/dist/provenance.js +335 -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 +14 -0
  59. package/dist/reach.js +140 -0
  60. package/dist/reach.js.map +1 -0
  61. package/dist/relation.d.ts +19 -0
  62. package/dist/relation.js +305 -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/site.d.ts +4 -0
  68. package/dist/site.js +31 -0
  69. package/dist/site.js.map +1 -1
  70. package/dist/std.d.ts +1 -0
  71. package/dist/std.js +73 -0
  72. package/dist/std.js.map +1 -0
  73. package/dist/subsume.d.ts +39 -0
  74. package/dist/subsume.js +526 -0
  75. package/dist/subsume.js.map +1 -0
  76. package/dist/trim.d.ts +19 -0
  77. package/dist/trim.js +155 -0
  78. package/dist/trim.js.map +1 -0
  79. package/dist/tsconfig.tsbuildinfo +1 -1
  80. package/dist/type.d.ts +17 -1
  81. package/dist/type.js.map +1 -1
  82. package/dist/unify.d.ts +2 -1
  83. package/dist/unify.js +253 -36
  84. package/dist/unify.js.map +1 -1
  85. package/dist/utility.d.ts +9 -1
  86. package/dist/utility.js +122 -1
  87. package/dist/utility.js.map +1 -1
  88. package/dist/val/AggFuncVal.d.ts +33 -0
  89. package/dist/val/AggFuncVal.js +202 -0
  90. package/dist/val/AggFuncVal.js.map +1 -0
  91. package/dist/val/ArithFuncVal.d.ts +31 -0
  92. package/dist/val/ArithFuncVal.js +62 -0
  93. package/dist/val/ArithFuncVal.js.map +1 -0
  94. package/dist/val/BagVal.d.ts +5 -0
  95. package/dist/val/BagVal.js +96 -5
  96. package/dist/val/BagVal.js.map +1 -1
  97. package/dist/val/CloseFuncVal.js +9 -1
  98. package/dist/val/CloseFuncVal.js.map +1 -1
  99. package/dist/val/ConjunctVal.d.ts +1 -1
  100. package/dist/val/ConjunctVal.js +19 -0
  101. package/dist/val/ConjunctVal.js.map +1 -1
  102. package/dist/val/ConstraintVal.d.ts +7 -1
  103. package/dist/val/ConstraintVal.js +490 -40
  104. package/dist/val/ConstraintVal.js.map +1 -1
  105. package/dist/val/CopyFuncVal.d.ts +1 -2
  106. package/dist/val/CopyFuncVal.js +7 -0
  107. package/dist/val/CopyFuncVal.js.map +1 -1
  108. package/dist/val/Decimal.d.ts +1 -0
  109. package/dist/val/Decimal.js +13 -0
  110. package/dist/val/Decimal.js.map +1 -1
  111. package/dist/val/DeprecateFuncVal.d.ts +11 -0
  112. package/dist/val/DeprecateFuncVal.js +47 -0
  113. package/dist/val/DeprecateFuncVal.js.map +1 -0
  114. package/dist/val/DisjunctVal.js +130 -21
  115. package/dist/val/DisjunctVal.js.map +1 -1
  116. package/dist/val/EachFuncVal.d.ts +15 -0
  117. package/dist/val/EachFuncVal.js +75 -0
  118. package/dist/val/EachFuncVal.js.map +1 -0
  119. package/dist/val/ExpectVal.js +27 -4
  120. package/dist/val/ExpectVal.js.map +1 -1
  121. package/dist/val/FeatureVal.js +1 -1
  122. package/dist/val/FeatureVal.js.map +1 -1
  123. package/dist/val/FilterFuncVal.d.ts +15 -0
  124. package/dist/val/FilterFuncVal.js +91 -0
  125. package/dist/val/FilterFuncVal.js.map +1 -0
  126. package/dist/val/FuncBaseVal.d.ts +6 -1
  127. package/dist/val/FuncBaseVal.js +171 -1
  128. package/dist/val/FuncBaseVal.js.map +1 -1
  129. package/dist/val/HideFuncVal.js.map +1 -1
  130. package/dist/val/IdFuncVal.d.ts +13 -0
  131. package/dist/val/IdFuncVal.js +54 -0
  132. package/dist/val/IdFuncVal.js.map +1 -0
  133. package/dist/val/JunctionVal.js +7 -1
  134. package/dist/val/JunctionVal.js.map +1 -1
  135. package/dist/val/KeyFuncVal.d.ts +1 -1
  136. package/dist/val/KeyFuncVal.js +38 -30
  137. package/dist/val/KeyFuncVal.js.map +1 -1
  138. package/dist/val/ListVal.js +101 -14
  139. package/dist/val/ListVal.js.map +1 -1
  140. package/dist/val/LowerFuncVal.js.map +1 -1
  141. package/dist/val/MapVal.js +93 -8
  142. package/dist/val/MapVal.js.map +1 -1
  143. package/dist/val/MatchFuncVal.d.ts +15 -0
  144. package/dist/val/MatchFuncVal.js +107 -0
  145. package/dist/val/MatchFuncVal.js.map +1 -0
  146. package/dist/val/MoveFuncVal.js.map +1 -1
  147. package/dist/val/NilVal.js +24 -0
  148. package/dist/val/NilVal.js.map +1 -1
  149. package/dist/val/OpBaseVal.d.ts +1 -1
  150. package/dist/val/OpBaseVal.js +19 -1
  151. package/dist/val/OpBaseVal.js.map +1 -1
  152. package/dist/val/OpenFuncVal.js +4 -1
  153. package/dist/val/OpenFuncVal.js.map +1 -1
  154. package/dist/val/PackFuncVal.d.ts +15 -0
  155. package/dist/val/PackFuncVal.js +108 -0
  156. package/dist/val/PackFuncVal.js.map +1 -0
  157. package/dist/val/PathFuncVal.js.map +1 -1
  158. package/dist/val/PlaceVal.d.ts +13 -0
  159. package/dist/val/PlaceVal.js +131 -0
  160. package/dist/val/PlaceVal.js.map +1 -0
  161. package/dist/val/PlusOpVal.js +11 -2
  162. package/dist/val/PlusOpVal.js.map +1 -1
  163. package/dist/val/PrefFuncVal.js.map +1 -1
  164. package/dist/val/PrefVal.d.ts +2 -2
  165. package/dist/val/PrefVal.js +78 -23
  166. package/dist/val/PrefVal.js.map +1 -1
  167. package/dist/val/RefVal.d.ts +1 -1
  168. package/dist/val/RefVal.js +89 -7
  169. package/dist/val/RefVal.js.map +1 -1
  170. package/dist/val/ReferFuncVal.d.ts +36 -0
  171. package/dist/val/ReferFuncVal.js +303 -0
  172. package/dist/val/ReferFuncVal.js.map +1 -0
  173. package/dist/val/ScalarKindVal.d.ts +1 -2
  174. package/dist/val/ScalarKindVal.js +0 -11
  175. package/dist/val/ScalarKindVal.js.map +1 -1
  176. package/dist/val/TopVal.js.map +1 -1
  177. package/dist/val/TypeFuncVal.js.map +1 -1
  178. package/dist/val/UpperFuncVal.js.map +1 -1
  179. package/dist/val/Val.d.ts +8 -1
  180. package/dist/val/Val.js +150 -1
  181. package/dist/val/Val.js.map +1 -1
  182. package/dist/val/VarVal.js.map +1 -1
  183. package/dist/val/arith.d.ts +6 -0
  184. package/dist/val/arith.js +170 -0
  185. package/dist/val/arith.js.map +1 -0
  186. package/dist/vet.d.ts +45 -0
  187. package/dist/vet.js +776 -0
  188. package/dist/vet.js.map +1 -0
  189. package/dist/walk.d.ts +2 -0
  190. package/dist/walk.js +91 -0
  191. package/dist/walk.js.map +1 -0
  192. package/grammar/aontu.gbnf +130 -0
  193. package/grammar/aontu.lark +113 -0
  194. package/package.json +21 -6
  195. package/skill/SKILL.md +37 -0
  196. package/skill/error-codes.md +62 -0
  197. package/skill/examples.md +99 -0
  198. package/skill/grammar-card.md +57 -0
  199. package/src/agentsmd.ts +135 -0
  200. package/src/aontu.ts +135 -4
  201. package/src/cli.ts +2858 -71
  202. package/src/ctx.ts +73 -1
  203. package/src/diff.ts +196 -0
  204. package/src/err.ts +42 -7
  205. package/src/graph.ts +135 -0
  206. package/src/hcanon.ts +169 -0
  207. package/src/hints.ts +208 -4
  208. package/src/jsonschema.ts +511 -0
  209. package/src/lang.ts +570 -70
  210. package/src/lsp.ts +281 -48
  211. package/src/mcp-server.ts +187 -0
  212. package/src/mcp.ts +993 -0
  213. package/src/mod-tool.ts +679 -0
  214. package/src/mod.ts +344 -0
  215. package/src/patch.ts +624 -0
  216. package/src/provenance.ts +430 -0
  217. package/src/query.ts +379 -0
  218. package/src/reach.ts +184 -0
  219. package/src/relation.ts +395 -0
  220. package/src/report-sarif.ts +137 -0
  221. package/src/site.ts +36 -1
  222. package/src/std.ts +73 -0
  223. package/src/subsume.ts +690 -0
  224. package/src/trim.ts +195 -0
  225. package/src/tsconfig.json +10 -4
  226. package/src/type.ts +51 -2
  227. package/src/unify.ts +274 -36
  228. package/src/utility.ts +139 -1
  229. package/src/val/AggFuncVal.ts +319 -0
  230. package/src/val/ArithFuncVal.ts +108 -0
  231. package/src/val/BagVal.ts +101 -4
  232. package/src/val/CloseFuncVal.ts +9 -1
  233. package/src/val/ConjunctVal.ts +20 -0
  234. package/src/val/ConstraintVal.ts +542 -43
  235. package/src/val/CopyFuncVal.ts +7 -1
  236. package/src/val/Decimal.ts +15 -0
  237. package/src/val/DeprecateFuncVal.ts +84 -0
  238. package/src/val/DisjunctVal.ts +139 -28
  239. package/src/val/EachFuncVal.ts +133 -0
  240. package/src/val/ExpectVal.ts +28 -6
  241. package/src/val/FeatureVal.ts +1 -1
  242. package/src/val/FilterFuncVal.ts +154 -0
  243. package/src/val/FuncBaseVal.ts +192 -1
  244. package/src/val/HideFuncVal.ts +0 -2
  245. package/src/val/IdFuncVal.ts +91 -0
  246. package/src/val/JunctionVal.ts +7 -1
  247. package/src/val/KeyFuncVal.ts +39 -35
  248. package/src/val/ListVal.ts +108 -15
  249. package/src/val/LowerFuncVal.ts +0 -1
  250. package/src/val/MapVal.ts +99 -8
  251. package/src/val/MatchFuncVal.ts +176 -0
  252. package/src/val/MoveFuncVal.ts +0 -2
  253. package/src/val/NilVal.ts +25 -0
  254. package/src/val/OpBaseVal.ts +20 -1
  255. package/src/val/OpenFuncVal.ts +4 -2
  256. package/src/val/PackFuncVal.ts +175 -0
  257. package/src/val/PathFuncVal.ts +0 -1
  258. package/src/val/PlaceVal.ts +193 -0
  259. package/src/val/PlusOpVal.ts +11 -2
  260. package/src/val/PrefFuncVal.ts +0 -1
  261. package/src/val/PrefVal.ts +79 -36
  262. package/src/val/RefVal.ts +91 -8
  263. package/src/val/ReferFuncVal.ts +387 -0
  264. package/src/val/ScalarKindVal.ts +0 -13
  265. package/src/val/TopVal.ts +0 -1
  266. package/src/val/TypeFuncVal.ts +0 -2
  267. package/src/val/UpperFuncVal.ts +0 -1
  268. package/src/val/Val.ts +205 -2
  269. package/src/val/VarVal.ts +0 -1
  270. package/src/val/arith.ts +316 -0
  271. package/src/vet.ts +992 -0
  272. package/src/walk.ts +99 -0
@@ -0,0 +1,335 @@
1
+ "use strict";
2
+ /* Copyright (c) 2025 Richard Rodger, MIT License */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.Provenance = exports.INNER_OF = exports.WRITTEN = exports.FROM_SPREAD = void 0;
5
+ exports.markSpread = markSpread;
6
+ // Set on a spread template's per-key clone, at the one place a spread
7
+ // is applied (MapVal/ListVal.unify). Nothing else reads it.
8
+ exports.FROM_SPREAD = '_fromSpread';
9
+ // THE AUTHORED MARK, and it is a property of the VALUE rather than a
10
+ // set of ids held beside it (the review's finding E). A contribution
11
+ // is a value the author wrote, and the recorder used to decide that by
12
+ // looking the operand's id up in a set stamped over the parsed tree --
13
+ // which is true of the parsed tree and of nothing derived from it. So
14
+ // every value that reached a path through a CLONE was dark: a default
15
+ // flowing into a `pack()`-generated child, a shape carried by a `$ref`,
16
+ // one side of an id()-merge. `why` answered "(no contributions:
17
+ // nothing met at this path)" over a value it had just printed, with
18
+ // exit 0 -- a false statement, and the one an audit surface may not
19
+ // make (use-cases/BUGS.md §23, §24).
20
+ //
21
+ // A clone of a written value IS that written value, re-instantiated
22
+ // somewhere else: it carries the author's site, so it can be pointed
23
+ // at. Val.clone therefore carries this mark, exactly as it carries the
24
+ // site -- provenance is part of the clone contract, not a recorder
25
+ // bolted beside it. Values the engine MINTS (a kind lifted while a
26
+ // disjunct trials its members, a fold's intermediate) are constructed
27
+ // rather than cloned and stay unmarked, which is what keeps the record
28
+ // to what the author can edit.
29
+ //
30
+ // The mark is only ever SET by an instrumented run (`why` calls
31
+ // writtenFrom; nothing else does), so an ordinary evaluation pays one
32
+ // undefined property read per clone.
33
+ exports.WRITTEN = '_written';
34
+ // THE CONTAINER A VALUE IS PART OF, when the two stand at the SAME
35
+ // path: a junction's members, a preference's inner value, a function's
36
+ // arguments, an operator's operands. `*1|integer` is one thing the
37
+ // author wrote, and `*1` is not a second thing beside it.
38
+ //
39
+ // The recorder already knew that where the container itself met
40
+ // something -- contributing it marked its members `inside` and the
41
+ // filter dropped them. But the container only appears as an operand
42
+ // when the fixpoint happens to meet it whole; where it resolves
43
+ // member-wise instead (a later sibling of a spread, a default reaching
44
+ // a generated child) the members arrived alone and the record split
45
+ // one written value into two contributions at two columns. Which
46
+ // happened was decided by evaluation order, so `why` answered
47
+ // differently for identical statements (use-cases/BUGS.md §22).
48
+ //
49
+ // So the relation is recorded as a fact about the DOCUMENT, at
50
+ // stamping time, and an operand is reported as the outermost written
51
+ // value it is part of. NOT set for a bag's children (they stand at
52
+ // their own, deeper paths) nor for a conjunct's terms (a conjunct is
53
+ // the statement that several things must all hold, and each term is
54
+ // one of them -- which is exactly what the author needs shown).
55
+ exports.INNER_OF = '_innerOf';
56
+ // Mark a spread clone and everything inside it, so a contribution
57
+ // several levels down a template is still known to have come from the
58
+ // template. ONLY on an instrumented run: the walk is O(template) per
59
+ // key per pass, which is real money on a large model and buys nothing
60
+ // when no one is recording.
61
+ //
62
+ // THE GUARD IS A CYCLE GUARD, NOT A "DONE" FLAG, and that distinction
63
+ // is the whole of the review's finding E for sibling position. A
64
+ // template is applied once per destination, and the fixpoint advances
65
+ // values IN PLACE between those applications (AGENTS.md, the mutation
66
+ // caveat): by the time the second key is spread, the template's
67
+ // `replicas` child is no longer the disjunction the first key saw but
68
+ // the value that meet produced. Skipping the walk because the
69
+ // CONTAINER was already marked left every one of those replacements
70
+ // unmarked, so `why` at the first sibling reported the written
71
+ // `*1|integer` as one contribution and at the second reported `*1` and
72
+ // `integer` as two -- identical statements, different answers, decided
73
+ // by which key the fixpoint reached first (use-cases/BUGS.md §22).
74
+ // Marking is idempotent, so re-walking costs a pass and changes
75
+ // nothing where nothing moved.
76
+ function markSpread(v, seen) {
77
+ const marked = seen ?? new Set();
78
+ if (null == v || true !== v.isVal || marked.has(v)) {
79
+ return;
80
+ }
81
+ marked.add(v);
82
+ v[exports.FROM_SPREAD] = true;
83
+ if (true === v.isMap && null != v.peg) {
84
+ for (const k of Object.keys(v.peg)) {
85
+ markSpread(v.peg[k], marked);
86
+ }
87
+ }
88
+ else if (true === v.isList && null != v.peg) {
89
+ for (const k of Object.keys(v.peg)) {
90
+ markSpread(v.peg[k], marked);
91
+ }
92
+ }
93
+ else if (Array.isArray(v.peg)) {
94
+ // A junction, a func's arguments, an op's operands: every one of
95
+ // them can hold the value that reaches the destination.
96
+ for (const m of v.peg) {
97
+ markSpread(m, marked);
98
+ }
99
+ }
100
+ else if (true === v.isPref) {
101
+ markSpread(v.peg, marked);
102
+ }
103
+ }
104
+ // The children that stand at the SAME path as v. See INNER_OF.
105
+ function samePathKids(v) {
106
+ if (true === v.isMap || true === v.isList || true === v.isConjunct) {
107
+ return [];
108
+ }
109
+ if (true === v.isPref) {
110
+ return null != v.peg && true === v.peg.isVal ? [v.peg] : [];
111
+ }
112
+ return Array.isArray(v.peg)
113
+ ? v.peg.filter((k) => null != k && true === k.isVal) : [];
114
+ }
115
+ // Order contributions the way the document reads: by file, then row,
116
+ // then column, with the canon as the last tiebreak so the order is
117
+ // total even for two values written at the same position (which a
118
+ // merged duplicate key can produce).
119
+ function cmpSite(a, b) {
120
+ return a.site.file.localeCompare(b.site.file) ||
121
+ a.site.row - b.site.row ||
122
+ a.site.col - b.site.col ||
123
+ a.canon.localeCompare(b.canon);
124
+ }
125
+ function roleOf(v) {
126
+ if (true === v[exports.FROM_SPREAD]) {
127
+ return 'spread';
128
+ }
129
+ if (true === v.isRef) {
130
+ return 'ref';
131
+ }
132
+ if (true === v.isPref) {
133
+ return 'pref';
134
+ }
135
+ return 'literal';
136
+ }
137
+ class Provenance {
138
+ constructor() {
139
+ this.paths = new Map();
140
+ // id -> the written container it names, for INNER_OF. The mark on a
141
+ // value is the container's ID rather than the container itself: a
142
+ // Val holding another Val as an own property is a reference cycle
143
+ // through the tree, and enough of the engine walks a value's own
144
+ // properties that one is not safe to introduce.
145
+ this.containers = new Map();
146
+ }
147
+ // Stamp the parsed tree with the AUTHORED mark: everything the
148
+ // author wrote, before unification starts. A value minted during
149
+ // unification — a kind lifted from a leaf while a disjunct trials
150
+ // its members, a fold's intermediate — is the engine's own work, not
151
+ // a contribution the author can be pointed at. A CLONE of a marked
152
+ // value keeps the mark (see WRITTEN above), because it is the same
153
+ // written value somewhere else. Called once, before unify, by `why`.
154
+ writtenFrom(v) {
155
+ if (null == v || true !== v.isVal || true === v[exports.WRITTEN]) {
156
+ return;
157
+ }
158
+ v[exports.WRITTEN] = true;
159
+ const kids = (true === v.isMap || true === v.isList) && null != v.peg
160
+ ? Object.keys(v.peg).map((k) => v.peg[k])
161
+ : Array.isArray(v.peg) ? v.peg
162
+ : null != v.peg && true === v.peg.isVal ? [v.peg]
163
+ : [];
164
+ for (const k of kids) {
165
+ this.writtenFrom(k);
166
+ }
167
+ // OUTERMOST WINS: the walk is top-down, so a value already pointed
168
+ // at a container is inside that one and this one, and the answer
169
+ // the author wants is the whole written statement.
170
+ for (const k of samePathKids(v)) {
171
+ if (null == k[exports.INNER_OF]) {
172
+ k[exports.INNER_OF] = v.id;
173
+ this.containers.set(v.id, v);
174
+ }
175
+ }
176
+ if (null != v.spread?.cj) {
177
+ this.writtenFrom(v.spread.cj);
178
+ }
179
+ }
180
+ // One meet. Both operands are candidate contributions; the result is
181
+ // remembered so a later meet does not mistake it for a source.
182
+ record(path, a, b, out) {
183
+ const key = path.join('.');
184
+ let rec = this.paths.get(key);
185
+ if (null == rec) {
186
+ rec = {
187
+ conjuncts: [], made: new Set(), seen: new Set(),
188
+ };
189
+ this.paths.set(key, rec);
190
+ }
191
+ this.contribute(rec, a);
192
+ this.contribute(rec, b);
193
+ if (null != out && true === out.isVal && out !== a && out !== b) {
194
+ rec.made.add(out.id);
195
+ }
196
+ }
197
+ contribute(rec, v) {
198
+ // TOP is the unit element and a nil is a failure, neither of which
199
+ // is information the author wrote. A value an earlier meet MADE is
200
+ // an intermediate; the source that made it is already recorded.
201
+ if (null == v || true !== v.isVal || true === v.isTop || true === v.isNil ||
202
+ rec.made.has(v.id) || rec.seen.has(v.id)) {
203
+ return;
204
+ }
205
+ // PART OF a written value is not a value beside it: report the
206
+ // whole statement the author wrote, whichever piece of it the
207
+ // fixpoint happened to meet here. See INNER_OF.
208
+ let outer = v;
209
+ for (let up = this.containers.get(outer[exports.INNER_OF]); null != up; up = this.containers.get(outer[exports.INNER_OF])) {
210
+ outer = up;
211
+ }
212
+ if (outer !== v) {
213
+ this.contribute(rec, outer);
214
+ return;
215
+ }
216
+ // Not the author's: see WRITTEN.
217
+ if (true !== v[exports.WRITTEN] && true !== v[exports.FROM_SPREAD]) {
218
+ return;
219
+ }
220
+ // A CONJUNCT is not one contribution, it is the statement that
221
+ // several must all hold — duplicate keys merged at parse, an
222
+ // explicit `a & b`. Its own site is nowhere (the merge has no
223
+ // source position), while its terms each have one, which is what
224
+ // the author needs to be shown.
225
+ if (true === v.isConjunct && Array.isArray(v.peg)) {
226
+ rec.seen.add(v.id);
227
+ for (const term of v.peg) {
228
+ this.contribute(rec, term);
229
+ }
230
+ return;
231
+ }
232
+ rec.seen.add(v.id);
233
+ rec.conjuncts.push({
234
+ canon: v.canon,
235
+ id: v.id,
236
+ role: roleOf(v),
237
+ // COALESCED, unlike vet's siteOf: a `why` run reads whatever
238
+ // source it was handed, and an inline document (a spec row, a
239
+ // piped stdin) has no file name to stamp. The Go port answers
240
+ // the empty string for the same value, so the two agree.
241
+ site: {
242
+ col: v.site.col, file: v.site.url ?? '', len: v.site.len,
243
+ row: v.site.row,
244
+ },
245
+ src: v.site.src,
246
+ });
247
+ }
248
+ // THE VALUE THAT STANDS at a path is a contribution when nothing met
249
+ // there and the author wrote it. A meet is where information
250
+ // vanishes, so a meet is what the recorder watches -- but a
251
+ // generator PLACES a value without meeting anything, and `why` then
252
+ // answered "(no contributions: nothing met at this path)" over a
253
+ // value it had just printed. That is literally true and practically
254
+ // false: the author is asking where the value came from, and it came
255
+ // from somewhere they can be shown (use-cases/BUGS.md §23).
256
+ //
257
+ // Only when the record is otherwise EMPTY. Where something did meet,
258
+ // the standing value is that meet's result -- an intermediate, and
259
+ // the recorder's oldest rule is that a result is not a source.
260
+ stands(path, v) {
261
+ const key = path.join('.');
262
+ const rec = this.paths.get(key);
263
+ if (null != rec && 0 < rec.conjuncts.length) {
264
+ return;
265
+ }
266
+ this.record(path, v, undefined, undefined);
267
+ }
268
+ // The record at one path. Empty when nothing met there and nothing
269
+ // the author wrote stands there either — which is a true and useful
270
+ // answer rather than an error.
271
+ //
272
+ // ONLY WHOLE WRITTEN VALUES are contributions. A Val's own unify
273
+ // re-enters `unite` at the same path — a disjunct trials each member
274
+ // there, a constraint meets its atoms there — and those members are
275
+ // PARTS OF one written value, not further values beside it. That is
276
+ // settled BEFORE a member is ever pushed, by the INNER_OF fact
277
+ // stamped over the document (see `contribute`), which is why no
278
+ // filter runs here: a per-path "inside" set used to do it, and it
279
+ // could only work where the container itself happened to meet
280
+ // something at the same path — the order-dependence finding E
281
+ // records.
282
+ at(path) {
283
+ const rec = this.paths.get(path.join('.'));
284
+ if (null == rec) {
285
+ return [];
286
+ }
287
+ // SOURCE ORDER, not meet order: the two are the same in simple
288
+ // cases and diverge with the fixpoint's fold order, which is an
289
+ // engine detail and a parity risk. Sites are parse data, identical
290
+ // in both ports, so ordering by them makes the record read as the
291
+ // document reads and pins it across implementations.
292
+ // ONE WRITTEN TOKEN IS ONE CONTRIBUTION, and the SITE is what
293
+ // identifies it -- not the val id, and not the canon.
294
+ //
295
+ // Not the id, because provenance travels through clones now: a
296
+ // written value and a clone of it are the same statement in the
297
+ // same place, and a path that met both would list it twice.
298
+ //
299
+ // Not the canon, because the same written value reaches a path at
300
+ // different stages of narrowing -- `3|(1|2)` as the author wrote
301
+ // it and `3|1|2` after a fold -- and both name one token.
302
+ //
303
+ // Not the role either: the role says how the value REACHED this
304
+ // path, not which value it is, and one written value can reach a
305
+ // path both ways (a template applied to a key whose value is also
306
+ // written there). Keeping the literal would throw away the more
307
+ // informative half, so the roles have a precedence.
308
+ //
309
+ // ONLY WHERE THE SITE IS REAL. An unsited contribution (row -1)
310
+ // cannot be told apart from another unsited one, so those are kept
311
+ // as they come rather than collapsed into whichever arrived first.
312
+ const shown = new Map();
313
+ const order = ['spread', 'ref', 'pref', 'literal'];
314
+ const out = [];
315
+ for (const c of rec.conjuncts.slice().sort(cmpSite)) {
316
+ if (c.site.row < 0) {
317
+ out.push(c);
318
+ continue;
319
+ }
320
+ const key = [c.src, c.site.file,
321
+ c.site.row, c.site.col, c.site.len].join('\u0000');
322
+ const had = shown.get(key);
323
+ if (null == had) {
324
+ shown.set(key, c);
325
+ out.push(c);
326
+ }
327
+ else if (order.indexOf(c.role) < order.indexOf(had.role)) {
328
+ had.role = c.role;
329
+ }
330
+ }
331
+ return out.map(({ id, ...rest }) => rest);
332
+ }
333
+ }
334
+ exports.Provenance = Provenance;
335
+ //# sourceMappingURL=provenance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provenance.js","sourceRoot":"","sources":["../src/provenance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { TrustOptions } from './type';
2
+ import type { VetFinding } from './vet';
3
+ import type { WhyRecord } from './provenance';
4
+ export type QueryView = 'json' | 'canon' | 'types' | 'keys';
5
+ export type QueryOptions = {
6
+ view?: QueryView;
7
+ depth?: number;
8
+ path?: string;
9
+ trust?: TrustOptions;
10
+ };
11
+ export type QueryReport = {
12
+ ok: boolean;
13
+ out: string;
14
+ findings: VetFinding[];
15
+ };
16
+ export declare function nearestKey(want: string, have: string[]): string | undefined;
17
+ export declare function pathParts(path: string): string[];
18
+ export declare function projectFor(v: any, view: QueryView, depth: number): string;
19
+ export declare function evalFailure(ctx: any): VetFinding;
20
+ export declare function noPathFinding(root: any, path: string): VetFinding;
21
+ export declare function get(src: string, path: string, opts?: QueryOptions): QueryReport;
22
+ export type WhyReport = {
23
+ ok: boolean;
24
+ record?: WhyRecord;
25
+ findings: VetFinding[];
26
+ };
27
+ export declare function why(src: string, path: string, opts?: QueryOptions): WhyReport;
package/dist/query.js ADDED
@@ -0,0 +1,294 @@
1
+ "use strict";
2
+ /* Copyright (c) 2025 Richard Rodger, MIT License */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.nearestKey = nearestKey;
5
+ exports.pathParts = pathParts;
6
+ exports.projectFor = projectFor;
7
+ exports.evalFailure = evalFailure;
8
+ exports.noPathFinding = noPathFinding;
9
+ exports.get = get;
10
+ exports.why = why;
11
+ // THE QUERY SURFACE (G7 phase 1,
12
+ // docs/capability-review/g7-machine-access.md): select one node of an
13
+ // evaluated document by path and render it — the slice an agent asks
14
+ // for, instead of the whole file as one JSON blob.
15
+ //
16
+ // Evaluation is still GLOBAL. Unification has no partial mode to sell:
17
+ // the whole document is evaluated and then one node is selected. What
18
+ // `get` buys is the SIZE OF THE ANSWER, not the cost of producing it.
19
+ //
20
+ // The three projections are lattice ABSTRACTIONS, and each is defined
21
+ // so that the view it prints is a valid Aontu document that SUBSUMES
22
+ // the truth — generalisation, never distortion:
23
+ //
24
+ // - `types` replaces every concrete leaf with its own kind, using
25
+ // the lattice's own superior() rather than a table of this file's
26
+ // opinions: {"replicas":3} becomes {"replicas":integer}.
27
+ // - `depth n` keeps structure to depth n and renders every elided
28
+ // subtree as `top` — "no further information at this tier".
29
+ // - `keys` is `depth 1` degenerated to a listing.
30
+ //
31
+ // That property is not a promise here: every projection row of
32
+ // test/spec/query.tsv asserts subsume(view, truth) == 'subsumes' in
33
+ // both runners, which G3 made mechanically checkable.
34
+ //
35
+ // Projections are NOT canonical form and are never fed to G6's hash,
36
+ // which is why they are named views rather than spellings of --canon.
37
+ const aontu_1 = require("./aontu");
38
+ const exactjson_1 = require("./exactjson");
39
+ const vet_1 = require("./vet");
40
+ const keyorder_1 = require("./keyorder");
41
+ const provenance_1 = require("./provenance");
42
+ const TOP = 'top';
43
+ // The nearest key at the parent of a path that named nothing, by a
44
+ // plain edit distance over the sibling names — the "did you mean"
45
+ // half of the no_path contract. Undefined when nothing is close
46
+ // enough to be worth suggesting.
47
+ function nearestKey(want, have) {
48
+ let best;
49
+ let bestd = Infinity;
50
+ for (const k of have) {
51
+ const d = editDistance(want, k);
52
+ if (d < bestd) {
53
+ bestd = d;
54
+ best = k;
55
+ }
56
+ }
57
+ // Half the name may differ, no more: past that the suggestion is
58
+ // noise, and a wrong suggestion costs more than none.
59
+ return bestd <= Math.max(1, Math.floor(want.length / 2)) ? best : undefined;
60
+ }
61
+ function editDistance(a, b) {
62
+ const prev = [];
63
+ for (let j = 0; j <= b.length; j++) {
64
+ prev[j] = j;
65
+ }
66
+ for (let i = 1; i <= a.length; i++) {
67
+ let diag = prev[0];
68
+ prev[0] = i;
69
+ for (let j = 1; j <= b.length; j++) {
70
+ const tmp = prev[j];
71
+ prev[j] = Math.min(prev[j] + 1, prev[j - 1] + 1, diag + (a[i - 1] === b[j - 1] ? 0 : 1));
72
+ diag = tmp;
73
+ }
74
+ }
75
+ return prev[b.length];
76
+ }
77
+ // The path split anchorAt walks: `$` and empty segments dropped, so
78
+ // `$`, `$.` and `` all name the root.
79
+ function pathParts(path) {
80
+ const trimmed = path.startsWith('$') ? path.slice(1) : path;
81
+ return trimmed.split('.').filter((p) => '' !== p);
82
+ }
83
+ // The queried path, normalised the way anchorAt reads it — so a
84
+ // finding names `$.a.b` whether the caller wrote that, `a.b` or
85
+ // `$.a.b.` — and `$` for the root.
86
+ function pathText(path) {
87
+ const parts = pathParts(path);
88
+ return '$' + (0 < parts.length ? '.' + parts.join('.') : '');
89
+ }
90
+ // The projection walk, exported for the direct unit tests (ADR-002,
91
+ // ts/test/coverage3.test.ts): a junction member that is itself a
92
+ // junction of more than one term keeps its parens, and no SOURCE
93
+ // reaches that arm because norm flattens junctions at unification.
94
+ function projectFor(v, view, depth) {
95
+ return project(v, view, depth);
96
+ }
97
+ // The canon-shaped views. One walk, two knobs: `types` generalises
98
+ // each leaf through the lattice, `depth` elides below its level. Bags
99
+ // recurse (their canon getters would render children through plain
100
+ // canon, which neither knob can reach); everything else is a leaf.
101
+ function project(v, view, depth) {
102
+ if (depth <= 0) {
103
+ return TOP;
104
+ }
105
+ if (true === v?.isMap) {
106
+ const keys = Object.keys(v.peg).sort(keyorder_1.cmpCodePoint);
107
+ return '{' +
108
+ (v.spread.cj ? '&:' + project(v.spread.cj, view, depth - 1) +
109
+ (0 < keys.length ? ',' : '') : '') +
110
+ keys.map((k) => JSON.stringify(k) +
111
+ (v.optionalKeys.includes(k) ? '?' : '') +
112
+ ':' +
113
+ project(v.peg[k], view, depth - 1)).join(',') +
114
+ '}';
115
+ }
116
+ if (true === v?.isList) {
117
+ const keys = Object.keys(v.peg);
118
+ return '[' +
119
+ (v.spread.cj ? '&:' + project(v.spread.cj, view, depth - 1) +
120
+ (0 < keys.length ? ',' : '') : '') +
121
+ keys.map((k) => project(v.peg[k], view, depth - 1)).join(',') +
122
+ ']';
123
+ }
124
+ // Junctions and prefs are TRANSPARENT: not a structural tier (so
125
+ // they do not spend a level of depth) but not a leaf either (so
126
+ // `*8080|integer` generalises to `*integer|integer` rather than
127
+ // collapsing to `top` and throwing the alternatives away).
128
+ if (true === v?.isPref) {
129
+ return '*' + project(v.peg, view, depth);
130
+ }
131
+ if (true === v?.isConjunct || true === v?.isDisjunct) {
132
+ return v.peg.map((m) => true === m?.isJunction && 1 < m.peg.length
133
+ ? '(' + project(m, view, depth) + ')'
134
+ : project(m, view, depth))
135
+ .join(true === v.isConjunct ? '&' : '|');
136
+ }
137
+ // A LEAF. Under `types` a CONCRETE scalar lifts to its own kind —
138
+ // superior() is the lattice's answer, so the view subsumes the truth
139
+ // by construction and not by this file's good intentions. Everything
140
+ // else is already an abstraction (a kind marker, a constraint, an
141
+ // unresolved reference) and is left alone: lifting `integer` to
142
+ // `number` would generalise a shape view that was already a shape.
143
+ return 'types' === view && true === v?.isScalar ? v.superior().canon : v.canon;
144
+ }
145
+ // The `keys` listing: the node's own key names (or list indices), one
146
+ // per line, code-point ordered as canon orders them. A leaf has none,
147
+ // which is an empty answer rather than an error — "nothing below
148
+ // here" is a true statement about a scalar.
149
+ function keyList(v) {
150
+ if (true === v?.isMap) {
151
+ return Object.keys(v.peg).sort(keyorder_1.cmpCodePoint).join('\n');
152
+ }
153
+ if (true === v?.isList) {
154
+ return Object.keys(v.peg).join('\n');
155
+ }
156
+ return '';
157
+ }
158
+ function finding(code, path, message, note) {
159
+ return {
160
+ code,
161
+ class: 'reference',
162
+ severity: 'error',
163
+ path,
164
+ message,
165
+ sites: [],
166
+ ...(null == note ? {} : { note }),
167
+ };
168
+ }
169
+ // A document that does not stand up has no node to select. The
170
+ // engine's own first error IS the report: the query surface adds
171
+ // nothing to a diagnosis the evaluator already made. The path is the
172
+ // DOCUMENT — what failed is the whole thing standing up, not the node
173
+ // the caller asked about, which may never have existed.
174
+ function evalFailure(ctx) {
175
+ // ctx.err is never empty at a call site: every failure that reaches
176
+ // one collected an error first — a parse that did not stand up, a
177
+ // root that came back nil. Not coalesced, on the vet siteOf
178
+ // precedent: an impossible state should fail loudly rather than be
179
+ // quietly papered over with a made-up code.
180
+ const err = ctx.err[0];
181
+ return finding(err.why, '$', err.msg);
182
+ }
183
+ // The refusal for a path that names nothing, shared by `get` and
184
+ // `why`: WHICH segment failed, and what was there instead — the "did
185
+ // you mean" the no_path contract promises. Walking again is cheap (the
186
+ // tree is in hand) and is the only way to name the parent.
187
+ function noPathFinding(root, path) {
188
+ const parts = pathParts(path);
189
+ let at = root;
190
+ let want = '';
191
+ for (const part of parts) {
192
+ const next = (0, vet_1.anchorAt)(at, part);
193
+ if (null == next) {
194
+ want = part;
195
+ break;
196
+ }
197
+ at = next;
198
+ }
199
+ const have = true === at?.isMap
200
+ ? Object.keys(at.peg).sort(keyorder_1.cmpCodePoint)
201
+ : (true === at?.isList ? Object.keys(at.peg) : []);
202
+ const near = nearestKey(want, have);
203
+ return finding('no_path', pathText(path), `The path ${path} names nothing in this document.`, null == near ? undefined : `did you mean ${near}?`);
204
+ }
205
+ // Evaluate the document, select the node at `path`, and render it.
206
+ function get(src, path, opts) {
207
+ const options = opts ?? {};
208
+ const view = options.view ?? 'json';
209
+ const aontu = new aontu_1.Aontu(null == options.trust ? undefined : { trust: options.trust });
210
+ const ctx = aontu.ctx({ collect: true });
211
+ const parseOpts = null == options.path ? undefined : { path: options.path };
212
+ const root = aontu.unify(src, parseOpts, ctx);
213
+ if (0 < ctx.err.length || null == root || true === root.isNil) {
214
+ return { ok: false, out: '', findings: [evalFailure(ctx)] };
215
+ }
216
+ const node = (0, vet_1.anchorAt)(root, path);
217
+ if (null == node) {
218
+ return { ok: false, out: '', findings: [noPathFinding(root, path)] };
219
+ }
220
+ if ('json' === view) {
221
+ // GENERATION CAN FAIL WHERE UNIFICATION DID NOT: `k: integer` is a
222
+ // perfectly good unified document and not a concrete value, so the
223
+ // json view of it is an error, exactly as `aontu file.aon` on the
224
+ // same document is. Under `collect` the failure lands on the
225
+ // context rather than throwing, so it has to be read back — the Go
226
+ // port's Gen returns it as an error and the two must agree.
227
+ const before = ctx.err.length;
228
+ const gen = node.gen(ctx);
229
+ if (before < ctx.err.length) {
230
+ const err = ctx.err[before];
231
+ return {
232
+ ok: false,
233
+ out: '',
234
+ findings: [finding(err?.why ?? 'no_gen', pathText(path), err?.msg ?? 'The value at this path is not concrete.')],
235
+ };
236
+ }
237
+ return { ok: true, out: (0, exactjson_1.exactJSON)(gen, 2), findings: [] };
238
+ }
239
+ if ('keys' === view) {
240
+ return { ok: true, out: keyList(node), findings: [] };
241
+ }
242
+ return {
243
+ ok: true,
244
+ out: project(node, view, options.depth ?? Infinity),
245
+ findings: [],
246
+ };
247
+ }
248
+ // WHY does the value at this path hold? Evaluate with the provenance
249
+ // recorder on, select the node, and answer the ordered contributions
250
+ // that met there — the positive twin of G2's error report.
251
+ //
252
+ // Two evaluations are NOT needed: the recorder rides the one run this
253
+ // call makes. What it costs is site materialisation and one map entry
254
+ // per path met, which an instrumented run pays knowingly.
255
+ function why(src, path, opts) {
256
+ const options = opts ?? {};
257
+ const aontu = new aontu_1.Aontu(null == options.trust ? undefined : { trust: options.trust });
258
+ const prov = new provenance_1.Provenance();
259
+ const ctx = aontu.ctx({ collect: true, prov });
260
+ const parseOpts = null == options.path ? undefined : { path: options.path };
261
+ // Parse and unify SEPARATELY, so the parsed tree can be stamped
262
+ // before the fixpoint runs: a contribution is a value the author
263
+ // wrote, and after unification there is no longer any way to tell
264
+ // one from a value the engine minted on the way.
265
+ const parsed = aontu.parse(src, parseOpts, ctx);
266
+ if (0 < ctx.err.length || null == parsed) {
267
+ return { ok: false, findings: [evalFailure(ctx)] };
268
+ }
269
+ prov.writtenFrom(parsed);
270
+ const root = aontu.unify(parsed, parseOpts, ctx);
271
+ if (0 < ctx.err.length || null == root || true === root.isNil) {
272
+ return { ok: false, findings: [evalFailure(ctx)] };
273
+ }
274
+ const node = (0, vet_1.anchorAt)(root, path);
275
+ if (null == node) {
276
+ return { ok: false, findings: [noPathFinding(root, path)] };
277
+ }
278
+ // The value that stands here is a contribution when nothing met
279
+ // (see Provenance.stands): a generator places a value without a
280
+ // meet, and "nothing met at this path" is not an answer to "where
281
+ // did this come from".
282
+ const parts = pathParts(path);
283
+ prov.stands(parts, node);
284
+ return {
285
+ ok: true,
286
+ record: {
287
+ conjuncts: prov.at(parts),
288
+ path: pathText(path),
289
+ value: node.canon,
290
+ },
291
+ findings: [],
292
+ };
293
+ }
294
+ //# sourceMappingURL=query.js.map