@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
@@ -192,6 +192,11 @@ export interface PostSynthDiagnostic {
192
192
  /** Where it is missing from (e.g. a root module name). */
193
193
  scope: string;
194
194
  };
195
+ /**
196
+ * The build root the finding is about, set by a {@link CrossRootCheck}
197
+ * (chant #1939). Absent from a per-build finding.
198
+ */
199
+ root?: string;
195
200
  }
196
201
 
197
202
  /**
@@ -214,16 +219,26 @@ export interface PostSynthCheck {
214
219
  * new check would otherwise change the audit output of every project.
215
220
  */
216
221
  auditOptIn?: boolean;
222
+ /**
223
+ * `"build"`, the default: the check sees one build. A check that reads
224
+ * across build roots is a {@link CrossRootCheck} instead (chant #1939).
225
+ */
226
+ scope?: "build";
217
227
  }
218
228
 
219
- /** Structural type guard — used to collect project-authored policy checks. */
229
+ /**
230
+ * Structural type guard — used to collect project-authored policy checks.
231
+ * A {@link CrossRootCheck} is not a `PostSynthCheck`, so a policy module or a
232
+ * lexicon's check directory that exports one never puts it in a per-build run.
233
+ */
220
234
  export function isPostSynthCheck(value: unknown): value is PostSynthCheck {
221
235
  return (
222
236
  typeof value === "object" &&
223
237
  value !== null &&
224
238
  typeof (value as PostSynthCheck).id === "string" &&
225
239
  typeof (value as PostSynthCheck).description === "string" &&
226
- typeof (value as PostSynthCheck).check === "function"
240
+ typeof (value as PostSynthCheck).check === "function" &&
241
+ (value as { scope?: unknown }).scope !== "cross-root"
227
242
  );
228
243
  }
229
244
 
@@ -259,11 +274,206 @@ export function runPostSynthChecks(
259
274
 
260
275
  const diagnostics: PostSynthDiagnostic[] = [];
261
276
  for (const check of checks) {
277
+ // chant #1939: a cross-root check never runs in a per-build pass, even
278
+ // when a caller hands one over untyped. runCrossRootChecks runs it.
279
+ if ((check as { scope?: unknown }).scope === "cross-root") continue;
262
280
  diagnostics.push(...check.check(ctx));
263
281
  }
264
282
  return diagnostics;
265
283
  }
266
284
 
