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
package/src/mcp.ts CHANGED
@@ -1,29 +1,5 @@
1
1
  /* Copyright (c) 2025 Richard Rodger, MIT License */
2
2
 
3
- // THE MCP TOOL LIBRARY (G7 phase 6,
4
- // docs/capability-review/g7-machine-access.md; completed to the full
5
- // CLI verb surface by the use-case review's MCP recommendation,
6
- // use-cases/SUPPORT.md): the verbs an agent calls, over the Model
7
- // Context Protocol, as a transport-free library. The split follows
8
- // the LSP's (docs/lsp.md): this file is the protocol and the tools,
9
- // ts/src/mcp-server.ts is stdio and nothing else, and the whole thing
10
- // is testable without a socket.
11
- //
12
- // Every tool returns THE SAME JSON CONTRACT THE CLI PRINTS. That is
13
- // the point of the surface: an agent that has read `aontu vet
14
- // --format json` output knows what the `vet` tool answers, and a
15
- // report copied from one to the other is the same object. The tools
16
- // add no vocabulary of their own.
17
- //
18
- // The server evaluates under a CONFINED resolver (G5, docs/trust.md):
19
- // a caller hands source text, and text that could reach out through
20
- // `@"..."` is exactly what a server must not run unconfined. By
21
- // default every include is denied; a server started with
22
- // `--root <dir>` (ts/src/mcp-server.ts) resolves includes confined
23
- // below that root instead — the CLI's `--trust root:<dir>` posture —
24
- // and lets every document argument arrive as a `<name>Path` file
25
- // under the same root. The package-resolver leg is never enabled
26
- // here.
27
3
 
28
4
  import { readFileSync, realpathSync } from 'node:fs'
