@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
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Following a squash merge to the pull request's original commits (#3035).
3
+ *
4
+ * - `forge` is a bare repository standing in for the forge: origin, with the
5
+ * pull request heads at refs/pull/<n>/head.
6
+ * - Pull request 7 has two commits: o1 changes line 2 of app/server.ts with
7
+ * `Chant-Run: run-a` and `Chant-Record: work:W-001`, and o2 changes line 4
8
+ * and is listed by run B's end. main squashes them into sq, "feature (#7)".
9
+ * - s-001 (path:app/server.ts) is decided; W-001 implements it.
10
+ * - "other (#8)" changes app/other.ts, and the forge has no ref for 8.
11
+ * - "fix (#9)" is committed on main itself, and refs/pull/9/head is that
12
+ * commit, as after a rebase merge: nothing to follow.
13
+ */
14
+
15
+ import { readFileSync } from "node:fs";
16
+ import { join } from "node:path";
17
+ import { afterAll, beforeAll, describe, expect, test } from "vitest";
18
+ import { cleanScratch, contract, git, REPO, repo, scratchDir, writeFiles } from "./__fixtures__/contract-repo";
19
+ import { intentGraph, type CommitNode, type IntentDocument } from "./intent";
20
+ import { formatIntent } from "./intent-cli";
21
+ import { intentRecord } from "./intent-record";
22
+ import intentRecordSchema from "./intent-record.schema.json";
23
+ import intentSchema from "./intent.schema.json";
24
+ import { parseFrontMatter } from "./records";
25
+ import { runsWrite, workspaceRuns } from "./runs-cli";
26
+ import runsSchema from "./runs.schema.json";
27
+ import { forgeOf, pullRequestOf } from "./squash";
28
+ import { readArgv } from "../cli/mcp/workspace-tools";
29
+
30
+ const REF = join(REPO, "reference-workspace");
31
+ const BASE = (() => {
32
+ const fm = parseFrontMatter(readFileSync(join(REF, "decisions", "ref-001-how-the-app-is-deployed.md"), "utf-8"));
33
+ if (!fm.ok) throw new Error(fm.message);
34
+ return fm.value;
35
+ })();
36
+ const decision = (id: string, fields: Record<string, unknown>) => `---\n${JSON.stringify({ ...BASE, id, title: `Decision ${id}`, state: "decided", supersedes: [], evidence: [], reviews: [], ...fields }, null, 2)}\n---\n\n# ${id}\n`;
37
+ const work = (id: string, fields: Record<string, unknown>) =>
38
+ `---\n${JSON.stringify({ schema: 1, id, title: `Work ${id}`, state: "open", implements: [], needs: [], constrains: [], evidence: [], opened_on: "2026-10-01", supersedes: [], ...fields }, null, 2)}\n---\n\n# ${id}\n\nWhat the work is.\n`;
39
+
40
+ const LINES = ["// The app server.", "export const a = 0;", "export const b = 0;", "export const c = 0;", "export const d = 0;"];
41
+ const text = (lines: string[]) => `${lines.join("\n")}\n`;
42
+ const edit = (lines: string[], at: number, to: string) => lines.map((l, i) => (i === at - 1 ? to : l));
43
+
44
+ type Doc = Exclude<IntentDocument, { error: unknown }>;
45
+
46
+ let root: string;
47
+ let forge: string;
48
+ const sha: Record<string, string> = {};
49
+
50
+ function commit(message: string[]): string {
51
+ git(root, "add", "-A");
52
+ git(root, "commit", "-q", ...message.flatMap((m) => ["-m", m]));
53
+ return git(root, "rev-parse", "HEAD");
54
+ }
55
+ async function record(fields: object): Promise<void> {
56
+ const doc = await runsWrite({ verb: "record", fields: JSON.stringify(fields), cwd: root });
57
+ if ("error" in doc) throw new Error(`${doc.error.code}: ${doc.error.message}`);
58
+ }
59
+ async function walk(region: string, followSquash: boolean): Promise<Doc> {
60
+ const { doc } = await intentGraph({ cwd: root, region, followSquash });
61
+ contract(intentSchema).expectValid(doc);
62
+ if ("error" in doc) throw new Error(`${doc.error.code}: ${doc.error.message}`);
63
+ return doc;
64
+ }
65
+ const commitNode = (doc: Doc, s: string) => doc.nodes.find((n): n is CommitNode => n.kind === "commit" && n.sha === s);
66
+
67
+ beforeAll(async () => {
68
+ root = repo({
69
+ "chant.workspace.json": JSON.stringify({ name: "squash", schema: 1, records: [{ kind: "decisions/decision.kind.mjs" }, { kind: "work/work.kind.mjs" }], members: [{ name: "app", dir: "app", kind: "other", because: "the app" }] }),
70
+ "decisions/decision.kind.mjs": readFileSync(join(REF, "decisions", "decision.kind.mjs"), "utf-8"),
71
+ "decisions/decision.schema.json": readFileSync(join(REF, "decisions", "decision.schema.json"), "utf-8"),
72
+ "work/work.kind.mjs": readFileSync(join(REF, "work", "work.kind.mjs"), "utf-8"),
73
+ "work/work.schema.json": readFileSync(join(REF, "work", "work.schema.json"), "utf-8"),
74
+ "app/server.ts": text(LINES),
75
+ "app/other.ts": "export const other = 0;\n",
76
+ "app/fix.ts": "export const fix = 0;\n",
77
+ "decisions/s-001-server.md": decision("s-001", { constrains: ["path:app/server.ts"] }),
78
+ "work/W-001-server.md": work("W-001", { implements: ["s-001"] }),
79
+ });
80
+ sha.c0 = commit(["the workspace"]);
81
+ const main = git(root, "rev-parse", "--abbrev-ref", "HEAD");
82
+ forge = scratchDir("chant-forge-");
83
+ git(forge, "init", "-q", "--bare");
84
+ git(root, "remote", "add", "origin", forge);
85
+
86
+ // Pull request 7, pushed to the forge's pull ref, and its branch gone from the clone.
87
+ git(root, "checkout", "-q", "-b", "feature");
88
+ writeFiles(root, { "app/server.ts": text(edit(LINES, 2, "export const a = 1;")) });
89
+ sha.o1 = commit(["a is 1", "Chant-Run: run-a\nChant-Record: work:W-001"]);
90
+ writeFiles(root, { "app/server.ts": text(edit(edit(LINES, 2, "export const a = 1;"), 4, "export const c = 1;")) });
91
+ sha.o2 = commit(["c is 1"]);
92
+ git(root, "push", "-q", "origin", "feature:refs/pull/7/head");
93
+ git(root, "checkout", "-q", main);
94
+ git(root, "branch", "-q", "-D", "feature");
95
+
96
+ await record({ id: "run-a", harness: "claude-code", model: "claude-opus-5-5", unit: "W-001", startedAt: "2026-10-01T10:00:00Z" });
97
+ await record({ id: "run-b", harness: "claude-code", model: "claude-sonnet", startedAt: "2026-10-01T11:00:00Z", commits: [sha.o2] });
98
+
99
+ git(root, "merge", "--squash", "-q", sha.o2);
100
+ sha.sq = commit(["feature (#7)"]);
101
+ writeFiles(root, { "app/other.ts": "export const other = 1;\n" });
102
+ sha.other = commit(["other (#8)"]);
103
+ writeFiles(root, { "app/fix.ts": "export const fix = 1;\n" });
104
+ sha.fix = commit(["fix (#9)"]);
105
+ git(root, "push", "-q", "origin", `${sha.fix}:refs/pull/9/head`);
106
+ }, 60_000);
107
+ afterAll(cleanScratch);
108
+
109
+ describe("squash commits", () => {
110
+ test("the forge comes from the remote, and the pull request from the subject", () => {
111
+ expect(forgeOf("https://github.com/INTENTIUS/chant.git")).toBe("github");
112
+ expect(forgeOf("git@github.com:INTENTIUS/chant.git")).toBe("github");
113
+ expect(forgeOf("https://github.acme.example/team/repo")).toBe("github");
114
+ expect(forgeOf("https://codeberg.org/forgejo/forgejo.git")).toBe("forgejo");
115
+ expect(forgeOf("ssh://git@forgejo.example.org:2222/team/repo.git")).toBe("forgejo");
116
+ expect(forgeOf("https://gitea.example.org/team/repo")).toBe("forgejo");
117
+ expect(forgeOf("/srv/git/repo.git")).toBeNull();
118
+ expect(forgeOf(null)).toBeNull();
119
+ expect(pullRequestOf("feature (#7)")).toBe(7);
120
+ expect(pullRequestOf("feature (#7) and more")).toBeNull();
121
+ // The MCP tools pass the option on, and leave it off by default.
122
+ expect(readArgv("workspace-graph", { intent: "app/server.ts", followSquash: true })).toEqual(["workspace", "graph", "--intent", "app/server.ts", "--follow-squash", "--json"]);
123
+ expect(readArgv("workspace-graph", { intent: "app/server.ts" })).toEqual(["workspace", "graph", "--intent", "app/server.ts", "--json"]);
124
+ expect(readArgv("workspace-runs", { followSquash: true })).toEqual(["workspace", "runs", "--follow-squash", "--json"]);
125
+ });
126
+
127
+ test("without --follow-squash the walk reads nothing from the forge", async () => {
128
+ const doc = await walk("app/server.ts", false);
129
+ const sq = commitNode(doc, sha.sq)!;
130
+ expect(sq.pullRequest).toBe(7);
131
+ expect(sq.squash).toBeUndefined();
132
+ expect(doc.edges.filter((e) => e.kind === "made-by" && e.from === sq.id)).toEqual([]);
133
+ expect(git(root, "for-each-ref", "refs/chant/pull/")).toBe("");
134
+ });
135
+
136
+ test("--follow-squash fetches the pull request's head and reports the original commits under the squash", async () => {
137
+ const doc = await walk("app/server.ts", true);
138
+ const sq = commitNode(doc, sha.sq)!;
139
+ expect(sq.squash).toMatchObject({ pullRequest: 7, forge: null, ref: "refs/chant/pull/7/head", head: sha.o2, fetched: true, followed: true });
140
+ expect(sq.squash!.commits.map((o) => [o.sha, o.subject, o.joins.run, o.joins.records.map((r) => `${r.kind}:${r.id}`)])).toEqual([
141
+ [sha.o1, "a is 1", "run-a", ["work:W-001"]],
142
+ [sha.o2, "c is 1", null, []],
143
+ ]);
144
+ expect(sq.squash!.commits[0].signature.level).toBe("unattested");
145
+ // The squash joins both runs, through the commit each made.
146
+ expect(doc.edges.filter((e) => e.kind === "made-by" && e.from === sq.id)).toEqual([
147
+ { kind: "made-by", from: sq.id, to: "run:run-a", joinedBy: ["squash"], via: [sha.o1] },
148
+ { kind: "made-by", from: sq.id, to: "run:run-b", joinedBy: ["squash"], via: [sha.o2] },
149
+ ]);
150
+ // o1's Chant-Record is carried by the squash, so it is s-001's own work.
151
+ expect(doc.edges).toContainEqual({ kind: "carries", from: sq.id, to: "record:work/W-001" });
152
+ expect(doc.edges).toContainEqual({ kind: "within", from: sq.id, to: "record:decision/s-001", state: "decided" });
153
+ // Blame at the head says which original wrote each line, so each line has the one run that wrote it.
154
+ expect(doc.why.blame.filter((s) => s.sha === sha.sq)).toEqual([
155
+ { start: 2, end: 2, commit: sq.id, sha: sha.sq, runs: ["run:run-a"], narrowedBy: null, joinedBy: ["squash"], via: [sha.o1] },
156
+ { start: 4, end: 4, commit: sq.id, sha: sha.sq, runs: ["run:run-b"], narrowedBy: null, joinedBy: ["squash"], via: [sha.o2] },
157
+ ]);
158
+ expect(doc.why.runs.map((r) => [r.run, r.lines, r.joinedBy])).toEqual([
159
+ ["run:run-b", 1, ["squash"]],
160
+ ["run:run-a", 1, ["squash"]],
161
+ ]);
162
+ expect(doc.why.gaps.map((g) => g.code)).not.toContain("intent-why-run-ambiguous");
163
+ const out = formatIntent(doc);
164
+ expect(out).toContain("squash #7: 2 original commits from refs/chant/pull/7/head, fetched");
165
+ expect(out).toContain(`(squashed from ${sha.o1.slice(0, 8)})`);
166
+
167
+ // The next read finds the ref in the clone and fetches nothing.
168
+ const again = await walk("app/server.ts", true);
169
+ expect(commitNode(again, sha.sq)!.squash).toMatchObject({ ref: "refs/chant/pull/7/head", fetched: false, followed: true });
170
+ });
171
+
172
+ test("a ref the forge doesn't have is reported, never fatal, and a rebased pull request is not a squash", async () => {
173
+ const other = await walk("app/other.ts", true);
174
+ expect(commitNode(other, sha.other)!.squash).toEqual({ pullRequest: 8, forge: null, ref: null, head: null, fetched: false, followed: false, commits: [] });
175
+ expect(other.reasons).toEqual([expect.objectContaining({ code: "squash-unfollowed", message: expect.stringContaining("refs/pull/8/head could not be fetched from origin") })]);
176
+ const fix = await walk("app/fix.ts", true);
177
+ expect(commitNode(fix, sha.fix)!.squash).toBeUndefined();
178
+ expect(fix.reasons).toEqual([]);
179
+ });
180
+
181
+ test("graph --intent --record counts the squash under the work its original commits carried", async () => {
182
+ const { doc } = await intentRecord({ cwd: root, record: "s-001", followSquash: true });
183
+ contract(intentRecordSchema).expectValid(doc);
184
+ if ("error" in doc) throw new Error(doc.error.message);
185
+ const sq = doc.commits.find((c) => c.sha === sha.sq)!;
186
+ expect(sq.bucket).toBe("own");
187
+ expect(sq.squash).toMatchObject({ pullRequest: 7, followed: true, commits: [{ sha: sha.o1 }, { sha: sha.o2 }] });
188
+ expect(sq.runs.map((r) => [r.id, r.joinedBy, r.via])).toEqual([
189
+ ["run-a", ["squash"], [sha.o1]],
190
+ ["run-b", ["squash"], [sha.o2]],
191
+ ]);
192
+ const plain = await intentRecord({ cwd: root, record: "s-001" });
193
+ if ("error" in plain.doc) throw new Error(plain.doc.error.message);
194
+ expect(plain.doc.commits.find((c) => c.sha === sha.sq)).toMatchObject({ bucket: "worked", runs: [] });
195
+ });
196
+
197
+ test("runs --json --follow-squash adds the squash to each run its original commits joined", async () => {
198
+ const doc = await workspaceRuns({ cwd: root, followSquash: true });
199
+ contract(runsSchema).expectValid(doc);
200
+ if ("error" in doc) throw new Error(doc.error.message);
201
+ expect(doc.filter.followSquash).toBe(true);
202
+ const byId = new Map(doc.runs.map((r) => [r.id, r]));
203
+ expect(byId.get("run-a")!.commits).toEqual([{ sha: sha.sq, patchId: expect.any(String), joinedBy: ["squash"], hunks: null, via: [sha.o1] }]);
204
+ expect(byId.get("run-b")!.commits.map((c) => [c.sha, c.joinedBy, c.via])).toEqual([
205
+ [sha.o2, ["record"], undefined],
206
+ [sha.sq, ["squash"], [sha.o2]],
207
+ ]);
208
+ expect(doc.reasons.map((r) => r.code)).toEqual(["squash-unfollowed"]);
209
+ const plain = await workspaceRuns({ cwd: root });
210
+ if ("error" in plain) throw new Error(plain.error.message);
211
+ expect(plain.runs.find((r) => r.id === "run-a")!.commits).toEqual([]);
212
+ });
213
+ });
@@ -171,11 +171,11 @@ describe("why the region is like this", () => {
171
171
  const doc = await walk("app/server.ts#createApp");
172
172
  expect(doc.why.lines).toEqual({ start: 2, end: 4 });
173
173
  expect(doc.why.blame).toEqual([
174
- { start: 2, end: 2, commit: `commit:${sha.c0}`, sha: sha.c0, runs: [], narrowedBy: null },
175
- { start: 3, end: 3, commit: `commit:${sha.c1}`, sha: sha.c1, runs: ["run:run-a"], narrowedBy: null },
176
- { start: 4, end: 4, commit: `commit:${sha.c0}`, sha: sha.c0, runs: [], narrowedBy: null },
174
+ { start: 2, end: 2, commit: `commit:${sha.c0}`, sha: sha.c0, runs: [], narrowedBy: null, joinedBy: [] },
175
+ { start: 3, end: 3, commit: `commit:${sha.c1}`, sha: sha.c1, runs: ["run:run-a"], narrowedBy: null, joinedBy: ["trailer"] },
176
+ { start: 4, end: 4, commit: `commit:${sha.c0}`, sha: sha.c0, runs: [], narrowedBy: null, joinedBy: [] },
177
177
  ]);
178
- expect(doc.why.runs).toEqual([{ run: "run:run-a", lines: 1, commits: [`commit:${sha.c1}`], unit: { id: "W-001", kind: null, node: "record:work/W-001" }, decisions: ["record:decision/s-001"] }]);
178
+ expect(doc.why.runs).toEqual([{ run: "run:run-a", lines: 1, commits: [`commit:${sha.c1}`], unit: { id: "W-001", kind: null, node: "record:work/W-001" }, decisions: ["record:decision/s-001"], joinedBy: ["trailer"] }]);
179
179
  expect(doc.why.decisions.map((d) => [d.decision, d.relevance, d.lines])).toEqual([
180
180
  ["record:decision/s-001", "carried", 1],
181
181
  ["record:decision/s-003", "path", 0],
@@ -199,7 +199,7 @@ describe("why the region is like this", () => {
199
199
 
200
200
  test("without hunks, a commit several runs made is ambiguous, and says so", async () => {
201
201
  const doc = await walk("app/server.ts:1");
202
- expect(doc.why.blame).toEqual([{ start: 1, end: 1, commit: `commit:${sha.c3}`, sha: sha.c3, runs: ["run:run-d", "run:run-e"], narrowedBy: null }]);
202
+ expect(doc.why.blame).toEqual([{ start: 1, end: 1, commit: `commit:${sha.c3}`, sha: sha.c3, runs: ["run:run-d", "run:run-e"], narrowedBy: null, joinedBy: ["record"] }]);
203
203
  expect(doc.why.gaps).toEqual([{ code: "intent-why-run-ambiguous", message: expect.any(String), lines: [{ start: 1, end: 1 }] }]);
204
204
  });
205
205
 
@@ -522,6 +522,9 @@
522
522
  },
523
523
  "joins": {
524
524
  "$ref": "#/$defs/trailerJoins"
525
+ },
526
+ "squash": {
527
+ "$ref": "#/$defs/squash"
525
528
  }
526
529
  }
527
530
  },
@@ -1004,6 +1007,51 @@
1004
1007
  }
1005
1008
  }
1006
1009
  }