285
+ // ---------------------------------------------------------------------------
286
+ // Cross-build-root mode (chant #1939)
287
+ // ---------------------------------------------------------------------------
288
+
289
+ /**
290
+ * One build root handed to {@link runCrossRootChecks}: a name, and the build
291
+ * result the caller already has for it. The caller decides what a root is
292
+ * (a workspace member, a project directory, an environment's build) and
293
+ * builds it; this module never builds or reads the disk.
294
+ */
295
+ export interface CrossRootInput {
296
+ /**
297
+ * The root's name, unique within one run. A workspace member's name, or a
298
+ * project-relative path. Findings name it in {@link PostSynthDiagnostic.root}.
299
+ */
300
+ root: string;
301
+ /** The root's directory, when it has one. */
302
+ dir?: string;
303
+ /** The environment this root was built for, when known. */
304
+ env?: string;
305
+ buildResult: PostSynthContext["buildResult"];
306
+ projectConfig?: Record<string, unknown>;
307
+ }
308
+
309
+ /**
310
+ * One build root as a cross-root check sees it: an ordinary
311
+ * {@link PostSynthContext} over that root's build, so a per-build helper
312
+ * (k8s's `allManifests(ctx)`) works on it unchanged, plus its name.
313
+ */
314
+ export interface BuildRootView extends PostSynthContext {
315
+ readonly root: string;
316
+ readonly dir?: string;
317
+ readonly docs: OutputDoc[];
318
+ }
319
+
320
+ /** An {@link OutputDoc} tagged with the build root it came from. */
321
+ export interface RootedOutputDoc extends OutputDoc {
322
+ root: string;
323
+ }
324
+
325
+ /**
326
+ * A link between two build roots, as the caller knows it (chant #2549): in a
327
+ * workspace, a member link from the declaration or one the members' graphs
328
+ * surface. A cross-root check that compares what the outputs say with what
329
+ * was written down reads these from {@link CrossRootContext.links}.
330
+ */
331
+ export interface CrossRootLink {
332
+ consumer: string;
333
+ producer: string;
334
+ output: string;
335
+ /** How the link was found: `declared`, `kind-reader`, or `inferred:<rule>` for one the roots' graphs surface. */
336
+ origin: string;
337
+ /** The consumer's parameter an inferred link feeds; null or absent for a declared one. */
338
+ input?: string | null;
339
+ /** Whether the link resolved against the producer's outputs, as the caller judged it. */
340
+ status?: string;
341
+ }
342
+
343
+ /** An entity tagged with the build root that declared it. */
344
+ export interface RootedEntity {
345
+ root: string;
346
+ name: string;
347
+ entity: Declarable;
348
+ }
349
+
350
+ /**
351
+ * Context provided to a {@link CrossRootCheck}. `roots` keeps every root's
352
+ * build apart; `docs` and `entities` are the union across roots, each entry
353
+ * tagged with its root, built lazily on first access.
354
+ */
355
+ export interface CrossRootContext {
356
+ /** Every root in the run, in the order the caller gave them. */
357
+ readonly roots: readonly BuildRootView[];
358
+ /** Look a root up by name. */
359
+ root(name: string): BuildRootView | undefined;
360
+ /** Every root's parsed output documents, tagged by root. Lazy. */
361
+ readonly docs: readonly RootedOutputDoc[];
362
+ /** Every root's entities, tagged by root. Lazy. */
363
+ readonly entities: readonly RootedEntity[];
364
+ /** The run's environment, when the caller set one for the whole run. */
365
+ readonly env?: string;
366
+ readonly activityContracts?: ReadonlyMap<string, ActivityContract>;
367
+ /** The links between roots the caller passed (#2549), or absent when it passed none. */
368
+ readonly links?: readonly CrossRootLink[];
369
+ }
370
+
371
+ /** What a cross-root run takes besides its roots. */
372
+ export interface CrossRootOptions {
373
+ env?: string;
374
+ activityContracts?: ReadonlyMap<string, ActivityContract>;
375
+ /** The links between roots (#2549), handed to every check as {@link CrossRootContext.links}. */
376
+ links?: readonly CrossRootLink[];
377
+ }
378
+
379
+ /**
380
+ * A check that reads across build roots (chant #1939). It declares
381
+ * `scope: "cross-root"`, and only {@link runCrossRootChecks} runs it:
382
+ * `chant build`, `chant lint` and every other per-build pass skip it, so a
383
+ * project that never asks for a cross-root run pays nothing for it.
384
+ */
385
+ export interface CrossRootCheck {
386
+ id: string;
387
+ description: string;
388
+ scope: "cross-root";
389
+ check(ctx: CrossRootContext): PostSynthDiagnostic[];
390
+ /** As {@link PostSynthCheck.auditOptIn}. */
391
+ auditOptIn?: boolean;
392
+ }
393
+
394
+ /** Structural type guard for {@link CrossRootCheck}. */
395
+ export function isCrossRootCheck(value: unknown): value is CrossRootCheck {
396
+ return (
397
+ typeof value === "object" &&
398
+ value !== null &&
399
+ typeof (value as CrossRootCheck).id === "string" &&
400
+ typeof (value as CrossRootCheck).description === "string" &&
401
+ typeof (value as CrossRootCheck).check === "function" &&
402
+ (value as CrossRootCheck).scope === "cross-root"
403
+ );
404
+ }
405
+
406
+ /**
407
+ * Build the {@link CrossRootContext} for a set of roots. Exported for tests
408
+ * and for a caller that runs checks itself; most callers want
409
+ * {@link runCrossRootChecks}. Throws on an empty or duplicate root name.
410
+ */
411
+ export function createCrossRootContext(
412
+ inputs: readonly CrossRootInput[],
413
+ opts?: CrossRootOptions,
414
+ ): CrossRootContext {
415
+ const seen = new Set<string>();
416
+ const roots: BuildRootView[] = inputs.map((input) => {
417
+ if (input.root.length === 0) throw new Error("cross-root run: a build root needs a name");
418
+ if (seen.has(input.root)) throw new Error(`cross-root run: build root "${input.root}" appears twice`);
419
+ seen.add(input.root);
420
+ const getDocs = createDocsAccessor(input.buildResult.outputs);
421
+ const env = input.env ?? opts?.env;
422
+ return {
423
+ root: input.root,
424
+ ...(input.dir ? { dir: input.dir, projectDir: input.dir } : {}),
425
+ outputs: input.buildResult.outputs,
426
+ entities: input.buildResult.entities,
427
+ env,
428
+ buildResult: input.buildResult,
429
+ ...(opts?.activityContracts ? { activityContracts: opts.activityContracts } : {}),
430
+ ...(input.projectConfig ? { projectConfig: input.projectConfig } : {}),
431
+ get docs(): OutputDoc[] {
432
+ return getDocs();
433
+ },
434
+ };
435
+ });
436
+ const byName = new Map(roots.map((r) => [r.root, r]));
437
+ let docs: RootedOutputDoc[] | undefined;
438
+ let entities: RootedEntity[] | undefined;
439
+ return {
440
+ roots,
441
+ root: (name) => byName.get(name),
442
+ get docs(): readonly RootedOutputDoc[] {
443
+ docs ??= roots.flatMap((r) => r.docs.map((d) => ({ ...d, root: r.root })));
444
+ return docs;
445
+ },
446
+ get entities(): readonly RootedEntity[] {
447
+ entities ??= roots.flatMap((r) =>
448
+ [...r.entities].map(([name, entity]) => ({ root: r.root, name, entity })),
449
+ );
450
+ return entities;
451
+ },
452
+ ...(opts?.env ? { env: opts.env } : {}),
453
+ ...(opts?.activityContracts ? { activityContracts: opts.activityContracts } : {}),
454
+ ...(opts?.links ? { links: opts.links } : {}),
455
+ };
456
+ }
457
+
458
+ /**
459
+ * Run the cross-root checks in `checks` over `roots` (chant #1939). Anything
460
+ * in `checks` that is not a {@link CrossRootCheck} is skipped, so a caller can
461
+ * pass a lexicon's whole check list. With no cross-root check to run it
462
+ * returns at once, without building a context.
463
+ */
464
+ export function runCrossRootChecks(
465
+ checks: ReadonlyArray<CrossRootCheck | PostSynthCheck>,
466
+ roots: readonly CrossRootInput[],
467
+ opts?: CrossRootOptions,
468
+ ): PostSynthDiagnostic[] {
469
+ const selected = checks.filter(isCrossRootCheck);
470
+ if (selected.length === 0) return [];
471
+ const ctx = createCrossRootContext(roots, opts);
472
+ const diagnostics: PostSynthDiagnostic[] = [];
473
+ for (const check of selected) diagnostics.push(...check.check(ctx));
474
+ return diagnostics;
475
+ }
476
+
267
477
  // chant #1138 — `applyConfiguredSeverity` (the `lint.rules` severity-override
