@intentius/chant 0.102.0 → 0.104.1

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 (471) hide show
  1. package/dist/audit/core.d.ts +2 -0
  2. package/dist/audit/core.d.ts.map +1 -1
  3. package/dist/audit/discover.d.ts.map +1 -1
  4. package/dist/change-set.d.ts +232 -0
  5. package/dist/change-set.d.ts.map +1 -0
  6. package/dist/cli/commands/audit.d.ts +7 -0
  7. package/dist/cli/commands/audit.d.ts.map +1 -1
  8. package/dist/cli/commands/build.d.ts.map +1 -1
  9. package/dist/cli/handlers/build.d.ts.map +1 -1
  10. package/dist/cli/handlers/change-set.d.ts +11 -0
  11. package/dist/cli/handlers/change-set.d.ts.map +1 -0
  12. package/dist/cli/handlers/fan-out.d.ts +33 -0
  13. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  14. package/dist/cli/handlers/operator.d.ts +7 -0
  15. package/dist/cli/handlers/operator.d.ts.map +1 -1
  16. package/dist/cli/handlers/pr.d.ts +31 -0
  17. package/dist/cli/handlers/pr.d.ts.map +1 -0
  18. package/dist/cli/handlers/run.d.ts.map +1 -1
  19. package/dist/cli/main.d.ts.map +1 -1
  20. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  21. package/dist/cli/mcp/workspace-tools.d.ts +3 -2
  22. package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
  23. package/dist/cli/registry.d.ts +63 -1
  24. package/dist/cli/registry.d.ts.map +1 -1
  25. package/dist/components/auto-release.d.ts +16 -0
  26. package/dist/components/auto-release.d.ts.map +1 -1
  27. package/dist/components/capability.d.ts +53 -0
  28. package/dist/components/capability.d.ts.map +1 -1
  29. package/dist/components/changed-files.d.ts +31 -0
  30. package/dist/components/changed-files.d.ts.map +1 -0
  31. package/dist/components/cli-support.d.ts +9 -1
  32. package/dist/components/cli-support.d.ts.map +1 -1
  33. package/dist/components/component.d.ts +24 -0
  34. package/dist/components/component.d.ts.map +1 -1
  35. package/dist/components/deploy-units.d.ts.map +1 -1
  36. package/dist/components/driver.d.ts +13 -0
  37. package/dist/components/driver.d.ts.map +1 -1
  38. package/dist/components/fan-out-output.d.ts +6 -0
  39. package/dist/components/fan-out-output.d.ts.map +1 -1
  40. package/dist/components/fan-out-record.d.ts +41 -0
  41. package/dist/components/fan-out-record.d.ts.map +1 -0
  42. package/dist/components/fan-out-run.d.ts +65 -0
  43. package/dist/components/fan-out-run.d.ts.map +1 -1
  44. package/dist/components/fan-out-support.d.ts +2 -0
  45. package/dist/components/fan-out-support.d.ts.map +1 -1
  46. package/dist/components/fan-out.d.ts +6 -0
  47. package/dist/components/fan-out.d.ts.map +1 -1
  48. package/dist/components/gated-wave-pipeline.d.ts +50 -0
  49. package/dist/components/gated-wave-pipeline.d.ts.map +1 -0
  50. package/dist/components/index.d.ts +1 -1
  51. package/dist/components/index.d.ts.map +1 -1
  52. package/dist/components/layers.d.ts +25 -0
  53. package/dist/components/layers.d.ts.map +1 -0
  54. package/dist/components/pr-pipeline.d.ts +61 -0
  55. package/dist/components/pr-pipeline.d.ts.map +1 -0
  56. package/dist/components/pr-run.d.ts +119 -0
  57. package/dist/components/pr-run.d.ts.map +1 -0
  58. package/dist/components/promote.d.ts.map +1 -1
  59. package/dist/components/verbs/shell.d.ts.map +1 -1
  60. package/dist/components/wave-plan.d.ts +49 -0
  61. package/dist/components/wave-plan.d.ts.map +1 -0
  62. package/dist/gated-waves.d.ts +147 -0
  63. package/dist/gated-waves.d.ts.map +1 -0
  64. package/dist/index.d.ts +1 -0
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/lexicon.d.ts +48 -0
  67. package/dist/lexicon.d.ts.map +1 -1
  68. package/dist/lifecycle/gate-ledger.d.ts +7 -0
  69. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  70. package/dist/lifecycle/git.d.ts +46 -1
  71. package/dist/lifecycle/git.d.ts.map +1 -1
  72. package/dist/lint/post-synth.d.ts +18 -0
  73. package/dist/lint/post-synth.d.ts.map +1 -1
  74. package/dist/op/activities/activity-contracts.d.ts +126 -0
  75. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  76. package/dist/op/activities/change-set.d.ts +62 -0
  77. package/dist/op/activities/change-set.d.ts.map +1 -0
  78. package/dist/op/activities/decide.d.ts +2 -0
  79. package/dist/op/activities/decide.d.ts.map +1 -1
  80. package/dist/op/activities/factory.d.ts +137 -0
  81. package/dist/op/activities/factory.d.ts.map +1 -0
  82. package/dist/op/activities/index.d.ts +4 -0
  83. package/dist/op/activities/index.d.ts.map +1 -1
  84. package/dist/op/activity-contract.d.ts.map +1 -1
  85. package/dist/op/builders.d.ts +11 -0
  86. package/dist/op/builders.d.ts.map +1 -1
  87. package/dist/op/decide-backend.d.ts +5 -1
  88. package/dist/op/decide-backend.d.ts.map +1 -1
  89. package/dist/op/decide-read-inputs.d.ts +4 -2
  90. package/dist/op/decide-read-inputs.d.ts.map +1 -1
  91. package/dist/op/factory.d.ts +83 -0
  92. package/dist/op/factory.d.ts.map +1 -0
  93. package/dist/op/index.d.ts +4 -1
  94. package/dist/op/index.d.ts.map +1 -1
  95. package/dist/op/op-ir.d.ts +2 -0
  96. package/dist/op/op-ir.d.ts.map +1 -1
  97. package/dist/op/op-verb-class.d.ts.map +1 -1
  98. package/dist/op/types.d.ts +8 -0
  99. package/dist/op/types.d.ts.map +1 -1
  100. package/dist/op/work-lease-run.d.ts.map +1 -1
  101. package/dist/plan-summary.d.ts +207 -0
  102. package/dist/plan-summary.d.ts.map +1 -0
  103. package/dist/pr-forge.d.ts +105 -0
  104. package/dist/pr-forge.d.ts.map +1 -0
  105. package/dist/pr-loop.d.ts +178 -0
  106. package/dist/pr-loop.d.ts.map +1 -0
  107. package/dist/telemetry-attribution.d.ts +31 -0
  108. package/dist/telemetry-attribution.d.ts.map +1 -1
  109. package/dist/terraform/hcl2json.d.ts +45 -0
  110. package/dist/terraform/hcl2json.d.ts.map +1 -0
  111. package/dist/terraform/parse.d.ts +4 -40
  112. package/dist/terraform/parse.d.ts.map +1 -1
  113. package/dist/vendor/js-yaml-load.d.ts +56 -0
  114. package/dist/vendor/js-yaml-load.d.ts.map +1 -0
  115. package/dist/workspace/box-cli.d.ts +12 -0
  116. package/dist/workspace/box-cli.d.ts.map +1 -0
  117. package/dist/workspace/box-factory.d.ts +27 -3
  118. package/dist/workspace/box-factory.d.ts.map +1 -1
  119. package/dist/workspace/box-listing.d.ts +85 -0
  120. package/dist/workspace/box-listing.d.ts.map +1 -0
  121. package/dist/workspace/box-publish.d.ts +147 -0
  122. package/dist/workspace/box-publish.d.ts.map +1 -0
  123. package/dist/workspace/broker-protocol.d.ts +190 -0
  124. package/dist/workspace/broker-protocol.d.ts.map +1 -0
  125. package/dist/workspace/checks.d.ts.map +1 -1
  126. package/dist/workspace/composites.d.ts +2 -2
  127. package/dist/workspace/composites.d.ts.map +1 -1
  128. package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts +17 -0
  129. package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts.map +1 -0
  130. package/dist/workspace/conformance/broker.d.ts +202 -0
  131. package/dist/workspace/conformance/broker.d.ts.map +1 -0
  132. package/dist/workspace/conformance/index.d.ts +2 -1
  133. package/dist/workspace/conformance/index.d.ts.map +1 -1
  134. package/dist/workspace/conformance/vitest.d.ts +9 -2
  135. package/dist/workspace/conformance/vitest.d.ts.map +1 -1
  136. package/dist/workspace/conformance/writer.d.ts +108 -14
  137. package/dist/workspace/conformance/writer.d.ts.map +1 -1
  138. package/dist/workspace/decide.d.ts +126 -12
  139. package/dist/workspace/decide.d.ts.map +1 -1
  140. package/dist/workspace/decision-points.schema.json +11 -4
  141. package/dist/workspace/declaration.d.ts +65 -0
  142. package/dist/workspace/declaration.d.ts.map +1 -1
  143. package/dist/workspace/declaration.schema.json +153 -4
  144. package/dist/workspace/environments.d.ts +36 -10
  145. package/dist/workspace/environments.d.ts.map +1 -1
  146. package/dist/workspace/factory-rules.d.ts +180 -0
  147. package/dist/workspace/factory-rules.d.ts.map +1 -0
  148. package/dist/workspace/init.d.ts +21 -0
  149. package/dist/workspace/init.d.ts.map +1 -1
  150. package/dist/workspace/intent-cli.d.ts +1 -1
  151. package/dist/workspace/intent-cli.d.ts.map +1 -1
  152. package/dist/workspace/intent-record.d.ts +28 -1
  153. package/dist/workspace/intent-record.d.ts.map +1 -1
  154. package/dist/workspace/intent.d.ts +102 -5
  155. package/dist/workspace/intent.d.ts.map +1 -1
  156. package/dist/workspace/json-edit.d.ts +24 -0
  157. package/dist/workspace/json-edit.d.ts.map +1 -0
  158. package/dist/workspace/jsonc.d.ts +11 -0
  159. package/dist/workspace/jsonc.d.ts.map +1 -1
  160. package/dist/workspace/kinds.d.ts +48 -0
  161. package/dist/workspace/kinds.d.ts.map +1 -1
  162. package/dist/workspace/lexicon-symbols.d.ts +29 -0
  163. package/dist/workspace/lexicon-symbols.d.ts.map +1 -0
  164. package/dist/workspace/lineage-upgrade.d.ts +31 -2
  165. package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
  166. package/dist/workspace/point-answer.schema.json +42 -2
  167. package/dist/workspace/points-cli.d.ts +10 -3
  168. package/dist/workspace/points-cli.d.ts.map +1 -1
  169. package/dist/workspace/points.d.ts +66 -5
  170. package/dist/workspace/points.d.ts.map +1 -1
  171. package/dist/workspace/reason-codes.d.ts +33 -4
  172. package/dist/workspace/reason-codes.d.ts.map +1 -1
  173. package/dist/workspace/record-sessions.d.ts +5 -7
  174. package/dist/workspace/record-sessions.d.ts.map +1 -1
  175. package/dist/workspace/records-cli.d.ts +7 -0
  176. package/dist/workspace/records-cli.d.ts.map +1 -1
  177. package/dist/workspace/records-close.d.ts +7 -3
  178. package/dist/workspace/records-close.d.ts.map +1 -1
  179. package/dist/workspace/records-write.d.ts +66 -6
  180. package/dist/workspace/records-write.d.ts.map +1 -1
  181. package/dist/workspace/records.d.ts +28 -9
  182. package/dist/workspace/records.d.ts.map +1 -1
  183. package/dist/workspace/runs-cli.d.ts +138 -6
  184. package/dist/workspace/runs-cli.d.ts.map +1 -1
  185. package/dist/workspace/runs.d.ts +132 -11
  186. package/dist/workspace/runs.d.ts.map +1 -1
  187. package/dist/workspace/session-kinds.d.ts +1 -1
  188. package/dist/workspace/session-kinds.d.ts.map +1 -1
  189. package/dist/workspace/squash.d.ts +80 -0
  190. package/dist/workspace/squash.d.ts.map +1 -0
  191. package/dist/workspace/status-gates.d.ts +2 -0
  192. package/dist/workspace/status-gates.d.ts.map +1 -1
  193. package/dist/workspace/status.d.ts +54 -0
  194. package/dist/workspace/status.d.ts.map +1 -1
  195. package/dist/workspace/symbols.d.ts +16 -5
  196. package/dist/workspace/symbols.d.ts.map +1 -1
  197. package/dist/workspace/trust/run-commits.d.ts +46 -0
  198. package/dist/workspace/trust/run-commits.d.ts.map +1 -0
  199. package/dist/workspace/trust/run-statement.d.ts +128 -0
  200. package/dist/workspace/trust/run-statement.d.ts.map +1 -0
  201. package/dist/workspace/trust/seal.d.ts +6 -1
  202. package/dist/workspace/trust/seal.d.ts.map +1 -1
  203. package/dist/workspace/trust/verify-cli.d.ts +1 -1
  204. package/dist/workspace/trust/verify.d.ts +16 -2
  205. package/dist/workspace/trust/verify.d.ts.map +1 -1
  206. package/dist/workspace/wip-cli.d.ts +21 -0
  207. package/dist/workspace/wip-cli.d.ts.map +1 -0
  208. package/dist/workspace/wip.d.ts +268 -0
  209. package/dist/workspace/wip.d.ts.map +1 -0
  210. package/dist/workspace/work-cli.d.ts.map +1 -1
  211. package/dist/workspace/work-evidence.d.ts +1 -1
  212. package/dist/workspace/work-evidence.d.ts.map +1 -1
  213. package/dist/workspace/work-size.d.ts +55 -0
  214. package/dist/workspace/work-size.d.ts.map +1 -0
  215. package/dist/workspace/workspace-kinds.schema.json +122 -0
  216. package/dist/workspace/write-lock-cli.d.ts +60 -0
  217. package/dist/workspace/write-lock-cli.d.ts.map +1 -0
  218. package/dist/workspace/write-lock.d.ts +152 -0
  219. package/dist/workspace/write-lock.d.ts.map +1 -0
  220. package/dist/workspace/write-scope.d.ts +6 -2
  221. package/dist/workspace/write-scope.d.ts.map +1 -1
  222. package/dist/yaml.d.ts +1 -1
  223. package/dist/yaml.d.ts.map +1 -1
  224. package/package.json +6 -1
  225. package/src/__fixtures__/change-set/lifecycle-plan.floci.json +59 -0
  226. package/src/__fixtures__/change-set/lifecycle-v1.ts.txt +4 -0
  227. package/src/__fixtures__/change-set/lifecycle-v2.ts.txt +4 -0
  228. package/src/__fixtures__/change-set/lifecycle.change-set.golden.json +95 -0
  229. package/src/__fixtures__/change-set/warden.change-set.golden.json +106 -0
  230. package/src/__fixtures__/change-set/warden.plan.json +44 -0
  231. package/src/__fixtures__/plan-summary/normalization-vectors.json +1593 -0
  232. package/src/__fixtures__/pr-loop/pr-apply-applied.note.golden.md +31 -0
  233. package/src/__fixtures__/pr-loop/pr-apply-refused.note.golden.md +31 -0
  234. package/src/__fixtures__/pr-loop/pr-plan.golden.json +127 -0
  235. package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +37 -0
  236. package/src/audit/core.test.ts +15 -0
  237. package/src/audit/core.ts +8 -2
  238. package/src/audit/discover.test.ts +11 -0
  239. package/src/audit/discover.ts +7 -2
  240. package/src/change-set-bundle.test.ts +57 -0
  241. package/src/change-set.test.ts +215 -0
  242. package/src/change-set.ts +445 -0
  243. package/src/cli/commands/audit-opt-in.test.ts +54 -0
  244. package/src/cli/commands/audit.ts +29 -2
  245. package/src/cli/commands/build.test.ts +19 -0
  246. package/src/cli/commands/build.ts +3 -2
  247. package/src/cli/handlers/build.ts +13 -1
  248. package/src/cli/handlers/change-set.test.ts +56 -0
  249. package/src/cli/handlers/change-set.ts +44 -0
  250. package/src/cli/handlers/fan-out.test.ts +221 -2
  251. package/src/cli/handlers/fan-out.ts +165 -75
  252. package/src/cli/handlers/graph.ts +3 -0
  253. package/src/cli/handlers/operator.test.ts +21 -0
  254. package/src/cli/handlers/operator.ts +34 -3
  255. package/src/cli/handlers/pr.ts +373 -0
  256. package/src/cli/handlers/run.ts +1 -0
  257. package/src/cli/main.test.ts +20 -0
  258. package/src/cli/main.ts +185 -23
  259. package/src/cli/mcp/never-over-mcp.test.ts +101 -0
  260. package/src/cli/mcp/op-tools.ts +24 -2
  261. package/src/cli/mcp/workspace-tools.test.ts +1 -1
  262. package/src/cli/mcp/workspace-tools.ts +34 -6
  263. package/src/cli/registry.ts +63 -1
  264. package/src/components/auto-release.ts +1 -1
  265. package/src/components/capability.ts +55 -0
  266. package/src/components/changed-files.ts +66 -0
  267. package/src/components/cli-support.ts +28 -5
  268. package/src/components/component.schema.json +17 -0
  269. package/src/components/component.ts +25 -0
  270. package/src/components/deploy-units.ts +3 -0
  271. package/src/components/driver.test.ts +52 -0
  272. package/src/components/driver.ts +31 -13
  273. package/src/components/fan-out-output.ts +42 -1
  274. package/src/components/fan-out-record.ts +69 -0
  275. package/src/components/fan-out-run.test.ts +17 -0
  276. package/src/components/fan-out-run.ts +304 -1
  277. package/src/components/fan-out-support.ts +3 -0
  278. package/src/components/fan-out-waves.test.ts +375 -0
  279. package/src/components/fan-out.ts +18 -17
  280. package/src/components/gated-wave-pipeline.ts +82 -0
  281. package/src/components/index.ts +1 -0
  282. package/src/components/layers.ts +30 -0
  283. package/src/components/pr-pipeline.ts +91 -0
  284. package/src/components/pr-run.test.ts +205 -0
  285. package/src/components/pr-run.ts +280 -0
  286. package/src/components/promote.ts +5 -0
  287. package/src/components/verbs/shell.test.ts +11 -0
  288. package/src/components/verbs/shell.ts +7 -3
  289. package/src/components/wave-plan.ts +124 -0
  290. package/src/discovery/sandbox/bundle.ts +1 -1
  291. package/src/gated-waves-bundle.test.ts +62 -0
  292. package/src/gated-waves.test.ts +118 -0
  293. package/src/gated-waves.ts +240 -0
  294. package/src/index.ts +1 -0
  295. package/src/lexicon.ts +51 -0
  296. package/src/lifecycle/gate-ledger.ts +7 -0
  297. package/src/lifecycle/git.ts +102 -16
  298. package/src/lint/post-synth.test.ts +19 -0
  299. package/src/lint/post-synth.ts +19 -1
  300. package/src/meta/declared-imports.test.ts +1 -1
  301. package/src/op/activities/activity-contracts.ts +84 -0
  302. package/src/op/activities/change-set.ts +114 -0
  303. package/src/op/activities/decide.ts +3 -0
  304. package/src/op/activities/factory.ts +675 -0
  305. package/src/op/activities/index.ts +6 -0
  306. package/src/op/activity-contract.test.ts +21 -1
  307. package/src/op/activity-contract.ts +19 -9
  308. package/src/op/builders.ts +23 -0
  309. package/src/op/decide-backend.ts +5 -1
  310. package/src/op/decide-read-inputs.ts +33 -5
  311. package/src/op/factory.e2e.test.ts +232 -0
  312. package/src/op/factory.ts +118 -0
  313. package/src/op/index.ts +9 -1
  314. package/src/op/op-ir.test.ts +9 -0
  315. package/src/op/op-ir.ts +4 -0
  316. package/src/op/op-verb-class.ts +3 -0
  317. package/src/op/types.ts +8 -0
  318. package/src/op/work-lease-run.ts +3 -0
  319. package/src/plan-summary.test.ts +263 -0
  320. package/src/plan-summary.ts +845 -0
  321. package/src/pr-forge.test.ts +237 -0
  322. package/src/pr-forge.ts +332 -0
  323. package/src/pr-loop-bundle.test.ts +46 -0
  324. package/src/pr-loop.test.ts +171 -0
  325. package/src/pr-loop.ts +324 -0
  326. package/src/telemetry-attribution.test.ts +23 -1
  327. package/src/telemetry-attribution.ts +51 -0
  328. package/src/terraform/hcl2json.test.ts +21 -0
  329. package/src/terraform/hcl2json.ts +81 -0
  330. package/src/terraform/parse.ts +11 -74
  331. package/src/vendor/js-yaml-load.test.ts +115 -0
  332. package/src/vendor/js-yaml-load.ts +1939 -0
  333. package/src/workspace/__fixtures__/studio-template-84c8b21.json +1 -1
  334. package/src/workspace/app-kind.test.ts +196 -0
  335. package/src/workspace/box-cli.ts +113 -0
  336. package/src/workspace/box-factory.test.ts +4 -1
  337. package/src/workspace/box-factory.ts +37 -4
  338. package/src/workspace/box-listing-write.schema.json +204 -0
  339. package/src/workspace/box-listing.test.ts +234 -0
  340. package/src/workspace/box-listing.ts +324 -0
  341. package/src/workspace/box-publish.schema.json +498 -0
  342. package/src/workspace/box-publish.test.ts +204 -0
  343. package/src/workspace/box-publish.ts +420 -0
  344. package/src/workspace/box-ship.test.ts +96 -0
  345. package/src/workspace/broker-protocol.schema.json +186 -0
  346. package/src/workspace/broker-protocol.test.ts +122 -0
  347. package/src/workspace/broker-protocol.ts +317 -0
  348. package/src/workspace/builder-tiers.test.ts +146 -0
  349. package/src/workspace/change-set.schema.json +460 -0
  350. package/src/workspace/chant-migrations.e2e.test.ts +17 -5
  351. package/src/workspace/checks/boxes.test.ts +3 -0
  352. package/src/workspace/checks.ts +10 -3
  353. package/src/workspace/component-environments.test.ts +105 -0
  354. package/src/workspace/composites.schema.json +23 -4
  355. package/src/workspace/composites.test.ts +8 -8
  356. package/src/workspace/composites.ts +13 -2
  357. package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +2 -2
  358. package/src/workspace/conformance/__fixtures__/reference-broker.ts +207 -0
  359. package/src/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +7 -2
  360. package/src/workspace/conformance/__writer_fixture__/answers/answer.schema.json +42 -2
  361. package/src/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
  362. package/src/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
  363. package/src/workspace/conformance/__writer_fixture__/decisions/points.json +96 -0
  364. package/src/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
  365. package/src/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
  366. package/src/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +14 -8
  367. package/src/workspace/conformance/__writer_fixture__/sessions/session.schema.json +187 -6
  368. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +25 -0
  369. package/src/workspace/conformance/broker.test.ts +122 -0
  370. package/src/workspace/conformance/broker.ts +792 -0
  371. package/src/workspace/conformance/conformance.e2e.test.ts +2 -1
  372. package/src/workspace/conformance/index.mjs +22 -1
  373. package/src/workspace/conformance/index.ts +5 -1
  374. package/src/workspace/conformance/vitest.ts +33 -1
  375. package/src/workspace/conformance/writer-conformance.e2e.test.ts +49 -3
  376. package/src/workspace/conformance/writer.test.ts +32 -2
  377. package/src/workspace/conformance/writer.ts +339 -28
  378. package/src/workspace/decide.test.ts +208 -4
  379. package/src/workspace/decide.ts +427 -73
  380. package/src/workspace/decision-points.schema.json +11 -4
  381. package/src/workspace/declaration.schema.json +153 -4
  382. package/src/workspace/declaration.ts +141 -0
  383. package/src/workspace/environments.ts +66 -14
  384. package/src/workspace/factory-rules.test.ts +62 -0
  385. package/src/workspace/factory-rules.ts +218 -0
  386. package/src/workspace/graph-cli.ts +2 -2
  387. package/src/workspace/graph.schema.json +67 -0
  388. package/src/workspace/identity.test.ts +23 -0
  389. package/src/workspace/init.ts +82 -2
  390. package/src/workspace/intent-cli.ts +26 -9
  391. package/src/workspace/intent-patch-id.test.ts +162 -0
  392. package/src/workspace/intent-record.schema.json +130 -3
  393. package/src/workspace/intent-record.ts +74 -28
  394. package/src/workspace/intent-reviews.test.ts +76 -0
  395. package/src/workspace/intent-squash.test.ts +213 -0
  396. package/src/workspace/intent-why.test.ts +5 -5
  397. package/src/workspace/intent.schema.json +234 -4
  398. package/src/workspace/intent.ts +260 -66
  399. package/src/workspace/json-edit.test.ts +121 -0
  400. package/src/workspace/json-edit.ts +142 -0
  401. package/src/workspace/jsonc.ts +20 -0
  402. package/src/workspace/kinds.ts +157 -2
  403. package/src/workspace/lexicon-symbols.test.ts +148 -0
  404. package/src/workspace/lexicon-symbols.ts +125 -0
  405. package/src/workspace/lineage-upgrade.test.ts +63 -0
  406. package/src/workspace/lineage-upgrade.ts +146 -5
  407. package/src/workspace/plan-summary.schema.json +155 -0
  408. package/src/workspace/point-answer.schema.json +42 -2
  409. package/src/workspace/points-cli.ts +42 -16
  410. package/src/workspace/points-write.schema.json +162 -4
  411. package/src/workspace/points.schema.json +157 -2
  412. package/src/workspace/points.test.ts +13 -1
  413. package/src/workspace/points.ts +118 -12
  414. package/src/workspace/pr-report.schema.json +95 -0
  415. package/src/workspace/profiles.test.ts +159 -0
  416. package/src/workspace/read-contract.test.ts +2 -2
  417. package/src/workspace/reason-codes.test.ts +13 -1
  418. package/src/workspace/reason-codes.ts +38 -4
  419. package/src/workspace/record-sessions.ts +9 -8
  420. package/src/workspace/records-amend.schema.json +78 -0
  421. package/src/workspace/records-cli.ts +20 -6
  422. package/src/workspace/records-close.schema.json +78 -0
  423. package/src/workspace/records-close.ts +31 -7
  424. package/src/workspace/records-concurrent.e2e.test.ts +135 -0
  425. package/src/workspace/records-concurrent.test.ts +145 -0
  426. package/src/workspace/records-formats.test.ts +46 -10
  427. package/src/workspace/records-new.schema.json +7 -0
  428. package/src/workspace/records-review.schema.json +78 -0
  429. package/src/workspace/records-sessions-write.test.ts +69 -0
  430. package/src/workspace/records-sessions.test.ts +22 -0
  431. package/src/workspace/records-write.ts +192 -25
  432. package/src/workspace/records.schema.json +16 -0
  433. package/src/workspace/records.ts +50 -9
  434. package/src/workspace/reference-kinds/app/package.json +10 -0
  435. package/src/workspace/reference-kinds/app/workspace-kinds.json +45 -0
  436. package/src/workspace/run-statement.schema.json +622 -0
  437. package/src/workspace/runs-cli.ts +343 -14
  438. package/src/workspace/runs-statement.test.ts +239 -0
  439. package/src/workspace/runs-write.schema.json +416 -5
  440. package/src/workspace/runs.schema.json +451 -4
  441. package/src/workspace/runs.test.ts +39 -0
  442. package/src/workspace/runs.ts +296 -35
  443. package/src/workspace/session-kinds.ts +3 -3
  444. package/src/workspace/squash.ts +198 -0
  445. package/src/workspace/status-contract.test.ts +5 -2
  446. package/src/workspace/status-gates.ts +3 -1
  447. package/src/workspace/status.schema.json +126 -3
  448. package/src/workspace/status.ts +90 -1
  449. package/src/workspace/symbols.ts +20 -9
  450. package/src/workspace/trust/run-commits.ts +115 -0
  451. package/src/workspace/trust/run-statement.ts +226 -0
  452. package/src/workspace/trust/seal.ts +8 -2
  453. package/src/workspace/trust/verify-cli.ts +6 -5
  454. package/src/workspace/trust/verify.ts +39 -6
  455. package/src/workspace/wip-cli.ts +97 -0
  456. package/src/workspace/wip-write.schema.json +504 -0
  457. package/src/workspace/wip.schema.json +334 -0
  458. package/src/workspace/wip.test.ts +294 -0
  459. package/src/workspace/wip.ts +753 -0
  460. package/src/workspace/work-cli.ts +3 -0
  461. package/src/workspace/work-evidence.schema.json +3 -0
  462. package/src/workspace/work-size.test.ts +77 -0
  463. package/src/workspace/work-size.ts +93 -0
  464. package/src/workspace/workspace-kinds.schema.json +122 -0
  465. package/src/workspace/write-lock-cli.ts +131 -0
  466. package/src/workspace/write-lock.schema.json +172 -0
  467. package/src/workspace/write-lock.test.ts +189 -0
  468. package/src/workspace/write-lock.ts +474 -0
  469. package/src/workspace/write-scope.test.ts +16 -1
  470. package/src/workspace/write-scope.ts +33 -11
  471. package/src/yaml.ts +31 -21
