@ontrails/warden 1.0.0-beta.13 → 1.0.0-beta.15

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 (474) hide show
  1. package/.turbo/turbo-lint.log +1 -1
  2. package/CHANGELOG.md +30 -0
  3. package/README.md +31 -20
  4. package/dist/cli.d.ts +19 -2
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +261 -64
  7. package/dist/cli.js.map +1 -1
  8. package/dist/draft.d.ts +5 -0
  9. package/dist/draft.d.ts.map +1 -0
  10. package/dist/draft.js +16 -0
  11. package/dist/draft.js.map +1 -0
  12. package/dist/drift.d.ts +10 -7
  13. package/dist/drift.d.ts.map +1 -1
  14. package/dist/drift.js +50 -16
  15. package/dist/drift.js.map +1 -1
  16. package/dist/formatters.d.ts +2 -1
  17. package/dist/formatters.d.ts.map +1 -1
  18. package/dist/formatters.js +15 -4
  19. package/dist/formatters.js.map +1 -1
  20. package/dist/index.d.ts +9 -17
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +10 -17
  23. package/dist/index.js.map +1 -1
  24. package/dist/rules/ast.d.ts +412 -7
  25. package/dist/rules/ast.d.ts.map +1 -1
  26. package/dist/rules/ast.js +1847 -102
  27. package/dist/rules/ast.js.map +1 -1
  28. package/dist/rules/circular-refs.d.ts +6 -0
  29. package/dist/rules/circular-refs.d.ts.map +1 -0
  30. package/dist/rules/circular-refs.js +83 -0
  31. package/dist/rules/circular-refs.js.map +1 -0
  32. package/dist/rules/context-no-surface-types.d.ts.map +1 -1
  33. package/dist/rules/context-no-surface-types.js +59 -3
  34. package/dist/rules/context-no-surface-types.js.map +1 -1
  35. package/dist/rules/contour-exists.d.ts +7 -0
  36. package/dist/rules/contour-exists.d.ts.map +1 -0
  37. package/dist/rules/contour-exists.js +113 -0
  38. package/dist/rules/contour-exists.js.map +1 -0
  39. package/dist/rules/contour-ids.d.ts +10 -0
  40. package/dist/rules/contour-ids.d.ts.map +1 -0
  41. package/dist/rules/contour-ids.js +12 -0
  42. package/dist/rules/contour-ids.js.map +1 -0
  43. package/dist/rules/cross-declarations.d.ts.map +1 -1
  44. package/dist/rules/cross-declarations.js +171 -57
  45. package/dist/rules/cross-declarations.js.map +1 -1
  46. package/dist/rules/dead-internal-trail.d.ts +3 -0
  47. package/dist/rules/dead-internal-trail.d.ts.map +1 -0
  48. package/dist/rules/dead-internal-trail.js +80 -0
  49. package/dist/rules/dead-internal-trail.js.map +1 -0
  50. package/dist/rules/draft-file-marking.d.ts +6 -0
  51. package/dist/rules/draft-file-marking.d.ts.map +1 -0
  52. package/dist/rules/draft-file-marking.js +87 -0
  53. package/dist/rules/draft-file-marking.js.map +1 -0
  54. package/dist/rules/draft-visible-debt.d.ts +12 -0
  55. package/dist/rules/draft-visible-debt.d.ts.map +1 -0
  56. package/dist/rules/draft-visible-debt.js +50 -0
  57. package/dist/rules/draft-visible-debt.js.map +1 -0
  58. package/dist/rules/error-mapping-completeness.d.ts +13 -0
  59. package/dist/rules/error-mapping-completeness.d.ts.map +1 -0
  60. package/dist/rules/error-mapping-completeness.js +160 -0
  61. package/dist/rules/error-mapping-completeness.js.map +1 -0
  62. package/dist/rules/example-valid.d.ts +6 -0
  63. package/dist/rules/example-valid.d.ts.map +1 -0
  64. package/dist/rules/example-valid.js +203 -0
  65. package/dist/rules/example-valid.js.map +1 -0
  66. package/dist/rules/fires-declarations.d.ts +16 -0
  67. package/dist/rules/fires-declarations.d.ts.map +1 -0
  68. package/dist/rules/fires-declarations.js +444 -0
  69. package/dist/rules/fires-declarations.js.map +1 -0
  70. package/dist/rules/implementation-returns-result.d.ts +9 -0
  71. package/dist/rules/implementation-returns-result.d.ts.map +1 -1
  72. package/dist/rules/implementation-returns-result.js +638 -76
  73. package/dist/rules/implementation-returns-result.js.map +1 -1
  74. package/dist/rules/incomplete-accessor-for-standard-op.d.ts +30 -0
  75. package/dist/rules/incomplete-accessor-for-standard-op.d.ts.map +1 -0
  76. package/dist/rules/incomplete-accessor-for-standard-op.js +226 -0
  77. package/dist/rules/incomplete-accessor-for-standard-op.js.map +1 -0
  78. package/dist/rules/incomplete-crud.d.ts +21 -0
  79. package/dist/rules/incomplete-crud.d.ts.map +1 -0
  80. package/dist/rules/incomplete-crud.js +368 -0
  81. package/dist/rules/incomplete-crud.js.map +1 -0
  82. package/dist/rules/index.d.ts +40 -7
  83. package/dist/rules/index.d.ts.map +1 -1
  84. package/dist/rules/index.js +91 -15
  85. package/dist/rules/index.js.map +1 -1
  86. package/dist/rules/intent-propagation.d.ts +3 -0
  87. package/dist/rules/intent-propagation.d.ts.map +1 -0
  88. package/dist/rules/intent-propagation.js +57 -0
  89. package/dist/rules/intent-propagation.js.map +1 -0
  90. package/dist/rules/missing-reconcile.d.ts +3 -0
  91. package/dist/rules/missing-reconcile.d.ts.map +1 -0
  92. package/dist/rules/missing-reconcile.js +44 -0
  93. package/dist/rules/missing-reconcile.js.map +1 -0
  94. package/dist/rules/missing-visibility.d.ts +3 -0
  95. package/dist/rules/missing-visibility.d.ts.map +1 -0
  96. package/dist/rules/missing-visibility.js +63 -0
  97. package/dist/rules/missing-visibility.js.map +1 -0
  98. package/dist/rules/no-direct-impl-in-route.d.ts.map +1 -1
  99. package/dist/rules/no-direct-impl-in-route.js +0 -3
  100. package/dist/rules/no-direct-impl-in-route.js.map +1 -1
  101. package/dist/rules/no-direct-implementation-call.js +1 -1
  102. package/dist/rules/no-direct-implementation-call.js.map +1 -1
  103. package/dist/rules/no-sync-result-assumption.d.ts.map +1 -1
  104. package/dist/rules/no-sync-result-assumption.js +870 -61
  105. package/dist/rules/no-sync-result-assumption.js.map +1 -1
  106. package/dist/rules/no-throw-in-detour-recover.d.ts +3 -0
  107. package/dist/rules/no-throw-in-detour-recover.d.ts.map +1 -0
  108. package/dist/rules/no-throw-in-detour-recover.js +147 -0
  109. package/dist/rules/no-throw-in-detour-recover.js.map +1 -0
  110. package/dist/rules/no-throw-in-detour-target.d.ts +4 -1
  111. package/dist/rules/no-throw-in-detour-target.d.ts.map +1 -1
  112. package/dist/rules/no-throw-in-detour-target.js +6 -3
  113. package/dist/rules/no-throw-in-detour-target.js.map +1 -1
  114. package/dist/rules/no-throw-in-implementation.d.ts +4 -2
  115. package/dist/rules/no-throw-in-implementation.d.ts.map +1 -1
  116. package/dist/rules/no-throw-in-implementation.js +6 -4
  117. package/dist/rules/no-throw-in-implementation.js.map +1 -1
  118. package/dist/rules/on-references-exist.d.ts +14 -0
  119. package/dist/rules/on-references-exist.d.ts.map +1 -0
  120. package/dist/rules/on-references-exist.js +109 -0
  121. package/dist/rules/on-references-exist.js.map +1 -0
  122. package/dist/rules/orphaned-signal.d.ts +3 -0
  123. package/dist/rules/orphaned-signal.d.ts.map +1 -0
  124. package/dist/rules/orphaned-signal.js +67 -0
  125. package/dist/rules/orphaned-signal.js.map +1 -0
  126. package/dist/rules/permit-governance.d.ts +3 -0
  127. package/dist/rules/permit-governance.d.ts.map +1 -0
  128. package/dist/rules/permit-governance.js +15 -0
  129. package/dist/rules/permit-governance.js.map +1 -0
  130. package/dist/rules/reference-exists.d.ts +6 -0
  131. package/dist/rules/reference-exists.d.ts.map +1 -0
  132. package/dist/rules/reference-exists.js +47 -0
  133. package/dist/rules/reference-exists.js.map +1 -0
  134. package/dist/rules/registry-names.d.ts +8 -0
  135. package/dist/rules/registry-names.d.ts.map +1 -0
  136. package/dist/rules/registry-names.js +83 -0
  137. package/dist/rules/registry-names.js.map +1 -0
  138. package/dist/rules/resource-declarations.d.ts +14 -0
  139. package/dist/rules/resource-declarations.d.ts.map +1 -0
  140. package/dist/rules/resource-declarations.js +413 -0
  141. package/dist/rules/resource-declarations.js.map +1 -0
  142. package/dist/rules/resource-exists.d.ts +6 -0
  143. package/dist/rules/resource-exists.d.ts.map +1 -0
  144. package/dist/rules/resource-exists.js +90 -0
  145. package/dist/rules/resource-exists.js.map +1 -0
  146. package/dist/rules/resource-id-grammar.d.ts +3 -0
  147. package/dist/rules/resource-id-grammar.d.ts.map +1 -0
  148. package/dist/rules/resource-id-grammar.js +39 -0
  149. package/dist/rules/resource-id-grammar.js.map +1 -0
  150. package/dist/rules/specs.d.ts.map +1 -1
  151. package/dist/rules/specs.js +5 -1
  152. package/dist/rules/specs.js.map +1 -1
  153. package/dist/rules/types.d.ts +53 -4
  154. package/dist/rules/types.d.ts.map +1 -1
  155. package/dist/rules/unreachable-detour-shadowing.d.ts +3 -0
  156. package/dist/rules/unreachable-detour-shadowing.d.ts.map +1 -0
  157. package/dist/rules/unreachable-detour-shadowing.js +202 -0
  158. package/dist/rules/unreachable-detour-shadowing.js.map +1 -0
  159. package/dist/rules/valid-describe-refs.d.ts.map +1 -1
  160. package/dist/rules/valid-describe-refs.js +132 -16
  161. package/dist/rules/valid-describe-refs.js.map +1 -1
  162. package/dist/rules/valid-detour-contract.d.ts +3 -0
  163. package/dist/rules/valid-detour-contract.d.ts.map +1 -0
  164. package/dist/rules/valid-detour-contract.js +47 -0
  165. package/dist/rules/valid-detour-contract.js.map +1 -0
  166. package/dist/rules/valid-detour-refs.d.ts.map +1 -1
  167. package/dist/rules/valid-detour-refs.js +73 -82
  168. package/dist/rules/valid-detour-refs.js.map +1 -1
  169. package/dist/rules/warden-export-symmetry.d.ts +7 -0
  170. package/dist/rules/warden-export-symmetry.d.ts.map +1 -0
  171. package/dist/rules/warden-export-symmetry.js +352 -0
  172. package/dist/rules/warden-export-symmetry.js.map +1 -0
  173. package/dist/rules/warden-rules-use-ast.d.ts +17 -0
  174. package/dist/rules/warden-rules-use-ast.d.ts.map +1 -0
  175. package/dist/rules/warden-rules-use-ast.js +778 -0
  176. package/dist/rules/warden-rules-use-ast.js.map +1 -0
  177. package/dist/trails/circular-refs.trail.d.ts +24 -0
  178. package/dist/trails/circular-refs.trail.d.ts.map +1 -0
  179. package/dist/trails/circular-refs.trail.js +29 -0
  180. package/dist/trails/circular-refs.trail.js.map +1 -0
  181. package/dist/trails/context-no-surface-types.trail.d.ts +2 -2
  182. package/dist/trails/context-no-surface-types.trail.d.ts.map +1 -1
  183. package/dist/trails/context-no-trailhead-types.trail.d.ts +2 -2
  184. package/dist/trails/context-no-trailhead-types.trail.d.ts.map +1 -1
  185. package/dist/trails/contour-exists.trail.d.ts +24 -0
  186. package/dist/trails/contour-exists.trail.d.ts.map +1 -0
  187. package/dist/trails/contour-exists.trail.js +21 -0
  188. package/dist/trails/contour-exists.trail.js.map +1 -0
  189. package/dist/trails/cross-declarations.trail.d.ts +2 -2
  190. package/dist/trails/cross-declarations.trail.d.ts.map +1 -1
  191. package/dist/trails/dead-internal-trail.trail.d.ts +24 -0
  192. package/dist/trails/dead-internal-trail.trail.d.ts.map +1 -0
  193. package/dist/trails/dead-internal-trail.trail.js +26 -0
  194. package/dist/trails/dead-internal-trail.trail.js.map +1 -0
  195. package/dist/trails/{provision-declarations.trail.d.ts → draft-file-marking.trail.d.ts} +3 -3
  196. package/dist/trails/draft-file-marking.trail.d.ts.map +1 -0
  197. package/dist/trails/draft-file-marking.trail.js +16 -0
  198. package/dist/trails/draft-file-marking.trail.js.map +1 -0
  199. package/dist/trails/draft-visible-debt.trail.d.ts +13 -0
  200. package/dist/trails/draft-visible-debt.trail.d.ts.map +1 -0
  201. package/dist/trails/draft-visible-debt.trail.js +16 -0
  202. package/dist/trails/draft-visible-debt.trail.js.map +1 -0
  203. package/dist/trails/error-mapping-completeness.trail.d.ts +13 -0
  204. package/dist/trails/error-mapping-completeness.trail.d.ts.map +1 -0
  205. package/dist/trails/error-mapping-completeness.trail.js +29 -0
  206. package/dist/trails/error-mapping-completeness.trail.js.map +1 -0
  207. package/dist/trails/{follow-declarations.trail.d.ts → example-valid.trail.d.ts} +3 -3
  208. package/dist/trails/example-valid.trail.d.ts.map +1 -0
  209. package/dist/trails/example-valid.trail.js +25 -0
  210. package/dist/trails/example-valid.trail.js.map +1 -0
  211. package/dist/trails/fires-declarations.trail.d.ts +13 -0
  212. package/dist/trails/fires-declarations.trail.d.ts.map +1 -0
  213. package/dist/trails/fires-declarations.trail.js +22 -0
  214. package/dist/trails/fires-declarations.trail.js.map +1 -0
  215. package/dist/trails/implementation-returns-result.trail.d.ts +2 -2
  216. package/dist/trails/implementation-returns-result.trail.d.ts.map +1 -1
  217. package/dist/trails/incomplete-accessor-for-standard-op.trail.d.ts +12 -0
  218. package/dist/trails/incomplete-accessor-for-standard-op.trail.d.ts.map +1 -0
  219. package/dist/trails/incomplete-accessor-for-standard-op.trail.js +60 -0
  220. package/dist/trails/incomplete-accessor-for-standard-op.trail.js.map +1 -0
  221. package/dist/trails/incomplete-crud.trail.d.ts +24 -0
  222. package/dist/trails/incomplete-crud.trail.d.ts.map +1 -0
  223. package/dist/trails/incomplete-crud.trail.js +39 -0
  224. package/dist/trails/incomplete-crud.trail.js.map +1 -0
  225. package/dist/trails/index.d.ts +29 -7
  226. package/dist/trails/index.d.ts.map +1 -1
  227. package/dist/trails/index.js +28 -6
  228. package/dist/trails/index.js.map +1 -1
  229. package/dist/trails/intent-propagation.trail.d.ts +24 -0
  230. package/dist/trails/intent-propagation.trail.d.ts.map +1 -0
  231. package/dist/trails/intent-propagation.trail.js +30 -0
  232. package/dist/trails/intent-propagation.trail.js.map +1 -0
  233. package/dist/trails/missing-reconcile.trail.d.ts +24 -0
  234. package/dist/trails/missing-reconcile.trail.d.ts.map +1 -0
  235. package/dist/trails/missing-reconcile.trail.js +33 -0
  236. package/dist/trails/missing-reconcile.trail.js.map +1 -0
  237. package/dist/trails/missing-visibility.trail.d.ts +24 -0
  238. package/dist/trails/missing-visibility.trail.d.ts.map +1 -0
  239. package/dist/trails/missing-visibility.trail.js +22 -0
  240. package/dist/trails/missing-visibility.trail.js.map +1 -0
  241. package/dist/trails/no-direct-impl-in-route.trail.d.ts +2 -2
  242. package/dist/trails/no-direct-impl-in-route.trail.d.ts.map +1 -1
  243. package/dist/trails/no-direct-implementation-call.trail.d.ts +2 -2
  244. package/dist/trails/no-direct-implementation-call.trail.d.ts.map +1 -1
  245. package/dist/trails/no-sync-result-assumption.trail.d.ts +2 -2
  246. package/dist/trails/no-sync-result-assumption.trail.d.ts.map +1 -1
  247. package/dist/trails/no-throw-in-detour-recover.trail.d.ts +13 -0
  248. package/dist/trails/no-throw-in-detour-recover.trail.d.ts.map +1 -0
  249. package/dist/trails/no-throw-in-detour-recover.trail.js +24 -0
  250. package/dist/trails/no-throw-in-detour-recover.trail.js.map +1 -0
  251. package/dist/trails/no-throw-in-detour-target.trail.d.ts +13 -3
  252. package/dist/trails/no-throw-in-detour-target.trail.d.ts.map +1 -1
  253. package/dist/trails/no-throw-in-implementation.trail.d.ts +2 -2
  254. package/dist/trails/no-throw-in-implementation.trail.d.ts.map +1 -1
  255. package/dist/trails/on-references-exist.trail.d.ts +24 -0
  256. package/dist/trails/on-references-exist.trail.d.ts.map +1 -0
  257. package/dist/trails/on-references-exist.trail.js +21 -0
  258. package/dist/trails/on-references-exist.trail.js.map +1 -0
  259. package/dist/trails/orphaned-signal.trail.d.ts +24 -0
  260. package/dist/trails/orphaned-signal.trail.d.ts.map +1 -0
  261. package/dist/trails/orphaned-signal.trail.js +36 -0
  262. package/dist/trails/orphaned-signal.trail.js.map +1 -0
  263. package/dist/trails/permit-governance.trail.d.ts +12 -0
  264. package/dist/trails/permit-governance.trail.d.ts.map +1 -0
  265. package/dist/trails/permit-governance.trail.js +47 -0
  266. package/dist/trails/permit-governance.trail.js.map +1 -0
  267. package/dist/trails/prefer-schema-inference.trail.d.ts +2 -2
  268. package/dist/trails/prefer-schema-inference.trail.d.ts.map +1 -1
  269. package/dist/trails/reference-exists.trail.d.ts +24 -0
  270. package/dist/trails/reference-exists.trail.d.ts.map +1 -0
  271. package/dist/trails/reference-exists.trail.js +25 -0
  272. package/dist/trails/reference-exists.trail.js.map +1 -0
  273. package/dist/trails/resource-declarations.trail.d.ts +13 -0
  274. package/dist/trails/resource-declarations.trail.d.ts.map +1 -0
  275. package/dist/trails/{provision-declarations.trail.js → resource-declarations.trail.js} +7 -7
  276. package/dist/trails/resource-declarations.trail.js.map +1 -0
  277. package/dist/trails/resource-exists.trail.d.ts +24 -0
  278. package/dist/trails/resource-exists.trail.d.ts.map +1 -0
  279. package/dist/trails/{provision-exists.trail.js → resource-exists.trail.js} +8 -8
  280. package/dist/trails/resource-exists.trail.js.map +1 -0
  281. package/dist/trails/resource-id-grammar.trail.d.ts +13 -0
  282. package/dist/trails/resource-id-grammar.trail.d.ts.map +1 -0
  283. package/dist/trails/resource-id-grammar.trail.js +38 -0
  284. package/dist/trails/resource-id-grammar.trail.js.map +1 -0
  285. package/dist/trails/run.d.ts +25 -9
  286. package/dist/trails/run.d.ts.map +1 -1
  287. package/dist/trails/run.js +63 -19
  288. package/dist/trails/run.js.map +1 -1
  289. package/dist/trails/schema.d.ts +28 -3
  290. package/dist/trails/schema.d.ts.map +1 -1
  291. package/dist/trails/schema.js +57 -4
  292. package/dist/trails/schema.js.map +1 -1
  293. package/dist/trails/unreachable-detour-shadowing.trail.d.ts +13 -0
  294. package/dist/trails/unreachable-detour-shadowing.trail.d.ts.map +1 -0
  295. package/dist/trails/unreachable-detour-shadowing.trail.js +44 -0
  296. package/dist/trails/unreachable-detour-shadowing.trail.js.map +1 -0
  297. package/dist/trails/valid-describe-refs.trail.d.ts +12 -3
  298. package/dist/trails/valid-describe-refs.trail.d.ts.map +1 -1
  299. package/dist/trails/valid-detour-contract.trail.d.ts +12 -0
  300. package/dist/trails/valid-detour-contract.trail.d.ts.map +1 -0
  301. package/dist/trails/valid-detour-contract.trail.js +66 -0
  302. package/dist/trails/valid-detour-contract.trail.js.map +1 -0
  303. package/dist/trails/valid-detour-refs.trail.d.ts +13 -3
  304. package/dist/trails/valid-detour-refs.trail.d.ts.map +1 -1
  305. package/dist/trails/warden-export-symmetry.trail.d.ts +13 -0
  306. package/dist/trails/warden-export-symmetry.trail.d.ts.map +1 -0
  307. package/dist/trails/warden-export-symmetry.trail.js +16 -0
  308. package/dist/trails/warden-export-symmetry.trail.js.map +1 -0
  309. package/dist/trails/warden-rules-use-ast.trail.d.ts +13 -0
  310. package/dist/trails/warden-rules-use-ast.trail.d.ts.map +1 -0
  311. package/dist/trails/warden-rules-use-ast.trail.js +41 -0
  312. package/dist/trails/warden-rules-use-ast.trail.js.map +1 -0
  313. package/dist/trails/wrap-rule.d.ts +16 -2
  314. package/dist/trails/wrap-rule.d.ts.map +1 -1
  315. package/dist/trails/wrap-rule.js +71 -11
  316. package/dist/trails/wrap-rule.js.map +1 -1
  317. package/package.json +7 -4
  318. package/src/__tests__/ast.test.ts +613 -0
  319. package/src/__tests__/circular-refs.test.ts +121 -0
  320. package/src/__tests__/cli.test.ts +360 -32
  321. package/src/__tests__/contour-exists.test.ts +203 -0
  322. package/src/__tests__/cross-declarations.test.ts +245 -0
  323. package/src/__tests__/dead-internal-trail.test.ts +81 -0
  324. package/src/__tests__/draft-rules-context.test.ts +150 -0
  325. package/src/__tests__/drift.test.ts +75 -5
  326. package/src/__tests__/error-mapping-completeness.test.ts +56 -0
  327. package/src/__tests__/example-valid.test.ts +101 -0
  328. package/src/__tests__/fires-declarations-param-destructure.test.ts +54 -0
  329. package/src/__tests__/fires-declarations.test.ts +652 -0
  330. package/src/__tests__/formatters.test.ts +2 -2
  331. package/src/__tests__/implementation-returns-result.test.ts +1016 -2
  332. package/src/__tests__/incomplete-accessor-for-standard-op.test.ts +337 -0
  333. package/src/__tests__/incomplete-crud.test.ts +498 -0
  334. package/src/__tests__/intent-propagation.test.ts +116 -0
  335. package/src/__tests__/missing-reconcile.test.ts +154 -0
  336. package/src/__tests__/missing-visibility.test.ts +108 -0
  337. package/src/__tests__/no-sync-result-assumption.test.ts +870 -39
  338. package/src/__tests__/no-throw-in-detour-recover.test.ts +93 -0
  339. package/src/__tests__/no-throw-in-implementation.test.ts +88 -0
  340. package/src/__tests__/on-references-exist.test.ts +151 -0
  341. package/src/__tests__/orphaned-signal.test.ts +137 -0
  342. package/src/__tests__/permit-governance.test.ts +66 -0
  343. package/src/__tests__/reference-exists.test.ts +281 -0
  344. package/src/__tests__/resource-declarations.test.ts +448 -0
  345. package/src/__tests__/resource-exists.test.ts +122 -0
  346. package/src/__tests__/resource-id-grammar.test.ts +50 -0
  347. package/src/__tests__/rules.test.ts +17 -77
  348. package/src/__tests__/topo-aware-rule.test.ts +257 -0
  349. package/src/__tests__/trails.test.ts +2 -2
  350. package/src/__tests__/unreachable-detour-shadowing.test.ts +128 -0
  351. package/src/__tests__/valid-describe-refs.test.ts +183 -0
  352. package/src/__tests__/valid-detour-contract.test.ts +86 -0
  353. package/src/__tests__/warden-export-symmetry.test.ts +251 -0
  354. package/src/__tests__/warden-rules-use-ast.test.ts +468 -0
  355. package/src/__tests__/wrap-rule.test.ts +3 -3
  356. package/src/cli.ts +458 -91
  357. package/src/draft.ts +22 -0
  358. package/src/drift.ts +63 -21
  359. package/src/formatters.ts +15 -4
  360. package/src/index.ts +62 -23
  361. package/src/rules/ast.ts +2715 -119
  362. package/src/rules/circular-refs.ts +154 -0
  363. package/src/rules/{context-no-trailhead-types.ts → context-no-surface-types.ts} +72 -12
  364. package/src/rules/contour-exists.ts +251 -0
  365. package/src/rules/contour-ids.ts +15 -0
  366. package/src/rules/cross-declarations.ts +277 -69
  367. package/src/rules/dead-internal-trail.ts +141 -0
  368. package/src/rules/draft-file-marking.ts +160 -0
  369. package/src/rules/draft-visible-debt.ts +87 -0
  370. package/src/rules/error-mapping-completeness.ts +273 -0
  371. package/src/rules/example-valid.ts +401 -0
  372. package/src/rules/fires-declarations.ts +609 -0
  373. package/src/rules/implementation-returns-result.ts +1042 -122
  374. package/src/rules/incomplete-accessor-for-standard-op.ts +315 -0
  375. package/src/rules/incomplete-crud.ts +579 -0
  376. package/src/rules/index.ts +95 -16
  377. package/src/rules/intent-propagation.ts +142 -0
  378. package/src/rules/missing-reconcile.ts +98 -0
  379. package/src/rules/missing-visibility.ts +110 -0
  380. package/src/rules/no-direct-impl-in-route.ts +0 -4
  381. package/src/rules/no-direct-implementation-call.ts +1 -1
  382. package/src/rules/no-sync-result-assumption.ts +1134 -96
  383. package/src/rules/no-throw-in-detour-recover.ts +225 -0
  384. package/src/rules/no-throw-in-implementation.ts +6 -4
  385. package/src/rules/on-references-exist.ts +194 -0
  386. package/src/rules/orphaned-signal.ts +150 -0
  387. package/src/rules/permit-governance.ts +25 -0
  388. package/src/rules/reference-exists.ts +98 -0
  389. package/src/rules/registry-names.ts +83 -0
  390. package/src/rules/{provision-declarations.ts → resource-declarations.ts} +208 -138
  391. package/src/rules/{provision-exists.ts → resource-exists.ts} +48 -51
  392. package/src/rules/resource-id-grammar.ts +65 -0
  393. package/src/rules/specs.ts +5 -1
  394. package/src/rules/types.ts +57 -4
  395. package/src/rules/unreachable-detour-shadowing.ts +375 -0
  396. package/src/rules/valid-describe-refs.ts +160 -32
  397. package/src/rules/valid-detour-contract.ts +78 -0
  398. package/src/rules/warden-export-symmetry.ts +533 -0
  399. package/src/rules/warden-rules-use-ast.ts +996 -0
  400. package/src/trails/circular-refs.trail.ts +29 -0
  401. package/src/trails/{context-no-trailhead-types.trail.ts → context-no-surface-types.trail.ts} +4 -4
  402. package/src/trails/contour-exists.trail.ts +21 -0
  403. package/src/trails/dead-internal-trail.trail.ts +26 -0
  404. package/src/trails/draft-file-marking.trail.ts +16 -0
  405. package/src/trails/draft-visible-debt.trail.ts +16 -0
  406. package/src/trails/error-mapping-completeness.trail.ts +29 -0
  407. package/src/trails/example-valid.trail.ts +25 -0
  408. package/src/trails/fires-declarations.trail.ts +22 -0
  409. package/src/trails/incomplete-accessor-for-standard-op.trail.ts +76 -0
  410. package/src/trails/incomplete-crud.trail.ts +39 -0
  411. package/src/trails/index.ts +40 -7
  412. package/src/trails/intent-propagation.trail.ts +30 -0
  413. package/src/trails/missing-reconcile.trail.ts +33 -0
  414. package/src/trails/missing-visibility.trail.ts +22 -0
  415. package/src/trails/no-throw-in-detour-recover.trail.ts +24 -0
  416. package/src/trails/on-references-exist.trail.ts +21 -0
  417. package/src/trails/orphaned-signal.trail.ts +36 -0
  418. package/src/trails/permit-governance.trail.ts +51 -0
  419. package/src/trails/reference-exists.trail.ts +25 -0
  420. package/src/trails/{provision-declarations.trail.ts → resource-declarations.trail.ts} +6 -6
  421. package/src/trails/{provision-exists.trail.ts → resource-exists.trail.ts} +7 -7
  422. package/src/trails/resource-id-grammar.trail.ts +39 -0
  423. package/src/trails/run.ts +121 -24
  424. package/src/trails/schema.ts +66 -4
  425. package/src/trails/unreachable-detour-shadowing.trail.ts +45 -0
  426. package/src/trails/valid-detour-contract.trail.ts +71 -0
  427. package/src/trails/warden-export-symmetry.trail.ts +16 -0
  428. package/src/trails/warden-rules-use-ast.trail.ts +45 -0
  429. package/src/trails/wrap-rule.ts +104 -12
  430. package/tsconfig.tests.json +10 -0
  431. package/tsconfig.tsbuildinfo +1 -1
  432. package/dist/rules/follow-declarations.d.ts +0 -13
  433. package/dist/rules/follow-declarations.d.ts.map +0 -1
  434. package/dist/rules/follow-declarations.js +0 -264
  435. package/dist/rules/follow-declarations.js.map +0 -1
  436. package/dist/rules/provision-declarations.d.ts +0 -14
  437. package/dist/rules/provision-declarations.d.ts.map +0 -1
  438. package/dist/rules/provision-declarations.js +0 -344
  439. package/dist/rules/provision-declarations.js.map +0 -1
  440. package/dist/rules/provision-exists.d.ts +0 -6
  441. package/dist/rules/provision-exists.d.ts.map +0 -1
  442. package/dist/rules/provision-exists.js +0 -89
  443. package/dist/rules/provision-exists.js.map +0 -1
  444. package/dist/rules/service-declarations.d.ts +0 -16
  445. package/dist/rules/service-declarations.d.ts.map +0 -1
  446. package/dist/rules/service-declarations.js +0 -346
  447. package/dist/rules/service-declarations.js.map +0 -1
  448. package/dist/rules/service-exists.d.ts +0 -8
  449. package/dist/rules/service-exists.d.ts.map +0 -1
  450. package/dist/rules/service-exists.js +0 -91
  451. package/dist/rules/service-exists.js.map +0 -1
  452. package/dist/trails/follow-declarations.trail.d.ts.map +0 -1
  453. package/dist/trails/follow-declarations.trail.js +0 -22
  454. package/dist/trails/follow-declarations.trail.js.map +0 -1
  455. package/dist/trails/provision-declarations.trail.d.ts.map +0 -1
  456. package/dist/trails/provision-declarations.trail.js.map +0 -1
  457. package/dist/trails/provision-exists.trail.d.ts +0 -15
  458. package/dist/trails/provision-exists.trail.d.ts.map +0 -1
  459. package/dist/trails/provision-exists.trail.js.map +0 -1
  460. package/dist/trails/service-declarations.trail.d.ts +0 -26
  461. package/dist/trails/service-declarations.trail.d.ts.map +0 -1
  462. package/dist/trails/service-declarations.trail.js +0 -27
  463. package/dist/trails/service-declarations.trail.js.map +0 -1
  464. package/dist/trails/service-exists.trail.d.ts +0 -32
  465. package/dist/trails/service-exists.trail.d.ts.map +0 -1
  466. package/dist/trails/service-exists.trail.js +0 -29
  467. package/dist/trails/service-exists.trail.js.map +0 -1
  468. package/src/__tests__/no-throw-in-detour-target.test.ts +0 -78
  469. package/src/__tests__/provision-declarations.test.ts +0 -318
  470. package/src/__tests__/provision-exists.test.ts +0 -122
  471. package/src/rules/no-throw-in-detour-target.ts +0 -150
  472. package/src/rules/valid-detour-refs.ts +0 -187
  473. package/src/trails/no-throw-in-detour-target.trail.ts +0 -20
  474. package/src/trails/valid-detour-refs.trail.ts +0 -24