268
478
  // pass over a set of `PostSynthDiagnostic`s) lives in `./config.ts`, not here,
269
479
  // even though it operates on this module's own type. This file is a leaf:
package/src/lint/rule.ts CHANGED
@@ -45,6 +45,12 @@ export interface LintDiagnostic {
45
45
  severity: Severity;
46
46
  /** Human-readable message */
47
47
  message: string;
48
+ /**
49
+ * The entity a post-synth check reported against, when it named one: the
50
+ * same name the message leads with in brackets, and the graph node's id
51
+ * (behold#919). Absent for a source-file rule.
52
+ */
53
+ entity?: string;
48
54
  /** Optional fix that can be applied */
49
55
  fix?: LintFix;
50
56
  }
@@ -28,6 +28,8 @@ export { ops016 } from "./ops016-gate-resume";
28
28
  export { ops017, ops017Check, workspaceIdentityGates } from "./ops017-gate-alias";
29
29
  export { ops018 } from "./ops018-shell-image-digest";
30
30
  export { sys010, sys010Check } from "./sys010-key-over-plain-http";
31
+ // OPS019 (#2554) reads across members, so it is a cross-root check that only `chant workspace run` runs.
32
+ export { ops019Check, parseWorkspaceOpTarget, formatWorkspaceOpTarget, OPS019_ID, type WorkspaceOpTarget } from "./ops019-workspace-op-target";
31
33
 