1010
+ },
1011
+ "reviews": {
1012
+ "description": "The review sessions whose comments led to this item (#3154, E21 in arugula-salad/hud#823): each record of a session kind read whose comments[].follow_ups, or its own follow_ups, name the item as <kind>:<id>. A commit that carries the item by its Chant-Record trailer joins back to the review through it. Absent when none does. Added within contract 1.",
1013
+ "type": "array",
1014
+ "items": {
1015
+ "type": "object",
1016
+ "required": [
1017
+ "id",
1018
+ "recordKind",
1019
+ "record",
1020
+ "path",
1021
+ "state",
1022
+ "comments"
1023
+ ],
1024
+ "properties": {
1025
+ "id": {
1026
+ "type": "string",
1027
+ "pattern": "^record:"
1028
+ },
1029
+ "recordKind": {
1030
+ "type": "string"
1031
+ },
1032
+ "record": {
1033
+ "type": "string"
1034
+ },
1035
+ "path": {
1036
+ "type": "string",
1037
+ "description": "The session record file, from the repository root."
1038
+ },
1039
+ "state": {
1040
+ "type": [
1041
+ "string",
1042
+ "null"
1043
+ ]
1044
+ },
1045
+ "comments": {
1046
+ "type": "array",
1047
+ "items": {
1048
+ "type": "integer",
1049
+ "minimum": 1
1050
+ },
1051
+ "description": "The comments whose follow_ups name the item, numbered from 1; empty when only the session's own follow_ups do."
1052
+ }
1053
+ }
1054
+ }
1007
1055
  }