29
5
  import {
@@ -71,7 +47,6 @@ export type McpResponse = {
71
47
  }
72
48
 
73
49
 
74
- // JSON-RPC's own codes, the three a server this small can raise.
75
50
  const PARSE_ERROR = -32700
76
51
  const METHOD_NOT_FOUND = -32601
77
52
  const INVALID_PARAMS = -32602
@@ -91,13 +66,6 @@ export type ToolDef = {
91
66
  // Argument validation beyond "required and a string": the message
92
67
  // for a call that could not be made, or undefined for a good call.
93
68
  check?: (a: any) => string | undefined
94
- // ENGINES THAT TAKE NO TRUST PROFILE (subsume, trimCheck,
95
- // relationCheck, patch) build their own evaluators, so the served
96
- // profile cannot ride into them as an argument the way it rides
97
- // into vet or get. Their documents are PRE-PARSED under the profile
98
- // by callTool instead (confinedParseFailure below), and `refuse` is
99
- // the tool's own error report for a document that fails it. A tool
100
- // whose engine takes `trust` directly declares no `refuse`.
101
69
  refuse?: (
102
70
  a: any, finding: VetFinding, trust: TrustOptions,
103
71
  paths: Record<string, string>) => any
@@ -106,22 +74,6 @@ export type ToolDef = {
106
74
  }
107
75
 
108
76
 
109
- // The trust profile a served evaluation runs under: no includes at
110
- // all — or, when the server was started with --root, includes
111
- // realpath-confined below that root (the CLI's `--trust root:<dir>`
112
- // semantics; docs/trust.md). The package-resolver leg is enabled by
113
- // neither.
114
- //
115
- // The profile is INJECTED into every tool by callTool rather than
116
- // applied by each tool for itself. That is deliberate: four of the six
117
- // original tools once called the library with no profile at all, so a
118
- // served `@"x.js"` was require()d in the server process, while the
119
- // module header claimed confinement. (That particular include is
120
- // refused outright now -- ADR-012 -- but a served document could still
121
- // read every file the server can.) A tool that must remember to
122
- // confine itself is a tool that eventually forgets, and the forgetting
123
- // is silent. With the profile arriving as an argument, a tool cannot
124
- // run unconfined without visibly discarding it.
125
77
  export function servedTrust(root?: string): TrustOptions {
126
78
  return null == root
127
79
  ? { include: 'none' }
@@ -133,17 +85,6 @@ function served(trust: TrustOptions): Aontu {
133
85
  }
134
86
 
135
87
 
136
- // DOES THIS DOCUMENT STAND UP UNDER THE SERVED PROFILE — or the
137
- // finding that says why not. This is the confinement gate for the
138
- // engines that take no trust profile, and parse is the whole include
139
- // story: `@"..."` resolves at parse time (ts/src/lang.ts), so a
140
- // document whose confined parse is clean either has no includes at
141
- // all (capability 'none') or resolves every one below the root — and
142
- // an engine that then re-resolves the same closure under the default
143
- // profile reads exactly the files the confined parse proved in
144
- // bounds. A parse that fails for any reason refuses the call: an
145
- // engine's own answer for a document this profile cannot read is not
146
- // an answer this server may compute.
147
88
  export function confinedParseFailure(
148
89
  src: string, trust: TrustOptions, path?: string
149
90
  ): VetFinding | undefined {
@@ -154,18 +95,6 @@ export function confinedParseFailure(
154
95
  }
155
96
 
156
97
 
157
- // Confinement is realpath-then-prefix-check, mirroring the include
158
- // resolver's own rule (ts/src/lang.ts, docs/trust.md): the file's
159
- // real path must sit below the root's real path, so a symlink inside
160
- // the root pointing outside it is an escape, not a loophole.
161
- //
162
- // A path that does not (fully) exist cannot be realpath'd whole, and
163
- // falling back to the LEXICAL form compares apples to oranges when the
164
- // root itself sits behind a symlink -- on macOS a root under /var
165
- // realpaths to /private/var, so a merely-missing file inside it read
166
- // as an escape instead of "cannot read" (the CI failure that bought
167
- // this comment). Realpath the deepest EXISTING ancestor and re-attach
168
- // the rest, so both sides of the prefix check are in real coordinates.
169
98
  function realpathOf(p: string): string {
170
99
  try {
171
100
  return realpathSync(p)
@@ -301,8 +230,6 @@ const TOOLS: ToolDef[] = [
301
230
  run: (a, trust, paths) => summaryOf(str(a.src), trust, paths.src),
302
231
  },
303
232
 
304
- // The evolution and change verbs (the use-case review's "MCP is a
305
- // read-only subset" gap, use-cases/09-agent-tools/README.md gap 11).
306
233
 
307
234
  {
308
235
  name: 'subsume',
@@ -419,11 +346,6 @@ const TOOLS: ToolDef[] = [
419
346
  },
420
347
  required: ['source'],
421
348
  docs: ['source'],
422
- // The pre-parse finding rides `errors`, exactly where the engine
423
- // puts its own reason for a document that does not stand up
424
- // (ts/src/relation.ts, the review's finding F). NOT `findings`:
425
- // RelationFinding is its own vocabulary (code, relation, at,
426
- // detail) and a document with no graph has no graph findings.
427
349
  refuse: (_a, finding) =>
428
350
  ({ verdict: 'error', findings: [], errors: [finding] }),
429
351
  run: (a, _trust, paths) =>
@@ -644,9 +566,6 @@ const TOOLS: ToolDef[] = [
644
566
  },
645
567
  required: ['source'],
646
568
  docs: ['source'],
647
- // The pre-parse finding rides `errors`, exactly where the engine
648
- // puts its own reason for a document that does not stand up
649
- // (ts/src/trim.ts, the review's finding F).
650
569
  refuse: (_a, finding) =>
651
570
  ({ verdict: 'error', redundant: [], errors: [finding] }),
652
571
  run: (a, _trust, paths) =>
@@ -784,15 +703,6 @@ function hashOf(
784
703
  }
785
704
 
786
705
 
787
- // ---------------------------------------------------------------------
788
- // THE BREAKING POLICY WRAPPER. Re-implemented from ts/src/cli.ts
789
- // (runBreaking and policyCompat) rather than extracted from it: cli.ts
790
- // owns the process-facing halves — files, git revisions, exit codes,
791
- // rendering — that a served tool must not import, and the policy
792
- // itself (which mode applies, which side is general, how verdicts
793
- // aggregate) is small enough that a shared home would be all seam.
794
- // cli.ts is the reference; a change there is a change here.
795
-
796
706
  type BreakingMode = 'backward' | 'forward' | 'full' | 'none'
797
707
 
798
708
  // Verdict aggregation: an error anywhere makes the run an error;
@@ -844,8 +754,6 @@ function policyCompatOf(
844
754
  }
845
755
 
846
756
 
847
- // The declared mode: the mode argument overrides the document's own
848
- // policy; neither means backward (v1-valid documents stay valid).
849
757
  function breakingMode(
850
758
  a: any, trust: TrustOptions, paths: Record<string, string>
851
759
  ): BreakingMode {
@@ -867,8 +775,6 @@ function breakingOf(
867
775
  new: { src: str(a.new), url: paths.new ?? 'new', path: paths.new },
868
776
  }
869
777
 
870
- // backward: the NEW document is the general side — every old
871
- // instance must still be admitted. forward: the old one is.
872
778
  const checks: Array<{
873
779
  general: typeof sides.old, specific: typeof sides.old
874
780
  }> = []
@@ -898,11 +804,6 @@ function breakingOf(
898
804
  }
899
805
 
900
806
 
901
- // ---------------------------------------------------------------------
902
- // The set tool: the CLI's `set` verb minus the filesystem — the patch
903
- // engine (ts/src/patch.ts) already answers with the new overlay text,
904
- // and the caller owns the write.
905
-
906
807
  // The assignments arrive structured ({path, value}) rather than as the
907
808
  // CLI's `<path>=<value>` spelling, and are re-joined for the engine's
908
809
  // parseAssignment — so the path must not smuggle a `=` that would move
@@ -937,12 +838,6 @@ function setError(overlay: string, finding: VetFinding): any {
937
838
 
938
839
  function setOf(
939
840
  a: any, trust: TrustOptions, paths: Record<string, string>): any {
940
- // THE ASSIGNMENT VALUES ARE DOCUMENTS TOO: each one is appended (or
941
- // spliced) into the overlay and evaluated there by the engine's
942
- // final vet, so a value that smuggles an include — or a newline and
943
- // then an include — gets the same confined pre-parse as the
944
- // documents themselves, wrapped exactly as the engine's own
945
- // spanValue wraps a fragment (ts/src/patch.ts).
946
841
  for (const x of a.assignments) {
947
842
  const denied = confinedParseFailure('v: ' + x.value, trust, paths.overlay)
948
843
  if (null != denied) {
@@ -960,13 +855,6 @@ function setOf(
960
855
  }
961
856
 
962
857
 
963
- // ---------------------------------------------------------------------
964
- // The tool list as MCP spells it: a name, a description, and a JSON
965
- // Schema for the arguments. With a served root, every document
966
- // property gains its `<name>Path` file alternative — and comes OFF the
967
- // `required` list, because JSON Schema's `required` cannot say "one of
968
- // the two"; callTool's own argument check still refuses a call that
969
- // carries neither.
970
858
  export function toolList(root?: string): any[] {
971
859
  return TOOLS.map((t) => {
972
860
  const properties: Record<string, any> = { ...t.properties }
@@ -1000,17 +888,6 @@ function refusal(text: string): any {
1000
888
  }
1001
889
 
1002
890
 
1003
- // One tool call. A tool that REFUSES (an invalid document, a path that
1004
- // names nothing, a document the served profile cannot read) is not a
1005
- // protocol error: it answers with its own report and `isError` false,
1006
- // because the report IS the answer the agent asked for. `isError` is
1007
- // reserved for a call that could not be made at all — an unknown tool,
1008
- // a missing or malformed argument, a file argument the server cannot
1009
- // serve.
1010
- // `opts.tools` is injectable for the same reason the watch loop's
1011
- // waiter is: the catch below is defensive code no document reaches --
1012
- // every verb answers with a report rather than throwing -- and code
1013
- // the suite cannot execute is code the ADR-002 floor cannot hold.
1014
891
  export function callTool(
1015
892
  name: string, args: any,
1016
893
  opts?: { root?: string, tools?: ToolDef[] }): any {
@@ -1024,13 +901,6 @@ export function callTool(
1024
901
  const a: any = { ...(args ?? {}) }
1025
902
  const paths: Record<string, string> = {}
1026
903
 
1027
- // THE FILE ALTERNATIVES (--root). A document that did not arrive as
1028
- // inline text may arrive as a `<name>Path` file — served only when
1029
- // the operator granted a root at startup, confined below it by the
1030
- // same realpath rule the include resolver applies, and recorded in
1031
- // `paths` so the engine resolves the file's own relative includes
1032
- // from its directory (the CLI's rule for a named file). Inline text
1033
- // wins when a caller sends both.
1034
904
  for (const doc of tool.docs ?? []) {
1035
905
  if ('string' === typeof a[doc]) {
1036
906
  continue
package/src/mod-tool.ts CHANGED
@@ -1,22 +1,5 @@
1
1
  /* Copyright (c) 2025 Richard Rodger, MIT License */
2
2
 
3
- // MODULE TOOLING (G6 phase 3, docs/capability-review/g6-distribution.md):
4
- // the LOCAL half — `aontu mod tidy`, `verify`, `vendor` and
5
- // `manifest`.
6
- //
7
- // Evaluation never touches the network, and neither does this: `tidy`
8
- // resolves versions and rewrites the lockfile from what is already in
9
- // the local stores, `verify` asks whether the stores still MEAN what
10
- // the lockfile pins and changes nothing, and `vendor` materialises the
11
- // locked closure into the project. Fetching and publishing are the
12
- // network half, and are not in this build (see the register).
13
- //
14
- // MINIMUM VERSION SELECTION, not a solver: each module declares the
15
- // MINIMUM version of each dependency it needs, and the selected version
16
- // is the maximum of those minima over the closure. Deterministic, and
17
- // deterministic without backtracking — the lockfile CONFIRMS the
18
- // resolution rather than determining it, which is why a tidy run can be
19
- // re-run to the same bytes.
20
3
 
21
4
  import {
22
5
  readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync,
@@ -37,11 +20,7 @@ export type ModLock = {
37
20
  mod: string
38
21
  // The selected version.
39
22
  v: string
40
- // The canon-hash of the module as it is in the local store.
41
23
  canon: string
42
- // The registry digest, carried over from a previous lockfile. Empty
43
- // when nothing has ever fetched this module: the OCI pin is the
44
- // registry's word, and only a fetch can hear it.
45
24
  oci: string
46
25
  }
47
26
 
@@ -49,22 +28,12 @@ export type ModTidyReport = {
49
28
  verdict: 'ok' | 'missing' | 'error'
50
29
  // The resolved closure, sorted by module.
51
30
  lock: ModLock[]
52
- // Modules named by a dependency but present in no local store, sorted.
53
31
  missing: string[]
54
- // Modules present in a store but which DO NOT EVALUATE standalone,
55
- // sorted. A pin is what a module MEANS, so there is nothing to pin
56
- // here and the lockfile is left alone.
57
32
  unevaluable: string[]
58
33
  }
59
34
 
60
35
  export type ModVerifyReport = {
61
- // `ok` the lockfile covers what the project declares and every
62
- // locked module still means what it pins; `mismatch` at least one
63
- // does not; `unlocked` the lockfile does not cover the project's own
64
- // dependencies; `missing` at least one locked module is not in any
65
- // store. In that order of precedence, most specific first.
66
36
  verdict: 'ok' | 'mismatch' | 'unlocked' | 'missing'
67
- // The locked modules that verified, sorted.
68
37
  verified: string[]
69
38
  // What the lockfile pins against what the store now means, for each
70
39
  // module that does not match, sorted by module.
@@ -85,19 +54,9 @@ export type ModVendorReport = {
85
54
  }
86
55
 
87
56
 
88
- // What the tooling needs from the engine, injected for the reason
89
- // ts/src/mod.ts's ModuleEval is: evaluating a module is what the
90
- // evaluator does, and the tooling is a caller of it rather than a
91
- // second implementation.
92
57
  export type ModToolEval = (src: string, path: string) =>
93
58
  {
94
59
  gen: any, hash: string, canon: string,
95
- // DID IT STAND UP ON ITS OWN? A module that does not evaluate has
96
- // no meaning to pin, and `canonHash` of the nil it collapses to is
97
- // the SAME string for every such module -- so a lockfile written
98
- // from one carries no information while looking exactly like one
99
- // that does (use-cases/BUGS.md §31). `aontu hash` already refuses
100
- // that file; `tidy` refuses it too, and this is what tells it.
101
60
  ok: boolean,
102
61
  }
103
62
 
@@ -134,10 +93,6 @@ function declaredDeps(file: string, options: ModToolOptions):
134
93
  }
135
94
 
136
95
 
137
- // Numeric-dotted version order: `1.10.0` is above `1.9.0`, which
138
- // STRING order gets wrong, and that is the whole reason this is not a
139
- // `<` on the text. A part that is not a number compares as text, after
140
- // every number — a pre-release tag is below no version and above none.
141
96
  export function versionCompare(a: string, b: string): number {
142
97
  const ap = a.split('.')
143
98
  const bp = b.split('.')
@@ -164,21 +119,6 @@ export function versionCompare(a: string, b: string): number {
164
119
  }
165
120
 
166
121
 
167
- // A dependency or lockfile key as a module ref this tooling may ACT
168
- // on, or undefined.
169
- //
170
- // Two ways to be unusable, one answer. A key that is not module-shaped
171
- // names nothing the resolver can find; a key that is shaped but whose
172
- // path cannot legally be a directory (`..` in it, a reserved device
173
- // name) must not be turned into one, which is the whole of the
174
- // traversal fix on this side. Both land in the caller's `missing`
175
- // bucket, because from the report's point of view they are the same
176
- // fact: the lockfile names something that cannot be resolved here.
177
- //
178
- // A STALE LOCKFILE IS THE REASON THIS EXISTS AT ALL. `resolveModule`
179
- // gates the evaluator, but `tidy`, `verify` and `vendor` read a
180
- // lockfile straight off disk -- one that may have been committed
181
- // before the gate existed -- so the gate has to be here too.
182
122
  function usableRef(mod: string): ModuleRef | undefined {
183
123
  const ref = parseModuleRef(mod)
184
124
  if (undefined === ref || undefined !== validateModulePath(ref.path)) {
@@ -230,21 +170,12 @@ function readLock(root: string): Record<string, ModLock> {
230
170
  }
231
171
 
232
172
 
233
- // The lockfile TEXT: canonical Aontu, one line, keys sorted. Built as
234
- // source and canonicalised by the engine rather than printed by hand,
235
- // so "canonical form" means what the language means by it and cannot
236
- // drift from it.
237
173
  export function lockText(entries: ModLock[], options: ModToolOptions): string {
238
174
  const parts = entries.map((e) =>
239
175
  JSON.stringify(e.mod) + ':{' +
240
176
  '"canon":' + JSON.stringify(e.canon) + ',' +
241
177
  '"oci":' + JSON.stringify(e.oci) + ',' +
242
178
  '"v":' + JSON.stringify(e.v) + '}')
243
- // Canonicalised by the ENGINE rather than printed by hand, so
244
- // "canonical form" means what the language means by it and cannot
245
- // drift from it. For a map of scalars that canon is also JSON, which
246
- // is what lets the resolver read a pin back without an evaluator
247
- // (ts/src/mod.ts lockHash).
248
179
  return options.eval('{"lock":{' + parts.join(',') + '}}', 'mod-lock.aon').canon
249
180
  }
250
181
 
@@ -255,10 +186,6 @@ export function modTidy(root: string, options: ModToolOptions): ModTidyReport {
255
186
  const selected: Record<string, string> = {}
256
187
  const missing: string[] = []
257
188
 
258
- // The closure, breadth-first from the project's own declarations. A
259
- // module already selected at a version at least as high contributes
260
- // nothing new, which is what makes this terminate without a cycle
261
- // check: the selected version only ever rises.
262
189
  let frontier = declaredDeps(pathJoin(root, 'mod.aon'), options)
263
190
  for (; 0 < Object.keys(frontier).length;) {
264
191
  const next: Record<string, string> = {}
@@ -307,16 +234,8 @@ export function modTidy(root: string, options: ModToolOptions): ModTidyReport {
307
234
  const ref = usableRef(mod) as ModuleRef
308
235
  const dir = storeDir(root, ref, previous[mod]?.canon ?? '', options) as string
309
236
  const main = pathJoin(dir, mainOf(dir, options))
310
- // RECOMPUTED, never carried over: the pin is what the module in
311
- // this store MEANS, and a tidy that copied the old hash forward
312
- // would pin what it used to mean.
313
237
  const got = existsSync(main) ?
314
238
  options.eval(readFileSync(main, 'utf8'), main) : undefined
315
- // A NIL PIN IS WORSE THAN NO PIN. A module that does not stand up
316
- // hashes to canonHash(nil) -- the same string for every broken
317
- // module -- so writing it would put a plausible, uninformative
318
- // pin in the lockfile and silently void the "breaks on any
319
- // semantic change in the closure" contract (BUGS.md §31).
320
239
  if (null != got && !got.ok) {
321
240
  unevaluable.push(mod)
322
241
  continue
@@ -367,17 +286,6 @@ function mainOf(dir: string, options: ModToolOptions): string {
367
286
  }
368
287
 
369
288
 
370
- // `aontu mod verify`: does every locked module still MEAN what the
371
- // lockfile pins? Recompute and compare, and CHANGE NOTHING.
372
- //
373
- // The verb exists because `tidy` cannot answer this question. Tidy
374
- // recomputes and REWRITES by design -- a pin is what a module means
375
- // now -- so tampering with a vendored module and running tidy makes
376
- // the lockfile agree with the tampering, `verdict: ok`, and the next
377
- // evaluation passes. That is correct for the job tidy does and useless
378
- // as a gate, which left a CI job that tidies before evaluating with no
379
- // integrity protection at all (use-cases/BUGS.md §32). Verification is
380
- // a question; answering it must not be an edit.
381
289
  export function modVerify(root: string, options: ModToolOptions):
382
290
  ModVerifyReport {
383
291
  const locked = readLock(root)
@@ -385,17 +293,6 @@ export function modVerify(root: string, options: ModToolOptions):
385
293
  const mismatched: { mod: string, want: string, got: string }[] = []
386
294
  const missing: string[] = []
387
295
 
388
- // NOTHING TO CHECK IS NOT A PASS. A project with no lockfile at all
389
- // -- or one whose lockfile predates a dependency someone added --
390
- // would otherwise verify clean, because the loop below walks what is
391
- // LOCKED and there is nothing locked to walk. That is the same shape
392
- // as the defect this verb exists to close: absence reading as
393
- // agreement. Every dependency the project itself declares must be in
394
- // the lockfile before the pins mean anything, and the repair is a
395
- // tidy rather than a fetch. Transitive dependencies need no separate
396
- // check: a locked module's own imports are resolved when its pin is
397
- // recomputed, so one that is unreachable makes its DEPENDANT fail to
398
- // evaluate and lands in `mismatched` below.
399
296
  const declared = declaredDeps(pathJoin(root, 'mod.aon'), options)
400
297
  const unlocked = Object.keys(declared)
401
298
  .filter((mod) => null == locked[mod]).sort()
@@ -417,10 +314,6 @@ export function modVerify(root: string, options: ModToolOptions):
417
314
  continue
418
315
  }
419
316
 
420
- // A module that no longer stands up is not a match: it has no
421
- // meaning to compare, and reporting `got: <hash of nil>` would
422
- // print the same string for every broken module. The empty `got`
423
- // says the store holds something that does not evaluate.
424
317
  const got = options.eval(readFileSync(main, 'utf8'), main)
425
318
  const want = locked[mod].canon
426
319
  if (got.ok && want === got.hash) {
@@ -464,17 +357,6 @@ export function modVendor(root: string, options: ModToolOptions):
464
357
  continue
465
358
  }
466
359
 
467
- // WHY THERE IS NO CONTAINMENT CHECK ON `to`, at the one write site
468
- // that copied a tree outside the project: `usableRef` above is the
469
- // gate, and after it a store path CANNOT escape. Every element is
470
- // non-empty and neither begins nor ends with `.`, so none is `.`
471
- // or `..`; MODULE_RE's element class admits no `/`, no `\` and no
472
- // leading slash, so no element can re-root the join. A second
473
- // lexical check here would be unreachable code, which ADR-002 asks
474
- // to be deleted rather than excluded -- so the invariant is pinned
475
- // by a test that drives the escape through this verb instead.
476
- // ANY NEW CALLER of moduleDir must go through usableRef too;
477
- // `mod get` is the next one.
478
360
  const to = moduleDir(vendorRoot, ref)
479
361
  if (from !== to) {
480
362
  copyTree(from, to)
@@ -508,33 +390,10 @@ function copyTree(from: string, to: string): void {
508
390
  }
509
391
 
510
392
 
511
- // THE PUBLISH BOUNDARY (G6 phase 4,
512
- // docs/capability-review/g6-distribution.md). A module is an OCI
513
- // artifact, and what a publish PUSHES is a manifest: a config media
514
- // type, one layer holding the module's source tree, and annotations
515
- // carrying the module path, its version and its canon-hash.
516
- //
517
- // The push needs a registry, which this build does not have. Everything
518
- // the push would ASSERT is local, and that is what `aontu mod manifest`
519
- // answers: the exact artifact description, computed the way the
520
- // registry would be told it, plus the gate that decides whether it may
521
- // be minted at all.
522
- //
523
- // WHY THE ANNOTATION MATTERS MORE THAN THE BYTES. "Has the truth
524
- // changed?" is one annotation read and a string compare -- no download,
525
- // no parse -- because the canon-hash pins MEANING rather than text. A
526
- // consumer holding `aon1-oQs6…` can ask a registry index whether the
527
- // module still hashes to it, and a reformat, a comment or a file split
528
- // will not move it.
529
-
530
393
  // The config media type the design fixes: an Aontu module is not an
531
394
  // image, and the type is what tells a registry so.
532
395
  export const MODULE_CONFIG_MEDIA_TYPE = 'application/vnd.aontu.module.v1+json'
533
396
 
534
- // The canon-hash annotation. OCI asks a custom key to be the reverse
535
- // DNS of a domain its author controls, and the project's own home is
536
- // the only domain it has -- inventing an `aontu.dev` would be a claim
537
- // it cannot back. The two facts OCI already has keys for use those.
538
397
  export const MODULE_ANNOTATION_CANON = 'com.github.rjrodger.aontu.canon'
539
398
  export const MODULE_ANNOTATION_MAJOR = 'com.github.rjrodger.aontu.major'
540
399
 
@@ -549,9 +408,6 @@ export type ModManifestReport = {
549
408
  // The canon-hash of the module's entry file, evaluated standalone.
550
409
  canon: string
551
410
  config: string
552
- // The layer's contents: every file of the source tree, relative,
553
- // forward-slashed and sorted, so two implementations on two platforms
554
- // describe the same layer.
555
411
  files: string[]
556
412
  annotations: Record<string, string>
557
413
  // What the module does not declare, sorted. A manifest cannot be
@@ -583,20 +439,12 @@ function modSelf(dir: string, options: ModToolOptions): ModSelf {
583
439
  }
584
440
 
585
441
 
586
- // The leading numeric component of a version, which is the major an
587
- // import spells. Empty when the version does not start with one: a
588
- // version whose major cannot be read cannot be published under a
589
- // module path, because the path is where the major lives.
590
442
  function majorOf(version: string): string {
591
443
  const m = /^(\d+)/.exec(version)
592
444
  return null == m ? '' : m[1]
593
445
  }
594
446
 
595
447
 
596
- // Every file of a module's source tree, relative and forward-slashed.
597
- // `aontu_meta/vendor/` is excluded: a published module carries its own
598
- // sources, not a copy of everyone else's -- a consumer resolves the
599
- // closure itself, and a nested vendor tree would publish the world.
600
448
  function layerFiles(dir: string, prefix = ''): string[] {
601
449
  const out: string[] = []
602
450
  for (const name of readdirSync(dir).sort()) {
@@ -688,16 +536,10 @@ export function modManifest(
688
536
  return report
689
537
  }
690
538
 
691
- // A MAJOR BUMP IS WHERE BREAKING IS ALLOWED. The major lives in the
692
- // module path, so a consumer of `@1` never sees `@2` unless it asks:
693
- // checking compatibility across majors would forbid the one change
694
- // the version scheme exists to express.
695
539
  if (majorOf(prior.version) !== major) {
696
540
  return report
697
541
  }
698
542
 
699
- // Backward compatibility: the NEW version is the general side, so
700
- // every instance the old one admitted must still be admitted.
701
543
  const gate = subsume(newSrc, readFileSync(priorMain, 'utf8'), {
702
544
  generalUrl: main,
703
545
  specificUrl: priorMain,