32
34
  export interface CoreOpCheckOptions {
33
35
  /** `decide.backends` from the project's chant.config, for SYS010 (#2828). */
@@ -0,0 +1,89 @@
1
+ /**
2
+ * OPS019: workspace-op-target (#2554, #2524 D17, ws-030). The design named
3
+ * this check OPS014; that id was already the ConvergeOp rule-table refusal,
4
+ * so it took the next free one.
5
+ *
6
+ * `chant workspace run` names its work as `<member>/<op>` targets. Before
7
+ * anything runs, every target is checked against the composed graph: each
8
+ * member's root, read under that member's own toolchain, with its Ops among
9
+ * its entities. A target fails when its member is not in the graph (not a
10
+ * `chant` member, or its read failed) or when the member declares no Op of
11
+ * that name.
12
+ *
13
+ * It is a {@link CrossRootCheck} (#1939), so only `runCrossRootChecks` runs
14
+ * it, and `chant build`, `chant lint` and a plain project never do.
15
+ */
16
+ import type { CrossRootCheck, PostSynthDiagnostic } from "../../post-synth";
17
+ import { isOpEntity } from "./support";
18
+
19
+ export const OPS019_ID = "OPS019";
20
+
21
+ /** One `<member>/<op>` target. */
22
+ export interface WorkspaceOpTarget {
23
+ member: string;
24
+ op: string;
25
+ }
26
+
27
+ /**
28
+ * Split `<member>/<op>` at its first `/`. A member name has no `/` (the
29
+ * declaration's name pattern rules it out). Returns null for a string with no
30
+ * `/`, or an empty member or op.
31
+ */
32
+ export function parseWorkspaceOpTarget(text: string): WorkspaceOpTarget | null {
33
+ const at = text.indexOf("/");
34
+ if (at <= 0 || at === text.length - 1) return null;
35
+ return { member: text.slice(0, at), op: text.slice(at + 1) };
36
+ }
37
+
38
+ export const formatWorkspaceOpTarget = (t: WorkspaceOpTarget): string => `${t.member}/${t.op}`;
39
+
40
+ function opName(entity: unknown): string | undefined {
41
+ const props = (entity as { props?: { name?: unknown } } | null)?.props;
42
+ return typeof props?.name === "string" ? props.name : undefined;
43
+ }
44
+
45
+ /** The OPS019 check over `targets`. */
46
+ export function ops019Check(targets: readonly WorkspaceOpTarget[]): CrossRootCheck {
47
+ return {
48
+ id: OPS019_ID,
49
+ description: "A workspace Op target names a member in the composed graph and an Op that member declares",
50
+ scope: "cross-root",
51
+ check(ctx) {
52
+ const diagnostics: PostSynthDiagnostic[] = [];
53
+ const opsByRoot = new Map<string, Set<string>>();
54
+ for (const e of ctx.entities) {
55
+ if (!isOpEntity(e.entity)) continue;
56
+ const name = opName(e.entity) ?? e.name;
57
+ const set = opsByRoot.get(e.root) ?? new Set<string>();
58
+ set.add(name);
59
+ opsByRoot.set(e.root, set);
60
+ }
61
+ for (const t of targets) {
62
+ const target = formatWorkspaceOpTarget(t);
63
+ if (!ctx.root(t.member)) {
64
+ diagnostics.push({
65
+ checkId: OPS019_ID,
66
+ severity: "error",
67
+ message: `${target}: member "${t.member}" is not in the composed graph. A workspace Op runs in a chant member whose graph could be read.`,
68
+ missing: { kind: "member", scope: t.member },
69
+ });
70
+ continue;
71
+ }
72
+ const ops = opsByRoot.get(t.member) ?? new Set<string>();
73
+ if (!ops.has(t.op)) {
74
+ const known = [...ops].sort();
75
+ diagnostics.push({
76
+ checkId: OPS019_ID,
77
+ severity: "error",
78
+ message:
79
+ `${target}: member "${t.member}" declares no Op named "${t.op}". ` +
80
+ (known.length > 0 ? `Its Ops: ${known.join(", ")}.` : "It declares no Ops."),
81
+ root: t.member,
82
+ missing: { kind: "op", scope: t.member },
83
+ });
84
+ }
85
+ }
86
+ return diagnostics;
87
+ },
88
+ };
89
+ }
@@ -35,7 +35,7 @@
35
35
  * `--live --env floci` read against azure silently went to real Azure.
36
36
  */
37
37
 
38
- import { environmentEndpoint, type EnvironmentDeclaration } from "./config";
38
+ import { environmentEndpoint, type EnvironmentDeclaration } from "./config-environments";
39
39
  import { emulatorsOf, endpointEnvVars, type EmulatorDeclaration } from "./op/emulator-lifecycle";
40
40
 
41
41
  /**
@@ -221,6 +221,31 @@ describe("observeEntities harness (#1201)", () => {
221
221
  });
222
222
  });
223
223
 
224
+ test("an absent entity's annotations are collected, and it stays in neither map (#4372)", async () => {
225
+ const result = await observeEntities(
226
+ [entity("a"), entity("b"), entity("c")],
227
+ adapterOf({
228
+ a: { present: meta() },
229
+ b: { absent: true, annotations: { planAction: "create", planAfterUnknown: ["id"] } },
230
+ c: { absent: true, annotations: {} },
231
+ }),
232
+ );
233
+ expect(Object.keys(result.resources)).toEqual(["a"]);
234
+ expect(result.unobserved).toBeUndefined();
235
+ expect(result.annotations).toEqual({ b: { planAction: "create", planAfterUnknown: ["id"] } });
236
+ // Through the normalizer and a merge with another part, unchanged.
237
+ const merged = mergeObservations([normalizeObservation(result), normalizeObservation({ other: meta() })]);
238
+ expect(merged.annotations).toEqual({ b: { planAction: "create", planAfterUnknown: ["id"] } });
239
+ expect(Object.keys(merged.resources).sort()).toEqual(["a", "other"]);
240
+ });
241
+
242
+ test("no annotations means no annotations key, on the envelope and the normalized form", async () => {
243
+ const result = await observeEntities([entity("b")], adapterOf({ b: { absent: true } }));
244
+ expect("annotations" in result).toBe(false);
245
+ expect("annotations" in normalizeObservation(result)).toBe(false);
246
+ expect("annotations" in mergeObservations([normalizeObservation(result)])).toBe(false);
247
+ });
248
+
224
249
  test("collects the queried address from every variant — the absent one especially (#1620)", async () => {
225
250
  const result = await observeEntities(
226
251
  [entity("a"), entity("b"), entity("c")],
@@ -149,6 +149,31 @@ export interface ObservationResult {
149
149
  * before this field an observation gave it no way to tell them apart.
150
150
  */
151
151
  sources?: Record<string, string>;
152
+ /**
153
+ * Facts the read learned about an entity beside its verdict (#4372), keyed
154
+ * by chant entity name, as attribute name -> value. The case it exists for
155
+ * is a Terraform plan's planned create: the plan says the block will be
156
+ * created and which of its values stay unknown until apply, but the block
157
+ * has no row in the plan's prior state, so it is OBSERVED-ABSENT, and
158
+ * absence is spelled "in neither map". Without this map those facts had
159
+ * nowhere to go.
160
+ *
161
+ * Additive metadata over the tri-state, like {@link queried} and
162
+ * {@link sources}: classification never reads it, ownership never comes
163
+ * from it, and an entity with annotations and no `resources` row is still
164
+ * absent. A renderer or search carries the attributes onto the declared
165
+ * node (`carryAnnotations` in ./lifecycle/observe.ts), where they read like
166
+ * any other attribute without making the node present.
167
+ */
168
+ annotations?: Record<string, Record<string, unknown>>;
169
+ /**
170
+ * Which read answered each root, and why it fell back when it did (#4384
171
+ * follow-up), keyed by a lexicon-chosen root key (terraform uses
172
+ * `terraform.roots.<root>`). Structured beside {@link notes}, which say the
173
+ * same thing in prose: a consumer reads this field and never matches note
174
+ * text, so rewording a note cannot change what it reports.
175
+ */
176
+ rootReads?: Record<string, RootRead>;
152
177
  /**
153
178
  * Notices about the read as a whole, not about any one entity (#1265) —
154
179
  * "the ownership filter could not be applied on this surface" is the
@@ -169,6 +194,20 @@ export interface ObservationResult {
169
194
  stackExports?: Record<string, Record<string, unknown>>;
170
195
  }
171
196
 
197
+ /**
198
+ * The read a root was asked for and the one that answered. `depth` is the read
199
+ * asked for (`"plan"` for a plan-depth root, `"live+plan"` for a live root at
200
+ * the plan depth). `fellBackTo` is set only when that read failed: the read that
201
+ * answered instead (`"live"` is live-plan alone, for a live root), or
202
+ * `"declared"` when none did.
203
+ * `reason` is a short machine-stable cause, not prose to match on.
204
+ */
205
+ export interface RootRead {
206
+ depth: string;
207
+ fellBackTo?: "state" | "live" | "declared";
208
+ reason?: string;
209
+ }
210
+
172
211
  /**
173
212
  * What `describeResources()` may return: the bare map (pre-#1089, still valid —
174
213
  * "I looked at everything") or the {@link ObservationResult} envelope.
@@ -183,6 +222,10 @@ export interface NormalizedObservation {
183
222
  queried: Record<string, string>;
184
223
  /** Which read answered, per entity name (#2267). Empty when the lexicon reported none. */
185
224
  sources: Record<string, string>;
225
+ /** Facts beside the verdict, per entity name (#4372). Absent when the lexicon reported none. */
226
+ annotations?: Record<string, Record<string, unknown>>;
227
+ /** Which read answered each root, structured. Absent when the lexicon reported none. */
228
+ rootReads?: Record<string, RootRead>;
186
229
  /** Run-level notices (#1265), distinct. Empty when the lexicon reported none. */
187
230
  notes: string[];
188
231
  /** Per-stack exports (#1279), keyed by stack name. Absent when the lexicon reported none. */
@@ -209,6 +252,8 @@ export function observation(
209
252
  notes?: string[],
210
253
  stackExports?: Record<string, Record<string, unknown>>,
211
254
  sources?: Record<string, string>,
255
+ annotations?: Record<string, Record<string, unknown>>,
256
+ rootReads?: Record<string, RootRead>,
212
257
  ): ObservationResult {
213
258
  return {
214
259
  observation: "v1",
@@ -216,6 +261,8 @@ export function observation(
216
261
  ...(unobserved && Object.keys(unobserved).length > 0 ? { unobserved } : {}),
217
262
  ...(queried && Object.keys(queried).length > 0 ? { queried } : {}),
218
263
  ...(sources && Object.keys(sources).length > 0 ? { sources } : {}),
264
+ ...(annotations && Object.keys(annotations).length > 0 ? { annotations } : {}),
265
+ ...(rootReads && Object.keys(rootReads).length > 0 ? { rootReads } : {}),
219
266
  ...(notes && notes.length > 0 ? { notes } : {}),
220
267
  ...(stackExports && Object.keys(stackExports).length > 0 ? { stackExports } : {}),
221
268
  };
@@ -236,6 +283,8 @@ export function normalizeObservation(value: DescribeResourcesResult | undefined)
236
283
  queried: value.queried ?? {},
237
284
  sources: value.sources ?? {},
238
285
  notes: [...new Set(value.notes ?? [])],
286
+ ...(value.annotations && Object.keys(value.annotations).length > 0 ? { annotations: value.annotations } : {}),
287
+ ...(value.rootReads && Object.keys(value.rootReads).length > 0 ? { rootReads: value.rootReads } : {}),
239
288
  ...(value.stackExports && Object.keys(value.stackExports).length > 0 ? { stackExports: value.stackExports } : {}),
240
289
  };
241
290
  }
@@ -287,11 +336,16 @@ export function mergeObservations(parts: Iterable<NormalizedObservation>): Norma
287
336
  // is one note (#1265).
288
337
  const notes = new Set<string>();
289
338
  const stackExports: Record<string, Record<string, unknown>> = {};
339
+ // Annotations (#4372) merge like `sources`: per entity, disjoint parts.
340
+ const annotations: Record<string, Record<string, unknown>> = {};
341
+ const rootReads: Record<string, RootRead> = {};
290
342
  for (const part of parts) {
291
343
  Object.assign(resources, part.resources);
292
344
  Object.assign(unobserved, part.unobserved);
293
345
  Object.assign(queried, part.queried);
294
346
  Object.assign(sources, part.sources);
347
+ Object.assign(annotations, part.annotations ?? {});
348
+ Object.assign(rootReads, part.rootReads ?? {});
295
349
  for (const n of part.notes) notes.add(n);
296
350
  Object.assign(stackExports, part.stackExports ?? {});
297
351
  }
@@ -304,6 +358,8 @@ export function mergeObservations(parts: Iterable<NormalizedObservation>): Norma
304
358
  queried,
305
359
  sources,
306
360
  notes: [...notes],
361
+ ...(Object.keys(annotations).length > 0 ? { annotations } : {}),
362
+ ...(Object.keys(rootReads).length > 0 ? { rootReads } : {}),
307
363
  ...(Object.keys(stackExports).length > 0 ? { stackExports } : {}),
308
364
  };