1008
1056
  }
1009
1057
  },
@@ -1156,7 +1204,8 @@
1156
1204
  "intent-region-unconstrained",
1157
1205
  "intent-decision-unimplemented",
1158
1206
  "intent-work-blocked",
1159
- "intent-work-open-decided-code"
1207
+ "intent-work-open-decided-code",
1208
+ "intent-commit-join-conflict"
1160
1209
  ]
1161
1210
  },
1162
1211
  {
@@ -1253,7 +1302,8 @@
1253
1302
  "code": {
1254
1303
  "enum": [
1255
1304
  "intent-history-shallow",
1256
- "intent-plugin-failed"
1305
+ "intent-plugin-failed",
1306
+ "squash-unfollowed"
1257
1307
  ]
1258
1308
  },
1259
1309
  "message": {
@@ -1938,10 +1988,25 @@
1938
1988
  "items": {
1939
1989
  "enum": [
1940
1990
  "trailer",
1941
- "record"
1991
+ "record",
1992
+ "patch-id",
1993
+ "squash"
1942
1994
  ]
1943
1995
  },
1944
- "description": "trailer: the commit carries Chant-Run with the run's id. record: the run's end lists the commit."
1996
+ "description": "trailer: the commit carries Chant-Run with the run's id. record: the run's end lists the commit. patch-id: neither holds, and the commit's git patch-id --stable equals a commit's the run's end recorded, as after a rebase or a cherry-pick that dropped the trailer (#3036); never alongside the others. Added within version 1. squash: the commit squashes a pull request whose original commits join the run one of those ways, and the read was asked to follow squashes (#3035); via names them. Added within version 1."
1997
+ },
1998
+ "recordedAs": {
1999
+ "type": "string",
2000
+ "pattern": "^[0-9a-f]{40,64}$",
2001
+ "description": "For a patch-id join (#3036): the commit the run's end recorded with the same patch-id, which this one rewrites. Added within version 1."
2002
+ },
2003
+ "via": {
2004
+ "type": "array",
2005
+ "items": {
2006
+ "type": "string",
2007
+ "pattern": "^[0-9a-f]{40,64}$"
2008
+ },
2009
+ "description": "For a squash join (#3035): the pull request's original commits through which the commit joins the run, oldest first. Added within version 1."
1945
2010
  }
1946
2011
  }