@@ -1,3 +1,3 @@
1
1
  $ oxlint ./src
2
2
  Found 0 warnings and 0 errors.
3
- Finished in 52ms on 56 files with 93 rules using 24 threads.
3
+ Finished in 73ms on 126 files with 93 rules using 24 threads.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @ontrails/warden
2
2
 
3
+ ## 1.0.0-beta.15
4
+
5
+ ### Minor Changes
6
+
7
+ - 4ad6b25: Lexicon rename cleanup (ADR-0023). Breaking for `@ontrails/core`, `@ontrails/cli`, and `@ontrails/tracing` at the boundary; internal-only churn for `@ontrails/warden`.
8
+
9
+ - **core**: the topo store schema renames `topo_provisions` / `topo_trail_provisions` → `topo_resources` / `topo_trail_resources` and `provision_count` → `resource_count`. Schema version bumped v4→v5. Stores still carrying the legacy schema are detected on open, dropped, and recreated from the new DDL — previous topo saves are cleared. Stored-data helpers `listTopoStoreProvisions` / `getTopoStoreProvision` / `readProvisionUsage` / `mapProvisionRow` renamed to their `resource` counterparts. TS row types `TopoTrailProvisionRow` / `TopoProvisionRow` renamed to `TopoTrailResourceRow` / `TopoResourceRow`.
10
+ - **cli**: CLI output mode env vars are now derived from the topo name per ADR-0023. Legacy globals `TRAILS_JSON` / `TRAILS_JSONL` are no longer honored — a topo named `stash` reads `STASH_JSON` / `STASH_JSONL`. `ActionResultContext` gains a `topoName: string` field; `resolveOutputMode(flags, topoName)` takes a topo name argument.
11
+ - **tracing**: legacy `.trails/dev/tracker.db` migration path removed. Any user still running a pre-rename beta build with a `tracker.db` should delete it or migrate before upgrading.
12
+ - **warden**: internal-only rename of `provisionDeclarations` / `provisionExists` rules and their trails to `resourceDeclarations` / `resourceExists`. No behavior change.
13
+
14
+ ### Patch Changes
15
+
16
+ - Updated dependencies [4ad6b25]
17
+ - @ontrails/core@1.0.0-beta.15
18
+ - @ontrails/permits@1.0.0-beta.15
19
+ - @ontrails/schema@1.0.0-beta.15
20
+
21
+ ## 1.0.0-beta.14
22
+
23
+ ### Minor Changes
24
+
25
+ - 69057e9: Add hierarchical CLI command trees and structured input, enforce established-only topo exports across trailheads, move developer topo and tracker state onto shared `trails.db` with pins and maintenance flows, and ship schema-derived stores through `@ontrails/store` and its Drizzle runtime.
26
+
27
+ ### Patch Changes
28
+
29
+ - Updated dependencies [69057e9]
30
+ - @ontrails/core@1.0.0-beta.14
31
+ - @ontrails/schema@1.0.0-beta.14
32
+
3
33
  ## 1.0.0-beta.13