309
365
  }
@@ -370,10 +426,14 @@ export interface DeclaredEntity {
370
426
  * issued against. The harness collects it into the result's `queried` map (and
371
427
  * onto the unobserved entry), so even an absent verdict — which records
372
428
  * nothing else — says where the provider was asked.
429
+ *
430
+ * An absent verdict may also carry `annotations` (#4372): attributes the read
431
+ * learned about the entity without finding it, collected into the result's
432
+ * `annotations` map. They never make it present.
373
433
  */
374
434
  export type EntityObservation =
375
435
  | { present: ResourceMetadata; queried?: string }
376
- | { absent: true; queried?: string }
436
+ | { absent: true; queried?: string; annotations?: Record<string, unknown> }
377
437
  | { unobserved: { reason: UnobservedReason; detail?: string }; queried?: string };
378
438
 
379
439
  /** What a lexicon supplies to drive the harness. `Client` is its transport handle. */
@@ -463,6 +523,7 @@ export async function observeEntities<Client>(
463
523
  const resources: Record<string, ResourceMetadata> = {};
464
524
  const unobserved: Record<string, UnobservedEntity> = {};
465
525
  const queried: Record<string, string> = {};
526
+ const annotations: Record<string, Record<string, unknown>> = {};
466
527
  const run = adapter.concurrently ?? ((items, fn) => boundedConcurrently(items, fn));
467
528
 
468
529
  await run(declared, async (entity) => {
@@ -486,11 +547,14 @@ export async function observeEntities<Client>(
486
547
  ...result.unobserved,
487
548
  ...(result.queried ? { queried: result.queried } : {}),
488
549
  };
550
+ } else if (result.annotations && Object.keys(result.annotations).length > 0) {
551
+ // `absent`: the verdict records nothing — in neither map is how the
552
+ // contract spells absence — but its address, when the adapter supplied
553
+ // one, lands in `queried` (#1620) so the absence can explain itself, and
554
+ // what the read learned about it lands in `annotations` (#4372).
555
+ annotations[entity.name] = result.annotations;
489
556
  }
490
- // `absent`: the verdict records nothing — in neither map is how the
491
- // contract spells absence — but its address, when the adapter supplied
492
- // one, lands in `queried` (#1620) so the absence can explain itself.
493
557
  });
494
558
 
495
- return observation(resources, unobserved, queried);
559
+ return observation(resources, unobserved, queried, undefined, undefined, undefined, annotations);
496
560
  }
