@intentius/chant 0.124.45 → 0.124.48

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 (772) hide show
  1. package/dist/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
  2. package/dist/__golden__/wave-loop/op-by-apply-hold.json +10 -0
  3. package/dist/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
  4. package/dist/__golden__/wave-loop/op-by-apply-pass.json +10 -0
  5. package/dist/__golden__/wave-loop/op-by-apply-skip.json +10 -0
  6. package/dist/__golden__/wave-loop/op-cost-member-clash.json +6 -0
  7. package/dist/__golden__/wave-loop/op-cost-member.json +13 -0
  8. package/dist/__golden__/wave-loop/op-denied-source.json +16 -0
  9. package/dist/__golden__/wave-loop/op-denied.json +16 -0
  10. package/dist/__golden__/wave-loop/op-discover-rest-short.json +6 -0
  11. package/dist/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
  12. package/dist/__golden__/wave-loop/op-discover-rest.json +26 -0
  13. package/dist/__golden__/wave-loop/op-discover-wide.json +26 -0
  14. package/dist/__golden__/wave-loop/op-held-on-again.json +16 -0
  15. package/dist/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
  16. package/dist/__golden__/wave-loop/op-held-on.json +16 -0
  17. package/dist/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
  18. package/dist/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
  19. package/dist/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
  20. package/dist/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
  21. package/dist/__golden__/wave-loop/op-hooks-held.json +13 -0
  22. package/dist/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
  23. package/dist/__golden__/wave-loop/op-hooks-pass.json +13 -0
  24. package/dist/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
  25. package/dist/__golden__/wave-loop/op-hooks-share.json +33 -0
  26. package/dist/__golden__/wave-loop/op-outcome-held.json +10 -0
  27. package/dist/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
  28. package/dist/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
  29. package/dist/__golden__/wave-loop/op-outcome-replan.json +10 -0
  30. package/dist/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
  31. package/dist/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
  32. package/dist/__golden__/wave-loop/op-overridden.json +16 -0
  33. package/dist/__golden__/wave-loop/op-per-run.json +20 -0
  34. package/dist/__golden__/wave-loop/op-point.json +13 -0
  35. package/dist/__golden__/wave-loop/op-pr-review.json +10 -0
  36. package/dist/__golden__/wave-loop/op-sealed.json +10 -0
  37. package/dist/__golden__/wave-loop/op-spend-change-only.json +10 -0
  38. package/dist/__golden__/wave-loop/op-spend.json +10 -0
  39. package/dist/__golden__/wave-loop/op-wave-commands.json +55 -0
  40. package/dist/__golden__/wave-loop/op-wide-refused.json +26 -0
  41. package/dist/__golden__/wave-loop/op-wide-waiting.json +29 -0
  42. package/dist/__golden__/wave-loop/op-wide.json +39 -0
  43. package/dist/action-pins.d.ts +61 -0
  44. package/dist/action-pins.d.ts.map +1 -0
  45. package/dist/action-pins.js +77 -0
  46. package/dist/capabilities/aws.paths +148 -0
  47. package/dist/capabilities/base-mappings.json +122 -0
  48. package/dist/capabilities/catalog.d.ts +89 -0
  49. package/dist/capabilities/catalog.d.ts.map +1 -0
  50. package/dist/capabilities/catalog.js +204 -0
  51. package/dist/capabilities/language.d.ts +103 -0
  52. package/dist/capabilities/language.d.ts.map +1 -0
  53. package/dist/capabilities/language.js +335 -0
  54. package/dist/capabilities/matcher.d.ts +65 -0
  55. package/dist/capabilities/matcher.d.ts.map +1 -0
  56. package/dist/capabilities/matcher.js +299 -0
  57. package/dist/capabilities/view.d.ts +207 -0
  58. package/dist/capabilities/view.d.ts.map +1 -0
  59. package/dist/capabilities/view.js +484 -0
  60. package/dist/cli/commands/carve.d.ts +3 -0
  61. package/dist/cli/commands/carve.d.ts.map +1 -1
  62. package/dist/cli/commands/carve.js +36 -7
  63. package/dist/cli/commands/import-report.d.ts +26 -0
  64. package/dist/cli/commands/import-report.d.ts.map +1 -0
  65. package/dist/cli/commands/import-report.js +65 -0
  66. package/dist/cli/commands/import.d.ts +11 -1
  67. package/dist/cli/commands/import.d.ts.map +1 -1
  68. package/dist/cli/commands/import.js +22 -3
  69. package/dist/cli/commands/lint.d.ts.map +1 -1
  70. package/dist/cli/commands/lint.js +1 -0
  71. package/dist/cli/commands/migrate.d.ts +13 -1
  72. package/dist/cli/commands/migrate.d.ts.map +1 -1
  73. package/dist/cli/commands/migrate.js +134 -10
  74. package/dist/cli/handlers/approve.d.ts.map +1 -1
  75. package/dist/cli/handlers/approve.js +21 -2
  76. package/dist/cli/handlers/build.d.ts.map +1 -1
  77. package/dist/cli/handlers/build.js +6 -1
  78. package/dist/cli/handlers/declared-graph.d.ts +44 -0
  79. package/dist/cli/handlers/declared-graph.d.ts.map +1 -0
  80. package/dist/cli/handlers/declared-graph.js +87 -0
  81. package/dist/cli/handlers/graph.d.ts +25 -0
  82. package/dist/cli/handlers/graph.d.ts.map +1 -1
  83. package/dist/cli/handlers/graph.js +93 -87
  84. package/dist/cli/handlers/ledger.d.ts +3 -0
  85. package/dist/cli/handlers/ledger.d.ts.map +1 -0
  86. package/dist/cli/handlers/ledger.js +55 -0
  87. package/dist/cli/handlers/migrate.d.ts.map +1 -1
  88. package/dist/cli/handlers/migrate.js +18 -11
  89. package/dist/cli/handlers/misc.d.ts.map +1 -1
  90. package/dist/cli/handlers/misc.js +12 -1
  91. package/dist/cli/handlers/pr-env.d.ts.map +1 -1
  92. package/dist/cli/handlers/pr-env.js +4 -3
  93. package/dist/cli/handlers/pr.d.ts +15 -1
  94. package/dist/cli/handlers/pr.d.ts.map +1 -1
  95. package/dist/cli/handlers/pr.js +143 -39
  96. package/dist/cli/handlers/query.d.ts +7 -2
  97. package/dist/cli/handlers/query.d.ts.map +1 -1
  98. package/dist/cli/handlers/query.js +16 -4
  99. package/dist/cli/handlers/release.d.ts.map +1 -1
  100. package/dist/cli/handlers/release.js +6 -3
  101. package/dist/cli/handlers/search-count.d.ts +89 -0
  102. package/dist/cli/handlers/search-count.d.ts.map +1 -0
  103. package/dist/cli/handlers/search-count.js +132 -0
  104. package/dist/cli/handlers/search.d.ts +356 -6
  105. package/dist/cli/handlers/search.d.ts.map +1 -1
  106. package/dist/cli/handlers/search.js +1039 -155
  107. package/dist/cli/main.d.ts.map +1 -1
  108. package/dist/cli/main.js +88 -17
  109. package/dist/cli/mcp/server.d.ts.map +1 -1
  110. package/dist/cli/mcp/server.js +3 -0
  111. package/dist/cli/mcp/tools/capabilities.d.ts +7 -0
  112. package/dist/cli/mcp/tools/capabilities.d.ts.map +1 -0
  113. package/dist/cli/mcp/tools/capabilities.js +27 -0
  114. package/dist/cli/mcp/workspace-tools.d.ts +3 -1
  115. package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
  116. package/dist/cli/mcp/workspace-tools.js +47 -2
  117. package/dist/cli/parse-args.d.ts.map +1 -1
  118. package/dist/cli/parse-args.js +100 -19
  119. package/dist/cli/registry.d.ts +36 -4
  120. package/dist/cli/registry.d.ts.map +1 -1
  121. package/dist/components/builders.d.ts +5 -1
  122. package/dist/components/builders.d.ts.map +1 -1
  123. package/dist/components/builders.js +5 -0
  124. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  125. package/dist/components/capability-plugin-loader.js +16 -1
  126. package/dist/components/capability-plugin.d.ts +14 -0
  127. package/dist/components/capability-plugin.d.ts.map +1 -1
  128. package/dist/components/pr-env-ports.d.ts +29 -0
  129. package/dist/components/pr-env-ports.d.ts.map +1 -0
  130. package/dist/components/pr-env-ports.js +77 -0
  131. package/dist/components/pr-env-run.d.ts +5 -21
  132. package/dist/components/pr-env-run.d.ts.map +1 -1
  133. package/dist/components/pr-env-run.js +6 -70
  134. package/dist/components/pr-environment.d.ts +2 -1
  135. package/dist/components/pr-environment.d.ts.map +1 -1
  136. package/dist/components/pr-environment.js +1 -1
  137. package/dist/components/pr-hooks.d.ts +21 -1
  138. package/dist/components/pr-hooks.d.ts.map +1 -1
  139. package/dist/components/pr-hooks.js +72 -4
  140. package/dist/components/pr-pipeline.d.ts +45 -10
  141. package/dist/components/pr-pipeline.d.ts.map +1 -1
  142. package/dist/components/pr-pipeline.js +47 -14
  143. package/dist/components/pr-policy.d.ts +36 -0
  144. package/dist/components/pr-policy.d.ts.map +1 -1
  145. package/dist/components/pr-policy.js +36 -0
  146. package/dist/components/starter-plugin.d.ts +1 -0
  147. package/dist/components/starter-plugin.d.ts.map +1 -1
  148. package/dist/components/starter-plugin.js +5 -1
  149. package/dist/components/verbs/index.d.ts +2 -0
  150. package/dist/components/verbs/index.d.ts.map +1 -1
  151. package/dist/components/verbs/index.js +2 -0
  152. package/dist/components/verbs/publish-artifact.d.ts +65 -0
  153. package/dist/components/verbs/publish-artifact.d.ts.map +1 -0
  154. package/dist/components/verbs/publish-artifact.js +74 -0
  155. package/dist/components/verbs/publish-image.d.ts +129 -0
  156. package/dist/components/verbs/publish-image.d.ts.map +1 -0
  157. package/dist/components/verbs/publish-image.js +145 -0
  158. package/dist/config-environments.d.ts +112 -0
  159. package/dist/config-environments.d.ts.map +1 -0
  160. package/dist/config-environments.js +114 -0
  161. package/dist/config.d.ts +32 -84
  162. package/dist/config.d.ts.map +1 -1
  163. package/dist/config.js +13 -96
  164. package/dist/gate-decision.d.ts +11 -2
  165. package/dist/gate-decision.d.ts.map +1 -1
  166. package/dist/gate-decision.js +15 -3
  167. package/dist/graph-detail.d.ts.map +1 -1
  168. package/dist/graph-detail.js +15 -3
  169. package/dist/graph-effective.d.ts +33 -2
  170. package/dist/graph-effective.d.ts.map +1 -1
  171. package/dist/graph-effective.js +215 -68
  172. package/dist/graph-ir.d.ts +48 -0
  173. package/dist/graph-ir.d.ts.map +1 -1
  174. package/dist/graph-ir.js +130 -0
  175. package/dist/graph-sub-template.d.ts +11 -0
  176. package/dist/graph-sub-template.d.ts.map +1 -0
  177. package/dist/graph-sub-template.js +19 -0
  178. package/dist/graph-walk.d.ts +66 -0
  179. package/dist/graph-walk.d.ts.map +1 -0
  180. package/dist/graph-walk.js +70 -0
  181. package/dist/import/parser.d.ts +19 -0
  182. package/dist/import/parser.d.ts.map +1 -1
  183. package/dist/lexicon.d.ts +80 -6
  184. package/dist/lexicon.d.ts.map +1 -1
  185. package/dist/lifecycle/gate-ledger.d.ts +11 -0
  186. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  187. package/dist/lifecycle/git.d.ts +2 -5
  188. package/dist/lifecycle/git.d.ts.map +1 -1
  189. package/dist/lifecycle/ledger-read.d.ts +65 -0
  190. package/dist/lifecycle/ledger-read.d.ts.map +1 -0
  191. package/dist/lifecycle/ledger-read.js +160 -0
  192. package/dist/lifecycle/observe.d.ts +28 -0
  193. package/dist/lifecycle/observe.d.ts.map +1 -1
  194. package/dist/lifecycle/observe.js +23 -1
  195. package/dist/lifecycle/release-workstation.d.ts +7 -0
  196. package/dist/lifecycle/release-workstation.d.ts.map +1 -1
  197. package/dist/lifecycle/release-workstation.js +25 -0
  198. package/dist/lifecycle/run-ledger.d.ts +4 -3
  199. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  200. package/dist/lifecycle/run-ledger.js +1 -0
  201. package/dist/lint/discover.js +3 -1
  202. package/dist/lint/post-synth.d.ts +127 -1
  203. package/dist/lint/post-synth.d.ts.map +1 -1
  204. package/dist/lint/post-synth.js +84 -2
  205. package/dist/lint/rule.d.ts +6 -0
  206. package/dist/lint/rule.d.ts.map +1 -1
  207. package/dist/lint/rules/op/index.d.ts +1 -0
  208. package/dist/lint/rules/op/index.d.ts.map +1 -1
  209. package/dist/lint/rules/op/index.js +2 -0
  210. package/dist/lint/rules/op/ops019-workspace-op-target.d.ts +32 -0
  211. package/dist/lint/rules/op/ops019-workspace-op-target.d.ts.map +1 -0
  212. package/dist/lint/rules/op/ops019-workspace-op-target.js +63 -0
  213. package/dist/live-endpoint.d.ts +1 -1
  214. package/dist/live-endpoint.d.ts.map +1 -1
  215. package/dist/live-endpoint.js +1 -1
  216. package/dist/observation.d.ts +48 -1
  217. package/dist/observation.d.ts.map +1 -1
  218. package/dist/observation.js +21 -5
  219. package/dist/op/activities/activity-contracts.d.ts +9 -6
  220. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  221. package/dist/op/activities/activity-contracts.js +5 -2
  222. package/dist/op/activities/index.d.ts +2 -2
  223. package/dist/op/activities/index.d.ts.map +1 -1
  224. package/dist/op/activities/index.js +1 -1
  225. package/dist/op/activities/review-agent.d.ts +90 -4
  226. package/dist/op/activities/review-agent.d.ts.map +1 -1
  227. package/dist/op/activities/review-agent.js +217 -19
  228. package/dist/op/activities/work-evidence.d.ts +8 -1
  229. package/dist/op/activities/work-evidence.d.ts.map +1 -1
  230. package/dist/op/activities/work-evidence.js +1 -0
  231. package/dist/op/builders.d.ts +9 -5
  232. package/dist/op/builders.d.ts.map +1 -1
  233. package/dist/op/builders.js +9 -5
  234. package/dist/op/composites/apply-op.d.ts +29 -2
  235. package/dist/op/composites/apply-op.d.ts.map +1 -1
  236. package/dist/op/composites/apply-op.js +20 -1
  237. package/dist/op/gate-approval.d.ts +11 -5
  238. package/dist/op/gate-approval.d.ts.map +1 -1
  239. package/dist/op/gate-approval.js +11 -6
  240. package/dist/op/gate-quorum.d.ts +100 -3
  241. package/dist/op/gate-quorum.d.ts.map +1 -1
  242. package/dist/op/gate-quorum.js +108 -6
  243. package/dist/op/gate-review.d.ts +9 -0
  244. package/dist/op/gate-review.d.ts.map +1 -1
  245. package/dist/op/gate-review.js +13 -0
  246. package/dist/op/gate.d.ts +44 -3
  247. package/dist/op/gate.d.ts.map +1 -1
  248. package/dist/op/gate.js +25 -4
  249. package/dist/op/index.d.ts +3 -3
  250. package/dist/op/index.d.ts.map +1 -1
  251. package/dist/op/index.js +1 -1
  252. package/dist/op/local-executor.d.ts +38 -3
  253. package/dist/op/local-executor.d.ts.map +1 -1
  254. package/dist/op/local-executor.js +48 -6
  255. package/dist/op/op-waves-run.d.ts +26 -1
  256. package/dist/op/op-waves-run.d.ts.map +1 -1
  257. package/dist/op/op-waves-run.js +259 -13
  258. package/dist/op/op-waves.d.ts +72 -5
  259. package/dist/op/op-waves.d.ts.map +1 -1
  260. package/dist/op/op-waves.js +110 -15
  261. package/dist/op/runtime.d.ts +11 -0
  262. package/dist/op/runtime.d.ts.map +1 -1
  263. package/dist/op/schedule-overdue.d.ts +16 -0
  264. package/dist/op/schedule-overdue.d.ts.map +1 -1
  265. package/dist/op/schedule-overdue.js +36 -0
  266. package/dist/op/stage-hooks.d.ts +9 -2
  267. package/dist/op/stage-hooks.d.ts.map +1 -1
  268. package/dist/op/stage-hooks.js +7 -5
  269. package/dist/op/workspace-run-env.d.ts +22 -0
  270. package/dist/op/workspace-run-env.d.ts.map +1 -0
  271. package/dist/op/workspace-run-env.js +21 -0
  272. package/dist/pr-forge.d.ts +24 -0
  273. package/dist/pr-forge.d.ts.map +1 -1
  274. package/dist/pr-forge.js +47 -0
  275. package/dist/pr-post.d.ts +42 -0
  276. package/dist/pr-post.d.ts.map +1 -1
  277. package/dist/pr-post.js +67 -1
  278. package/dist/read-filter.d.ts +65 -0
  279. package/dist/read-filter.d.ts.map +1 -0
  280. package/dist/read-filter.js +179 -0
  281. package/dist/run-event.d.ts +1 -1
  282. package/dist/run-event.d.ts.map +1 -1
  283. package/dist/terraform/carve.d.ts +24 -3
  284. package/dist/terraform/carve.d.ts.map +1 -1
  285. package/dist/terraform/carve.js +32 -14
  286. package/dist/terraform/cuts.d.ts +97 -0
  287. package/dist/terraform/cuts.d.ts.map +1 -0
  288. package/dist/terraform/cuts.js +138 -0
  289. package/dist/terraform/folds.d.ts +26 -0
  290. package/dist/terraform/folds.d.ts.map +1 -0
  291. package/dist/terraform/folds.js +38 -0
  292. package/dist/terraform/graph.d.ts.map +1 -1
  293. package/dist/terraform/graph.js +10 -0
  294. package/dist/terraform/reach.d.ts +140 -0
  295. package/dist/terraform/reach.d.ts.map +1 -0
  296. package/dist/terraform/reach.js +170 -0
  297. package/dist/terraform/score.d.ts +14 -0
  298. package/dist/terraform/score.d.ts.map +1 -1
  299. package/dist/terraform/score.js +14 -31
  300. package/dist/terraform/state.d.ts.map +1 -1
  301. package/dist/terraform/state.js +4 -2
  302. package/dist/terraform/types.d.ts +8 -0
  303. package/dist/terraform/types.d.ts.map +1 -1
  304. package/dist/wave-blocked.d.ts +10 -1
  305. package/dist/wave-blocked.d.ts.map +1 -1
  306. package/dist/wave-blocked.js +31 -3
  307. package/dist/wave-runtime.mjs +266 -256
  308. package/dist/workspace/capabilities-contract.d.ts +66 -0
  309. package/dist/workspace/capabilities-contract.d.ts.map +1 -0
  310. package/dist/workspace/capabilities-contract.js +107 -0
  311. package/dist/workspace/capabilities.schema.json +229 -0
  312. package/dist/workspace/check.schema.json +11 -2
  313. package/dist/workspace/checks/ci-branch.d.ts +44 -0
  314. package/dist/workspace/checks/ci-branch.d.ts.map +1 -0
  315. package/dist/workspace/checks/ci-branch.js +133 -0
  316. package/dist/workspace/checks/links.d.ts +3 -0
  317. package/dist/workspace/checks/links.d.ts.map +1 -1
  318. package/dist/workspace/checks/links.js +12 -1
  319. package/dist/workspace/checks/org.d.ts +48 -0
  320. package/dist/workspace/checks/org.d.ts.map +1 -0
  321. package/dist/workspace/checks/org.js +156 -0
  322. package/dist/workspace/checks.d.ts +11 -1
  323. package/dist/workspace/checks.d.ts.map +1 -1
  324. package/dist/workspace/checks.js +59 -7
  325. package/dist/workspace/ci-branches.d.ts +16 -0
  326. package/dist/workspace/ci-branches.d.ts.map +1 -1
  327. package/dist/workspace/ci-branches.js +27 -0
  328. package/dist/workspace/ci-green-cli.js +7 -7
  329. package/dist/workspace/ci-green-workflow.d.ts +1 -1
  330. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  331. package/dist/workspace/ci-green-workflow.js +13 -8
  332. package/dist/workspace/ci-green.d.ts +14 -0
  333. package/dist/workspace/ci-green.d.ts.map +1 -1
  334. package/dist/workspace/ci-green.js +44 -11
  335. package/dist/workspace/ci-run.d.ts +9 -1
  336. package/dist/workspace/ci-run.d.ts.map +1 -1
  337. package/dist/workspace/ci-run.js +67 -6
  338. package/dist/workspace/ci-serve.d.ts +9 -0
  339. package/dist/workspace/ci-serve.d.ts.map +1 -1
  340. package/dist/workspace/ci-serve.js +114 -76
  341. package/dist/workspace/compose-graph.d.ts +23 -0
  342. package/dist/workspace/compose-graph.d.ts.map +1 -1
  343. package/dist/workspace/compose-graph.js +3 -1
  344. package/dist/workspace/composites.d.ts +4 -1
  345. package/dist/workspace/composites.d.ts.map +1 -1
  346. package/dist/workspace/composites.js +5 -2
  347. package/dist/workspace/composites.schema.json +22 -0
  348. package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
  349. package/dist/workspace/conformance/index.d.ts +1 -1
  350. package/dist/workspace/conformance/index.d.ts.map +1 -1
  351. package/dist/workspace/conformance/index.js +39 -2
  352. package/dist/workspace/cross-root-lint.d.ts +56 -0
  353. package/dist/workspace/cross-root-lint.d.ts.map +1 -0
  354. package/dist/workspace/cross-root-lint.js +111 -0
  355. package/dist/workspace/dbt-models-reader.d.ts +44 -0
  356. package/dist/workspace/dbt-models-reader.d.ts.map +1 -0
  357. package/dist/workspace/dbt-models-reader.js +356 -0
  358. package/dist/workspace/dbt-project-common.d.ts +40 -0
  359. package/dist/workspace/dbt-project-common.d.ts.map +1 -0
  360. package/dist/workspace/dbt-project-common.js +106 -0
  361. package/dist/workspace/dbt-project-reader.d.ts +4 -3
  362. package/dist/workspace/dbt-project-reader.d.ts.map +1 -1
  363. package/dist/workspace/dbt-project-reader.js +14 -108
  364. package/dist/workspace/decision-rank.d.ts +26 -0
  365. package/dist/workspace/decision-rank.d.ts.map +1 -0
  366. package/dist/workspace/decision-rank.js +16 -0
  367. package/dist/workspace/declaration.d.ts +43 -2
  368. package/dist/workspace/declaration.d.ts.map +1 -1
  369. package/dist/workspace/declaration.js +45 -11
  370. package/dist/workspace/declaration.schema.json +133 -24
  371. package/dist/workspace/environments.d.ts +26 -2
  372. package/dist/workspace/environments.d.ts.map +1 -1
  373. package/dist/workspace/environments.js +26 -2
  374. package/dist/workspace/flyway-dir.d.ts +39 -0
  375. package/dist/workspace/flyway-dir.d.ts.map +1 -0
  376. package/dist/workspace/flyway-dir.js +104 -0
  377. package/dist/workspace/flyway-layout.d.ts +96 -0
  378. package/dist/workspace/flyway-layout.d.ts.map +1 -0
  379. package/dist/workspace/flyway-layout.js +308 -0
  380. package/dist/workspace/graph-cache.d.ts +8 -0
  381. package/dist/workspace/graph-cache.d.ts.map +1 -1
  382. package/dist/workspace/graph-cache.js +27 -3
  383. package/dist/workspace/graph-cli.d.ts +39 -2
  384. package/dist/workspace/graph-cli.d.ts.map +1 -1
  385. package/dist/workspace/graph-cli.js +92 -32
  386. package/dist/workspace/graph.schema.json +182 -0
  387. package/dist/workspace/intent.d.ts +2 -3
  388. package/dist/workspace/intent.d.ts.map +1 -1
  389. package/dist/workspace/intent.js +5 -9
  390. package/dist/workspace/kind-link-readers.d.ts +59 -2
  391. package/dist/workspace/kind-link-readers.d.ts.map +1 -1
  392. package/dist/workspace/kind-link-readers.js +17 -1
  393. package/dist/workspace/kind-readers.d.ts +3 -0
  394. package/dist/workspace/kind-readers.d.ts.map +1 -1
  395. package/dist/workspace/kind-readers.js +7 -1
  396. package/dist/workspace/kinds.d.ts +66 -2
  397. package/dist/workspace/kinds.d.ts.map +1 -1
  398. package/dist/workspace/kinds.js +98 -4
  399. package/dist/workspace/ledger.schema.json +158 -0
  400. package/dist/workspace/lexicon-outputs.d.ts +20 -1
  401. package/dist/workspace/lexicon-outputs.d.ts.map +1 -1
  402. package/dist/workspace/lexicon-outputs.js +102 -10
  403. package/dist/workspace/lineage-check.d.ts +3 -0
  404. package/dist/workspace/lineage-check.d.ts.map +1 -1
  405. package/dist/workspace/lineage-check.js +23 -4
  406. package/dist/workspace/links.d.ts +8 -1
  407. package/dist/workspace/links.d.ts.map +1 -1
  408. package/dist/workspace/links.js +25 -1
  409. package/dist/workspace/ls.d.ts +8 -0
  410. package/dist/workspace/ls.d.ts.map +1 -1
  411. package/dist/workspace/ls.js +7 -1
  412. package/dist/workspace/ls.schema.json +7 -0
  413. package/dist/workspace/member-commands.d.ts +10 -1
  414. package/dist/workspace/member-commands.d.ts.map +1 -1
  415. package/dist/workspace/member-commands.js +71 -6
  416. package/dist/workspace/migrate-links.d.ts +45 -0
  417. package/dist/workspace/migrate-links.d.ts.map +1 -0
  418. package/dist/workspace/migrate-links.js +100 -0
  419. package/dist/workspace/migration-dirs.d.ts +74 -0
  420. package/dist/workspace/migration-dirs.d.ts.map +1 -0
  421. package/dist/workspace/migration-dirs.js +254 -0
  422. package/dist/workspace/nested-graph.d.ts +2 -0
  423. package/dist/workspace/nested-graph.d.ts.map +1 -1
  424. package/dist/workspace/nested-graph.js +32 -1
  425. package/dist/workspace/reason-codes.d.ts +18 -0
  426. package/dist/workspace/reason-codes.d.ts.map +1 -1
  427. package/dist/workspace/reason-codes.js +23 -0
  428. package/dist/workspace/records-cli.d.ts +11 -0
  429. package/dist/workspace/records-cli.d.ts.map +1 -1
  430. package/dist/workspace/records-cli.js +57 -5
  431. package/dist/workspace/records.schema.json +5 -0
  432. package/dist/workspace/release-candidates.d.ts +2 -0
  433. package/dist/workspace/release-candidates.d.ts.map +1 -1
  434. package/dist/workspace/release-candidates.js +5 -2
  435. package/dist/workspace/release-train.d.ts +53 -0
  436. package/dist/workspace/release-train.d.ts.map +1 -0
  437. package/dist/workspace/release-train.js +134 -0
  438. package/dist/workspace/release-workflow.d.ts.map +1 -1
  439. package/dist/workspace/release-workflow.js +4 -3
  440. package/dist/workspace/repo-ref.d.ts +45 -0
  441. package/dist/workspace/repo-ref.d.ts.map +1 -0
  442. package/dist/workspace/repo-ref.js +114 -0
  443. package/dist/workspace/run-event.schema.json +2 -2
  444. package/dist/workspace/runs-cli.d.ts +9 -0
  445. package/dist/workspace/runs-cli.d.ts.map +1 -1
  446. package/dist/workspace/runs-cli.js +48 -3
  447. package/dist/workspace/runs.schema.json +7 -0
  448. package/dist/workspace/search-cli.d.ts +204 -0
  449. package/dist/workspace/search-cli.d.ts.map +1 -0
  450. package/dist/workspace/search-cli.js +466 -0
  451. package/dist/workspace/search-contract.d.ts +56 -0
  452. package/dist/workspace/search-contract.d.ts.map +1 -0
  453. package/dist/workspace/search-contract.js +70 -0
  454. package/dist/workspace/search.schema.json +822 -0
  455. package/dist/workspace/status-decisions.d.ts +37 -0
  456. package/dist/workspace/status-decisions.d.ts.map +1 -0
  457. package/dist/workspace/status-decisions.js +147 -0
  458. package/dist/workspace/status-gates.d.ts +9 -0
  459. package/dist/workspace/status-gates.d.ts.map +1 -1
  460. package/dist/workspace/status.d.ts +4 -0
  461. package/dist/workspace/status.d.ts.map +1 -1
  462. package/dist/workspace/status.js +14 -2
  463. package/dist/workspace/status.schema.json +6 -0
  464. package/dist/workspace/work-cli.d.ts.map +1 -1
  465. package/dist/workspace/work-cli.js +5 -3
  466. package/dist/workspace/work-evidence-ops.d.ts +83 -0
  467. package/dist/workspace/work-evidence-ops.d.ts.map +1 -0
  468. package/dist/workspace/work-evidence-ops.js +169 -0
  469. package/dist/workspace/work-evidence.d.ts +12 -2
  470. package/dist/workspace/work-evidence.d.ts.map +1 -1
  471. package/dist/workspace/work-evidence.js +21 -3
  472. package/dist/workspace/work-evidence.schema.json +49 -2
  473. package/dist/workspace/workspace-gates.d.ts +110 -0
  474. package/dist/workspace/workspace-gates.d.ts.map +1 -0
  475. package/dist/workspace/workspace-gates.js +140 -0
  476. package/dist/workspace/workspace-kinds.schema.json +58 -3
  477. package/dist/workspace/workspace-ledger.d.ts +76 -0
  478. package/dist/workspace/workspace-ledger.d.ts.map +1 -0
  479. package/dist/workspace/workspace-ledger.js +91 -0
  480. package/dist/workspace/workspace-run.d.ts +112 -0
  481. package/dist/workspace/workspace-run.d.ts.map +1 -0
  482. package/dist/workspace/workspace-run.js +432 -0
  483. package/package.json +1 -1
  484. package/src/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
  485. package/src/__golden__/wave-loop/op-by-apply-hold.json +10 -0
  486. package/src/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
  487. package/src/__golden__/wave-loop/op-by-apply-pass.json +10 -0
  488. package/src/__golden__/wave-loop/op-by-apply-skip.json +10 -0
  489. package/src/__golden__/wave-loop/op-cost-member-clash.json +6 -0
  490. package/src/__golden__/wave-loop/op-cost-member.json +13 -0
  491. package/src/__golden__/wave-loop/op-denied-source.json +16 -0
  492. package/src/__golden__/wave-loop/op-denied.json +16 -0
  493. package/src/__golden__/wave-loop/op-discover-rest-short.json +6 -0
  494. package/src/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
  495. package/src/__golden__/wave-loop/op-discover-rest.json +26 -0
  496. package/src/__golden__/wave-loop/op-discover-wide.json +26 -0
  497. package/src/__golden__/wave-loop/op-held-on-again.json +16 -0
  498. package/src/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
  499. package/src/__golden__/wave-loop/op-held-on.json +16 -0
  500. package/src/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
  501. package/src/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
  502. package/src/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
  503. package/src/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
  504. package/src/__golden__/wave-loop/op-hooks-held.json +13 -0
  505. package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
  506. package/src/__golden__/wave-loop/op-hooks-pass.json +13 -0
  507. package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
  508. package/src/__golden__/wave-loop/op-hooks-share.json +33 -0
  509. package/src/__golden__/wave-loop/op-outcome-held.json +10 -0
  510. package/src/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
  511. package/src/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
  512. package/src/__golden__/wave-loop/op-outcome-replan.json +10 -0
  513. package/src/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
  514. package/src/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
  515. package/src/__golden__/wave-loop/op-overridden.json +16 -0
  516. package/src/__golden__/wave-loop/op-per-run.json +20 -0
  517. package/src/__golden__/wave-loop/op-point.json +13 -0
  518. package/src/__golden__/wave-loop/op-pr-review.json +10 -0
  519. package/src/__golden__/wave-loop/op-sealed.json +10 -0
  520. package/src/__golden__/wave-loop/op-spend-change-only.json +10 -0
  521. package/src/__golden__/wave-loop/op-spend.json +10 -0
  522. package/src/__golden__/wave-loop/op-wave-commands.json +55 -0
  523. package/src/__golden__/wave-loop/op-wide-refused.json +26 -0
  524. package/src/__golden__/wave-loop/op-wide-waiting.json +29 -0
  525. package/src/__golden__/wave-loop/op-wide.json +39 -0
  526. package/src/__snapshots__/okf.test.ts.snap +10 -0
  527. package/src/action-pins.test.ts +78 -0
  528. package/src/action-pins.ts +92 -0
  529. package/src/capabilities/aws.paths +148 -0
  530. package/src/capabilities/base-mappings.json +122 -0
  531. package/src/capabilities/catalog.ts +230 -0
  532. package/src/capabilities/language.test.ts +191 -0
  533. package/src/capabilities/language.ts +373 -0
  534. package/src/capabilities/matcher.ts +315 -0
  535. package/src/capabilities/view-compose.test.ts +76 -0
  536. package/src/capabilities/view.ts +631 -0
  537. package/src/cli/commands/carve-score-once.test.ts +99 -0
  538. package/src/cli/commands/carve.ts +37 -6
  539. package/src/cli/commands/check-lexicon.test.ts +2 -2
  540. package/src/cli/commands/import-report.ts +71 -0
  541. package/src/cli/commands/import.ts +33 -3
  542. package/src/cli/commands/lint.ts +1 -0
  543. package/src/cli/commands/migrate-dialect.test.ts +145 -0
  544. package/src/cli/commands/migrate.ts +132 -11
  545. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +4 -4
  546. package/src/cli/handlers/approve.ts +23 -2
  547. package/src/cli/handlers/build.ts +7 -1
  548. package/src/cli/handlers/declared-graph.ts +99 -0
  549. package/src/cli/handlers/graph.test.ts +94 -3
  550. package/src/cli/handlers/graph.ts +123 -96
  551. package/src/cli/handlers/ledger.ts +54 -0
  552. package/src/cli/handlers/migrate.ts +21 -12
  553. package/src/cli/handlers/misc.ts +10 -1
  554. package/src/cli/handlers/pr-env.ts +3 -4
  555. package/src/cli/handlers/pr.ts +138 -36
  556. package/src/cli/handlers/query.ts +16 -4
  557. package/src/cli/handlers/release.ts +6 -3
  558. package/src/cli/handlers/search-build-roots.test.ts +144 -0
  559. package/src/cli/handlers/search-count.test.ts +191 -0
  560. package/src/cli/handlers/search-count.ts +165 -0
  561. package/src/cli/handlers/search-json.test.ts +333 -0
  562. package/src/cli/handlers/search-live.test.ts +387 -0
  563. package/src/cli/handlers/search-paths.test.ts +235 -0
  564. package/src/cli/handlers/search.ts +1291 -166
  565. package/src/cli/main.test.ts +43 -3
  566. package/src/cli/main.ts +88 -17
  567. package/src/cli/mcp/server.test.ts +3 -3
  568. package/src/cli/mcp/server.ts +3 -0
  569. package/src/cli/mcp/tools/capabilities.ts +32 -0
  570. package/src/cli/mcp/workspace-tools.e2e.test.ts +21 -1
  571. package/src/cli/mcp/workspace-tools.ts +47 -2
  572. package/src/cli/parse-args.ts +79 -15
  573. package/src/cli/registry.ts +36 -4
  574. package/src/components/builders.ts +8 -0
  575. package/src/components/capability-plugin-loader.ts +13 -1
  576. package/src/components/capability-plugin.ts +16 -0
  577. package/src/components/pr-env-ports.ts +89 -0
  578. package/src/components/pr-env-run-bundle.test.ts +54 -0
  579. package/src/components/pr-env-run.ts +5 -76
  580. package/src/components/pr-environment.ts +2 -1
  581. package/src/components/pr-hooks.test.ts +73 -5
  582. package/src/components/pr-hooks.ts +95 -5
  583. package/src/components/pr-pipeline.ts +64 -16
  584. package/src/components/pr-policy.test.ts +64 -1
  585. package/src/components/pr-policy.ts +53 -0
  586. package/src/components/registry.test.ts +1 -1
  587. package/src/components/starter-plugin.ts +6 -0
  588. package/src/components/verbs/index.ts +2 -0
  589. package/src/components/verbs/publish-artifact.test.ts +60 -0
  590. package/src/components/verbs/publish-artifact.ts +122 -0
  591. package/src/components/verbs/publish-image.test.ts +101 -0
  592. package/src/components/verbs/publish-image.ts +265 -0
  593. package/src/config-environments.ts +160 -0
  594. package/src/config.ts +44 -124
  595. package/src/gate-decision-bundle.test.ts +1 -0
  596. package/src/gate-decision-identity.test.ts +9 -0
  597. package/src/gate-decision.ts +26 -3
  598. package/src/graph-detail.ts +15 -3
  599. package/src/graph-effective.ts +226 -75
  600. package/src/graph-ir.test.ts +163 -0
  601. package/src/graph-ir.ts +174 -0
  602. package/src/graph-sub-template.ts +22 -0
  603. package/src/graph-walk.test.ts +44 -0
  604. package/src/graph-walk.ts +102 -0
  605. package/src/import/parser.ts +20 -0
  606. package/src/lexicon.ts +84 -6
  607. package/src/lifecycle/gate-ledger.ts +8 -0
  608. package/src/lifecycle/git.ts +2 -2
  609. package/src/lifecycle/ledger-read.test.ts +107 -0
  610. package/src/lifecycle/ledger-read.ts +195 -0
  611. package/src/lifecycle/observe.test.ts +27 -1
  612. package/src/lifecycle/observe.ts +43 -1
  613. package/src/lifecycle/release-workstation.ts +24 -0
  614. package/src/lifecycle/run-ledger.ts +5 -2
  615. package/src/lint/cross-root.test.ts +122 -0
  616. package/src/lint/discover.ts +3 -1
  617. package/src/lint/post-synth.ts +212 -2
  618. package/src/lint/rule.ts +6 -0
  619. package/src/lint/rules/op/index.ts +2 -0
  620. package/src/lint/rules/op/ops019-workspace-op-target.ts +89 -0
  621. package/src/live-endpoint.ts +1 -1
  622. package/src/observation.test.ts +25 -0
  623. package/src/observation.ts +69 -5
  624. package/src/op/activities/activity-contracts.ts +5 -2
  625. package/src/op/activities/index.ts +2 -2
  626. package/src/op/activities/review-agent.test.ts +221 -4
  627. package/src/op/activities/review-agent.ts +265 -22
  628. package/src/op/activities/work-evidence.ts +9 -1
  629. package/src/op/builders.ts +9 -5
  630. package/src/op/composites/apply-op.test.ts +108 -0
  631. package/src/op/composites/apply-op.ts +37 -2
  632. package/src/op/gate-approval.test.ts +6 -1
  633. package/src/op/gate-approval.ts +12 -6
  634. package/src/op/gate-quorum-at-base.test.ts +211 -0
  635. package/src/op/gate-quorum.ts +156 -8
  636. package/src/op/gate-review.ts +14 -0
  637. package/src/op/gate.ts +67 -8
  638. package/src/op/index.ts +3 -2
  639. package/src/op/local-executor.ts +69 -9
  640. package/src/op/op-waves-depends-on.test.ts +81 -0
  641. package/src/op/op-waves-hook-targets.test.ts +4 -2
  642. package/src/op/op-waves-quorum-product.test.ts +158 -0
  643. package/src/op/op-waves-run.ts +288 -14
  644. package/src/op/op-waves.ts +143 -14
  645. package/src/op/runtime.ts +8 -0
  646. package/src/op/schedule-overdue.ts +33 -0
  647. package/src/op/stage-hooks.ts +13 -5
  648. package/src/op/workspace-run-env.ts +29 -0
  649. package/src/pr-forge-bundle.test.ts +2 -2
  650. package/src/pr-forge.test.ts +47 -0
  651. package/src/pr-forge.ts +68 -0
  652. package/src/pr-post-open.e2e.test.ts +36 -0
  653. package/src/pr-post.test.ts +102 -3
  654. package/src/pr-post.ts +89 -1
  655. package/src/read-filter.test.ts +54 -0
  656. package/src/read-filter.ts +193 -0
  657. package/src/run-event.ts +1 -1
  658. package/src/stage-hooks-bundle.test.ts +1 -0
  659. package/src/terraform/carve.ts +52 -15
  660. package/src/terraform/cuts.test.ts +173 -0
  661. package/src/terraform/cuts.ts +188 -0
  662. package/src/terraform/folds.ts +44 -0
  663. package/src/terraform/graph.ts +9 -0
  664. package/src/terraform/radius.test.ts +90 -0
  665. package/src/terraform/reach.test.ts +146 -0
  666. package/src/terraform/reach.ts +247 -0
  667. package/src/terraform/score.ts +27 -29
  668. package/src/terraform/state.ts +3 -1
  669. package/src/terraform/types.ts +8 -0
  670. package/src/wave-blocked.ts +28 -3
  671. package/src/wave-loop-golden.test.ts +4 -3
  672. package/src/workspace/behold-kinds.test.ts +1 -1
  673. package/src/workspace/capabilities-contract.test.ts +88 -0
  674. package/src/workspace/capabilities-contract.ts +132 -0
  675. package/src/workspace/capabilities.schema.json +229 -0
  676. package/src/workspace/check-contract.test.ts +7 -6
  677. package/src/workspace/check.schema.json +11 -2
  678. package/src/workspace/checks/ci-branch.test.ts +128 -0
  679. package/src/workspace/checks/ci-branch.ts +141 -0
  680. package/src/workspace/checks/links.ts +12 -1
  681. package/src/workspace/checks/org.ts +169 -0
  682. package/src/workspace/checks.ts +64 -7
  683. package/src/workspace/ci-branches.ts +31 -0
  684. package/src/workspace/ci-green-branches.test.ts +153 -0
  685. package/src/workspace/ci-green-cli.ts +7 -7
  686. package/src/workspace/ci-green-workflow.test.ts +4 -3
  687. package/src/workspace/ci-green-workflow.ts +13 -9
  688. package/src/workspace/ci-green.ts +49 -12
  689. package/src/workspace/ci-run.test.ts +72 -1
  690. package/src/workspace/ci-run.ts +68 -8
  691. package/src/workspace/ci-serve.test.ts +95 -0
  692. package/src/workspace/ci-serve.ts +106 -65
  693. package/src/workspace/component-environments.test.ts +25 -2
  694. package/src/workspace/compose-graph.ts +19 -3
  695. package/src/workspace/composites.schema.json +22 -0
  696. package/src/workspace/composites.test.ts +39 -8
  697. package/src/workspace/composites.ts +6 -2
  698. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
  699. package/src/workspace/conformance/conformance.e2e.test.ts +14 -1
  700. package/src/workspace/conformance/index.ts +31 -2
  701. package/src/workspace/cross-root-lint.test.ts +90 -0
  702. package/src/workspace/cross-root-lint.ts +126 -0
  703. package/src/workspace/dbt-kind.test.ts +3 -2
  704. package/src/workspace/dbt-models-reader.ts +362 -0
  705. package/src/workspace/dbt-models.test.ts +248 -0
  706. package/src/workspace/dbt-project-common.ts +113 -0
  707. package/src/workspace/dbt-project-reader.ts +29 -112
  708. package/src/workspace/decision-rank.ts +40 -0
  709. package/src/workspace/declaration.schema.json +133 -24
  710. package/src/workspace/declaration.ts +84 -15
  711. package/src/workspace/environments.ts +40 -4
  712. package/src/workspace/flyway-dir.ts +113 -0
  713. package/src/workspace/flyway-layout.ts +337 -0
  714. package/src/workspace/graph-cache.ts +27 -3
  715. package/src/workspace/graph-cli.ts +119 -32
  716. package/src/workspace/graph-contract.test.ts +4 -2
  717. package/src/workspace/graph.schema.json +182 -0
  718. package/src/workspace/identity.test.ts +14 -2
  719. package/src/workspace/intent.ts +6 -14
  720. package/src/workspace/kind-link-readers.ts +68 -3
  721. package/src/workspace/kind-readers.e2e.test.ts +28 -0
  722. package/src/workspace/kind-readers.test.ts +1 -1
  723. package/src/workspace/kind-readers.ts +7 -1
  724. package/src/workspace/kinds.test.ts +12 -7
  725. package/src/workspace/kinds.ts +132 -7
  726. package/src/workspace/ledger.schema.json +158 -0
  727. package/src/workspace/lexicon-outputs.ts +132 -13
  728. package/src/workspace/lineage-check.ts +30 -7
  729. package/src/workspace/links.ts +24 -1
  730. package/src/workspace/ls-contract.test.ts +1 -1
  731. package/src/workspace/ls.schema.json +7 -0
  732. package/src/workspace/ls.ts +10 -1
  733. package/src/workspace/member-commands.ts +82 -3
  734. package/src/workspace/member-file-schema.test.ts +124 -0
  735. package/src/workspace/migrate-links.test.ts +99 -0
  736. package/src/workspace/migrate-links.ts +108 -0
  737. package/src/workspace/migration-dirs.test.ts +272 -0
  738. package/src/workspace/migration-dirs.ts +267 -0
  739. package/src/workspace/nested-graph.ts +32 -1
  740. package/src/workspace/org-scope.test.ts +238 -0
  741. package/src/workspace/reason-codes.test.ts +13 -1
  742. package/src/workspace/reason-codes.ts +23 -0
  743. package/src/workspace/records-cli.ts +58 -5
  744. package/src/workspace/records.schema.json +5 -0
  745. package/src/workspace/release-candidates.ts +7 -2
  746. package/src/workspace/release-train.ts +157 -0
  747. package/src/workspace/release-workflow.ts +4 -3
  748. package/src/workspace/repo-ref.ts +113 -0
  749. package/src/workspace/run-event.schema.json +2 -2
  750. package/src/workspace/runs-cli.ts +48 -4
  751. package/src/workspace/runs.schema.json +7 -0
  752. package/src/workspace/search-cli.e2e.test.ts +305 -0
  753. package/src/workspace/search-cli.ts +591 -0
  754. package/src/workspace/search-contract.ts +95 -0
  755. package/src/workspace/search.schema.json +822 -0
  756. package/src/workspace/status-contract.test.ts +46 -1
  757. package/src/workspace/status-decisions.test.ts +100 -0
  758. package/src/workspace/status-decisions.ts +151 -0
  759. package/src/workspace/status-gates.ts +9 -0
  760. package/src/workspace/status.schema.json +6 -0
  761. package/src/workspace/status.ts +17 -3
  762. package/src/workspace/where-filters.test.ts +39 -0
  763. package/src/workspace/work-cli.ts +5 -3
  764. package/src/workspace/work-evidence-ops.test.ts +176 -0
  765. package/src/workspace/work-evidence-ops.ts +189 -0
  766. package/src/workspace/work-evidence.schema.json +49 -2
  767. package/src/workspace/work-evidence.ts +22 -3
  768. package/src/workspace/workspace-gates.ts +200 -0
  769. package/src/workspace/workspace-kinds.schema.json +58 -3
  770. package/src/workspace/workspace-ledger.ts +130 -0
  771. package/src/workspace/workspace-run.test.ts +322 -0
  772. package/src/workspace/workspace-run.ts +461 -0