4
34
 
5
35
  ### Minor Changes
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @ontrails/warden
2
2
 
3
- AST-based code convention rules for Trails. 13 lint rules that catch contract violations at development time, plus lock drift detection and CI formatters.
3
+ AST-based code convention rules for Trails. Built-in lint rules catch contract violations at development time, alongside lock drift detection and CI formatters.
4
4
 
5
- Structural checks (cross target existence, declared provision existence, recursive crossing, example schema validation) live in `validateTopo()` from `@ontrails/core`. Warden handles the code-level rules that need AST analysis.
5
+ Structural checks (cross target existence, declared resource existence, recursive crossing, example schema validation) live in `validateTopo()` from `@ontrails/core`. Warden handles the code-level rules that need AST analysis.
6
6
 
7
7
  ## Usage
8
8
 
@@ -20,7 +20,7 @@ Or programmatically:
20
20
  ```typescript
21
21
  import { runWarden, formatWardenReport } from '@ontrails/warden';
22
22
 
23
- const report = await runWarden(app, { exitCode: true });
23
+ const report = await runWarden({ topo: graph });
24
24
  console.log(formatWardenReport(report));
25
25
  ```
26
26
 
@@ -30,17 +30,20 @@ console.log(formatWardenReport(report));
30
30
  | --- | --- | --- |