@@ -152,7 +152,8 @@ export const reviewAgentContract = activityContract(
152
152
  op: z.string(),
153
153
  changeSet: z.object({ digest: z.string(), entries: z.array(z.unknown()) }).passthrough().optional(),
154
154
  changeSetFile: z.string().optional(),
155
- mode: z.enum(["comment", "report"]).optional(),
155
+ mode: z.enum(["comment", "report", "handoff"]).optional(),
156
+ dir: z.string().optional(),
156
157
  title: z.string().optional(),
157
158
  description: z.string().optional(),
158
159
  base: z.string().optional(),
@@ -162,13 +163,14 @@ export const reviewAgentContract = activityContract(
162
163
  timeout: z.number().positive().optional(),
163
164
  }),
164
165
  z.object({
165
- mode: z.enum(["comment", "report"]),
166
+ mode: z.enum(["comment", "report", "handoff"]),
166
167
  risk: z.enum(["low", "medium", "high", "unknown"]),
167
168
  exitCode: z.number().nullable(),
168
169
  summary: z.string(),
169
170
  commentUrl: z.string().optional(),
170
171
  pullRequest: z.string().optional(),
171
172
  mergeRequest: z.string().optional(),
173
+ recordFile: z.string().optional(),
172
174
  }),
173
175
  );