1947
2012
  },
@@ -2048,6 +2113,26 @@
2048
2113
  null
2049
2114
  ],
2050
2115
  "description": "hunks: runs' recorded hunks chose among the runs that made the commit, and a run whose hunks miss the lines is left out. null: every run that made the commit is listed."
2116
+ },
2117
+ "joinedBy": {
2118
+ "type": "array",
2119
+ "items": {
2120
+ "enum": [
2121
+ "trailer",
2122
+ "record",
2123
+ "patch-id",
2124
+ "squash"
2125
+ ]
2126
+ },
2127
+ "description": "How the runs in runs join the commit, as their made-by edges say, without repeats; empty with no runs. patch-id marks a join by content, which a reader shows apart from a trailer or a record (#3036). Added within version 1, so an older document may lack it."
2128
+ },
2129
+ "via": {
2130
+ "type": "array",
2131
+ "items": {
2132
+ "type": "string",
2133
+ "pattern": "^[0-9a-f]{40,64}$"
2134
+ },
2135
+ "description": "Only on the lines of a followed squash (#3035): the original commit that last wrote them, one of the commit node's squash.commits, by git blame at the pull request's head, and runs keeps that commit's runs and the squash's own. Empty when the file at the head differs from the squash's, so blame there can't say. Added within version 1."
2051
2136
  }