31
31
  | `no-throw-in-implementation` | error | `throw` inside blaze bodies |
32
32
  | `implementation-returns-result` | error | Blaze functions returning raw values instead of `Result` |
33
- | `context-no-trailhead-types` | error | Trailhead type imports (`Request`, `McpSession`) in trail files |
34
- | `no-sync-result-assumption` | error | Missing `await` on `.trailhead()` results |
35
- | `valid-detour-refs` | error | Detour targets that do not exist in the topo |
36
- | `no-throw-in-detour-target` | error | `throw` inside detour target trails |
37
- | `no-direct-implementation-call` | warn | Direct `.trailhead()` calls bypassing `ctx.cross()` |
38
- | `no-direct-impl-in-route` | warn | Direct `.trailhead()` calls inside trail bodies with `crosses` |
33
+ | `context-no-surface-types` | error | Surface type imports (`Request`, `McpSession`) in trail files |
34
+ | `no-sync-result-assumption` | error | Missing `await` on `.blaze()` results |
35
+ | `valid-detour-contract` | error | Detours with non-constructor `on` values or non-callable `recover` values |
36
+ | `no-throw-in-detour-recover` | error | `throw` inside detour `recover` functions |
37
+ | `unreachable-detour-shadowing` | error | Later detours made unreachable by earlier same-or-broader `on:` error types |
38
+ | `no-direct-implementation-call` | warn | Direct `.blaze()` calls bypassing `ctx.cross()` |
39
+ | `no-direct-impl-in-route` | warn | Direct `.blaze()` calls inside trail bodies with `crosses` |
39
40
  | `prefer-schema-inference` | warn | Redundant field overrides already derivable from the schema |