@@ -0,0 +1,337 @@
1
+ /**
2
+ * A Flyway project's layout, read from a workspace tree (#4400): its
3
+ * `flyway.toml` or `flyway.conf`, the locations it names, read recursively,
4
+ * and the placeholders it substitutes.
5
+ *
6
+ * This is the layout reading of sql-yodeler's `src/check/flyway.ts` (#250),
7
+ * moved here so the workspace kind and `yodel check` share one reader. It
8
+ * works on a {@link WorkspaceTree} and tree-relative paths instead of the
9
+ * file system, and it never runs Flyway or connects to a database.
10
+ *
11
+ * The configuration is the first `flyway.toml`, else `flyway.conf`, found in
12
+ * the directory checked or a directory above it, up to the tree's root. Its
13
+ * locations are read relative to the file's own directory:
14
+ *
15
+ * filesystem:<path> that directory
16
+ * classpath:<path> src/main/resources/<path> (and, for code
17
+ * <path> migrations, src/main/java/<path> and src/main/kotlin/<path>)
18
+ *
19
+ * With no configuration, or one that names no location, the directory
20
+ * checked is the one location. A location outside the tree is reported by
21
+ * {@link FlywayConfig.outside}, not read. A Java or Kotlin migration in a
22
+ * location is not SQL and is reported by {@link codeMigrations}.
23
+ *
24
+ * Placeholders are `${name}` (the prefix and suffix are configurable), from
25
+ * `flyway.placeholders.<name>` (conf) or `[flyway.placeholders]` (toml), plus
26
+ * Flyway's own: `flyway:defaultSchema`, `flyway:user`, `flyway:database`,
27
+ * `flyway:timestamp`, `flyway:filename`, `flyway:workingDirectory`,
28
+ * `flyway:table` and `flyway:environment`. {@link substitute} replaces them
29
+ * for a replay; the reader that lists migrations leaves the text as it is.
30
+ */
31
+
32
+ import { posix } from "node:path";
33
+ import { joinPath, type WorkspaceTree } from "./tree";
34
+
35
+ export interface FlywayConfig {
36
+ /** The configuration file, tree-relative; undefined with none. */
37
+ file?: string;
38
+ /** Where file names are relative to: the configuration's directory, else the directory checked. Tree-relative. */
39
+ root: string;
40
+ /** The SQL locations, tree-relative directories. */
41
+ locations: string[];
42
+ /** Directories code migrations (Java, Kotlin) of a classpath location would be in. */
43
+ codeLocations: string[];
44
+ /** Locations the configuration names that lie outside the tree, as written. */
45
+ outside: string[];
46
+ placeholders: Record<string, string>;
47
+ placeholderPrefix: string;
48
+ placeholderSuffix: string;
49
+ placeholderReplacement: boolean;
50
+ sqlMigrationPrefix: string;
51
+ repeatableSqlMigrationPrefix: string;
52
+ baselineMigrationPrefix: string;
53
+ undoSqlMigrationPrefix: string;
54
+ sqlMigrationSeparator: string;
55
+ sqlMigrationSuffixes: string[];
56
+ defaultSchema?: string;
57
+ user?: string;
58
+ database?: string;
59
+ /** The JDBC URL, when the configuration has one. */
60
+ url?: string;
61
+ /** The dialect the URL names: `postgres` or `clickhouse`; undefined for another or none. */
62
+ dialect?: string;
63
+ table: string;
64
+ environment?: string;
65
+ }
66
+
67
+ /** The first `flyway.toml`, else `flyway.conf`, in `dir` or a directory above it, up to the tree's root. */
68
+ export function findFlywayConfig(tree: WorkspaceTree, dir: string): string | undefined {
69
+ let at = dir;
70
+ for (;;) {
71
+ for (const name of ["flyway.toml", "flyway.conf"]) {
72
+ const f = joinPath(at, name);
73
+ if (tree.stat(f) === "file") return f;
74
+ }
75
+ if (at === "" || at === ".") return undefined;
76
+ at = posix.dirname(at) === "." ? "" : posix.dirname(at);
77
+ }
78
+ }
79
+
80
+ type Values = Record<string, string | string[] | boolean>;
81
+
82
+ /** Java-properties `flyway.*` keys, without the `flyway.` prefix. */
83
+ export function parseFlywayConf(text: string): Values {
84
+ const out: Values = {};
85
+ const lines = text.split(/\r?\n/);
86
+ for (let i = 0; i < lines.length; i++) {
87
+ let line = lines[i] ?? "";
88
+ while (/\\$/.test(line) && i + 1 < lines.length) line = line.slice(0, -1) + (lines[++i] ?? "").trimStart();
89
+ const t = line.trim();
90
+ if (t === "" || t.startsWith("#") || t.startsWith("!")) continue;
91
+ const m = /^([^=:\s]+)\s*[=:]\s*(.*)$/.exec(t);
92
+ if (!m) continue;
93
+ const key = m[1] ?? "";
94
+ if (!key.startsWith("flyway.")) continue;
95
+ out[key.slice("flyway.".length)] = (m[2] ?? "").trim();
96
+ }
97
+ return out;
98
+ }
99
+
100
+ /** A TOML document, as far as Flyway's configuration uses it: tables, strings, arrays of strings, booleans and numbers. */
101
+ export function parseToml(text: string): Record<string, Values> {
102
+ const tables: Record<string, Values> = { "": {} };
103
+ let current = "";
104
+ const lines = text.split(/\r?\n/);
105
+ for (let i = 0; i < lines.length; i++) {
106
+ const t = stripComment(lines[i] ?? "").trim();
107
+ if (t === "") continue;
108
+ const table = /^\[\s*([^\]]+?)\s*\]$/.exec(t);
109
+ if (table) {
110
+ current = (table[1] ?? "").split(".").map((k) => unquote(k.trim())).join(".");
111
+ tables[current] ??= {};
112
+ continue;
113
+ }
114
+ const kv = /^("[^"]*"|'[^']*'|[A-Za-z0-9_.:-]+)\s*=\s*(.*)$/.exec(t);
115
+ if (!kv) continue;
116
+ let raw = kv[2] ?? "";
117
+ // A multi-line array runs to its closing bracket.
118
+ while (raw.trimStart().startsWith("[") && !balanced(raw) && i + 1 < lines.length) raw += ` ${stripComment(lines[++i] ?? "").trim()}`;
119
+ const path = unquote(kv[1] ?? "").split(".");
120
+ const key = path.pop() ?? "";
121
+ const where = [current, ...path].filter(Boolean).join(".");
122
+ tables[where] ??= {};
123
+ tables[where][key] = tomlValue(raw.trim());
124
+ }
125
+ return tables;
126
+ }
127
+
128
+ function stripComment(line: string): string {
129
+ let quote: string | undefined;
130
+ for (let i = 0; i < line.length; i++) {
131
+ const c = line[i];
132
+ if (quote) {
133
+ if (c === "\\" && quote === '"') i++;
134
+ else if (c === quote) quote = undefined;
135
+ } else if (c === '"' || c === "'") quote = c;
136
+ else if (c === "#") return line.slice(0, i);
137
+ }
138
+ return line;
139
+ }
140
+
141
+ const balanced = (s: string) => (s.match(/\[/g) ?? []).length <= (s.match(/\]/g) ?? []).length;
142
+
143
+ function unquote(s: string): string {
144
+ if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) return s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\");
145
+ return s;
146
+ }
147
+
148
+ function tomlValue(raw: string): string | string[] | boolean {
149
+ if (raw === "true" || raw === "false") return raw === "true";
150
+ if (raw.startsWith("[")) {
151
+ const inner = raw.replace(/^\[/, "").replace(/\]\s*$/, "");
152
+ return (inner.match(/"(?:[^"\\]|\\.)*"|'[^']*'|[^,\s]+/g) ?? []).map((v) => unquote(v.trim())).filter((v) => v !== "");
153
+ }
154
+ return unquote(raw);
155
+ }
156
+
157
+ const list = (v: string | string[] | boolean | undefined): string[] | undefined =>
158
+ v === undefined || typeof v === "boolean" ? undefined : Array.isArray(v) ? v : v.split(",").map((s) => s.trim()).filter(Boolean);
159
+ const str = (v: string | string[] | boolean | undefined): string | undefined => (typeof v === "string" ? v : Array.isArray(v) ? v.join(",") : undefined);
160
+
161
+ /** The database name a JDBC URL names: the path after the host. */
162
+ function databaseOf(url: string | undefined): string | undefined {
163
+ const m = url === undefined ? null : /^jdbc:[a-z0-9]+:\/\/[^/]+\/([^?;]+)/i.exec(url);
164
+ return m?.[1] ?? undefined;
165
+ }
166
+
167
+ /** The dialect a JDBC URL names. */
168
+ function dialectOf(url: string | undefined): string | undefined {
169
+ const m = url === undefined ? null : /^jdbc:([a-z0-9]+):/i.exec(url);
170
+ const driver = m?.[1]?.toLowerCase();
171
+ return driver === "postgresql" ? "postgres" : driver === "clickhouse" ? "clickhouse" : undefined;
172
+ }
173
+
174
+ /** The configuration `file` holds, or the defaults with `dir` as the one location when there is none. */
175
+ export function readFlywayConfig(tree: WorkspaceTree, file: string | undefined, dir: string): FlywayConfig {
176
+ let values: Values = {};
177
+ let placeholders: Record<string, string> = {};
178
+ if (file !== undefined) {
179
+ const text = tree.read(file);
180
+ if (file.endsWith(".toml")) {
181
+ const t = parseToml(text);
182
+ const flyway = t.flyway ?? {};
183
+ const name = str(flyway.environment) ?? "default";
184
+ const env = t[`environments.${name}`] ?? {};
185
+ values = { ...flyway, ...(t[`environments.${name}.flyway`] ?? {}), ...(env.url !== undefined ? { url: env.url } : {}), ...(env.user !== undefined ? { user: env.user } : {}), ...(env.schemas !== undefined ? { schemas: env.schemas } : {}) };
186
+ if (str(flyway.environment) !== undefined) values.environment = name;
187
+ placeholders = Object.fromEntries(Object.entries({ ...(t["flyway.placeholders"] ?? {}), ...(t[`environments.${name}.flyway.placeholders`] ?? {}) }).map(([k, v]) => [k, str(v) ?? String(v)]));
188
+ } else {
189
+ values = parseFlywayConf(text);
190
+ placeholders = Object.fromEntries(Object.entries(values).flatMap(([k, v]) => (k.startsWith("placeholders.") ? [[k.slice("placeholders.".length), str(v) ?? ""]] : [])));
191
+ }
192
+ }
193
+ const root = file === undefined ? dir : posix.dirname(file) === "." ? "" : posix.dirname(file);
194
+ const named = list(values.locations) ?? [];
195
+ const locations: string[] = [];
196
+ const codeLocations: string[] = [];
197
+ const outside: string[] = [];
198
+ const inside = (...parts: string[]): string | undefined => {
199
+ const p = posix.normalize(joinPath(...parts)) || ".";
200
+ if (p === ".." || p.startsWith("../") || posix.isAbsolute(p)) return undefined;
201
+ return p === "." ? "" : p;
202
+ };
203
+ for (const l of named) {
204
+ const m = /^(filesystem|classpath):(.*)$/.exec(l);
205
+ const kind = m?.[1] ?? "classpath";
206
+ const raw = m?.[2] ?? l;
207
+ if (kind === "filesystem") {
208
+ const at = posix.isAbsolute(raw) ? undefined : inside(root, raw);
209
+ if (at === undefined) outside.push(l);
210
+ else locations.push(at);
211
+ } else {
212
+ const path = raw.replace(/^\/+/, "");
213
+ const res = inside(root, "src/main/resources", path);
214
+ if (res === undefined) outside.push(l);
215
+ else {
216
+ locations.push(res);
217
+ for (const lang of ["java", "kotlin"]) {
218
+ const c = inside(root, "src/main", lang, path);
219
+ if (c !== undefined) codeLocations.push(c);
220
+ }
221
+ }
222
+ }
223
+ }
224
+ if (named.length === 0) locations.push(dir);
225
+ const schemas = list(values.schemas);
226
+ const replacement = values.placeholderReplacement;
227
+ const defaultSchema = str(values.defaultSchema) ?? schemas?.[0];
228
+ const user = str(values.user);
229
+ const url = str(values.url);
230
+ const database = databaseOf(url);
231
+ const dialect = dialectOf(url);
232
+ const environment = str(values.environment);
233
+ return {
234
+ ...(file !== undefined ? { file } : {}),
235
+ root,
236
+ locations,
237
+ codeLocations,
238
+ outside,
239
+ placeholders,
240
+ placeholderPrefix: str(values.placeholderPrefix) ?? "${",
241
+ placeholderSuffix: str(values.placeholderSuffix) ?? "}",
242
+ placeholderReplacement: !(replacement === false || replacement === "false"),
243
+ sqlMigrationPrefix: str(values.sqlMigrationPrefix) ?? "V",
244
+ repeatableSqlMigrationPrefix: str(values.repeatableSqlMigrationPrefix) ?? "R",
245
+ baselineMigrationPrefix: str(values.baselineMigrationPrefix) ?? "B",
246
+ undoSqlMigrationPrefix: str(values.undoSqlMigrationPrefix) ?? "U",
247
+ sqlMigrationSeparator: str(values.sqlMigrationSeparator) ?? "__",
248
+ sqlMigrationSuffixes: list(values.sqlMigrationSuffixes) ?? [".sql"],
249
+ ...(defaultSchema !== undefined ? { defaultSchema } : {}),
250
+ ...(user !== undefined ? { user } : {}),
251
+ ...(database !== undefined ? { database } : {}),
252
+ ...(url !== undefined ? { url } : {}),
253
+ ...(dialect !== undefined ? { dialect } : {}),
254
+ table: str(values.table) ?? "flyway_schema_history",
255
+ ...(environment !== undefined ? { environment } : {}),
256
+ };
257
+ }
258
+
259
+ /** Every file under `dir`, recursively, tree-relative, sorted; none when it does not exist. */
260
+ export function walk(tree: WorkspaceTree, dir: string): string[] {
261
+ const entries = tree.list(dir);
262
+ if (!entries) return [];
263
+ const out: string[] = [];
264
+ for (const e of [...entries].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))) {
265
+ const p = joinPath(dir, e.name);
266
+ if (e.type === "dir") out.push(...walk(tree, p));
267
+ else out.push(p);
268
+ }
269
+ return out;
270
+ }
271
+
272
+ const base = (f: string): string => posix.basename(f);
273
+
274
+ /** A Flyway SQL callback (`beforeMigrate.sql`, `afterEachMigrate__notify.sql`, ...): run around a migrate, not a migration. */
275
+ export const isCallback = (file: string): boolean => /^(before|after)[A-Z][A-Za-z]*(__.*)?\.[A-Za-z]+$/.test(base(file));
276
+
277
+ /** The code migrations (Java, Kotlin) in `config`'s locations, relative to the tree. */
278
+ export function codeMigrations(tree: WorkspaceTree, config: FlywayConfig): string[] {
279
+ const code = /\.(java|kt|class)$/;
280
+ const prefixes = [config.sqlMigrationPrefix, config.repeatableSqlMigrationPrefix, config.baselineMigrationPrefix].filter(Boolean);
281
+ const migration = (f: string) => code.test(f) && prefixes.some((p) => base(f).startsWith(p)) && base(f).includes(config.sqlMigrationSeparator);
282
+ return [...new Set([...config.locations, ...config.codeLocations])].flatMap((d) => walk(tree, d)).filter(migration);
283
+ }
284
+
285
+ /** The values Flyway gives its own placeholders, for `file`. */
286
+ function builtins(config: FlywayConfig, file: string, fallback: { defaultSchema?: string | undefined }): Record<string, string | undefined> {
287
+ return {
288
+ "flyway:defaultSchema": config.defaultSchema ?? fallback.defaultSchema,
289
+ "flyway:user": config.user,
290
+ "flyway:database": config.database,
291
+ "flyway:timestamp": new Date().toISOString().replace("T", " ").replace(/\..*$/, ""),
292
+ "flyway:filename": base(file),
293
+ "flyway:workingDirectory": process.cwd(),
294
+ "flyway:table": config.table,
295
+ "flyway:environment": config.environment,
296
+ };
297
+ }
298
+
299
+ const escape = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
300
+
301
+ /** A placeholder with no value; `file` is as the caller passed it, `line` is from 1. */
302
+ export class FlywayPlaceholderError extends Error {
303
+ constructor(
304
+ readonly file: string,
305
+ readonly line: number,
306
+ readonly placeholder: string,
307
+ readonly name: string,
308
+ readonly where: string,
309
+ ) {
310
+ super(`${file}:${String(line)}: no value for the placeholder ${placeholder}; set it in ${where} (flyway.placeholders.${name} in flyway.conf, [flyway.placeholders] in flyway.toml)`);
311
+ }
312
+ }
313
+
314
+ /**
315
+ * `text` with its placeholders replaced, line by line so line numbers hold.
316
+ * A placeholder with no value throws a {@link FlywayPlaceholderError} naming
317
+ * `file` and the line, as Flyway's own run would fail.
318
+ */
319
+ export function substitute(text: string, file: string, config: FlywayConfig, fallback: { defaultSchema?: string | undefined } = {}): string {
320
+ if (!config.placeholderReplacement) return text;
321
+ const values: Record<string, string | undefined> = { ...builtins(config, file, fallback), ...config.placeholders };
322
+ const lower = new Map(Object.entries(values).map(([k, v]) => [k.toLowerCase(), v]));
323
+ const pattern = new RegExp(`${escape(config.placeholderPrefix)}([A-Za-z0-9_.:-]+)${escape(config.placeholderSuffix)}`, "g");
324
+ return text
325
+ .split("\n")
326
+ .map((line, i) =>
327
+ line.replace(pattern, (whole, name: string) => {
328
+ const v = values[name] ?? lower.get(name.toLowerCase());
329
+ if (v === undefined) {
330
+ const where = config.file === undefined ? "a flyway.toml or flyway.conf beside the migrations" : config.file;
331
+ throw new FlywayPlaceholderError(file, i + 1, whole, name, where);
332
+ }
333
+ return v;
334
+ }),
335
+ )
336
+ .join("\n");
337
+ }
@@ -368,9 +368,7 @@ export function splitCached(plan: MemberPlan, args: ParsedArgs, cache: GraphCach
368
368
  // A member read through a generated reader project (#2874) is also keyed on
369
369
  // the kind's graph block and the version of the package that reads it.
370
370
  const reader = unit.reader ? readerStamp(unit.reader) : "";
371
- const abs = unit.dir === "." ? plan.workspace.root : join(plan.workspace.root, ...unit.dir.split("/"));
372
- const revision = at ? { commit: at, dir: unit.dir } : undefined;
373
- const stamp = memberStamp(abs, unit.exclude, revision);
371
+ const { abs, revision, stamp } = unitStamp(plan, unit, at);
374
372
  if (!stamp) continue;
375
373
  stamps.set(unit.id, stamp.value);
376
374
  const key = cacheKey({ member: unit.member, dir: unit.dir, stamp: stamp.value, toolchain: `${tool}\0${reader}`, argv, env });
@@ -385,6 +383,32 @@ export function splitCached(plan: MemberPlan, args: ParsedArgs, cache: GraphCach
385
383
  return { hits, stamps, pending, started };
386
384
  }
387
385
 
386
+ /** One unit's stamp, and what it was taken over: the member's directory on disk, and the commit for `--at`. */
387
+ function unitStamp(plan: MemberPlan, unit: RunUnit, at: string | null): { abs: string; revision?: { commit: string; dir: string }; stamp: Stamp | undefined } {
388
+ const abs = unit.dir === "." ? plan.workspace.root : join(plan.workspace.root, ...unit.dir.split("/"));
389
+ const revision = at ? { commit: at, dir: unit.dir } : undefined;
390
+ return { abs, ...(revision ? { revision } : {}), stamp: memberStamp(abs, unit.exclude, revision) };
391
+ }
392
+
393
+ /**
394
+ * Every member unit's stamp, by unit id, by the rule {@link splitCached} keys
395
+ * the cache on (ws-059), with no cache read. A read that is never cached, such
396
+ * as `chant workspace search` (#4374), still stamps its members this way, so a
397
+ * reader compares stamps across documents with one meaning. A unit whose stamp
398
+ * can't be taken is left out.
399
+ */
400
+ export function planStamps(plan: MemberPlan, at: string | null): Map<string, string> {
401
+ const stamps = new Map<string, string>();
402
+ for (const group of plan.groups) {
403
+ for (const unit of group.units) {
404
+ if (unit.group) continue;
405
+ const { stamp } = unitStamp(plan, unit, at);
406
+ if (stamp) stamps.set(unit.id, stamp.value);
407
+ }
408
+ }
409
+ return stamps;
410
+ }
411
+
388
412
  /** The plan without the units in `ids`; a toolchain left with no units is dropped. */
389
413
  export function withoutUnits(plan: MemberPlan, ids: ReadonlySet<string>): MemberPlan {
390
414
  if (ids.size === 0) return plan;
@@ -31,11 +31,14 @@ import { dirname, join, resolve } from "node:path";
31
31
  import { formatError } from "../cli/format";
32
32
  import type { CommandContext, ParsedArgs } from "../cli/registry";
33
33
  import { graphBox, plantability, type Plantable } from "./box-factory";
34
- import { composeWorkspaceGraph, readMemberIr, type ComposedMember, type ComposeInput, type WorkspaceGraph } from "./compose-graph";
35
- import { openGraphCache, splitCached, storeReads, withoutUnits } from "./graph-cache";
36
- import { readDeclaration, readerVersion, WORKSPACE_ERROR_CODES, WorkspaceReadError, type ErrorLocation } from "./declaration";
37
- import { describePlan, emitDocument, executePlan, memberStatus, planJson, planMembers, type MemberPlan, type Toolchain, type UnitResult } from "./member-commands";
38
- import { loadKindRegistry } from "./kinds";
34
+ import { composedId, composeWorkspaceGraph, readMemberIr, type ComposedMember, type ComposeInput, type WorkspaceGraph } from "./compose-graph";
35
+ import { isViewDocument, prefixView } from "../capabilities/view";
36
+ import { refusedCapabilityView } from "./nested-graph";
37
+ import { openGraphCache, planStamps, splitCached, storeReads, withoutUnits } from "./graph-cache";
38
+ import { readDeclaration, readerVersion, WORKSPACE_ERROR_CODES, WorkspaceReadError, type Declaration, type ErrorLocation, type RepoRef } from "./declaration";
39
+ import { describePlan, emitDocument, executePlan, memberStatus, planJson, planMembers, type MemberArgv, type MemberPlan, type Toolchain, type UnitResult } from "./member-commands";
40
+ import { loadKindRegistry, REPO_KIND, type KindRegistry } from "./kinds";
41
+ import { repoIdentity } from "./repo-ref";
39
42
  import { readKindLinks } from "./kind-link-readers";
40
43
  import { prepareKindReaders, type PreparedReaders } from "./kind-readers";
41
44
  import { recordLinkRows } from "./record-assets";
@@ -168,6 +171,7 @@ function compose(
168
171
  only: string[] | undefined,
169
172
  declarationMembers: { name: string; dir: string; kind: string }[],
170
173
  live = false,
174
+ capabilityView = false,
171
175
  ): { inputs: ComposeInput[]; failed: boolean } {
172
176
  // A member that ran was read live when --live was given, and says when (#2875).
173
177
  const read = (member: ComposedMember, r: UnitResult): ComposedMember => {
@@ -203,6 +207,12 @@ function compose(
203
207
  }
204
208
  const member = read(memberStatus(m.name, m.dir, m.kind, "composed", null, r.chant), r);
205
209
  member.irVersion = ir.irVersion;
210
+ // The member's own capability view (#4378), with composed ids; null when its chant printed none.
211
+ if (capabilityView) {
212
+ const view = (ir.ir as { capabilityView?: unknown }).capabilityView;
213
+ member.capabilityView = isViewDocument(view) ? prefixView(view, composedId(m.name, "")) : null;
214
+ }
215
+ delete (ir.ir as { capabilityView?: unknown }).capabilityView;
206
216
  inputs.push({ member, ir: ir.ir });
207
217
  }
208
218
  return { inputs, failed };
@@ -212,58 +222,125 @@ function compose(
212
222
  export function planGraph(query: GraphQuery): MemberPlan {
213
223
  const located = locateWorkspace(query.cwd, query.at);
214
224
  const declaration = readDeclaration(located.tree, "", { rootChant: true });
215
- const kinds = loadKindRegistry(declaration.pins, located.rootOnDisk).registry;
216
- return planMembers("graph", located.rootOnDisk, { only: query.members, reader: query.reader, tree: located.tree, kinds });
225
+ const { registry: kinds, problems } = loadKindRegistry(declaration.pins, located.rootOnDisk);
226
+ return planMembers("graph", located.rootOnDisk, { only: query.members, reader: query.reader, tree: located.tree, kinds, kindProblems: problems.map((p) => p.message) });
217
227
  }
218
228
 
219
- /** Read and compose the graph, and build the document. Never throws a {@link WorkspaceReadError}. */
220
- export async function workspaceGraph(query: GraphQuery): Promise<GraphResult> {
221
- const head: Head = { $schema: GRAPH_OUTPUT_SCHEMA_ID, contract: GRAPH_CONTRACT_VERSION, chant: readerVersion() };
229
+ /** The members of a workspace read, each read under its own toolchain: what graph and search compose (#4374). */
230
+ export interface MemberReads {
231
+ located: LocatedWorkspace;
232
+ declaration: Declaration;
233
+ kinds: KindRegistry;
234
+ /** The plan the members ran from. */
235
+ plan: MemberPlan;
236
+ /** Each member's answer, the cache's included, in no particular order. */
237
+ results: UnitResult[];
238
+ /** The members the cache answered. */
239
+ served: ReadonlySet<string>;
240
+ /** Each member's stamp, by unit id (ws-059). */
241
+ stamps: ReadonlyMap<string, string>;
242
+ /** With {@link GraphQuery.components}: each member's component graph run. */
243
+ components?: UnitResult[];
244
+ }
245
+
246
+ export interface MemberReadOptions {
247
+ /** The command line each member runs; `chant graph --format ir` and the verb's flags by default. */
248
+ argvFor?: MemberArgv;
249
+ /**
250
+ * Answer members from the per-member cache and store what they print
251
+ * (ws-059). Only a read whose output is a graph IR may be cached. When
252
+ * off, every member is still stamped by the same rule.
253
+ */
254
+ cache: boolean;
255
+ }
256
+
257
+ /**
258
+ * Plan the members a workspace read covers, run each under its own toolchain
259
+ * (ws-021) at the revision asked for, and return what they printed. One
260
+ * fan-out, shared by `chant workspace graph` and `chant workspace search`
261
+ * (#4374): `--at` exports the tree once, a member of a package's kind runs in
262
+ * its reader project, and every member is stamped by the rule of ws-059. The
263
+ * exported tree and the reader projects are removed before this returns.
264
+ * Throws a {@link WorkspaceReadError} when the declaration can't be read.
265
+ */
266
+ export async function readMembers(query: GraphQuery, options: MemberReadOptions): Promise<MemberReads> {
222
267
  let exported: string | undefined;
223
268
  let readers: PreparedReaders | undefined;
224
- if (query.args?.live && query.at !== undefined) {
225
- return { doc: { ...head, error: { code: "live-at-revision", message: LIVE_AT_REVISION, location: null } }, failed: true };
226
- }
227
269
  try {
228
270
  const located = locateWorkspace(query.cwd, query.at);
229
271
  const declaration = readDeclaration(located.tree, "", { rootChant: true });
230
272
  // Kinds are read before planning: a package kind with a graph block runs (#2874).
231
- const kinds = loadKindRegistry(declaration.pins, located.rootOnDisk).registry;
232
- let plan = planMembers("graph", located.rootOnDisk, { only: query.members, reader: query.reader, tree: located.tree, kinds });
273
+ const { registry: kinds, problems } = loadKindRegistry(declaration.pins, located.rootOnDisk);
274
+ const kindProblems = problems.map((p) => p.message);
275
+ let plan = planMembers("graph", located.rootOnDisk, { only: query.members, reader: query.reader, tree: located.tree, kinds, kindProblems });
233
276
  const args = (query.args ?? {}) as ParsedArgs;
234
277
  // Members whose last source read still stands are answered from the cache (#2876).
235
278
  // A composites read runs every member's component graph as well, so it reads everything.
236
- const cache = query.noCache || query.components ? undefined : openGraphCache(located.rootOnDisk);
279
+ const cache = !options.cache || query.noCache || query.components ? undefined : openGraphCache(located.rootOnDisk);
237
280
  const split = cache ? splitCached(plan, args, cache, located.at) : undefined;
281
+ const stamps = split?.stamps ?? (options.cache ? new Map<string, string>() : planStamps(plan, located.at));
238
282
  const served = new Set(split?.hits.map((h) => h.id));
239
283
  if (located.at !== null && withoutUnits(plan, served).groups.length > 0) {
240
284
  exported = exportRevision(located, withoutUnits(plan, served).groups.flatMap((g) => g.units.map((u) => u.dir)));
241
- plan = planMembers("graph", exported, { only: query.members, reader: query.reader, tree: workingTree(exported), kinds });
285
+ plan = planMembers("graph", exported, { only: query.members, reader: query.reader, tree: workingTree(exported), kinds, kindProblems });
242
286
  }
243
287
  // Only the members that run get a reader project; a served member needs none.
244
288
  const toRun = withoutUnits(plan, served);
245
289
  readers = prepareKindReaders(toRun, exported ?? located.rootOnDisk);
246
- const [ran, components] = await Promise.all([
247
- executePlan(toRun, args),
290
+ const [first, components] = await Promise.all([
291
+ executePlan(toRun, args, options.argvFor),
248
292
  query.components ? executePlan(plan, args, () => componentGraphArgv(args)) : Promise.resolve(undefined),
249
293
  ]);
294
+ const ran = args.capabilityView && !options.argvFor ? await withoutViewWhereRefused(toRun, args, first) : first;
250
295
  if (cache && split) storeReads(split, ran, cache);
251
296
  const results = [...(split?.hits ?? []), ...ran];
252
297
  if (query.inTree) await query.inTree(exported ?? located.rootOnDisk, declaration.members.filter((m) => !query.members?.length || query.members.includes(m.name)));
253
298
  for (const r of components ?? []) if (r.stderr.trim() && query.onStderr) query.onStderr(r.stderr.endsWith("\n") ? r.stderr : `${r.stderr}\n`);
254
299
  for (const r of results) if (r.stderr.trim() && query.onStderr) query.onStderr(r.stderr.endsWith("\n") ? r.stderr : `${r.stderr}\n`);
255
- const { inputs, failed } = compose(plan, results, query.members, declaration.members, !!args.live);
300
+ return { located, declaration, kinds, plan, results, served, stamps, ...(components ? { components } : {}) };
301
+ } finally {
302
+ readers?.cleanup();
303
+ if (exported) rmSync(dirname(exported), { recursive: true, force: true });
304
+ }
305
+ }
306
+
307
+ /**
308
+ * A member's chant from before #4378 refuses `--capability-view` as a flag
309
+ * it doesn't know. Read those members again without it, so the graph still
310
+ * composes them; they carry `capabilityView: null`, which a capability search
311
+ * reports as `member-chant-too-old`.
312
+ */
313
+ async function withoutViewWhereRefused(plan: MemberPlan, args: ParsedArgs, results: UnitResult[]): Promise<UnitResult[]> {
314
+ const refused = new Set(results.filter((r) => r.exitCode !== 0 && refusedCapabilityView(r.stderr)).map((r) => r.id));
315
+ if (refused.size === 0) return results;
316
+ const others = new Set(results.filter((r) => !refused.has(r.id)).map((r) => r.id));
317
+ const again = await executePlan(withoutUnits(plan, others), { ...args, capabilityView: false });
318
+ const byId = new Map(again.map((r) => [r.id, r]));
319
+ return results.map((r) => byId.get(r.id) ?? r);
320
+ }
321
+
322
+ /** Read and compose the graph, and build the document. Never throws a {@link WorkspaceReadError}. */
323
+ export async function workspaceGraph(query: GraphQuery): Promise<GraphResult> {
324
+ const head: Head = { $schema: GRAPH_OUTPUT_SCHEMA_ID, contract: GRAPH_CONTRACT_VERSION, chant: readerVersion() };
325
+ if (query.args?.live && query.at !== undefined) {
326
+ return { doc: { ...head, error: { code: "live-at-revision", message: LIVE_AT_REVISION, location: null } }, failed: true };
327
+ }
328
+ try {
329
+ const { located, declaration, kinds, plan, results, served, stamps, components } = await readMembers(query, { cache: true });
330
+ const args = (query.args ?? {}) as ParsedArgs;
331
+ const { inputs, failed } = compose(plan, results, query.members, declaration.members, !!args.live, !!args.capabilityView);
256
332
  for (const { member } of inputs) {
257
333
  if (member.status !== "composed") continue;
258
334
  member.cached = served.has(member.name);
259
- member.stamp = split?.stamps.get(member.name) ?? null;
335
+ member.stamp = stamps.get(member.name) ?? null;
260
336
  }
261
337
  // Links (#2539) resolve against the declaration that was read, the revision's for --at, and the kinds installed now.
262
338
  // A kind's link reader (#3932) reads the member's files in the tree read, as check does.
263
- const graph = composeWorkspaceGraph({ name: declaration.name, root: located.root }, inputs, { declaration, kinds, read: readKindLinks(declaration, located.tree, kinds) });
339
+ const graph = composeWorkspaceGraph({ name: declaration.name, root: located.root, repo: repoIdentity(located.rootOnDisk) }, inputs, { declaration, kinds, read: readKindLinks(declaration, located.tree, kinds) });
264
340
  // The box's factory and listing (#3146), from the declaration read, so --at gives them at that revision.
265
341
  for (const member of graph.members) member.box = graphBox(declaration.members.find((m) => m.name === member.name)?.box ?? null, located.tree, declaration.members);
266
342
  // Nested workspaces (#2551, ws-071): read-only, through their own chant workspace graph.
343
+ // Repo members (#3168): another repository's workspace at its pinned revision, read the same way.
267
344
  const nestedFailed = await expandNested(graph, declaration.members, query, located.rootOnDisk, located.at);
268
345
  let recordsFailed = false;
269
346
  if (query.kind !== undefined) {
@@ -285,41 +362,51 @@ export async function workspaceGraph(query: GraphQuery): Promise<GraphResult> {
285
362
  } catch (err) {
286
363
  if (!(err instanceof WorkspaceReadError)) throw err;
287
364
  return { doc: { ...head, error: { code: err.code, message: err.message, location: err.location ?? null } }, failed: true };
288
- } finally {
289
- readers?.cleanup();
290
- if (exported) rmSync(dirname(exported), { recursive: true, force: true });
291
365
  }
292
366
  }
293
367
 
294
368
  /**
295
369
  * Expand every member of kind `workspace` the query covers, read-only (#2551,
296
- * ws-071). Returns whether one could not be read.
370
+ * ws-071), and every member of kind `repo` the same way, at its pinned
371
+ * revision, fetched into the user's cache (#3168). Returns whether one could
372
+ * not be read.
297
373
  */
298
374
  async function expandNested(
299
375
  graph: WorkspaceGraph,
300
- members: readonly { name: string; dir: string; kind: string }[],
376
+ members: readonly { name: string; dir: string; kind: string; repo: RepoRef | null }[],
301
377
  query: GraphQuery,
302
378
  rootOnDisk: string,
303
379
  at: string | null,
304
380
  ): Promise<boolean> {
305
- const nested = members.filter((m) => m.kind === "workspace" && (!query.members?.length || query.members.includes(m.name)));
381
+ const covered = (m: { name: string }) => !query.members?.length || query.members.includes(m.name);
382
+ const nested = members.filter((m) => (m.kind === "workspace" || (m.kind === REPO_KIND && m.repo !== null)) && covered(m));
306
383
  if (nested.length === 0) return false;
307
384
  const { foldNested, readNested } = await import("./nested-graph");
385
+ const { fetchRepoAt } = await import("./repo-ref");
308
386
  const reads = await Promise.all(
309
387
  nested.map(async (m) => {
388
+ if (m.repo) {
389
+ // The other repository at its pinned revision, whatever revision the outer read is at.
390
+ const fetched = fetchRepoAt(m.repo, rootOnDisk);
391
+ if (!fetched.ok) return { m, read: null, missing: fetched.message };
392
+ if (!existsSync(fetched.dir)) return { m, read: null, missing: `${m.repo.url} at ${m.repo.rev} has no directory ${m.repo.workspace}` };
393
+ return { m, read: await readNested(fetched.dir, query.args ?? {}, m.repo.rev, GRAPH_OUTPUT_SCHEMA_ID, GRAPH_CONTRACT_VERSION, query.reader), missing: null };
394
+ }
310
395
  const abs = join(rootOnDisk, ...m.dir.split("/"));
311
- if (!existsSync(abs)) return { m, read: null };
312
- return { m, read: await readNested(abs, query.args ?? {}, at, GRAPH_OUTPUT_SCHEMA_ID, GRAPH_CONTRACT_VERSION, query.reader) };
396
+ if (!existsSync(abs)) return { m, read: null, missing: null };
397
+ return { m, read: await readNested(abs, query.args ?? {}, at, GRAPH_OUTPUT_SCHEMA_ID, GRAPH_CONTRACT_VERSION, query.reader), missing: null };
313
398
  }),
314
399
  );
315
400
  let failed = false;
316
- for (const { m, read } of reads) {
401
+ for (const { m, read, missing } of reads) {
317
402
  const member = graph.members.find((x) => x.name === m.name);
318
403
  if (!member) continue;
404
+ if (m.repo) member.repo = { ...m.repo, read: read?.ok ? (read.doc.workspace.repo ?? null) : null };
319
405
  if (!read) {
320
406
  failed = true;
321
407
  member.status = "failed";
322
- member.reason = { code: "dir-missing", message: `the nested workspace's directory ${m.dir} does not exist` };
408
+ // A repo that can't be fetched is a read that failed; the contract's codes stay as they are.
409
+ member.reason = missing !== null ? { code: "command-failed", message: missing } : { code: "dir-missing", message: `the nested workspace's directory ${m.dir} does not exist` };
323
410
  continue;
324
411
  }
325
412
  if (read.stderr.trim() && query.onStderr) query.onStderr(read.stderr.endsWith("\n") ? read.stderr : `${read.stderr}\n`);
@@ -230,7 +230,9 @@ describe("chant workspace graph on the chant repo (#2557)", () => {
230
230
  const g = result(doc);
231
231
  expectValid(g);
232
232
  expect(failed).toBe(false);
233
- expect(g.workspace).toEqual({ name: "chant", root: "." });
233
+ expect(g.workspace).toMatchObject({ name: "chant", root: "." });
234
+ // The repo identity (#3168) is this checkout's origin, whatever it is here.
235
+ expect(g.workspace.repo === null || typeof g.workspace.repo === "string").toBe(true);
234
236
  expect(g.at).toBeNull();
235
237
  expect(g.members.every((m) => m.status === "skipped" && m.reason?.code === "kind-not-run")).toBe(true);
236
238
  });
@@ -294,7 +296,7 @@ describe("chant workspace graph on built workspaces", () => {
294
296
  for (const at of [undefined, sha]) {
295
297
  const g = result((await workspaceGraph({ cwd: join(top, "infra", "api"), at })).doc);
296
298
  expectValid(g);
297
- expect(g.workspace).toEqual({ name: "acme", root: "infra" });
299
+ expect(g.workspace).toEqual({ name: "acme", root: "infra", repo: null });
298
300
  expect(g.nodes.map((n) => n.id)).toEqual(["api/Queue"]);
299
301
  }
300
302
  });