2052
2137
  }
2053
2138
  },
@@ -2156,6 +2241,18 @@
2156
2241
  "type": "string"
2157
2242
  },
2158
2243
  "description": "The decision nodes it carried out: the ones its work item implements and the decision records it names."
2244
+ },
2245
+ "joinedBy": {
2246
+ "type": "array",
2247
+ "items": {
2248
+ "enum": [
2249
+ "trailer",
2250
+ "record",
2251
+ "patch-id",
2252
+ "squash"
2253
+ ]
2254
+ },
2255
+ "description": "How the run joins the commits in commits, as their made-by edges say, without repeats (#3036). Added within version 1, so an older document may lack it."
2159
2256
  }
2160
2257
  }
2161
2258
  },
@@ -2185,6 +2282,139 @@
2185
2282
  "description": "The lines the gap is about, for intent-why-uncommitted and intent-why-run-ambiguous."
2186
2283
  }
2187
2284
  }
2285
+ },
2286
+ "squash": {
2287
+ "type": "object",
2288
+ "description": "Present only when the read follows squashes (--follow-squash, #3035) and the commit squashes a pull request: its subject ends with (#<n>), it has one parent, and the pull request's head is not in its history. The commit carries what the original commits' trailers carry and joins their runs. Added within version 1.",
2289
+ "required": [
2290
+ "pullRequest",
2291
+ "forge",
2292
+ "ref",
2293
+ "head",
2294
+ "fetched",
2295
+ "followed",
2296
+ "commits"
2297
+ ],
2298
+ "properties": {
2299
+ "pullRequest": {
2300
+ "type": "integer",
2301
+ "minimum": 1
2302
+ },
2303
+ "forge": {
2304
+ "enum": [
2305
+ "github",
2306
+ "forgejo",
2307
+ null
2308
+ ],
2309
+ "description": "The forge origin points at, from its URL, or null for one chant doesn't know or no origin. Both keep the pull request's head at refs/pull/<n>/head."
2310
+ },
2311
+ "ref": {
2312
+ "type": [
2313
+ "string",
2314
+ "null"
2315
+ ],
2316
+ "description": "The local ref the head was read from: refs/chant/pull/<n>/head where a read fetched it, refs/pull/<n>/head, or refs/remotes/origin/pr/<n>. Null when none could be read."
2317
+ },
2318
+ "head": {
2319
+ "oneOf": [
2320
+ {
2321
+ "type": "string",
2322
+ "pattern": "^[0-9a-f]{40,64}$"
2323
+ },
2324
+ {
2325
+ "type": "null"
2326
+ }
2327
+ ],
2328
+ "description": "The pull request's head commit, or null."
2329
+ },
2330
+ "fetched": {
2331
+ "type": "boolean",
2332
+ "description": "Whether this read fetched the ref from origin."
2333
+ },
2334
+ "followed": {
2335
+ "type": "boolean",
2336
+ "description": "Whether the original commits were read. When false, squash-unfollowed in reasons says why, and commits is empty."
2337
+ },
2338
+ "commits": {
2339
+ "type": "array",
2340
+ "items": {
2341
+ "type": "object",
2342
+ "required": [
2343
+ "sha",
2344
+ "subject",
2345
+ "author",
2346
+ "date",
2347
+ "trailers",
2348
+ "signature",
2349
+ "joins"
2350
+ ],
2351
+ "properties": {
2352
+ "sha": {
2353
+ "type": "string",
2354
+ "pattern": "^[0-9a-f]{40,64}$"
2355
+ },
2356
+ "subject": {
2357
+ "type": "string"
2358
+ },
2359
+ "author": {
2360
+ "type": "object",
2361
+ "required": [
2362
+ "name",
2363
+ "email"
2364
+ ],
2365
+ "properties": {
2366
+ "name": {
2367
+ "type": "string"
2368
+ },
2369
+ "email": {
2370
+ "type": "string"
2371
+ }
2372
+ }
2373
+ },
2374
+ "date": {
2375
+ "type": "string"
2376
+ },
2377
+ "trailers": {
2378
+ "type": "object",
2379
+ "additionalProperties": {
2380
+ "type": "array",
2381
+ "items": {
2382
+ "type": "string"
2383
+ }
2384
+ }
2385
+ },
2386
+ "joins": {
2387
+ "$ref": "#/$defs/trailerJoins"
2388
+ },
2389
+ "signature": {
2390
+ "type": "object",
2391
+ "required": [
2392
+ "level",
2393
+ "reason"
2394
+ ],
2395
+ "properties": {
2396
+ "level": {
2397
+ "enum": [
2398
+ "attested",
2399
+ "attested-unverifiable-here",
2400
+ "adopted",
2401
+ "unattested"
2402
+ ],
2403
+ "description": "The commit's provenance level, judged by the signers at base as records judges a record (#2547)."
2404
+ },
2405
+ "reason": {
2406
+ "type": "string"
2407
+ },
2408
+ "principal": {
2409
+ "type": "string"
2410
+ }
2411
+ }
2412
+ }
2413
+ }
2414
+ },
2415
+ "description": "The original commits, oldest first: the head's commits the squash's parent doesn't have, merges left out."
2416
+ }
2417
+ }
2188
2418
  }
2189
2419
  }
2190
2420
  }