40
41
  | `cross-declarations` | error/warn | `ctx.cross()` calls that drift from declared `crosses: [...]` |
41
- | `provision-declarations` | error/warn | `provision.from(ctx)` / `ctx.provision()` usage that drifts from declared `provisions: [...]` |
42
- | `provision-exists` | error | Declared or referenced provision IDs that do not resolve in project context |
42
+ | `resource-declarations` | error/warn | `resource.from(ctx)` / `ctx.resource()` usage that drifts from declared `resources: [...]` |
43
+ | `resource-exists` | error | Declared or referenced resource IDs that do not resolve in project context |
43
44
  | `valid-describe-refs` | warn | `@see` refs in `.describe()` that do not resolve |
45
+ | `draft-file-marking` | error | Draft-bearing files missing `_draft.*` or `*.draft.*` filename markers |
46
+ | `draft-visible-debt` | warn | Draft IDs remaining in source files that need promotion or removal |
44
47
 
45
48
  ## Drift detection
46
49
 
@@ -49,9 +52,9 @@ Warden integrates with `@ontrails/schema` to detect when the topo has changed wi
49
52
  ```typescript
50
53
  import { checkDrift } from '@ontrails/warden';
51
54
 
52
- const drift = await checkDrift(app);
55
+ const drift = await checkDrift(process.cwd(), graph);
53
56
  if (drift.stale) {
54
- console.log('lock file is stale -- regenerate with `trails survey generate`');
57
+ console.log('lock file is stale -- regenerate with `trails topo export`');
55
58
  }
56
59
  ```
57
60
 
@@ -63,7 +66,7 @@ Add to lefthook for pre-push enforcement:
63
66
  pre-push:
64
67
  commands:
65
68
  warden:
66
- blaze: trails warden --exit-code
69
+ run: trails warden --exit-code
67
70
  tags: governance
68
71
  ```
69
72
 
@@ -75,10 +78,14 @@ import { formatGitHubAnnotations, formatJson, formatSummary } from '@ontrails/wa
75
78
 
76
79
  ## Trail-based API
77
80
 
78
- Every built-in warden rule is also available as a composable trail. This makes rules queryable, testable, and invocable through any Trails trailhead.
81
+ Every built-in warden rule is also available as a composable trail. This makes rules queryable, testable, and invocable through any Trails surface.
79
82
 
80
83
  ```typescript