174
176
 
@@ -265,6 +267,7 @@ export const workEvidenceContract = activityContract(
265
267
  title: z.string(),
266
268
  url: z.string().optional(),
267
269
  path: z.string().optional(),
270
+ ops: z.record(z.string(), z.unknown()).optional(),
268
271
  kind: z.string().optional(),
269
272
  cwd: z.string().optional(),
270
273
  }),
@@ -164,8 +164,8 @@ export type {
164
164
  // The review agent (#4299): a model reviews the change set against the pull
165
165
  // request's own text and posts one sticky note. Only the activity and its
166
166
  // marker are re-exported, since the registry collects every exported function.
167
- export { reviewAgent, reviewMarker } from "./review-agent";
168
- export type { ReviewAgentArgs, ReviewAgentResult, ReviewAgentMode, ReviewRisk } from "./review-agent";
167
+ export { parseReviewResult, postReviewNote, readReviewRecord, REVIEW_DIR_ENV, REVIEW_MARKER_PREFIX, REVIEW_RECORD, reviewAgent, reviewMarker } from "./review-agent";
168
+ export type { PostReviewNoteArgs, PostReviewNoteResult, ReviewAgentArgs, ReviewAgentResult, ReviewAgentMode, ReviewRecord, ReviewRisk } from "./review-agent";
169
169
 
170
170
  // The propose-only template upgrade (#2550). Loads the workspace code on first
171
171
  // call only, so importing this module loads nothing under `workspace/`.