@@ -194,6 +194,69 @@ describe("chant workspace upgrade", () => {
194
194
  expect(git(proj, ["status", "--porcelain"])).toBe("");
195
195
  });
196
196
 
197
+ describe("a CI workflow a chant member builds is rebuilt with this chant (#3244)", () => {
198
+ const WS = JSON.stringify({ name: "proj", schema: 1, members: [{ name: "delivery", dir: "delivery", kind: "chant" }] }, null, 2) + "\n";
199
+ const PKG = JSON.stringify({ name: "delivery", scripts: { "ci:build": "chant build ci --lexicon github -o ../.github/workflows/ci.yml", "ci:check": "npm run ci:build && git diff --exit-code ../.github/workflows/ci.yml", "agents": "chant build agents --lexicon fountain -o ../.studio/agents.yaml" } }, null, 2) + "\n";
200
+ const OLD = "steps:\n - uses: actions/checkout@v4\n";
201
+ const NEW = "steps:\n - uses: actions/checkout@v7\n";
202
+ /** A chant whose github lexicon now emits @v7: `build` writes NEW where -o points. */
203
+ const builds = (calls: Array<{ command: string; cwd: string; args?: readonly string[] }>, output = NEW): ChantRunner => async (command, cwd, args) => {
204
+ calls.push({ command, cwd, args });
205
+ const o = args?.indexOf("-o") ?? -1;
206
+ if (o >= 0) put(cwd, args![o + 1], output);
207
+ return { exitCode: 0, output: "" };
208
+ };
209
+
210
+ beforeEach(() => {
211
+ release("v2.0.0", { "chant.workspace.json": WS, "delivery/chant.config.ts": "export default {};\n", "delivery/package.json": PKG, ".github/workflows/ci.yml": OLD });
212
+ });
213
+
214
+ test("an upgrade to the same version puts the rebuilt workflow in the patch, and only the CI workflow", async () => {
215
+ // A box planted at v2.0.0 with the chant of then.
216
+ const port = ledger();
217
+ const staged0 = await upgradeCommand({ root: proj, to: "v2.0.0", runChant: passing, ledger: port, now: "2026-10-03T00:00:00.000Z" });
218
+ port.approve(staged0.staged!.digest, "2026-10-03T00:01:00.000Z");
219
+ expect((await upgradeCommand({ root: proj, to: "v2.0.0", runChant: passing, ledger: port, now: "2026-10-03T00:02:00.000Z" })).outcome).toBe("applied");
220
+ commitProject("at v2");
221
+ expect(read(proj, ".github/workflows/ci.yml")).toBe(OLD);
222
+
223
+ // chant is upgraded; the template is not. The workflow ci.ts builds now differs.
224
+ const calls: Array<{ command: string; cwd: string; args?: readonly string[] }> = [];
225
+ const staged = await stageUpgrade({ root: proj, to: "v2.0.0", runChant: builds(calls) });
226
+ try {
227
+ expect(staged.workflows).toEqual([{ member: "delivery", script: "ci:build", path: ".github/workflows/ci.yml", command: "chant build ci --lexicon github -o ../.github/workflows/ci.yml", status: "rebuilt" }]);
228
+ expect(calls[0]).toEqual({ command: "build", cwd: join(staged.worktreeProject, "delivery"), args: ["ci", "--lexicon", "github", "-o", "../.github/workflows/ci.yml"] });
229
+ // The agents script writes no CI workflow, so it is not run.
230
+ expect(calls.some((c) => c.args?.includes("agents"))).toBe(false);
231
+ expect(staged.changed).toBe(true);
232
+ expect(staged.changedPaths).toEqual([".github/workflows/ci.yml"]);
233
+ expect(staged.governance?.paths).toEqual([".github/workflows/ci.yml"]);
234
+ expect(read(proj, ".github/workflows/ci.yml")).toBe(OLD);
235
+ } finally {
236
+ staged.dispose();
237
+ }
238
+
239
+ // Once it is committed as built, the next upgrade finds nothing to do.
240
+ put(proj, ".github/workflows/ci.yml", NEW);
241
+ commitProject("ci:build");
242
+ const again = await stageUpgrade({ root: proj, to: "v2.0.0", runChant: builds([]) });
243
+ try {
244
+ expect(again.workflows.map((w) => w.status)).toEqual(["unchanged"]);
245
+ expect(again.changed).toBe(false);
246
+ } finally {
247
+ again.dispose();
248
+ }
249
+ });
250
+
251
+ test("a workflow that does not build fails the build check and stays as it was", async () => {
252
+ const failing: ChantRunner = async (_command, _cwd, args) => (args?.length ? { exitCode: 1, output: "cannot find @intentius/chant-lexicon-github\n" } : { exitCode: 0, output: "" });
253
+ const result = await upgradeCommand({ root: proj, to: "v2.0.0", runChant: failing });
254
+ expect(result.outcome).toBe("checks-failed");
255
+ expect(result.staged!.workflows.map((w) => w.status)).toEqual(["failed"]);
256
+ expect(result.staged!.checks).toEqual(expect.arrayContaining([expect.objectContaining({ name: "build", status: "failed", member: "delivery", detail: expect.stringMatching(/\.github\/workflows\/ci\.yml could not be rebuilt[\s\S]*cannot find/) })]));
257
+ });
258
+ });
259
+
197
260
  test("gates on the patch digest, then applies exactly the approved patch", async () => {
198
261
  release("v2.0.0", { "README.md": "starter v2\n" });
199
262
  const port = ledger();
@@ -21,6 +21,9 @@
21
21
  * 4. Merge per file (ws-005): an edited file takes the new version only when
22
22
  * every hunk merges cleanly. Otherwise it stays as it was, with one manual
23
23
  * step. The worktree never holds conflict markers.
24
+ * Then rebuild each CI workflow a chant member's package.json builds with
25
+ * `chant build ... -o <workflow>` (#3244), with the chant doing the
26
+ * upgrade, so the committed workflow follows that chant's composites.
24
27
  * 5. Check the worktree: `chant build` and `chant lint` when the project is a
25
28
  * chant project, and the lineage checks of `chant workspace check`.
26
29
  * 6. Bind the gate to the digest of the resulting patch: the pending fact and
@@ -34,7 +37,7 @@
34
37
  */
35
38
 
36
39
  import { execFileSync, spawn } from "node:child_process";
37
- import { chmodSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
40
+ import { chmodSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
38
41
  import { tmpdir } from "node:os";
39
42
  import { basename, dirname, join, relative, resolve, sep } from "node:path";
40
43
  import { computePlanDigest } from "../lifecycle/plan-digest";
@@ -64,6 +67,7 @@ import { pathsInsideNested } from "./nesting";
64
67
  import { carryParameters, readManifest, substituteParameters } from "./template-manifest";
65
68
  import { repinSubstituted, type RepinnedRecord } from "./template-pins";
66
69
  import { workingTree } from "./tree";
70
+ import { splitCommandLine } from "./checks/generated";
67
71
 
68
72
  /** The kind the patch digest is taken under, so it never collides with another kind of plan. */
69
73
  export const UPGRADE_PLAN_KIND = "workspace-upgrade";
@@ -86,22 +90,26 @@ export interface UpgradeCheck {
86
90
  member?: string;
87
91
  }
88
92
 
89
- /** Runs `chant build` or `chant lint` in a directory. */
90
- export type ChantRunner = (command: "build" | "lint", cwd: string) => Promise<{ exitCode: number; output: string }>;
93
+ /**
94
+ * Runs `chant build` or `chant lint` in a directory, with `args` after the
95
+ * command when given (a workflow rebuild's `ci --lexicon github -o <file>`,
96
+ * #3244).
97
+ */
98
+ export type ChantRunner = (command: "build" | "lint", cwd: string, args?: readonly string[]) => Promise<{ exitCode: number; output: string }>;
91
99
 
92
100
  /**
93
101
  * The default runner: this same chant, in a child process. The child sees the
94
102
  * worktree's sources and resolves packages the way the project does, since the
95
103
  * worktree sits inside the project.
96
104
  */
97
- export const spawnChant: ChantRunner = (command, cwd) =>
105
+ export const spawnChant: ChantRunner = (command, cwd, args = []) =>
98
106
  new Promise((resolvePromise, reject) => {
99
107
  const entry = process.argv[1];
100
108
  if (!entry) {
101
109
  reject(new UpgradeError("cannot find the chant entry point to run build and lint in the worktree"));
102
110
  return;
103
111
  }
104
- const child = spawn(process.execPath, [...process.execArgv, entry, command], { cwd, stdio: ["ignore", "pipe", "pipe"], env: process.env });
112
+ const child = spawn(process.execPath, [...process.execArgv, entry, command, ...args], { cwd, stdio: ["ignore", "pipe", "pipe"], env: process.env });
105
113
  const out: Buffer[] = [];
106
114
  child.stdout.on("data", (c: Buffer) => out.push(c));
107
115
  child.stderr.on("data", (c: Buffer) => out.push(c));
@@ -139,6 +147,121 @@ export interface UpgradeOptions {
139
147
  runChant?: ChantRunner;
140
148
  }
141
149
 
150
+ /**
151
+ * A CI workflow a chant member's package.json builds, and what rebuilding it
152
+ * did (#3244). `rebuilt`: the workflow chant builds now differs from the one
153
+ * committed, and the patch carries the new one. `unchanged`: it is the same.
154
+ * `failed`: the build failed, the file is left as the merge left it, and the
155
+ * upgrade's `build` check fails with the output.
156
+ */
157
+ export interface RebuiltWorkflow {
158
+ /** The chant member whose package.json script builds it. */
159
+ member: string;
160
+ /** The script's name, such as `ci:build`. */
161
+ script: string;
162
+ /** The workflow, relative to the repository root. */
163
+ path: string;
164
+ /** The command line, as the script has it. */
165
+ command: string;
166
+ status: "rebuilt" | "unchanged" | "failed";
167
+ /** The tail of the build's output, when it failed. */
168
+ detail?: string;
169
+ }
170
+
171
+ /** A CI workflow path a forge reads, relative to the repository root. The governance list's pipeline entries. */
172
+ const CI_WORKFLOW = [/(^|\/)\.github\/workflows\/[^/]+\.ya?ml$/, /(^|\/)\.forgejo\/workflows\/[^/]+\.ya?ml$/, /(^|\/)\.gitea\/workflows\/[^/]+\.ya?ml$/, /(^|\/)\.gitlab-ci\.ya?ml$/];
173
+
174
+ /**
175
+ * The CI workflows the chant members under `worktreeProject` build: each
176
+ * package.json script that is one `chant build ... -o <file>` command (no
177
+ * shell, no `&&`), whose output is a committed CI workflow inside the scope.
178
+ * The studio kit's template has `"ci:build": "chant build ci --lexicon github
179
+ * -o ../.github/workflows/ci.yml"` in delivery/, and its CI fails when the
180
+ * committed workflow differs from what ci/ci.ts builds.
181
+ */
182
+ function workflowBuilds(worktree: string, worktreeProject: string, scopeRepoPath: string): Array<{ member: string; script: string; command: string; args: string[]; abs: string; path: string }> {
183
+ const out: Array<{ member: string; script: string; command: string; args: string[]; abs: string; path: string }> = [];
184
+ for (const member of chantMemberDirs(worktreeProject)) {
185
+ const dir = member === "." ? worktreeProject : join(worktreeProject, member);
186
+ let scripts: Record<string, unknown>;
187
+ try {
188
+ scripts = (JSON.parse(readFileSync(join(dir, "package.json"), "utf-8")) as { scripts?: Record<string, unknown> }).scripts ?? {};
189
+ } catch {
190
+ continue;
191
+ }
192
+ for (const [script, line] of Object.entries(scripts)) {
193
+ if (typeof line !== "string") continue;
194
+ const words = splitCommandLine(line);
195
+ if (!words || words[0] !== "chant" || words[1] !== "build") continue;
196
+ const flag = words.findIndex((w) => w === "-o" || w === "--output");
197
+ const target = flag >= 0 ? words[flag + 1] : words.find((w) => w.startsWith("--output="))?.slice("--output=".length);
198
+ if (!target) continue;
199
+ const abs = resolve(dir, target);
200
+ const path = relative(worktree, abs).split(sep).join("/");
201
+ if (path.startsWith("../") || !CI_WORKFLOW.some((re) => re.test(path))) continue;
202
+ if (scopeRepoPath !== "." && !path.startsWith(`${scopeRepoPath}/`)) continue;
203
+ if (!existsSync(abs)) continue;
204
+ out.push({ member, script, command: line, args: words.slice(2), abs, path });
205
+ }
206
+ }
207
+ return out;
208
+ }
209
+
210
+ /**
211
+ * Rebuild the CI workflows {@link workflowBuilds} finds (#3244), each in its
212
+ * member's directory of the staging worktree with that member's node_modules
213
+ * linked in from the project. A workflow is built from the member's sources
214
+ * through the lexicon's composites, so upgrading chant can change it with no
215
+ * change to the sources (#2621 moved Checkout and SetupNode from v4 to v7),
216
+ * and a committed copy then fails the project's own ci:check. Rebuilding it
217
+ * here puts the new workflow in the patch the gate approves. The links are
218
+ * removed before the patch is taken. A build that fails leaves the file as
219
+ * the merge left it.
220
+ */
221
+ async function rebuildWorkflows(root: string, worktree: string, worktreeProject: string, scopeRepoPath: string, run: ChantRunner): Promise<RebuiltWorkflow[]> {
222
+ const builds = workflowBuilds(worktree, worktreeProject, scopeRepoPath);
223
+ if (builds.length === 0) return [];
224
+ const linked: string[] = [];
225
+ const results: RebuiltWorkflow[] = [];
226
+ try {
227
+ for (const member of new Set(builds.map((b) => b.member))) {
228
+ if (member === ".") continue;
229
+ const from = join(root, member, "node_modules");
230
+ const to = join(worktreeProject, member, "node_modules");
231
+ if (existsSync(from) && !existsSync(to) && existsSync(dirname(to))) {
232
+ symlinkSync(from, to, "dir");
233
+ linked.push(to);
234
+ }
235
+ }
236
+ for (const b of builds) {
237
+ const before = readFileSync(b.abs);
238
+ const r = await run("build", b.member === "." ? worktreeProject : join(worktreeProject, b.member), b.args);
239
+ const base = { member: b.member, script: b.script, path: b.path, command: b.command };
240
+ if (r.exitCode !== 0) {
241
+ writeFileSync(b.abs, before);
242
+ results.push({ ...base, status: "failed", detail: tail(r.output) });
243
+ continue;
244
+ }
245
+ const after = existsSync(b.abs) ? readFileSync(b.abs) : null;
246
+ if (after === null) {
247
+ writeFileSync(b.abs, before);
248
+ results.push({ ...base, status: "failed", detail: `\`${b.command}\` exited 0 and wrote no ${b.path}` });
249
+ continue;
250
+ }
251
+ results.push({ ...base, status: after.equals(before) ? "unchanged" : "rebuilt" });
252
+ }
253
+ } finally {
254
+ for (const l of linked) {
255
+ try {
256
+ if (lstatSync(l).isSymbolicLink()) unlinkSync(l);
257
+ } catch {
258
+ // Already gone.
259
+ }
260
+ }
261
+ }
262
+ return results;
263
+ }
264
+
142
265
  export interface GovernanceChange {
143
266
  /** Changed governance paths, relative to the repository root. */
144
267
  paths: string[];
@@ -166,6 +289,8 @@ export interface StagedUpgrade {
166
289
  migrations: string[];
167
290
  /** The migrations chant ships (./chant-migrations.ts) that found something to move, applied or not. */
168
291
  chantMigrations: ChantMigrationReport[];
292
+ /** The CI workflows a chant member builds, rebuilt with this chant before the patch was taken (#3244). */
293
+ workflows: RebuiltWorkflow[];
169
294
  written: string[];
170
295
  merged: string[];
171
296
  removed: string[];
@@ -694,6 +819,10 @@ export async function stageUpgrade(options: UpgradeOptions): Promise<StagedUpgra
694
819
  writeLock(worktreeProject, next);
695
820
  const lockText = renderLock(next);
696
821
 
822
+ // The CI workflows a chant member builds, rebuilt with this chant (#3244),
823
+ // before the patch is taken so the gate approves them with the rest.
824
+ const workflows = lineage.kind === "template" ? await rebuildWorkflows(root, worktree, worktreeProject, scopeRepoPath, options.runChant ?? spawnChant) : [];
825
+
697
826
  // The patch, taken before anything else runs in the worktree.
698
827
  gitOut(worktree, ["add", "-A"]);
699
828
  if (!lockTracked) gitOut(worktree, ["rm", "--cached", "-q", "--ignore-unmatch", "--", lockRepoPath]);
@@ -730,6 +859,14 @@ export async function stageUpgrade(options: UpgradeOptions): Promise<StagedUpgra
730
859
 
731
860
  // 5. Checks.
732
861
  const checks: UpgradeCheck[] = [];
862
+ for (const w of workflows.filter((w) => w.status === "failed")) {
863
+ checks.push({
864
+ name: "build",
865
+ status: "failed",
866
+ member: w.member,
867
+ detail: `${w.path} could not be rebuilt with \`${w.command}\` (the ${w.script} script), so it may differ from what this chant builds:\n${w.detail ?? ""}`,
868
+ });
869
+ }
733
870
  for (const m of chantMigrations.filter((m) => !m.applied)) {
734
871
  checks.push({
735
872
  name: "migration",
@@ -783,6 +920,7 @@ export async function stageUpgrade(options: UpgradeOptions): Promise<StagedUpgra
783
920
  ...(upstream.commit ? { commit: { ...(lineage.address?.commit ? { from: lineage.address.commit } : {}), to: upstream.commit } } : {}),
784
921
  migrations: [...plan.chain.map((m) => m.migration.id), ...chantMigrations.filter((m) => m.applied).map((m) => m.id)],
785
922
  chantMigrations,
923
+ workflows,
786
924
  written: result.written,
787
925
  merged: result.merged,
788
926
  removed: result.removed,
@@ -885,6 +1023,9 @@ export function describeStaged(staged: StagedUpgrade): string[] {
885
1023
  for (const n of m.notMoved) lines.push(` not moved: ${n.what} -> ${n.where}`);
886
1024
  for (const c of m.conflicts) lines.push(` conflict: ${at(c.path)}: ${c.reason}`);
887
1025
  }
1026
+ for (const w of staged.workflows) {
1027
+ if (w.status !== "unchanged") lines.push(` workflow ${w.status === "rebuilt" ? "rebuilt" : "not rebuilt"}: ${w.path} (${w.script}: ${w.command})`);
1028
+ }
888
1029
  for (const p of staged.written) lines.push(` updated: ${at(p)}`);
889
1030
  for (const p of staged.merged) lines.push(` merged: ${at(p)}`);
890
1031
  for (const p of staged.removed) lines.push(` removed: ${at(p)}`);
@@ -0,0 +1,155 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://intentius.io/chant/schemas/workspace/plan-summary/v1/plan-summary.schema.json",
4
+ "title": "plan summary",
5
+ "description": "The grouped plan summary (#3188): a change-set document's members, or one member's instances, grouped by their normalized changes, with every destroy, replacement, failure and hole by name. Written by `chant change-set summary --format json` and by groupChangeSet in @intentius/chant/plan-summary. Reviewers read it; no gate binds it. Version 1 of the workspace read contract. Readers ignore fields they do not know; a field is only ever added within a version.",
6
+ "type": "object",
7
+ "required": ["$schema", "contract", "changeSet", "unit", "units", "groups", "failed", "destroys", "holes", "imports", "forgets", "sideEffects"],
8
+ "properties": {
9
+ "$schema": { "const": "https://intentius.io/chant/schemas/workspace/plan-summary/v1/plan-summary.schema.json" },
10
+ "contract": { "const": 1 },
11
+ "changeSet": {
12
+ "type": "string",
13
+ "pattern": "^(?:jcs1-)?sha256:[0-9a-f]{64}$",
14
+ "description": "The digest of the change-set document summarized."
15
+ },
16
+ "unit": {
17
+ "enum": ["member", "instance"],
18
+ "description": "member: each unit is a member of the document. instance: each unit is one resource instance of the document's one member."
19
+ },
20
+ "units": {
21
+ "type": "integer",
22
+ "minimum": 0,
23
+ "description": "Members, failed ones included, or the changing instances."
24
+ },
25
+ "groups": {
26
+ "type": "array",
27
+ "description": "Largest first. For instances, sorted by resource first.",
28
+ "items": { "$ref": "#/$defs/group" }
29
+ },
30
+ "failed": {
31
+ "type": "array",
32
+ "description": "Members that failed to plan. None is in a group.",
33
+ "items": {
34
+ "type": "object",
35
+ "required": ["member", "reason"],
36
+ "properties": {
37
+ "member": { "type": "string" },
38
+ "scope": { "type": "string" },
39
+ "reason": { "type": "string" }
40
+ }
41
+ }
42
+ },
43
+ "destroys": {
44
+ "type": "array",
45
+ "description": "Every delete and replace in the document, failed members' included, sorted by member and address.",
46
+ "items": { "$ref": "#/$defs/destroy" }
47
+ },
48
+ "imports": {
49
+ "type": "array",
50
+ "description": "Every entry that imports an object into state, sorted by member and address. An import is not a destroy.",
51
+ "items": { "$ref": "#/$defs/import" }
52
+ },
53
+ "forgets": {
54
+ "type": "array",
55
+ "description": "Every forget: the plan stops tracking the object and leaves it running. Never in destroys, and a destroy is never here.",
56
+ "items": { "$ref": "#/$defs/forget" }
57
+ },
58
+ "sideEffects": {
59
+ "type": "array",
60
+ "description": "Every provider-defined action an apply runs (Terraform actions blocks), sorted by member and address.",
61
+ "items": { "$ref": "#/$defs/sideEffect" }
62
+ },
63
+ "holes": {
64
+ "type": "array",
65
+ "description": "Every address a member's planner could not read.",
66
+ "items": {
67
+ "type": "object",
68
+ "required": ["member", "address", "reason"],
69
+ "properties": {
70
+ "member": { "type": "string" },
71
+ "address": { "type": "string" },
72
+ "type": { "type": "string" },
73
+ "reason": { "type": "string" }
74
+ }
75
+ }
76
+ }
77
+ },
78
+ "$defs": {
79
+ "action": { "enum": ["create", "update", "replace", "delete", "read", "no-op", "forget"] },
80
+ "import": {
81
+ "type": "object",
82
+ "required": ["member", "address", "type", "action"],
83
+ "properties": {
84
+ "member": { "type": "string" },
85
+ "address": { "type": "string" },
86
+ "type": { "type": "string" },
87
+ "action": { "$ref": "#/$defs/action", "description": "What else the plan does to the object; no-op when the import changes nothing." }
88
+ }
89
+ },
90
+ "forget": {
91
+ "type": "object",
92
+ "required": ["member", "address", "type"],
93
+ "properties": {
94
+ "member": { "type": "string" },
95
+ "address": { "type": "string" },
96
+ "type": { "type": "string" },
97
+ "deposed": { "type": "string" }
98
+ }
99
+ },
100
+ "sideEffect": {
101
+ "type": "object",
102
+ "required": ["member", "address", "type"],
103
+ "properties": {
104
+ "member": { "type": "string" },
105
+ "address": { "type": "string", "description": "The invocation's address, or its action type when the planner gives none." },
106
+ "type": { "type": "string" },
107
+ "trigger": { "type": "string", "description": "The resource whose lifecycle triggers it." },
108
+ "event": { "type": "string" }
109
+ }
110
+ },
111
+ "destroy": {
112
+ "type": "object",
113
+ "required": ["member", "address", "type", "action"],
114
+ "properties": {
115
+ "member": { "type": "string" },
116
+ "address": { "type": "string", "description": "The real address, never normalized." },
117
+ "type": { "type": "string" },
118
+ "action": { "enum": ["delete", "replace"] },
119
+ "deposed": { "type": "string" }
120
+ }
121
+ },
122
+ "change": {
123
+ "type": "object",
124
+ "required": ["line", "action", "count"],
125
+ "properties": {
126
+ "line": { "type": "string", "description": "The action's symbol, the normalized address and, for an update or replace, the attributes it writes. Values are never printed." },
127
+ "action": { "$ref": "#/$defs/action" },
128
+ "count": { "type": "integer", "minimum": 1, "description": "How many times one unit makes this change." },
129
+ "differsFrom": { "type": "string", "description": "The baseline group whose change at the same address and action this one differs from." },
130
+ "differsIn": { "type": "array", "items": { "type": "string" }, "description": "The attributes it differs in." }
131
+ }
132
+ },
133
+ "group": {
134
+ "type": "object",
135
+ "required": ["id", "units", "outlier", "noChanges", "changes", "destroys"],
136
+ "properties": {
137
+ "id": {
138
+ "type": "string",
139
+ "pattern": "^[0-9a-f]{12}$",
140
+ "description": "Twelve hex characters of computePlanDigest(\"plan-summary-group\", { resource, changes }) over the group's sorted normalized changes. The same change gets the same id in every run, so a report can link one group across commits. A change to the normalization rules can change it."
141
+ },
142
+ "resource": { "type": "string", "description": "For instance groups, the expansion: the address with its instance keys removed." },
143
+ "units": { "type": "array", "items": { "type": "string" }, "description": "Member names or instance addresses, sorted." },
144
+ "outlier": { "type": "boolean", "description": "A group of one beside other groups of the same expansion." },
145
+ "noChanges": { "type": "boolean" },
146
+ "changes": { "type": "array", "items": { "$ref": "#/$defs/change" } },
147
+ "extends": { "type": "string", "description": "The group whose whole change this one contains." },
148
+ "plus": { "type": "array", "items": { "$ref": "#/$defs/change" }, "description": "What it adds to that group's change." },
149
+ "destroys": { "type": "array", "items": { "$ref": "#/$defs/destroy" }, "description": "Every delete and replace a unit of this group makes. Each is also in the top-level destroys." },
150
+ "sideEffects": { "type": "array", "items": { "$ref": "#/$defs/sideEffect" }, "description": "Every triggered action a unit of this group runs." },
151
+ "provisional": { "const": true, "description": "Its units are provisional plans, planned before what they read applied. Part of the id, so they never share a group with real plans. Absent on a group of real plans." }
152
+ }
153
+ }
154
+ }
155
+ }
@@ -2,7 +2,7 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "urn:intentius:chant:point-answer:1",
4
4
  "title": "Decision point answer front matter",
5
- "description": "The front matter of one answer to a decision point (ws-058, #2739), as `chant workspace points ask` and `points answer` write it into the records directory of a record kind with an `answers` block. One record per point, declaration and inputs: its id is the point's name and the first 12 hex digits of the inputs hash, so the same question is answered once. A table's answer is `answered`; a model's answer at or above its threshold is `proposed` until a person confirms it; a question no decider before the quorum answered is `escalated`, open for people. A workspace copies this file next to its answer kind, as reference-workspace/answers/ does. Values stay within what YAML and JSON share. Fields other than these must start with x-.",
5
+ "description": "The front matter of one answer to a decision point (ws-058, #2739), as `chant workspace points ask` and `points answer` write it into the records directory of a record kind with an `answers` block. One record per point, declaration and inputs: its id is the point's name and the first 12 hex digits of the inputs hash, so the same question is answered once. A table's answer is `answered`; a model's answer at or above its threshold is `proposed` until a person confirms it; a question no decider before the quorum answered is `escalated`, open for people. An answer never changes in place: `points retract` escalates the question to people again and moves the answer into `retractions` (#3351, ws-084). An ad-hoc point's answer keeps the question and candidates its ask gave as `asked`, and they are part of the inputs hash (#3403). A workspace copies this file next to its answer kind, as reference-workspace/answers/ does. Values stay within what YAML and JSON share. Fields other than these must start with x-.",
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
8
  "patternProperties": { "^x-": {} },
@@ -14,6 +14,21 @@
14
14
  "point_version": { "$ref": "#/definitions/sha256", "description": "sha256 of the point's declaration when it was asked. Editing the question or any decider changes it." },
15
15
  "question_type": { "enum": ["noul", "choice", "score"] },
16
16
  "candidates": { "type": "array", "minItems": 2, "items": { "type": ["string", "boolean"] }, "description": "The answers the question allowed: true and false, a choice's options, or a score's levels." },
17
+ "asked": {
18
+ "type": "object",
19
+ "description": "An ad-hoc point's question as its ask gave it (`points ask --candidates`, #3403): its text, and its criteria in the point's question type's shape, from which candidates come. People's answer is one of them.",
20
+ "required": ["question", "criteria"],
21
+ "properties": {
22
+ "question": { "type": "string", "minLength": 1 },
23
+ "criteria": {
24
+ "oneOf": [
25
+ { "type": "object", "minProperties": 2, "maxProperties": 255, "additionalProperties": { "type": "string" } },
26
+ { "type": "array", "minItems": 2, "maxItems": 10, "uniqueItems": true, "items": { "type": "string", "minLength": 1 } }
27
+ ]
28
+ }
29
+ },
30
+ "additionalProperties": false
31
+ },
17
32
  "inputs": { "type": "object", "description": "The state the deciders saw, input name to value." },
18
33
  "inputs_hash": { "$ref": "#/definitions/sha256", "description": "sha256 of the point, its version and its inputs. The same hash is answered once." },
19
34
  "constrains": { "type": "array", "items": { "type": "string", "minLength": 1 }, "description": "What the question is about, such as a work item's id." },
@@ -36,12 +51,20 @@
36
51
  "probabilities": { "$ref": "#/definitions/probabilities" },
37
52
  "confidence": { "$ref": "#/definitions/unit" },
38
53
  "threshold": { "$ref": "#/definitions/unit" },
54
+ "reason": { "type": "string", "minLength": 1, "description": "model: the model's own explanation of its answer, when the backend gave one (#3345). Kept when a person confirms the proposal; moved into the escalations as model_reason when people answer otherwise." },
39
55
  "escalations": {
40
56
  "type": "array",
41
57
  "description": "The deciders asked before the one that answered, or before the quorum, and why each did not answer.",
42
58
  "items": { "$ref": "#/definitions/escalation" }
43
59
  },
44
60
  "answered_by": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 }, "description": "The people who answered or confirmed it." },
61
+ "note": { "type": "string", "minLength": 1, "description": "What the people who answered wrote with their answer (`points answer --note`, #3351). Moved into the retraction when the answer is retracted." },
62
+ "relayed_by": { "type": "string", "minLength": 1, "description": "Who carried the answer to chant for the people in answered_by (`points answer --relayed-by`, #3402), such as a follower relaying a person's answer through hud. It does not count toward the quorum. Moved into the retraction as answer_relayed_by when the answer is retracted." },
63
+ "retractions": {
64
+ "type": "array",
65
+ "description": "Answers people took back, oldest first (`points retract`, #3351): each answer as it was, and who retracted it, when and why. A retracted question is escalated to people again.",
66
+ "items": { "$ref": "#/definitions/retraction" }
67
+ },
45
68
  "asked_on": { "$ref": "#/definitions/date" },
46
69
  "answered_on": { "$ref": "#/definitions/date" },
47
70
  "source": {
@@ -76,6 +99,22 @@
76
99
  "unit": { "type": "number", "minimum": 0, "maximum": 1 },
77
100
  "date": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" },
78
101
  "probabilities": { "type": "object", "additionalProperties": { "$ref": "#/definitions/unit" } },
102
+ "retraction": {
103
+ "type": "object",
104
+ "required": ["answer", "decider", "by", "on"],
105
+ "properties": {
106
+ "answer": { "type": ["string", "boolean"], "description": "The answer retracted." },
107
+ "decider": { "type": "object", "required": ["kind"], "properties": { "kind": { "enum": ["table", "model", "quorum"] } }, "description": "Who gave it: the record's decider as it was." },
108
+ "answered_by": { "type": "array", "items": { "type": "string", "minLength": 1 } },
109
+ "answered_on": { "$ref": "#/definitions/date" },
110
+ "answer_note": { "type": "string", "minLength": 1, "description": "The note the answer carried." },
111
+ "answer_relayed_by": { "type": "string", "minLength": 1, "description": "Who relayed the answer (#3402)." },
112
+ "by": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 }, "description": "Who retracted it." },
113
+ "on": { "$ref": "#/definitions/date" },
114
+ "note": { "type": "string", "minLength": 1, "description": "Why it was retracted (`points retract --note`)." }
115
+ },
116
+ "additionalProperties": false
117
+ },
79
118
  "escalation": {
80
119
  "type": "object",
81
120
  "required": ["kind", "reason"],
@@ -87,7 +126,8 @@
87
126
  "answer": { "type": ["string", "boolean", "null"] },
88
127
  "probabilities": { "$ref": "#/definitions/probabilities" },
89
128
  "confidence": { "$ref": "#/definitions/unit" },
90
- "threshold": { "$ref": "#/definitions/unit" }
129
+ "threshold": { "$ref": "#/definitions/unit" },
130
+ "model_reason": { "type": "string", "minLength": 1, "description": "model: the model's own explanation of the answer it gave, when the backend gave one (#3345). reason is why the decider did not answer." }
91
131
  },
92
132
  "additionalProperties": false
93
133
  }