81
- import { wardenTopo, runWardenTrails } from '@ontrails/warden';
84
+ import {
85
+ runTopoAwareWardenTrails,
86
+ runWardenTrails,
87
+ wardenTopo,
88
+ } from '@ontrails/warden';
82
89
 
83
90
  // Inspect the warden rule trails
84
91
  console.log(wardenTopo.ids()); // ['warden.rule.no-throw-in-implementation', ...]
@@ -86,8 +93,11 @@ console.log(wardenTopo.ids()); // ['warden.rule.no-throw-in-implementation', ...
86
93
  // Run all rule trails against a source file
87
94
  const diagnostics = await runWardenTrails(filePath, sourceCode, {
88
95
  knownTrailIds: myApp.ids(),
89
- knownProvisionIds: myApp.provisionIds(),
96
+ knownResourceIds: myApp.resourceIds(),
90
97
  });
98
+
99
+ // Run built-in topo-aware rule trails once against the resolved graph
100
+ const topoDiagnostics = await runTopoAwareWardenTrails(myApp);
91
101
  ```
92
102
 
93
103
  To wrap a custom rule as a trail, use `wrapRule` (imported from `@ontrails/warden/trails/wrap-rule`). This is the same factory used internally to build all built-in rule trails.
@@ -96,12 +106,13 @@ To wrap a custom rule as a trail, use `wrapRule` (imported from `@ontrails/warde
96
106
 
97
107
  | Export | What it does |
98
108
  | --- | --- |
99
- | `runWarden(app, options?)` | Run all rules and drift checks, return a report |
109
+ | `runWarden(options?)` | Run all rules and drift checks, return a report |
100
110
  | `formatWardenReport(report)` | Human-readable report |
101
- | `checkDrift(app)` | Check if the lock file matches the current topo |
111
+ | `checkDrift(rootDir, topo?)` | Check if the lock file matches the current topo |
102
112
  | `wardenRules` | Registry of all built-in rules |
103
113
  | `wardenTopo` | `Topo` of all built-in rule trails (one per rule) |
104
- | `runWardenTrails(filePath, sourceCode, options?)` | Dispatch all rule trails for a file, collect diagnostics |
114
+ | `runWardenTrails(filePath, sourceCode, options?)` | Dispatch file-scoped rule trails for a file, collect diagnostics |
115
+ | `runTopoAwareWardenTrails(topo)` | Dispatch built-in topo-aware rule trails once for a resolved topo |
105
116
  | `formatGitHubAnnotations(report)` | GitHub Actions annotation format |
106
117
  | `formatJson(report)` | Machine-readable JSON |
107
118
  | `formatSummary(report)` | Compact summary line |
package/dist/cli.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import type { Topo } from '@ontrails/core';
8
8
  import type { DriftResult } from './drift.js';
9
- import type { WardenDiagnostic } from './rules/types.js';
9
+ import type { TopoAwareWardenRule, WardenDiagnostic } from './rules/types.js';
10
10
  /**
11
11
  * Options for the warden CLI runner.
12
12
  */
@@ -17,8 +17,25 @@ export interface WardenOptions {
17
17
  readonly lintOnly?: boolean | undefined;
18
18
  /** Only run drift detection, skip lint rules */
19
19
  readonly driftOnly?: boolean | undefined;
20
- /** App topology for drift detection. When provided, enables real trailhead lock comparison. */
20
+ /**
21
+ * App topology for drift detection. When provided, enables real trailhead
22
+ * lock comparison and unlocks the topo-aware rule dispatch path.
23
+ *
24
+ * @remarks
25
+ * Topo-aware rules (both built-in `wardenTopoRules` and `extraTopoRules`)
26
+ * only fire when a `Topo` is supplied. Runs without a topo silently skip
27
+ * topo-aware dispatch — callers that depend on a topo-aware rule firing
28
+ * must pass `topo` explicitly.
29
+ */
21
30
  readonly topo?: Topo | undefined;
31
+ /**
32
+ * Extra topo-aware rules to run in addition to the built-in registry.
33
+ *
34
+ * Primarily a test hook — production callers should register rules via
35
+ * `wardenTopoRules` in `rules/index.ts`. These rules are only invoked
36
+ * when `topo` is also supplied (see `topo` remarks).
37
+ */
38
+ readonly extraTopoRules?: readonly TopoAwareWardenRule[] | undefined;
22
39
  }
23
40
  /**
24
41
  * Result of a warden run.
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAU9C,OAAO,KAAK,EAGV,gBAAgB,EAEjB,MAAM,kBAAkB,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,gDAAgD;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACzC,+FAA+F;IAC/F,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,QAAQ,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAClD,0CAA0C;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAwND;;GAEG;AACH,eAAO,MAAM,SAAS,GACpB,UAAS,aAAkB,KAC1B,OAAO,CAAC,YAAY,CAqBtB,CAAC;AAsDF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,YAAY,KAAG,MAmBzD,CAAC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAG3C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAiB9C,OAAO,KAAK,EAGV,mBAAmB,EACnB,gBAAgB,EAEjB,MAAM,kBAAkB,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,gDAAgD;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACzC;;;;;;;;;OASG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IACjC;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,mBAAmB,EAAE,GAAG,SAAS,CAAC;CACtE;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,QAAQ,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAClD,0CAA0C;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAqiBD;;GAEG;AACH,eAAO,MAAM,SAAS,GACpB,UAAS,aAAkB,KAC1B,OAAO,CAAC,YAAY,CAwBtB,CAAC;AA2DF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,YAAY,KAAG,MAmBzD,CAAC"}
package/dist/cli.js CHANGED
@@ -5,9 +5,11 @@
5
5
  * and returns a structured report.
6
6
  */
7
7
  import { resolve } from 'node:path';
8
+ import { getContourReferences } from '@ontrails/core';
8
9
  import { checkDrift } from './drift.js';
9
- import { collectProvisionDefinitionIds, findConfigProperty, findTrailDefinitions, parse, walk, } from './rules/ast.js';
10
- import { wardenRules } from './rules/index.js';
10
+ import { collectContourDefinitionIds, collectContourReferenceTargetsByName, collectCrudTableIds as collectCrudTableIdsFromAst, collectCrossTargetTrailIds, collectOnTargetSignalIds as collectOnTargetSignalIdsFromAst, collectReconcileTableIds as collectReconcileTableIdsFromAst, collectResourceDefinitionIds, collectSignalDefinitionIds, collectTrailIntentsById, findTrailDefinitions, parse, } from './rules/ast.js';
11
+ import { collectFileCrudCoverage } from './rules/incomplete-crud.js';
12
+ import { wardenRules, wardenTopoRules } from './rules/index.js';
11
13
  /**
12
14
  * Collect all .ts files under a directory, excluding node_modules, dist, and .git.
13
15
  */
@@ -36,6 +38,68 @@ const collectTsFiles = (dir) => {
36
38
  }
37
39
  return files;
38
40
  };
41
+ const createMutableProjectContext = () => ({
42
+ contourReferencesByName: new Map(),
43
+ crossTargetTrailIds: new Set(),
44
+ crudCoverageByEntity: new Map(),
45
+ crudTableIds: new Set(),
46
+ knownContourIds: new Set(),
47
+ knownResourceIds: new Set(),
48
+ knownSignalIds: new Set(),
49
+ knownTrailIds: new Set(),
50
+ onTargetSignalIds: new Set(),
51
+ reconcileTableIds: new Set(),
52
+ trailIntentsById: new Map(),
53
+ });
54
+ const addContourReferenceTargets = (context, contourName, targets) => {
55
+ const existing = context.contourReferencesByName.get(contourName);
56
+ if (existing) {
57
+ for (const target of targets) {
58
+ existing.add(target);
59
+ }
60
+ return;
61
+ }
62
+ context.contourReferencesByName.set(contourName, new Set(targets));
63
+ };
64
+ const toProjectContext = (context) => ({
65
+ ...(context.contourReferencesByName.size > 0
66
+ ? {
67
+ contourReferencesByName: new Map([...context.contourReferencesByName.entries()].map(([name, targets]) => [name, [...targets]])),
68
+ }
69
+ : {}),
70
+ ...(context.crudTableIds.size > 0
71
+ ? { crudTableIds: context.crudTableIds }
72
+ : {}),
73
+ ...(context.crudCoverageByEntity.size > 0
74
+ ? {
75
+ crudCoverageByEntity: new Map([...context.crudCoverageByEntity.entries()].map(([entityId, operations]) => [
76
+ entityId,
77
+ new Set(operations),
78
+ ])),
79
+ }
80
+ : {}),
81
+ crossTargetTrailIds: context.crossTargetTrailIds,
82
+ knownContourIds: context.knownContourIds,
83
+ knownResourceIds: context.knownResourceIds,
84
+ knownSignalIds: context.knownSignalIds,
85
+ knownTrailIds: context.knownTrailIds,
86
+ ...(context.onTargetSignalIds.size > 0
87
+ ? { onTargetSignalIds: context.onTargetSignalIds }
88
+ : {}),
89
+ ...(context.reconcileTableIds.size > 0
90
+ ? { reconcileTableIds: context.reconcileTableIds }
91
+ : {}),
92
+ trailIntentsById: context.trailIntentsById,
93
+ });
94
+ const collectKnownContourIds = (sourceCode, filePath, knownContourIds) => {
95
+ const ast = parse(filePath, sourceCode);
96
+ if (!ast) {
97
+ return;
98
+ }
99
+ for (const id of collectContourDefinitionIds(ast)) {
100
+ knownContourIds.add(id);
101
+ }
102
+ };
39
103
  const collectKnownTrailIds = (sourceCode, filePath, knownTrailIds) => {
40
104
  const ast = parse(filePath, sourceCode);
41
105
  if (!ast) {
@@ -45,35 +109,80 @@ const collectKnownTrailIds = (sourceCode, filePath, knownTrailIds) => {
45
109
  knownTrailIds.add(def.id);
46
110
  }
47
111
  };
48
- const collectDetourTargetTrailIds = (sourceCode, filePath, detourTargetTrailIds) => {
112
+ const collectCrossedTrailIds = (sourceCode, filePath, crossTargetTrailIds) => {
49
113
  const ast = parse(filePath, sourceCode);
50
114
  if (!ast) {
51
115
  return;
52
116
  }
53
- for (const def of findTrailDefinitions(ast)) {
54
- const detoursProp = findConfigProperty(def.config, 'detours');
55
- if (!detoursProp) {
56
- continue;
117
+ for (const id of collectCrossTargetTrailIds(ast, sourceCode)) {
118
+ crossTargetTrailIds.add(id);
119
+ }
120
+ };
121
+ const collectKnownResourceIds = (sourceCode, filePath, knownResourceIds) => {
122
+ const ast = parse(filePath, sourceCode);
123
+ if (!ast) {
124
+ return;
125
+ }
126
+ for (const id of collectResourceDefinitionIds(ast)) {
127
+ knownResourceIds.add(id);
128
+ }
129
+ };
130
+ const collectKnownSignalIds = (sourceCode, filePath, knownSignalIds) => {
131
+ const ast = parse(filePath, sourceCode);
132
+ if (!ast) {
133
+ return;
134
+ }
135
+ for (const id of collectSignalDefinitionIds(ast)) {
136
+ knownSignalIds.add(id);
137
+ }
138
+ };
139
+ const collectTrailIntents = (sourceCode, filePath, trailIntentsById) => {
140
+ const ast = parse(filePath, sourceCode);
141
+ if (!ast) {
142
+ return;
143
+ }
144
+ for (const [id, intent] of collectTrailIntentsById(ast)) {
145
+ trailIntentsById.set(id, intent);
146
+ }
147
+ };
148
+ const collectCrudTableIds = (sourceCode, filePath, crudTableIds) => {
149
+ const ast = parse(filePath, sourceCode);
150
+ if (!ast) {
151
+ return;
152
+ }
153
+ for (const id of collectCrudTableIdsFromAst(ast)) {
154
+ crudTableIds.add(id);
155
+ }
156
+ };
157
+ const collectOnTargetSignalIds = (sourceCode, filePath, onTargetSignalIds) => {
158
+ const ast = parse(filePath, sourceCode);
159
+ if (!ast) {
160
+ return;
161
+ }
162
+ for (const id of collectOnTargetSignalIdsFromAst(ast, sourceCode)) {
163
+ onTargetSignalIds.add(id);
164
+ }
165
+ };
166
+ const collectCrudCoverageByEntity = (sourceCode, filePath, coverageByEntity) => {
167
+ const ast = parse(filePath, sourceCode);
168
+ if (!ast) {
169
+ return;
170
+ }
171
+ for (const [entityId, operations] of collectFileCrudCoverage(ast, sourceCode)) {
172
+ const bucket = coverageByEntity.get(entityId) ?? new Set();
173
+ for (const operation of operations) {
174
+ bucket.add(operation);
57
175
  }
58
- // Walk the detours value for string literals that look like trail IDs
59
- walk(detoursProp, (node) => {
60
- if (node.type !== 'Literal') {
61
- return;
62
- }
63
- const val = node.value;
64
- if (val && val.includes('.')) {
65
- detourTargetTrailIds.add(val);
66
- }
67
- });
176
+ coverageByEntity.set(entityId, bucket);
68
177
  }
69
178
  };
70
- const collectKnownProvisionIds = (sourceCode, filePath, knownProvisionIds) => {
179
+ const collectReconcileTableIds = (sourceCode, filePath, reconcileTableIds) => {
71
180
  const ast = parse(filePath, sourceCode);
72
181
  if (!ast) {
73
182
  return;
74
183
  }
75
- for (const id of collectProvisionDefinitionIds(ast)) {
76
- knownProvisionIds.add(id);
184
+ for (const id of collectReconcileTableIdsFromAst(ast)) {
185
+ reconcileTableIds.add(id);
77
186
  }
78
187
  };
79
188
  const loadSourceFiles = async (rootDir) => {
@@ -91,65 +200,145 @@ const loadSourceFiles = async (rootDir) => {
91
200
  }
92
201
  return sourceFiles;
93
202
  };
94
- const collectTopoDetourTargetTrailIds = (appTopo) => {
95
- const detourTargetTrailIds = new Set();
203
+ const collectTopoKnownIds = (appTopo, context) => {
204
+ for (const name of appTopo.contours.keys()) {
205
+ context.knownContourIds.add(name);
206
+ }
207
+ for (const id of appTopo.trails.keys()) {
208
+ context.knownTrailIds.add(id);
209
+ }
210
+ for (const id of appTopo.resources.keys()) {
211
+ context.knownResourceIds.add(id);
212
+ }
213
+ for (const id of appTopo.signals.keys()) {
214
+ context.knownSignalIds.add(id);
215
+ }
216
+ };
217
+ const collectTopoCrossesAndIntents = (appTopo, context) => {
96
218
  for (const trail of appTopo.trails.values()) {
97
- const detours = trail['detours'];
98
- if (!detours) {
99
- continue;
100
- }
101
- for (const targets of Object.values(detours)) {
102
- for (const id of targets) {
103
- detourTargetTrailIds.add(id);
104
- }
219
+ context.trailIntentsById.set(trail.id, trail.intent);
220
+ for (const crossedTrailId of trail.crosses) {
221
+ context.crossTargetTrailIds.add(crossedTrailId);
105
222
  }
106
223
  }
107
- return detourTargetTrailIds;
108
224
  };
109
- const buildProjectContextFromTopo = (appTopo) => {
110
- const knownTrailIds = new Set(appTopo.trails.keys());
111
- const knownProvisionIds = new Set(appTopo.provisions.keys());
112
- const detourTargetTrailIds = collectTopoDetourTargetTrailIds(appTopo);
113
- return {
114
- detourTargetTrailIds,
115
- knownProvisionIds,
116
- knownTrailIds,
117
- };
225
+ const collectTopoContourReferences = (appTopo, context) => {
226
+ for (const contour of appTopo.listContours()) {
227
+ addContourReferenceTargets(context, contour.name, getContourReferences(contour).map((reference) => reference.contour));
228
+ }
229
+ };
230
+ const collectTopoTrailContext = (appTopo, context) => {
231
+ collectTopoKnownIds(appTopo, context);
232
+ collectTopoCrossesAndIntents(appTopo, context);
233
+ collectTopoContourReferences(appTopo, context);
234
+ };
235
+ const collectFileKnownIds = (sourceFile, context) => {
236
+ collectKnownContourIds(sourceFile.sourceCode, sourceFile.filePath, context.knownContourIds);
237
+ collectKnownTrailIds(sourceFile.sourceCode, sourceFile.filePath, context.knownTrailIds);
238
+ collectKnownResourceIds(sourceFile.sourceCode, sourceFile.filePath, context.knownResourceIds);
239
+ collectKnownSignalIds(sourceFile.sourceCode, sourceFile.filePath, context.knownSignalIds);
240
+ };
241
+ const collectFileTrailRelationships = (sourceFile, context) => {
242
+ collectCrossedTrailIds(sourceFile.sourceCode, sourceFile.filePath, context.crossTargetTrailIds);
243
+ collectTrailIntents(sourceFile.sourceCode, sourceFile.filePath, context.trailIntentsById);
244
+ };
245
+ const collectFileSupplementalProjectContext = (sourceFile, context) => {
246
+ collectCrudTableIds(sourceFile.sourceCode, sourceFile.filePath, context.crudTableIds);
247
+ collectOnTargetSignalIds(sourceFile.sourceCode, sourceFile.filePath, context.onTargetSignalIds);
248
+ collectReconcileTableIds(sourceFile.sourceCode, sourceFile.filePath, context.reconcileTableIds);
249
+ collectCrudCoverageByEntity(sourceFile.sourceCode, sourceFile.filePath, context.crudCoverageByEntity);
250
+ };
251
+ const collectFileProjectContext = (sourceFile, context) => {
252
+ collectFileKnownIds(sourceFile, context);
253
+ collectFileTrailRelationships(sourceFile, context);
254
+ collectFileSupplementalProjectContext(sourceFile, context);
118
255
  };
119
- const buildProjectContextFromFiles = (sourceFiles) => {
120
- const knownTrailIds = new Set();
121
- const knownProvisionIds = new Set();
122
- const detourTargetTrailIds = new Set();
256
+ const collectFileContourReferences = (sourceFile, context) => {
257
+ const ast = parse(sourceFile.filePath, sourceFile.sourceCode);
258
+ if (!ast) {
259
+ return;
260
+ }
261
+ const referencesByName = collectContourReferenceTargetsByName(ast, context.knownContourIds);
262
+ for (const [contourName, targets] of referencesByName) {
263
+ addContourReferenceTargets(context, contourName, targets);
264
+ }
265
+ };
266
+ const buildProjectContext = (sourceFiles, appTopo) => {
267
+ const context = createMutableProjectContext();
268
+ if (appTopo) {
269
+ collectTopoTrailContext(appTopo, context);
270
+ for (const sourceFile of sourceFiles) {
271
+ collectFileSupplementalProjectContext(sourceFile, context);
272
+ }
273
+ }
274
+ else {
275
+ for (const sourceFile of sourceFiles) {
276
+ collectFileProjectContext(sourceFile, context);
277
+ }
278
+ }
123
279
  for (const sourceFile of sourceFiles) {
124
- collectKnownTrailIds(sourceFile.sourceCode, sourceFile.filePath, knownTrailIds);
125
- collectKnownProvisionIds(sourceFile.sourceCode, sourceFile.filePath, knownProvisionIds);
126
- collectDetourTargetTrailIds(sourceFile.sourceCode, sourceFile.filePath, detourTargetTrailIds);
280
+ collectFileContourReferences(sourceFile, context);
127
281
  }
282
+ return toProjectContext(context);
283
+ };
284
+ const isProjectAwareRule = (rule) => 'checkWithContext' in rule;
285
+ const topoRuleFailureDiagnostic = (rule, error) => {
286
+ const cause = error instanceof Error ? error : new Error(String(error));
128
287
  return {
129
- detourTargetTrailIds,
130
- knownProvisionIds,
131
- knownTrailIds,
288
+ filePath: '<topo>',
289
+ line: 1,
290
+ message: `Topo-aware rule "${rule.name}" threw: ${cause.message}`,
291
+ rule: rule.name,
292
+ severity: 'error',
132
293
  };
133
294
  };
134
- const isProjectAwareRule = (rule) => 'checkWithContext' in rule;
135
295
  /**
136
- * Lint all files against all warden rules.
296
+ * Run all registered topo-aware rules against the resolved topo.
297
+ *
298
+ * Topo-aware rules fire exactly once per run (not per file) because they
299
+ * inspect the compiled trail graph, not source text.
137
300
  */
138
- const lintFiles = async (rootDir, appTopo) => {
139
- const allDiagnostics = [];
140
- const sourceFiles = await loadSourceFiles(rootDir);
141
- const context = appTopo
142
- ? buildProjectContextFromTopo(appTopo)
143
- : buildProjectContextFromFiles(sourceFiles);
301
+ const lintTopo = async (appTopo, extraTopoRules) => {
302
+ const diagnostics = [];
303
+ const rules = [
304
+ ...wardenTopoRules.values(),
305
+ ...extraTopoRules,
306
+ ];
307
+ for (const rule of rules) {
308
+ try {
309
+ diagnostics.push(...(await rule.checkTopo(appTopo)));
310
+ }
311
+ catch (error) {
312
+ diagnostics.push(topoRuleFailureDiagnostic(rule, error));
313
+ }
314
+ }
315
+ return diagnostics;
316
+ };
317
+ const lintSourceFiles = (sourceFiles, context) => {
318
+ const diagnostics = [];
144
319
  for (const sourceFile of sourceFiles) {
145
320
  for (const rule of wardenRules.values()) {
146
321
  if (isProjectAwareRule(rule)) {
147
- allDiagnostics.push(...rule.checkWithContext(sourceFile.sourceCode, sourceFile.filePath, context));
322
+ diagnostics.push(...rule.checkWithContext(sourceFile.sourceCode, sourceFile.filePath, context));
148
323
  continue;
149
324
  }
150
- allDiagnostics.push(...rule.check(sourceFile.sourceCode, sourceFile.filePath));
325
+ diagnostics.push(...rule.check(sourceFile.sourceCode, sourceFile.filePath));
151
326
  }
152
327
  }
328
+ return diagnostics;
329
+ };
330
+ /**
331
+ * Lint all files against all warden rules.
332
+ */
333
+ const lintFiles = async (rootDir, appTopo, extraTopoRules = []) => {
334
+ const sourceFiles = await loadSourceFiles(rootDir);
335
+ const context = buildProjectContext(sourceFiles, appTopo);
336
+ const allDiagnostics = [
337
+ ...lintSourceFiles(sourceFiles, context),
338
+ ];
339
+ if (appTopo) {
340
+ allDiagnostics.push(...(await lintTopo(appTopo, extraTopoRules)));
341
+ }
153
342
  return allDiagnostics;
154
343
  };
155
344
  /**
@@ -159,7 +348,7 @@ export const runWarden = async (options = {}) => {
159
348
  const rootDir = resolve(options.rootDir ?? process.cwd());
160
349
  const allDiagnostics = options.driftOnly
161
350
  ? []
162
- : await lintFiles(rootDir, options.topo);
351
+ : await lintFiles(rootDir, options.topo, options.extraTopoRules ?? []);
163
352
  const drift = options.lintOnly
164
353
  ? null
165
354
  : await checkDrift(rootDir, options.topo);
@@ -169,7 +358,9 @@ export const runWarden = async (options = {}) => {
169
358
  diagnostics: allDiagnostics,
170
359
  drift,
171
360
  errorCount,
172
- passed: errorCount === 0 && !(drift?.stale ?? false),
361
+ passed: errorCount === 0 &&
362
+ !(drift?.stale ?? false) &&
363
+ drift?.blockedReason === undefined,
173
364
  warnCount,
174
365
  };
175
366
  };
@@ -196,8 +387,11 @@ const formatDriftSection = (drift) => {
196
387
  if (drift === null) {
197
388
  return [];
198
389
  }
390
+ if (drift.blockedReason !== undefined) {
391
+ return [`Drift: blocked (${drift.blockedReason})`, ''];
392
+ }
199
393
  const label = drift.stale
200
- ? 'Drift: trailhead.lock is stale (regenerate with `trails survey generate`)'
394
+ ? 'Drift: trails.lock is stale (regenerate with `trails topo export`)'
201
395
  : 'Drift: clean';
202
396
  return [label, ''];
203
397
  };
@@ -212,7 +406,10 @@ const formatResultLine = (report) => {
212
406
  if (report.errorCount > 0) {
213
407
  parts.push(`${report.errorCount} errors`);
214
408
  }
215
- if (report.drift?.stale) {
409
+ if (report.drift?.blockedReason !== undefined) {
410
+ parts.push('established exports blocked');
411
+ }
412
+ else if (report.drift?.stale) {
216
413
  parts.push('drift detected');
217
414
  }
218
415
  return `Result: FAIL (${parts.join(', ')})`;