@intentius/chant 0.101.0 → 0.104.0

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 (739) hide show
  1. package/dist/agents/checks.d.ts.map +1 -1
  2. package/dist/attrref.d.ts.map +1 -1
  3. package/dist/audit/core.d.ts +2 -0
  4. package/dist/audit/core.d.ts.map +1 -1
  5. package/dist/audit/discover.d.ts.map +1 -1
  6. package/dist/audit/nginx.d.ts.map +1 -1
  7. package/dist/audit/prior-art.d.ts +48 -0
  8. package/dist/audit/prior-art.d.ts.map +1 -1
  9. package/dist/behaviour-kinds.d.ts.map +1 -1
  10. package/dist/builder.d.ts.map +1 -1
  11. package/dist/change-set.d.ts +232 -0
  12. package/dist/change-set.d.ts.map +1 -0
  13. package/dist/cli/commands/audit.d.ts +7 -0
  14. package/dist/cli/commands/audit.d.ts.map +1 -1
  15. package/dist/cli/commands/build.d.ts.map +1 -1
  16. package/dist/cli/commands/carve-emit.d.ts.map +1 -1
  17. package/dist/cli/commands/check-lexicon.d.ts +16 -0
  18. package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
  19. package/dist/cli/commands/import.d.ts +8 -0
  20. package/dist/cli/commands/import.d.ts.map +1 -1
  21. package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
  22. package/dist/cli/commands/init.d.ts +19 -0
  23. package/dist/cli/commands/init.d.ts.map +1 -1
  24. package/dist/cli/commands/onboard.d.ts +9 -0
  25. package/dist/cli/commands/onboard.d.ts.map +1 -1
  26. package/dist/cli/commands/pinned-upgrade.d.ts +19 -5
  27. package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -1
  28. package/dist/cli/handlers/build.d.ts.map +1 -1
  29. package/dist/cli/handlers/change-set.d.ts +11 -0
  30. package/dist/cli/handlers/change-set.d.ts.map +1 -0
  31. package/dist/cli/handlers/dev.d.ts.map +1 -1
  32. package/dist/cli/handlers/fan-out.d.ts +33 -0
  33. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  34. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  35. package/dist/cli/handlers/misc.d.ts.map +1 -1
  36. package/dist/cli/handlers/operator.d.ts +16 -0
  37. package/dist/cli/handlers/operator.d.ts.map +1 -1
  38. package/dist/cli/handlers/pr.d.ts +31 -0
  39. package/dist/cli/handlers/pr.d.ts.map +1 -0
  40. package/dist/cli/handlers/run.d.ts.map +1 -1
  41. package/dist/cli/lsp/server.d.ts.map +1 -1
  42. package/dist/cli/main.d.ts.map +1 -1
  43. package/dist/cli/mcp/op-tools.d.ts.map +1 -1
  44. package/dist/cli/mcp/server.d.ts.map +1 -1
  45. package/dist/cli/mcp/tools/build.d.ts.map +1 -1
  46. package/dist/cli/mcp/tools/composites.d.ts.map +1 -1
  47. package/dist/cli/mcp/tools/explain.d.ts.map +1 -1
  48. package/dist/cli/mcp/tools/import.d.ts.map +1 -1
  49. package/dist/cli/mcp/tools/lint.d.ts.map +1 -1
  50. package/dist/cli/mcp/tools/scaffold.d.ts.map +1 -1
  51. package/dist/cli/mcp/tools/search.d.ts.map +1 -1
  52. package/dist/cli/mcp/workspace-tools.d.ts +4 -3
  53. package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
  54. package/dist/cli/registry.d.ts +74 -3
  55. package/dist/cli/registry.d.ts.map +1 -1
  56. package/dist/codegen/fetch.d.ts.map +1 -1
  57. package/dist/codegen/naming.d.ts.map +1 -1
  58. package/dist/codegen/pinned-upgrade.d.ts +67 -3
  59. package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
  60. package/dist/codegen/registry.d.ts.map +1 -1
  61. package/dist/components/auto-release.d.ts +16 -0
  62. package/dist/components/auto-release.d.ts.map +1 -1
  63. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  64. package/dist/components/capability.d.ts +53 -0
  65. package/dist/components/capability.d.ts.map +1 -1
  66. package/dist/components/changed-files.d.ts +31 -0
  67. package/dist/components/changed-files.d.ts.map +1 -0
  68. package/dist/components/cli-support.d.ts +9 -1
  69. package/dist/components/cli-support.d.ts.map +1 -1
  70. package/dist/components/component.d.ts +24 -0
  71. package/dist/components/component.d.ts.map +1 -1
  72. package/dist/components/deploy-units.d.ts.map +1 -1
  73. package/dist/components/driver.d.ts +13 -0
  74. package/dist/components/driver.d.ts.map +1 -1
  75. package/dist/components/fan-out-output.d.ts +6 -0
  76. package/dist/components/fan-out-output.d.ts.map +1 -1
  77. package/dist/components/fan-out-record.d.ts +41 -0
  78. package/dist/components/fan-out-record.d.ts.map +1 -0
  79. package/dist/components/fan-out-run.d.ts +65 -0
  80. package/dist/components/fan-out-run.d.ts.map +1 -1
  81. package/dist/components/fan-out-support.d.ts +2 -0
  82. package/dist/components/fan-out-support.d.ts.map +1 -1
  83. package/dist/components/fan-out.d.ts +6 -0
  84. package/dist/components/fan-out.d.ts.map +1 -1
  85. package/dist/components/gated-wave-pipeline.d.ts +50 -0
  86. package/dist/components/gated-wave-pipeline.d.ts.map +1 -0
  87. package/dist/components/index.d.ts +1 -1
  88. package/dist/components/index.d.ts.map +1 -1
  89. package/dist/components/layers.d.ts +25 -0
  90. package/dist/components/layers.d.ts.map +1 -0
  91. package/dist/components/pr-pipeline.d.ts +61 -0
  92. package/dist/components/pr-pipeline.d.ts.map +1 -0
  93. package/dist/components/pr-run.d.ts +119 -0
  94. package/dist/components/pr-run.d.ts.map +1 -0
  95. package/dist/components/promote.d.ts.map +1 -1
  96. package/dist/components/starter-plugin.d.ts.map +1 -1
  97. package/dist/components/verbs/process-runner.d.ts.map +1 -1
  98. package/dist/components/verbs/r2-sync.d.ts.map +1 -1
  99. package/dist/components/verbs/run-agent.d.ts.map +1 -1
  100. package/dist/components/verbs/sbom-generator.d.ts.map +1 -1
  101. package/dist/components/verbs/shell.d.ts.map +1 -1
  102. package/dist/components/verbs/sign.d.ts.map +1 -1
  103. package/dist/components/verbs/verify.d.ts.map +1 -1
  104. package/dist/components/verbs/vuln-gate.d.ts.map +1 -1
  105. package/dist/components/verbs/vuln-scan.d.ts.map +1 -1
  106. package/dist/components/verbs/wrangler.d.ts.map +1 -1
  107. package/dist/components/wave-plan.d.ts +49 -0
  108. package/dist/components/wave-plan.d.ts.map +1 -0
  109. package/dist/composite.d.ts.map +1 -1
  110. package/dist/config.d.ts +19 -7
  111. package/dist/config.d.ts.map +1 -1
  112. package/dist/declarable.d.ts +16 -0
  113. package/dist/declarable.d.ts.map +1 -1
  114. package/dist/discovery/cache.d.ts.map +1 -1
  115. package/dist/discovery/fold-import.d.ts +15 -5
  116. package/dist/discovery/fold-import.d.ts.map +1 -1
  117. package/dist/discovery/param-deps.d.ts +16 -0
  118. package/dist/discovery/param-deps.d.ts.map +1 -1
  119. package/dist/discovery/sandbox/policy-wire.d.ts.map +1 -1
  120. package/dist/discovery/specifier-resolve.d.ts +37 -0
  121. package/dist/discovery/specifier-resolve.d.ts.map +1 -0
  122. package/dist/errors.d.ts.map +1 -1
  123. package/dist/fold/fold.d.ts +3 -1
  124. package/dist/fold/fold.d.ts.map +1 -1
  125. package/dist/gated-waves.d.ts +147 -0
  126. package/dist/gated-waves.d.ts.map +1 -0
  127. package/dist/graph-detail.d.ts.map +1 -1
  128. package/dist/graph-ir.d.ts.map +1 -1
  129. package/dist/graph-layout.d.ts.map +1 -1
  130. package/dist/import/base-parser.d.ts.map +1 -1
  131. package/dist/import/embedded.d.ts +7 -0
  132. package/dist/import/embedded.d.ts.map +1 -1
  133. package/dist/import/parser-options.d.ts +14 -0
  134. package/dist/import/parser-options.d.ts.map +1 -0
  135. package/dist/import/parser.d.ts +17 -0
  136. package/dist/import/parser.d.ts.map +1 -1
  137. package/dist/index.d.ts +1 -0
  138. package/dist/index.d.ts.map +1 -1
  139. package/dist/kubectl-context.d.ts.map +1 -1
  140. package/dist/lexicon-output.d.ts.map +1 -1
  141. package/dist/lexicon-schema.d.ts +3 -3
  142. package/dist/lexicon.d.ts +103 -3
  143. package/dist/lexicon.d.ts.map +1 -1
  144. package/dist/lifecycle/assert-live.d.ts.map +1 -1
  145. package/dist/lifecycle/gate-ledger.d.ts +22 -0
  146. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  147. package/dist/lifecycle/git.d.ts +46 -1
  148. package/dist/lifecycle/git.d.ts.map +1 -1
  149. package/dist/lifecycle/member-ledger.d.ts.map +1 -1
  150. package/dist/lifecycle/observe.d.ts.map +1 -1
  151. package/dist/lifecycle/plan-ledger.d.ts.map +1 -1
  152. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  153. package/dist/lifecycle/scenario.d.ts.map +1 -1
  154. package/dist/lifecycle/status.d.ts.map +1 -1
  155. package/dist/lifecycle/work-lease.d.ts +61 -2
  156. package/dist/lifecycle/work-lease.d.ts.map +1 -1
  157. package/dist/lint/config.d.ts +8 -8
  158. package/dist/lint/engine.d.ts +6 -0
  159. package/dist/lint/engine.d.ts.map +1 -1
  160. package/dist/lint/post-synth.d.ts +18 -0
  161. package/dist/lint/post-synth.d.ts.map +1 -1
  162. package/dist/lsp/lexicon-providers.d.ts.map +1 -1
  163. package/dist/op/activities/activity-contracts.d.ts +137 -11
  164. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  165. package/dist/op/activities/apply.d.ts +79 -9
  166. package/dist/op/activities/apply.d.ts.map +1 -1
  167. package/dist/op/activities/change-set.d.ts +62 -0
  168. package/dist/op/activities/change-set.d.ts.map +1 -0
  169. package/dist/op/activities/decide.d.ts +2 -0
  170. package/dist/op/activities/decide.d.ts.map +1 -1
  171. package/dist/op/activities/factory.d.ts +137 -0
  172. package/dist/op/activities/factory.d.ts.map +1 -0
  173. package/dist/op/activities/index.d.ts +5 -1
  174. package/dist/op/activities/index.d.ts.map +1 -1
  175. package/dist/op/activities/lexicon-upgrade.d.ts +44 -12
  176. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -1
  177. package/dist/op/activity-contract.d.ts +1 -1
  178. package/dist/op/activity-contract.d.ts.map +1 -1
  179. package/dist/op/activity-failure.d.ts.map +1 -1
  180. package/dist/op/activity-profiles.d.ts.map +1 -1
  181. package/dist/op/builders.d.ts +11 -0
  182. package/dist/op/builders.d.ts.map +1 -1
  183. package/dist/op/composites/apply-op.d.ts +12 -5
  184. package/dist/op/composites/apply-op.d.ts.map +1 -1
  185. package/dist/op/composites/lexicon-upgrade-op.d.ts +22 -6
  186. package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -1
  187. package/dist/op/decide-backend.d.ts +5 -1
  188. package/dist/op/decide-backend.d.ts.map +1 -1
  189. package/dist/op/decide-read-inputs.d.ts +4 -2
  190. package/dist/op/decide-read-inputs.d.ts.map +1 -1
  191. package/dist/op/emulator-lifecycle.d.ts +21 -2
  192. package/dist/op/emulator-lifecycle.d.ts.map +1 -1
  193. package/dist/op/factory.d.ts +83 -0
  194. package/dist/op/factory.d.ts.map +1 -0
  195. package/dist/op/gate-approval.d.ts +5 -1
  196. package/dist/op/gate-approval.d.ts.map +1 -1
  197. package/dist/op/gate-wait.d.ts.map +1 -1
  198. package/dist/op/gate.d.ts +19 -3
  199. package/dist/op/gate.d.ts.map +1 -1
  200. package/dist/op/index.d.ts +6 -1
  201. package/dist/op/index.d.ts.map +1 -1
  202. package/dist/op/local-executor.d.ts +6 -0
  203. package/dist/op/local-executor.d.ts.map +1 -1
  204. package/dist/op/op-ir.d.ts +2 -0
  205. package/dist/op/op-ir.d.ts.map +1 -1
  206. package/dist/op/op-verb-class.d.ts.map +1 -1
  207. package/dist/op/operator.d.ts.map +1 -1
  208. package/dist/op/run-context.d.ts +39 -0
  209. package/dist/op/run-context.d.ts.map +1 -0
  210. package/dist/op/run-live.d.ts.map +1 -1
  211. package/dist/op/runtimes/local.d.ts.map +1 -1
  212. package/dist/op/source-archive.d.ts.map +1 -1
  213. package/dist/op/steward-beside.d.ts.map +1 -1
  214. package/dist/op/steward-points.d.ts.map +1 -1
  215. package/dist/op/steward.d.ts.map +1 -1
  216. package/dist/op/types.d.ts +16 -3
  217. package/dist/op/types.d.ts.map +1 -1
  218. package/dist/op/work-lease-run.d.ts +24 -4
  219. package/dist/op/work-lease-run.d.ts.map +1 -1
  220. package/dist/plan-summary.d.ts +207 -0
  221. package/dist/plan-summary.d.ts.map +1 -0
  222. package/dist/pr-forge.d.ts +105 -0
  223. package/dist/pr-forge.d.ts.map +1 -0
  224. package/dist/pr-loop.d.ts +178 -0
  225. package/dist/pr-loop.d.ts.map +1 -0
  226. package/dist/project-root.d.ts.map +1 -1
  227. package/dist/provenance.d.ts +21 -0
  228. package/dist/provenance.d.ts.map +1 -1
  229. package/dist/pseudo-parameter.d.ts.map +1 -1
  230. package/dist/reconcile.d.ts.map +1 -1
  231. package/dist/secret-materialization.d.ts.map +1 -1
  232. package/dist/telemetry-attribution.d.ts +31 -0
  233. package/dist/telemetry-attribution.d.ts.map +1 -1
  234. package/dist/terraform/emit-source.d.ts.map +1 -1
  235. package/dist/terraform/hcl2json.d.ts +45 -0
  236. package/dist/terraform/hcl2json.d.ts.map +1 -0
  237. package/dist/terraform/parse.d.ts +4 -40
  238. package/dist/terraform/parse.d.ts.map +1 -1
  239. package/dist/testing.d.ts.map +1 -1
  240. package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
  241. package/dist/workspace/__fixtures__/decide-workspace.d.ts +1 -1
  242. package/dist/workspace/__fixtures__/decide-workspace.d.ts.map +1 -1
  243. package/dist/workspace/agent-cli.d.ts +5 -0
  244. package/dist/workspace/agent-cli.d.ts.map +1 -1
  245. package/dist/workspace/box-cli.d.ts +12 -0
  246. package/dist/workspace/box-cli.d.ts.map +1 -0
  247. package/dist/workspace/box-factory.d.ts +97 -0
  248. package/dist/workspace/box-factory.d.ts.map +1 -0
  249. package/dist/workspace/box-listing.d.ts +85 -0
  250. package/dist/workspace/box-listing.d.ts.map +1 -0
  251. package/dist/workspace/box-publish.d.ts +147 -0
  252. package/dist/workspace/box-publish.d.ts.map +1 -0
  253. package/dist/workspace/broker-protocol.d.ts +190 -0
  254. package/dist/workspace/broker-protocol.d.ts.map +1 -0
  255. package/dist/workspace/changes.d.ts.map +1 -1
  256. package/dist/workspace/chant-migrations/chud-lexicon-exit.d.ts.map +1 -1
  257. package/dist/workspace/checks/boxes.d.ts.map +1 -1
  258. package/dist/workspace/checks.d.ts +5 -0
  259. package/dist/workspace/checks.d.ts.map +1 -1
  260. package/dist/workspace/compose-graph.d.ts +10 -0
  261. package/dist/workspace/compose-graph.d.ts.map +1 -1
  262. package/dist/workspace/composites.d.ts +2 -2
  263. package/dist/workspace/composites.d.ts.map +1 -1
  264. package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts +17 -0
  265. package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts.map +1 -0
  266. package/dist/workspace/conformance/broker.d.ts +202 -0
  267. package/dist/workspace/conformance/broker.d.ts.map +1 -0
  268. package/dist/workspace/conformance/index.d.ts +68 -6
  269. package/dist/workspace/conformance/index.d.ts.map +1 -1
  270. package/dist/workspace/conformance/vitest.d.ts +19 -3
  271. package/dist/workspace/conformance/vitest.d.ts.map +1 -1
  272. package/dist/workspace/conformance/writer.d.ts +462 -0
  273. package/dist/workspace/conformance/writer.d.ts.map +1 -0
  274. package/dist/workspace/decide.d.ts +126 -12
  275. package/dist/workspace/decide.d.ts.map +1 -1
  276. package/dist/workspace/decision-points.schema.json +11 -4
  277. package/dist/workspace/declaration.d.ts +156 -4
  278. package/dist/workspace/declaration.d.ts.map +1 -1
  279. package/dist/workspace/declaration.schema.json +383 -5
  280. package/dist/workspace/environments.d.ts +36 -10
  281. package/dist/workspace/environments.d.ts.map +1 -1
  282. package/dist/workspace/factory-rules.d.ts +180 -0
  283. package/dist/workspace/factory-rules.d.ts.map +1 -0
  284. package/dist/workspace/generated-files.d.ts.map +1 -1
  285. package/dist/workspace/graph-cache.d.ts.map +1 -1
  286. package/dist/workspace/graph-cli.d.ts +2 -0
  287. package/dist/workspace/graph-cli.d.ts.map +1 -1
  288. package/dist/workspace/identity.d.ts +111 -0
  289. package/dist/workspace/identity.d.ts.map +1 -0
  290. package/dist/workspace/init.d.ts +21 -0
  291. package/dist/workspace/init.d.ts.map +1 -1
  292. package/dist/workspace/intent-cli.d.ts +7 -4
  293. package/dist/workspace/intent-cli.d.ts.map +1 -1
  294. package/dist/workspace/intent-record.d.ts +36 -2
  295. package/dist/workspace/intent-record.d.ts.map +1 -1
  296. package/dist/workspace/intent.d.ts +249 -8
  297. package/dist/workspace/intent.d.ts.map +1 -1
  298. package/dist/workspace/json-edit.d.ts +24 -0
  299. package/dist/workspace/json-edit.d.ts.map +1 -0
  300. package/dist/workspace/jsonc.d.ts +11 -0
  301. package/dist/workspace/jsonc.d.ts.map +1 -1
  302. package/dist/workspace/kinds.d.ts +66 -4
  303. package/dist/workspace/kinds.d.ts.map +1 -1
  304. package/dist/workspace/lexicon-symbols.d.ts +29 -0
  305. package/dist/workspace/lexicon-symbols.d.ts.map +1 -0
  306. package/dist/workspace/lineage-hash-index.d.ts.map +1 -1
  307. package/dist/workspace/lineage-lock.d.ts +2 -2
  308. package/dist/workspace/lineage-lock.d.ts.map +1 -1
  309. package/dist/workspace/lineage-upgrade.d.ts +31 -2
  310. package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
  311. package/dist/workspace/links.d.ts.map +1 -1
  312. package/dist/workspace/point-answer.schema.json +42 -2
  313. package/dist/workspace/points-cli.d.ts +10 -3
  314. package/dist/workspace/points-cli.d.ts.map +1 -1
  315. package/dist/workspace/points.d.ts +66 -5
  316. package/dist/workspace/points.d.ts.map +1 -1
  317. package/dist/workspace/principal-classes.d.ts +114 -0
  318. package/dist/workspace/principal-classes.d.ts.map +1 -0
  319. package/dist/workspace/reason-codes.d.ts +53 -4
  320. package/dist/workspace/reason-codes.d.ts.map +1 -1
  321. package/dist/workspace/record-assets.d.ts.map +1 -1
  322. package/dist/workspace/record-sessions.d.ts +5 -7
  323. package/dist/workspace/record-sessions.d.ts.map +1 -1
  324. package/dist/workspace/records-checkout.d.ts +54 -0
  325. package/dist/workspace/records-checkout.d.ts.map +1 -0
  326. package/dist/workspace/records-cli.d.ts +34 -1
  327. package/dist/workspace/records-cli.d.ts.map +1 -1
  328. package/dist/workspace/records-close.d.ts +7 -3
  329. package/dist/workspace/records-close.d.ts.map +1 -1
  330. package/dist/workspace/records-since.d.ts.map +1 -1
  331. package/dist/workspace/records-write.d.ts +68 -7
  332. package/dist/workspace/records-write.d.ts.map +1 -1
  333. package/dist/workspace/records.d.ts +43 -9
  334. package/dist/workspace/records.d.ts.map +1 -1
  335. package/dist/workspace/runs-cli.d.ts +296 -0
  336. package/dist/workspace/runs-cli.d.ts.map +1 -0
  337. package/dist/workspace/runs.d.ts +544 -0
  338. package/dist/workspace/runs.d.ts.map +1 -0
  339. package/dist/workspace/session-kinds.d.ts +1 -1
  340. package/dist/workspace/session-kinds.d.ts.map +1 -1
  341. package/dist/workspace/source-block.d.ts +1 -1
  342. package/dist/workspace/source-block.d.ts.map +1 -1
  343. package/dist/workspace/squash.d.ts +80 -0
  344. package/dist/workspace/squash.d.ts.map +1 -0
  345. package/dist/workspace/status-gates.d.ts +17 -3
  346. package/dist/workspace/status-gates.d.ts.map +1 -1
  347. package/dist/workspace/status.d.ts +64 -0
  348. package/dist/workspace/status.d.ts.map +1 -1
  349. package/dist/workspace/symbols.d.ts +63 -0
  350. package/dist/workspace/symbols.d.ts.map +1 -0
  351. package/dist/workspace/trailer-joins.d.ts +46 -0
  352. package/dist/workspace/trailer-joins.d.ts.map +1 -0
  353. package/dist/workspace/trailers.d.ts +89 -0
  354. package/dist/workspace/trailers.d.ts.map +1 -0
  355. package/dist/workspace/trust/attestor.d.ts.map +1 -1
  356. package/dist/workspace/trust/rotation.d.ts.map +1 -1
  357. package/dist/workspace/trust/run-commits.d.ts +46 -0
  358. package/dist/workspace/trust/run-commits.d.ts.map +1 -0
  359. package/dist/workspace/trust/run-statement.d.ts +128 -0
  360. package/dist/workspace/trust/run-statement.d.ts.map +1 -0
  361. package/dist/workspace/trust/seal.d.ts +38 -0
  362. package/dist/workspace/trust/seal.d.ts.map +1 -1
  363. package/dist/workspace/trust/test-repo.d.ts.map +1 -1
  364. package/dist/workspace/trust/verify-cli.d.ts +1 -1
  365. package/dist/workspace/trust/verify.d.ts +16 -2
  366. package/dist/workspace/trust/verify.d.ts.map +1 -1
  367. package/dist/workspace/wip-cli.d.ts +21 -0
  368. package/dist/workspace/wip-cli.d.ts.map +1 -0
  369. package/dist/workspace/wip.d.ts +268 -0
  370. package/dist/workspace/wip.d.ts.map +1 -0
  371. package/dist/workspace/work-cli.d.ts +39 -3
  372. package/dist/workspace/work-cli.d.ts.map +1 -1
  373. package/dist/workspace/work-evidence.d.ts +1 -1
  374. package/dist/workspace/work-evidence.d.ts.map +1 -1
  375. package/dist/workspace/work-size.d.ts +55 -0
  376. package/dist/workspace/work-size.d.ts.map +1 -0
  377. package/dist/workspace/work.d.ts +26 -1
  378. package/dist/workspace/work.d.ts.map +1 -1
  379. package/dist/workspace/workspace-kinds.schema.json +122 -0
  380. package/dist/workspace/workspace-principals.schema.json +60 -0
  381. package/dist/workspace/write-lock-cli.d.ts +60 -0
  382. package/dist/workspace/write-lock-cli.d.ts.map +1 -0
  383. package/dist/workspace/write-lock.d.ts +152 -0
  384. package/dist/workspace/write-lock.d.ts.map +1 -0
  385. package/dist/workspace/write-scope.d.ts +83 -19
  386. package/dist/workspace/write-scope.d.ts.map +1 -1
  387. package/dist/yaml.d.ts +21 -39
  388. package/dist/yaml.d.ts.map +1 -1
  389. package/package.json +7 -2
  390. package/src/__fixtures__/change-set/lifecycle-plan.floci.json +59 -0
  391. package/src/__fixtures__/change-set/lifecycle-v1.ts.txt +4 -0
  392. package/src/__fixtures__/change-set/lifecycle-v2.ts.txt +4 -0
  393. package/src/__fixtures__/change-set/lifecycle.change-set.golden.json +95 -0
  394. package/src/__fixtures__/change-set/warden.change-set.golden.json +106 -0
  395. package/src/__fixtures__/change-set/warden.plan.json +44 -0
  396. package/src/__fixtures__/plan-summary/normalization-vectors.json +1593 -0
  397. package/src/__fixtures__/pr-loop/pr-apply-applied.note.golden.md +31 -0
  398. package/src/__fixtures__/pr-loop/pr-apply-refused.note.golden.md +31 -0
  399. package/src/__fixtures__/pr-loop/pr-plan.golden.json +127 -0
  400. package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +37 -0
  401. package/src/audit/core.test.ts +15 -0
  402. package/src/audit/core.ts +8 -2
  403. package/src/audit/discover.test.ts +11 -0
  404. package/src/audit/discover.ts +7 -2
  405. package/src/audit/prior-art.ts +15 -0
  406. package/src/change-set-bundle.test.ts +57 -0
  407. package/src/change-set.test.ts +215 -0
  408. package/src/change-set.ts +445 -0
  409. package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +1 -1
  410. package/src/cli/commands/audit-opt-in.test.ts +54 -0
  411. package/src/cli/commands/audit.ts +29 -2
  412. package/src/cli/commands/build.test.ts +19 -0
  413. package/src/cli/commands/build.ts +3 -2
  414. package/src/cli/commands/carve-emit-state.test.ts +4 -0
  415. package/src/cli/commands/carve-emit.ts +5 -19
  416. package/src/cli/commands/check-lexicon.test.ts +62 -1
  417. package/src/cli/commands/check-lexicon.ts +36 -6
  418. package/src/cli/commands/import-live.test.ts +18 -0
  419. package/src/cli/commands/import-parser-options.test.ts +133 -0
  420. package/src/cli/commands/import.ts +21 -3
  421. package/src/cli/commands/init-lexicon/templates/project.ts +1 -1
  422. package/src/cli/commands/init.test.ts +8 -1
  423. package/src/cli/commands/init.ts +23 -8
  424. package/src/cli/commands/lint.test.ts +37 -0
  425. package/src/cli/commands/onboard.test.ts +53 -3
  426. package/src/cli/commands/onboard.ts +52 -4
  427. package/src/cli/commands/pinned-upgrade.ts +73 -33
  428. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +2 -2
  429. package/src/cli/handlers/build.ts +13 -1
  430. package/src/cli/handlers/change-set.test.ts +56 -0
  431. package/src/cli/handlers/change-set.ts +44 -0
  432. package/src/cli/handlers/components.ts +2 -2
  433. package/src/cli/handlers/dev.ts +8 -6
  434. package/src/cli/handlers/fan-out.test.ts +221 -2
  435. package/src/cli/handlers/fan-out.ts +165 -75
  436. package/src/cli/handlers/graph.ts +3 -0
  437. package/src/cli/handlers/lifecycle.test.ts +67 -0
  438. package/src/cli/handlers/lifecycle.ts +6 -5
  439. package/src/cli/handlers/misc.ts +2 -0
  440. package/src/cli/handlers/operator.test.ts +21 -0
  441. package/src/cli/handlers/operator.ts +121 -6
  442. package/src/cli/handlers/pr.ts +373 -0
  443. package/src/cli/handlers/run.test.ts +111 -0
  444. package/src/cli/handlers/run.ts +86 -24
  445. package/src/cli/handlers/scenario.ts +2 -2
  446. package/src/cli/main.test.ts +21 -0
  447. package/src/cli/main.ts +246 -30
  448. package/src/cli/mcp/never-over-mcp.test.ts +101 -0
  449. package/src/cli/mcp/op-tools.ts +24 -2
  450. package/src/cli/mcp/workspace-tools.test.ts +5 -2
  451. package/src/cli/mcp/workspace-tools.ts +62 -7
  452. package/src/cli/registry.ts +74 -3
  453. package/src/codegen/pinned-upgrade-multi.test.ts +157 -0
  454. package/src/codegen/pinned-upgrade-tags.test.ts +112 -0
  455. package/src/codegen/pinned-upgrade.test.ts +104 -0
  456. package/src/codegen/pinned-upgrade.ts +250 -56
  457. package/src/codegen/testdata/postgres-tags.json +242 -0
  458. package/src/components/auto-release.ts +1 -1
  459. package/src/components/capability.ts +55 -0
  460. package/src/components/changed-files.ts +66 -0
  461. package/src/components/cli-support.ts +28 -5
  462. package/src/components/component.schema.json +17 -0
  463. package/src/components/component.ts +25 -0
  464. package/src/components/deploy-units.ts +3 -0
  465. package/src/components/driver.test.ts +52 -0
  466. package/src/components/driver.ts +31 -13
  467. package/src/components/fan-out-output.ts +42 -1
  468. package/src/components/fan-out-record.ts +69 -0
  469. package/src/components/fan-out-run.test.ts +17 -0
  470. package/src/components/fan-out-run.ts +304 -1
  471. package/src/components/fan-out-support.ts +3 -0
  472. package/src/components/fan-out-waves.test.ts +375 -0
  473. package/src/components/fan-out.ts +18 -17
  474. package/src/components/gated-wave-pipeline.ts +82 -0
  475. package/src/components/index.ts +1 -0
  476. package/src/components/layers.ts +30 -0
  477. package/src/components/pr-pipeline.ts +91 -0
  478. package/src/components/pr-run.test.ts +205 -0
  479. package/src/components/pr-run.ts +280 -0
  480. package/src/components/promote.ts +5 -0
  481. package/src/components/verbs/shell.test.ts +11 -0
  482. package/src/components/verbs/shell.ts +7 -3
  483. package/src/components/wave-plan.ts +124 -0
  484. package/src/config.test.ts +21 -0
  485. package/src/config.ts +15 -0
  486. package/src/declarable.test.ts +21 -0
  487. package/src/declarable.ts +19 -0
  488. package/src/discovery/fold-composite.test.ts +41 -5
  489. package/src/discovery/fold-import.test.ts +129 -0
  490. package/src/discovery/fold-import.ts +643 -131
  491. package/src/discovery/fold-package-composite.test.ts +264 -0
  492. package/src/discovery/fold-specifiers.test.ts +191 -0
  493. package/src/discovery/param-deps.test.ts +66 -1
  494. package/src/discovery/param-deps.ts +45 -0
  495. package/src/discovery/sandbox/bundle.ts +1 -1
  496. package/src/discovery/specifier-resolve.ts +344 -0
  497. package/src/fold/fold.test.ts +39 -1
  498. package/src/fold/fold.ts +83 -9
  499. package/src/fold-provenance.test.ts +140 -0
  500. package/src/gated-waves-bundle.test.ts +62 -0
  501. package/src/gated-waves.test.ts +118 -0
  502. package/src/gated-waves.ts +240 -0
  503. package/src/graph-ir.test.ts +83 -0
  504. package/src/graph-ir.ts +29 -0
  505. package/src/import/embedded.test.ts +20 -0
  506. package/src/import/embedded.ts +13 -0
  507. package/src/import/parser-options.ts +46 -0
  508. package/src/import/parser.ts +20 -0
  509. package/src/index.ts +1 -0
  510. package/src/lexicon.ts +106 -3
  511. package/src/lifecycle/gate-ledger.ts +23 -0
  512. package/src/lifecycle/git.ts +102 -16
  513. package/src/lifecycle/observe.test.ts +18 -0
  514. package/src/lifecycle/observe.ts +6 -4
  515. package/src/lifecycle/snapshot.ts +2 -2
  516. package/src/lifecycle/work-lease.test.ts +1 -1
  517. package/src/lifecycle/work-lease.ts +93 -2
  518. package/src/lint/engine.test.ts +55 -0
  519. package/src/lint/engine.ts +30 -4
  520. package/src/lint/output-docs.test.ts +59 -56
  521. package/src/lint/post-synth.test.ts +19 -0
  522. package/src/lint/post-synth.ts +19 -1
  523. package/src/meta/declared-imports.test.ts +1 -1
  524. package/src/op/activities/activity-contracts.ts +84 -0
  525. package/src/op/activities/apply.test.ts +189 -5
  526. package/src/op/activities/apply.ts +230 -8
  527. package/src/op/activities/change-set.ts +114 -0
  528. package/src/op/activities/decide.ts +3 -0
  529. package/src/op/activities/factory.ts +675 -0
  530. package/src/op/activities/index.ts +9 -0
  531. package/src/op/activities/lexicon-upgrade.test.ts +160 -6
  532. package/src/op/activities/lexicon-upgrade.ts +154 -51
  533. package/src/op/activity-contract.test.ts +21 -1
  534. package/src/op/activity-contract.ts +19 -9
  535. package/src/op/builders.ts +23 -0
  536. package/src/op/composites/apply-op.ts +12 -5
  537. package/src/op/composites/composites.test.ts +30 -3
  538. package/src/op/composites/lexicon-upgrade-op.test.ts +7 -2
  539. package/src/op/composites/lexicon-upgrade-op.ts +29 -8
  540. package/src/op/decide-backend.ts +5 -1
  541. package/src/op/decide-read-inputs.ts +33 -5
  542. package/src/op/emulator-lifecycle.test.ts +23 -0
  543. package/src/op/emulator-lifecycle.ts +52 -14
  544. package/src/op/factory.e2e.test.ts +232 -0
  545. package/src/op/factory.ts +118 -0
  546. package/src/op/gate-approval.test.ts +74 -0
  547. package/src/op/gate-approval.ts +5 -1
  548. package/src/op/gate.ts +31 -5
  549. package/src/op/index.ts +11 -1
  550. package/src/op/local-executor.test.ts +15 -0
  551. package/src/op/local-executor.ts +40 -12
  552. package/src/op/local-output.ts +1 -1
  553. package/src/op/op-ir.test.ts +9 -0
  554. package/src/op/op-ir.ts +4 -0
  555. package/src/op/op-verb-class.ts +3 -0
  556. package/src/op/operator.ts +4 -0
  557. package/src/op/run-context.test.ts +141 -0
  558. package/src/op/run-context.ts +51 -0
  559. package/src/op/runtimes/local.test.ts +14 -0
  560. package/src/op/runtimes/local.ts +2 -0
  561. package/src/op/steward-beside.ts +2 -0
  562. package/src/op/types.ts +16 -3
  563. package/src/op/work-lease-run.test.ts +47 -0
  564. package/src/op/work-lease-run.ts +76 -11
  565. package/src/plan-summary.test.ts +263 -0
  566. package/src/plan-summary.ts +845 -0
  567. package/src/pr-forge.test.ts +237 -0
  568. package/src/pr-forge.ts +332 -0
  569. package/src/pr-loop-bundle.test.ts +46 -0
  570. package/src/pr-loop.test.ts +171 -0
  571. package/src/pr-loop.ts +324 -0
  572. package/src/provenance.ts +35 -0
  573. package/src/telemetry-attribution.test.ts +23 -1
  574. package/src/telemetry-attribution.ts +51 -0
  575. package/src/terraform/hcl2json.test.ts +21 -0
  576. package/src/terraform/hcl2json.ts +81 -0
  577. package/src/terraform/parse.ts +11 -74
  578. package/src/workspace/agent-cli.ts +7 -3
  579. package/src/workspace/agent.schema.json +22 -0
  580. package/src/workspace/app-kind.test.ts +196 -0
  581. package/src/workspace/box-cli.ts +113 -0
  582. package/src/workspace/box-factory.test.ts +323 -0
  583. package/src/workspace/box-factory.ts +136 -0
  584. package/src/workspace/box-listing-write.schema.json +204 -0
  585. package/src/workspace/box-listing.test.ts +234 -0
  586. package/src/workspace/box-listing.ts +324 -0
  587. package/src/workspace/box-publish.schema.json +498 -0
  588. package/src/workspace/box-publish.test.ts +204 -0
  589. package/src/workspace/box-publish.ts +420 -0
  590. package/src/workspace/box-ship.test.ts +96 -0
  591. package/src/workspace/broker-protocol.schema.json +186 -0
  592. package/src/workspace/broker-protocol.test.ts +122 -0
  593. package/src/workspace/broker-protocol.ts +317 -0
  594. package/src/workspace/builder-tiers.test.ts +146 -0
  595. package/src/workspace/change-set.schema.json +460 -0
  596. package/src/workspace/changes.schema.json +12 -20
  597. package/src/workspace/changes.ts +4 -1
  598. package/src/workspace/chant-migrations.e2e.test.ts +17 -5
  599. package/src/workspace/checks/boxes.test.ts +5 -0
  600. package/src/workspace/checks.ts +39 -8
  601. package/src/workspace/component-environments.test.ts +105 -0
  602. package/src/workspace/compose-graph.ts +7 -0
  603. package/src/workspace/composites.schema.json +23 -4
  604. package/src/workspace/composites.test.ts +8 -8
  605. package/src/workspace/composites.ts +13 -2
  606. package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +2 -2
  607. package/src/workspace/conformance/__fixtures__/reference-broker.ts +207 -0
  608. package/src/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +32 -0
  609. package/src/workspace/conformance/__writer_fixture__/answers/answer.schema.json +135 -0
  610. package/src/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
  611. package/src/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
  612. package/src/workspace/conformance/__writer_fixture__/decisions/points.json +228 -0
  613. package/src/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
  614. package/src/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
  615. package/src/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +54 -0
  616. package/src/workspace/conformance/__writer_fixture__/sessions/session.schema.json +289 -0
  617. package/src/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
  618. package/src/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
  619. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +603 -0
  620. package/src/workspace/conformance/broker.test.ts +122 -0
  621. package/src/workspace/conformance/broker.ts +792 -0
  622. package/src/workspace/conformance/conformance.e2e.test.ts +36 -3
  623. package/src/workspace/conformance/index.mjs +51 -3
  624. package/src/workspace/conformance/index.ts +107 -15
  625. package/src/workspace/conformance/vitest.ts +76 -2
  626. package/src/workspace/conformance/writer-conformance.e2e.test.ts +177 -0
  627. package/src/workspace/conformance/writer.test.ts +186 -0
  628. package/src/workspace/conformance/writer.ts +1191 -0
  629. package/src/workspace/decide.test.ts +208 -4
  630. package/src/workspace/decide.ts +433 -73
  631. package/src/workspace/decision-points.schema.json +11 -4
  632. package/src/workspace/declaration.schema.json +383 -5
  633. package/src/workspace/declaration.ts +315 -10
  634. package/src/workspace/environments.ts +66 -14
  635. package/src/workspace/factory-rules.test.ts +62 -0
  636. package/src/workspace/factory-rules.ts +218 -0
  637. package/src/workspace/graph-cli.ts +6 -3
  638. package/src/workspace/graph.schema.json +314 -0
  639. package/src/workspace/identity.test.ts +219 -0
  640. package/src/workspace/identity.ts +186 -0
  641. package/src/workspace/init.ts +82 -2
  642. package/src/workspace/intent-cli.ts +84 -13
  643. package/src/workspace/intent-patch-id.test.ts +162 -0
  644. package/src/workspace/intent-record.schema.json +336 -1
  645. package/src/workspace/intent-record.ts +96 -16
  646. package/src/workspace/intent-reviews.test.ts +76 -0
  647. package/src/workspace/intent-squash.test.ts +213 -0
  648. package/src/workspace/intent-why.test.ts +274 -0
  649. package/src/workspace/intent.schema.json +950 -9
  650. package/src/workspace/intent.test.ts +11 -2
  651. package/src/workspace/intent.ts +722 -65
  652. package/src/workspace/json-edit.test.ts +121 -0
  653. package/src/workspace/json-edit.ts +142 -0
  654. package/src/workspace/jsonc.ts +20 -0
  655. package/src/workspace/kinds.ts +201 -39
  656. package/src/workspace/lexicon-symbols.test.ts +148 -0
  657. package/src/workspace/lexicon-symbols.ts +125 -0
  658. package/src/workspace/lineage-upgrade.test.ts +63 -0
  659. package/src/workspace/lineage-upgrade.ts +146 -5
  660. package/src/workspace/plan-summary.schema.json +155 -0
  661. package/src/workspace/point-answer.schema.json +42 -2
  662. package/src/workspace/points-cli.ts +42 -16
  663. package/src/workspace/points-write.schema.json +163 -4
  664. package/src/workspace/points.schema.json +157 -2
  665. package/src/workspace/points.test.ts +13 -1
  666. package/src/workspace/points.ts +118 -12
  667. package/src/workspace/pr-report.schema.json +95 -0
  668. package/src/workspace/principal-classes.test.ts +175 -0
  669. package/src/workspace/principal-classes.ts +307 -0
  670. package/src/workspace/profiles.test.ts +159 -0
  671. package/src/workspace/read-contract.test.ts +2 -2
  672. package/src/workspace/reason-codes.test.ts +23 -3
  673. package/src/workspace/reason-codes.ts +61 -4
  674. package/src/workspace/record-sessions.ts +9 -8
  675. package/src/workspace/records-amend.schema.json +80 -0
  676. package/src/workspace/records-checkout.ts +106 -0
  677. package/src/workspace/records-cli.ts +123 -17
  678. package/src/workspace/records-close.schema.json +79 -0
  679. package/src/workspace/records-close.ts +31 -7
  680. package/src/workspace/records-concurrent.e2e.test.ts +135 -0
  681. package/src/workspace/records-concurrent.test.ts +145 -0
  682. package/src/workspace/records-formats.test.ts +46 -10
  683. package/src/workspace/records-new.schema.json +9 -0
  684. package/src/workspace/records-review.schema.json +80 -0
  685. package/src/workspace/records-sessions-write.test.ts +69 -0
  686. package/src/workspace/records-sessions.test.ts +22 -0
  687. package/src/workspace/records-uncommitted.test.ts +171 -0
  688. package/src/workspace/records-write.ts +219 -30
  689. package/src/workspace/records.schema.json +88 -1
  690. package/src/workspace/records.ts +76 -8
  691. package/src/workspace/reference-kinds/app/package.json +10 -0
  692. package/src/workspace/reference-kinds/app/workspace-kinds.json +45 -0
  693. package/src/workspace/run-statement.schema.json +622 -0
  694. package/src/workspace/runs-cli.ts +710 -0
  695. package/src/workspace/runs-statement.test.ts +239 -0
  696. package/src/workspace/runs-write.schema.json +994 -0
  697. package/src/workspace/runs.schema.json +1257 -0
  698. package/src/workspace/runs.test.ts +281 -0
  699. package/src/workspace/runs.ts +970 -0
  700. package/src/workspace/session-kinds.ts +3 -3
  701. package/src/workspace/squash.ts +198 -0
  702. package/src/workspace/status-contract.test.ts +10 -2
  703. package/src/workspace/status-gates.ts +25 -9
  704. package/src/workspace/status.schema.json +252 -4
  705. package/src/workspace/status.ts +110 -1
  706. package/src/workspace/symbols.ts +191 -0
  707. package/src/workspace/trailer-joins.test.ts +171 -0
  708. package/src/workspace/trailer-joins.ts +82 -0
  709. package/src/workspace/trailers.ts +148 -0
  710. package/src/workspace/trust/run-commits.ts +115 -0
  711. package/src/workspace/trust/run-statement.ts +226 -0
  712. package/src/workspace/trust/seal.ts +58 -1
  713. package/src/workspace/trust/verify-cli.ts +6 -5
  714. package/src/workspace/trust/verify.ts +39 -6
  715. package/src/workspace/wip-cli.ts +97 -0
  716. package/src/workspace/wip-write.schema.json +504 -0
  717. package/src/workspace/wip.schema.json +334 -0
  718. package/src/workspace/wip.test.ts +294 -0
  719. package/src/workspace/wip.ts +753 -0
  720. package/src/workspace/work-cli.e2e.test.ts +28 -1
  721. package/src/workspace/work-cli.ts +136 -8
  722. package/src/workspace/work-evidence.schema.json +5 -0
  723. package/src/workspace/work-history.schema.json +73 -1
  724. package/src/workspace/work-history.test.ts +48 -5
  725. package/src/workspace/work-kind-fields.test.ts +154 -0
  726. package/src/workspace/work-lease.schema.json +14 -1
  727. package/src/workspace/work-size.test.ts +77 -0
  728. package/src/workspace/work-size.ts +93 -0
  729. package/src/workspace/work.ts +82 -0
  730. package/src/workspace/workspace-kinds.schema.json +122 -0
  731. package/src/workspace/workspace-principals.schema.json +60 -0
  732. package/src/workspace/write-lock-cli.ts +131 -0
  733. package/src/workspace/write-lock.schema.json +172 -0
  734. package/src/workspace/write-lock.test.ts +189 -0
  735. package/src/workspace/write-lock.ts +474 -0
  736. package/src/workspace/write-scope.test.ts +144 -3
  737. package/src/workspace/write-scope.ts +192 -45
  738. package/src/yaml.test.ts +111 -1
  739. package/src/yaml.ts +141 -549
@@ -0,0 +1,675 @@
1
+ /**
2
+ * The factory reference Op's activities (#3406, ws-087): the rules of
3
+ * `../../workspace/factory-rules.ts` run against a workspace, and the two
4
+ * places an orchestrator's execution plugs in, the builder and the check, run
5
+ * as commands in the run's worktree.
6
+ *
7
+ * factoryPick which work items are buildable now, in order (the lease claims the first free one)
8
+ * factoryAsk the leased item's tier and, for an ask, the understand answer, through `decide`
9
+ * factoryBuild the builder hook, in the worktree, unless understand said not to build
10
+ * factoryCheck the check hook (or the box's `factory.check`), with its evidence on each criterion
11
+ * factoryRecord the outcome: done (amended, proposals added, committed with chant's trailers),
12
+ * dropped (committed), redraft or ask (nothing), or not_done (kept by the run)
13
+ *
14
+ * `factoryOp` in `../factory.ts` declares them in that order. An open
15
+ * question in `factoryAsk` stops the run waiting, as `decide` does.
16
+ *
17
+ * Commands run with no shell, split as `box publish` splits a publisher, and
18
+ * asynchronously, so the lease heartbeat keeps running while a builder works.
19
+ */
20
+
21
+ import { spawn } from "node:child_process";
22
+ import { mkdirSync, realpathSync, writeFileSync } from "node:fs";
23
+ import { dirname, join, relative, resolve, sep } from "node:path";
24
+ import type { FactoryClaim, FactoryContext, FactoryItem } from "../../workspace/factory-rules";
25
+
26
+ /** The run's work lease, as `workLeaseOutput()` hands it to a step. */
27
+ export interface FactoryLease {
28
+ item: string;
29
+ holder: string;
30
+ token: string;
31
+ worktree?: string | null;
32
+ branch?: string | null;
33
+ }
34
+
35
+ export interface FactoryPickArgs {
36
+ cwd?: string;
37
+ /** The work kind file, when the declaration names several. */
38
+ kind?: string;
39
+ }
40
+
41
+ export interface FactoryPickResult {
42
+ /** Buildable work items, in record order: the lease claims the first nobody holds. */
43
+ candidates: string[];
44
+ /** Every other item the work kind reads, with why it waits. */
45
+ held: { item: string; hold: string; message: string }[];
46
+ /** One key per candidate, naming the state it was read in, for a steward's ready step. */
47
+ keys: string[];
48
+ }
49
+
50
+ export interface FactoryAskResult {
51
+ item: string;
52
+ ask: boolean;
53
+ tier: string;
54
+ /** The understand point's answer for an ask, or null for an item that isn't one. */
55
+ understand: string | null;
56
+ /** The lease outcome the understand answer leads to, or null when the item is built. */
57
+ outcome: "dropped" | "redraft" | "ask" | null;
58
+ }
59
+
60
+ export interface FactoryBuildResult {
61
+ ran: boolean;
62
+ finished: boolean;
63
+ exitCode: number | null;
64
+ /** Paths the guard put back; the reference Op applies no guard of its own, so this is empty unless a hook reports one. */
65
+ reverted: string[];
66
+ note: string;
67
+ /** The builder's last JSON line on stdout, as it printed it, or null: its own report (agent, model, session, run), which the check and after hooks get as FACTORY_BUILD. */
68
+ report: Record<string, unknown> | null;
69
+ }
70
+
71
+ export interface FactoryCheckResult {
72
+ ran: boolean;
73
+ ok: boolean;
74
+ command: string | null;
75
+ /** The criteria the check's evidence was attached to. */
76
+ evidence: string[];
77
+ log: string | null;
78
+ /** The check's last JSON line on stdout, as it printed it, or null. */
79
+ report: Record<string, unknown> | null;
80
+ }
81
+
82
+ export interface FactoryRecordResult {
83
+ outcome: "done" | "not_done" | "dropped" | "redraft" | "ask";
84
+ reason: string | null;
85
+ commit: string | null;
86
+ implementsProposed: { decision: string; paths: string[] }[];
87
+ }
88
+
89
+ // ── shared reads ─────────────────────────────────────────────────────────────
90
+
91
+ interface WorkRead {
92
+ kindFile: string;
93
+ kindName: string;
94
+ work: NonNullable<import("../../workspace/records").LoadedRecordKind["kind"]["work"]>;
95
+ states: string[];
96
+ stateField: string;
97
+ items: Map<string, FactoryItem & { path: string; acceptance: { id: string; verification: string; met: boolean }[] }>;
98
+ intentDecided: boolean | null;
99
+ }
100
+
101
+ /** Whether the declared kind file `file` is the one `kind` names, as a path from `cwd` (such as ../work/work.kind.mjs) or a trailing part of it. */
102
+ function sameKind(file: string, kind: string, cwd: string): boolean {
103
+ const real = (p: string) => {
104
+ try {
105
+ return realpathSync(p);
106
+ } catch {
107
+ return p;
108
+ }
109
+ };
110
+ return real(resolve(cwd, kind)) === real(file) || file.endsWith(kind.replace(/^(\.\.?\/)+/, ""));
111
+ }
112
+
113
+ /** The work kind's items and the box's intent, read through the read contract. */
114
+ async function readWork(cwd: string, kind?: string): Promise<WorkRead> {
115
+ const { declaredKindFiles, queryDeclaredRecords } = await import("../../workspace/records-cli");
116
+ const { loadRecordKind } = await import("../../workspace/records");
117
+ const files = declaredKindFiles(cwd);
118
+ const set = await queryDeclaredRecords(files, { cwd });
119
+ let found: WorkRead | undefined;
120
+ const decisionStates = new Map<string, { state: string | null; rank: number }>();
121
+ for (const [i, doc] of set.kinds.entries()) {
122
+ if ("error" in doc) continue;
123
+ const loaded = await loadRecordKind(files[i].file, cwd);
124
+ if (!loaded.kind.work) {
125
+ for (const r of doc.records) if (r.id) decisionStates.set(r.id, { state: r.state, rank: r.state ? (loaded.kind.approval?.[r.state] ?? 0) : 0 });
126
+ continue;
127
+ }
128
+ if (found || (kind !== undefined && !sameKind(files[i].file, kind, cwd))) continue;
129
+ const work = loaded.kind.work;
130
+ const states = loaded.kind.states ?? [];
131
+ const items: WorkRead["items"] = new Map();
132
+ for (const r of doc.records) {
133
+ if (r.id === null) continue;
134
+ const data = r.data;
135
+ const tier = work.tier ? data?.[work.tier.field] : undefined;
136
+ items.set(r.id, {
137
+ id: r.id,
138
+ path: r.path,
139
+ state: r.state,
140
+ openState: work.open,
141
+ proposedState: states[0] !== undefined && states[0] !== work.open ? states[0] : null,
142
+ ready: r.ready ?? false,
143
+ data,
144
+ tier: typeof tier === "string" ? tier : null,
145
+ contract: r.contract ?? null,
146
+ warnings: r.warnings.map((w) => w.code),
147
+ answers: (r.answers ?? []).map((a) => ({ id: a.id, point: a.point, state: a.state, answer: a.answer })),
148
+ leased: !!r.lease,
149
+ acceptance: (r.acceptance?.criteria ?? []).map((c) => ({ id: c.id, verification: c.verification, met: c.met })),
150
+ });
151
+ }
152
+ found = { kindFile: files[i].file, kindName: loaded.kind.name, work, states, stateField: loaded.kind.stateField ?? "state", items, intentDecided: null };
153
+ }
154
+ if (!found) throw new Error("the factory reads a work kind, and the declaration names none");
155
+ // The box's intent (#2850): while the decision a box block names is not approved, nothing is picked.
156
+ const { readDeclaration } = await import("../../workspace/declaration");
157
+ const { locateWorkspace } = await import("../../workspace/which-chant");
158
+ const intents = readDeclaration(locateWorkspace(cwd).tree).members.map((m) => m.box?.intent).filter((x): x is string => typeof x === "string");
159
+ if (intents.length > 0) found.intentDecided = intents.every((id) => (decisionStates.get(id)?.rank ?? 0) > 0);
160
+ return found;
161
+ }
162
+
163
+ async function gitOut(args: string[], cwd: string): Promise<{ ok: boolean; out: string }> {
164
+ const r = await run(["git", ...args], cwd, {});
165
+ return { ok: r.code === 0, out: r.stdout.trim() };
166
+ }
167
+
168
+ /**
169
+ * A record path from the repository's top: records --json reports paths from
170
+ * the repository root, but outside the process's own directory that report can
171
+ * come back relative to the process instead, so it is resolved and made relative again.
172
+ */
173
+ async function fromTop(cwd: string, path: string): Promise<string> {
174
+ if (!path.startsWith("../")) return path;
175
+ const top = (await gitOut(["rev-parse", "--show-toplevel"], cwd)).out;
176
+ try {
177
+ return relative(realpathSync(top), realpathSync(resolve(process.cwd(), path))).split(sep).join("/");
178
+ } catch {
179
+ return path;
180
+ }
181
+ }
182
+
183
+ /** The item as its work branch holds it: the state there, and whether the branch is in HEAD. Null when there is no branch. */
184
+ async function branchState(cwd: string, id: string, path: string): Promise<FactoryContext["branch"]> {
185
+ const ref = `refs/heads/chant/work/${id}`;
186
+ if (!(await gitOut(["rev-parse", "--verify", "-q", ref], cwd)).ok) return null;
187
+ const shown = await gitOut(["show", `${ref}:${await fromTop(cwd, path)}`], cwd);
188
+ let state: string | null = null;
189
+ if (shown.ok) {
190
+ const { parseFrontMatter } = await import("../../workspace/records");
191
+ const fm = parseFrontMatter(shown.out);
192
+ if (fm.ok && typeof fm.value.state === "string") state = fm.value.state;
193
+ }
194
+ const applied = (await gitOut(["merge-base", "--is-ancestor", ref, "HEAD"], cwd)).ok;
195
+ return { state, applied };
196
+ }
197
+
198
+ /** The points the workspace declares, by name, or an empty set when it declares none. */
199
+ async function declaredPoints(cwd: string): Promise<Set<string>> {
200
+ try {
201
+ const { workspacePoints } = await import("../../workspace/points-cli");
202
+ const doc = await workspacePoints({ cwd });
203
+ return "error" in doc ? new Set() : new Set(doc.points.map((p) => p.name));
204
+ } catch {
205
+ return new Set();
206
+ }
207
+ }
208
+
209
+ /** The question a point would ask about the item as it is now, without writing anything; null when it can't be read. */
210
+ async function dryQuestion(cwd: string, point: string, id: string): Promise<{ state: string; answer: string | boolean | null } | null> {
211
+ try {
212
+ const { workspacePoints } = await import("../../workspace/points-cli");
213
+ const doc = await workspacePoints({ cwd });
214
+ if ("error" in doc) return null;
215
+ const p = doc.points.find((x) => x.name === point);
216
+ if (!p) return null;
217
+ const { readInputs } = await import("../decide-read-inputs");
218
+ const { inputs } = await readInputs(p.inputs.map((i) => i.name), { "work-item": id }, cwd);
219
+ const { askPoint } = await import("../../workspace/decide");
220
+ const out = await askPoint({ cwd, point, inputs, subject: id, dryRun: true });
221
+ // Only a question already asked holds an item: one nobody asked yet is what the run asks.
222
+ if ("error" in out || !out.reused) return null;
223
+ return { state: out.question.state, answer: out.question.answer as string | boolean | null };
224
+ } catch {
225
+ return null;
226
+ }
227
+ }
228
+
229
+ async function contextFor(cwd: string, item: FactoryItem & { path: string }, intentDecided: boolean | null, points: Set<string>): Promise<FactoryContext> {
230
+ const { workHistory } = await import("../../workspace/work-cli");
231
+ const h = await workHistory({ id: item.id, cwd });
232
+ const claims: FactoryClaim[] = "error" in h ? [] : h.claims.map((c) => ({ token: c.token, ended: c.ended, outcome: c.release?.outcome ?? null, attempt: c.attempt }));
233
+ const attempts = "error" in h ? { exhausted: false } : { exhausted: h.attempts.exhausted };
234
+ const { isAsk, TIER_POINT, UNDERSTAND_POINT } = await import("../../workspace/factory-rules");
235
+ return {
236
+ intentDecided,
237
+ claims,
238
+ attempts,
239
+ branch: await branchState(cwd, item.id, item.path),
240
+ questions: {
241
+ tier: item.tier === null && points.has(TIER_POINT) ? await dryQuestion(cwd, TIER_POINT, item.id) : null,
242
+ understand: isAsk(item.data) && points.has(UNDERSTAND_POINT) ? await dryQuestion(cwd, UNDERSTAND_POINT, item.id) : null,
243
+ },
244
+ };
245
+ }
246
+
247
+ // ── commands ─────────────────────────────────────────────────────────────────
248
+
249
+ interface Ran {
250
+ code: number | null;
251
+ stdout: string;
252
+ stderr: string;
253
+ }
254
+
255
+ /** Run argv in cwd, without a shell, asynchronously. */
256
+ function run(argv: readonly string[], cwd: string, env: NodeJS.ProcessEnv): Promise<Ran> {
257
+ return new Promise((settle) => {
258
+ const child = spawn(argv[0], argv.slice(1), { cwd, env: { ...process.env, ...env }, stdio: ["ignore", "pipe", "pipe"] });
259
+ let stdout = "";
260
+ let stderr = "";
261
+ child.stdout.on("data", (b: Buffer) => (stdout += b.toString("utf8")));
262
+ // A hook's stderr is its log: it goes to the run's log as it comes, as a shell step's does.
263
+ child.stderr.on("data", (b: Buffer) => {
264
+ stderr += b.toString("utf8");
265
+ process.stderr.write(b);
266
+ });
267
+ child.on("error", (err) => settle({ code: null, stdout, stderr: `${stderr}${err.message}` }));
268
+ child.on("close", (code) => settle({ code, stdout, stderr }));
269
+ });
270
+ }
271
+
272
+ /** The last line of `stdout` that is a JSON object, or null. */
273
+ function lastJson(stdout: string): Record<string, unknown> | null {
274
+ const lines = stdout.split("\n").map((l) => l.trim()).filter(Boolean);
275
+ for (let i = lines.length - 1; i >= 0; i--) {
276
+ try {
277
+ const v: unknown = JSON.parse(lines[i]);
278
+ if (v !== null && typeof v === "object" && !Array.isArray(v)) return v as Record<string, unknown>;
279
+ } catch {
280
+ // Not this line.
281
+ }
282
+ }
283
+ return null;
284
+ }
285
+
286
+ /**
287
+ * Start the build from the checkout's HEAD (#382). A branch behind HEAD moves up to it; one with
288
+ * commits HEAD doesn't have, such as work an earlier run left under a lease it lost, has them kept
289
+ * at refs/chant/kept/<item>/earlier-<commit> first, so no attempt builds on another's work unasked.
290
+ */
291
+ async function freshStart(cwd: string, worktree: string, id: string): Promise<void> {
292
+ const head = (await gitOut(["rev-parse", "HEAD"], await checkoutRoot(cwd))).out;
293
+ const tip = (await gitOut(["rev-parse", "HEAD"], worktree)).out;
294
+ if (!head || !tip || head === tip) return;
295
+ if (!(await gitOut(["merge-base", "--is-ancestor", tip, head], worktree)).ok) {
296
+ await gitOut(["update-ref", `refs/chant/kept/${id}/earlier-${tip.slice(0, 12)}`, tip], worktree);
297
+ }
298
+ await gitOut(["reset", "-q", "--hard", head], worktree);
299
+ }
300
+
301
+ /**
302
+ * The checkout's copy of the item, carried into the worktree when the worktree's differs or is missing
303
+ * (#382): an item written in the checkout and not committed yet, such as the box's first build, or an
304
+ * ask its author rewrote, is the one the run builds, as the points were asked about it.
305
+ */
306
+ async function carryItem(cwd: string, worktree: string, id: string): Promise<void> {
307
+ const { copyFileSync, existsSync, readFileSync } = await import("node:fs");
308
+ const there = (await readWork(cwd)).items.get(id);
309
+ if (!there) return;
310
+ const checkout = await checkoutRoot(cwd);
311
+ const rel = await fromTop(cwd, there.path);
312
+ const from = join(checkout, ...rel.split("/"));
313
+ const to = join(worktree, ...rel.split("/"));
314
+ if (!existsSync(from)) return;
315
+ if (existsSync(to) && readFileSync(to).equals(readFileSync(from))) return;
316
+ mkdirSync(dirname(to), { recursive: true });
317
+ copyFileSync(from, to);
318
+ }
319
+
320
+ async function words(command: string): Promise<string[]> {
321
+ const { splitCommand } = await import("../../workspace/box-publish");
322
+ return splitCommand(command);
323
+ }
324
+
325
+ function leaseOf(lease: FactoryLease | undefined, step: string): FactoryLease & { worktree: string } {
326
+ if (!lease || typeof lease.item !== "string" || typeof lease.token !== "string") throw new Error(`${step} runs under the factory Op's work lease: pass workLeaseOutput() as lease`);
327
+ if (!lease.worktree) throw new Error(`${step} needs the run's worktree: the factory Op changes the checkout, so its lease makes one`);
328
+ return lease as FactoryLease & { worktree: string };
329
+ }
330
+
331
+ const today = () => new Date().toISOString().slice(0, 10);
332
+
333
+ /** Amend `id` in `cwd` through chant, refusing on any write error. */
334
+ async function amend(cwd: string, kindFile: string, id: string, fields: Record<string, unknown>): Promise<void> {
335
+ const { amendRecord } = await import("../../workspace/records-write");
336
+ const doc = await amendRecord({ kind: kindFile, id, fields: JSON.stringify(fields), cwd });
337
+ if ("error" in doc) throw new Error(`the factory could not amend ${id}: ${doc.error.code}: ${doc.error.message}`);
338
+ }
339
+
340
+ /** The kind file as seen from the worktree: the same path under the worktree when it sits in the checkout. */
341
+ function inWorktree(kindFile: string, checkout: string, worktree: string): string {
342
+ const real = (p: string) => {
343
+ try {
344
+ return realpathSync(p);
345
+ } catch {
346
+ return p;
347
+ }
348
+ };
349
+ const [file, top, tree] = [real(kindFile), real(checkout), real(worktree)];
350
+ // Read from the worktree already (it sits under the checkout's .git), or outside the checkout: as it is.
351
+ if (file.startsWith(`${tree}/`) || !file.startsWith(`${top}/`)) return file;
352
+ return join(tree, file.slice(top.length + 1));
353
+ }
354
+
355
+ async function checkoutRoot(cwd: string): Promise<string> {
356
+ return (await gitOut(["rev-parse", "--show-toplevel"], cwd)).out || cwd;
357
+ }
358
+
359
+ /** Commit everything in the worktree with chant's trailers (ws-075). Null when there was nothing to commit. */
360
+ async function commitAll(worktree: string, subject: string, item: string, kindName: string, token: string, runId?: string, extra: { agent?: string; records?: string[]; body?: string } = {}): Promise<string | null> {
361
+ await gitOut(["add", "-A"], worktree);
362
+ if ((await gitOut(["diff", "--cached", "--quiet"], worktree)).ok) return null;
363
+ const { formatChantTrailers } = await import("../../workspace/trailers");
364
+ const records = [`${kindName}:${item}`, ...(extra.records ?? []).filter((r) => r !== `${kindName}:${item}`)];
365
+ const trailers = formatChantTrailers({ ...(extra.agent ? { agent: extra.agent } : {}), lease: token, ...(runId ? { run: runId } : {}), records });
366
+ const r = await run(["git", "-c", "commit.gpgsign=false", "commit", "-q", "--no-verify", "-m", subject, ...(extra.body ? ["-m", extra.body] : []), "-m", trailers.join("\n")], worktree, {});
367
+ if (r.code !== 0) throw new Error(`the factory could not commit ${item}: ${r.stderr.trim()}`);
368
+ return (await gitOut(["rev-parse", "HEAD"], worktree)).out;
369
+ }
370
+
371
+ // ── the activities ───────────────────────────────────────────────────────────
372
+
373
+ /** Which work items are buildable now (#3406 rule 1). */
374
+ export async function factoryPick(args: FactoryPickArgs = {}): Promise<FactoryPickResult> {
375
+ const cwd = args.cwd ?? process.cwd();
376
+ const { pickable, readyKey } = await import("../../workspace/factory-rules");
377
+ const w = await readWork(cwd, args.kind);
378
+ const points = await declaredPoints(cwd);
379
+ const out: FactoryPickResult = { candidates: [], held: [], keys: [] };
380
+ for (const item of w.items.values()) {
381
+ if (item.state !== null && item.state !== item.openState && item.state !== item.proposedState) continue;
382
+ const ctx = await contextFor(cwd, item, w.intentDecided, points);
383
+ const verdict = pickable(item, ctx);
384
+ if (verdict.ok) {
385
+ out.candidates.push(item.id);
386
+ out.keys.push(readyKey(item, ctx, item.data));
387
+ } else {
388
+ out.held.push({ item: item.id, hold: verdict.hold, message: verdict.message });
389
+ // Said in the run's log too, so whoever reads why nothing was built sees it.
390
+ console.error(`factoryPick: skipped ${item.id}: ${verdict.message}`);
391
+ }
392
+ }
393
+ return out;
394
+ }
395
+
396
+ export interface FactoryReadyArgs {
397
+ cwd?: string;
398
+ kind?: string;
399
+ /** A command run in `cwd` that prints a JSON list of more keys, for work the factory's own pick can't see yet, such as a box whose intent was just decided and has no first build's item (#382). */
400
+ also?: string;
401
+ }
402
+
403
+ /**
404
+ * The steward's ready step for the factory Op (#382, `factoryReady` in ../factory.ts): one key per
405
+ * buildable item, naming the state it was read in, so a person's answer, a retry or a changed item
406
+ * starts a run and the same state does not start another. Only reads.
407
+ */
408
+ export async function factoryReady(args: FactoryReadyArgs = {}): Promise<string[]> {
409
+ const cwd = args.cwd ?? process.cwd();
410
+ const keys = (await factoryPick({ cwd, ...(args.kind !== undefined ? { kind: args.kind } : {}) })).keys;
411
+ if (args.also) {
412
+ const r = await run(await words(args.also), cwd, {});
413
+ if (r.code !== 0) throw new Error(`factoryReady: ${args.also} exited ${r.code}: ${r.stderr.trim().split("\n").slice(-3).join(" ")}`);
414
+ let more: unknown;
415
+ try {
416
+ more = JSON.parse(r.stdout.trim().split("\n").pop() ?? "[]");
417
+ } catch {
418
+ throw new Error(`factoryReady: ${args.also} printed no JSON list on its last line`);
419
+ }
420
+ if (!Array.isArray(more)) throw new Error(`factoryReady: ${args.also} printed no JSON list on its last line`);
421
+ for (const k of more) keys.push(typeof k === "string" ? k : JSON.stringify(k));
422
+ }
423
+ return keys;
424
+ }
425
+
426
+ export interface FactoryAskArgs {
427
+ lease: FactoryLease;
428
+ cwd?: string;
429
+ kind?: string;
430
+ /** Backends for the points' model deciders, in place of `decide.backends` in chant.config. */
431
+ backends?: import("./decide").DecideArgs["backends"];
432
+ }
433
+
434
+ /** The leased item's tier and understand answer (#3406 rules 2 and 3). An open question stops the run waiting. */
435
+ export async function factoryAsk(args: FactoryAskArgs): Promise<FactoryAskResult> {
436
+ const cwd = args.cwd ?? process.cwd();
437
+ if (!args.lease?.item) throw new Error("factoryAsk runs under the factory Op's work lease: pass workLeaseOutput() as lease");
438
+ const id = args.lease.item;
439
+ const { isAsk, understandOutcome, TIER_POINT, UNDERSTAND_POINT } = await import("../../workspace/factory-rules");
440
+ const w = await readWork(cwd, args.kind);
441
+ const item = w.items.get(id);
442
+ if (!item) throw new Error(`no record of the work kind has id ${id}`);
443
+ const points = await declaredPoints(cwd);
444
+ const { decide } = await import("./decide");
445
+ const ask = isAsk(item.data);
446
+ let understand: string | null = null;
447
+ if (ask && points.has(UNDERSTAND_POINT)) understand = String((await decide({ point: UNDERSTAND_POINT, read: { "work-item": id }, subject: id, cwd, ...(args.backends ? { backends: args.backends } : {}) })).answer);
448
+ else if (ask) understand = "proceed";
449
+ const outcome = understandOutcome(understand);
450
+ let tier = item.tier;
451
+ if (tier === null && outcome === null) {
452
+ tier = points.has(TIER_POINT) ? String((await decide({ point: TIER_POINT, read: { "work-item": id }, subject: id, cwd, ...(args.backends ? { backends: args.backends } : {}) })).answer) : (w.work.tier?.tiers[0] ?? "small");
453
+ }
454
+ return { item: id, ask, tier: tier ?? w.work.tier?.tiers[0] ?? "small", understand, outcome };
455
+ }
456
+
457
+ export interface FactoryBuildArgs {
458
+ lease: FactoryLease;
459
+ ask: FactoryAskResult;
460
+ /** The builder hook: a command run in the worktree, with FACTORY_ITEM, FACTORY_TIER, FACTORY_TOKEN, FACTORY_HOLDER, FACTORY_WORKTREE and FACTORY_CONTEXT set. */
461
+ builder: string;
462
+ /** The context hook's output path, or a command that prints the context bundle's path; passed as FACTORY_CONTEXT. */
463
+ context?: string;
464
+ cwd?: string;
465
+ }
466
+
467
+ /** Run the builder hook in the worktree, unless understand said not to build (#3406). */
468
+ export async function factoryBuild(args: FactoryBuildArgs): Promise<FactoryBuildResult> {
469
+ const lease = leaseOf(args.lease, "factoryBuild");
470
+ if (args.ask.outcome !== null) return { ran: false, finished: false, exitCode: null, reverted: [], note: `understand answered ${args.ask.understand}: nothing is built`, report: null };
471
+ // A kept ask opens before it is built: chant writes the state in the worktree, so it goes with the build.
472
+ const cwd = args.cwd ?? process.cwd();
473
+ await freshStart(cwd, lease.worktree, lease.item);
474
+ await carryItem(cwd, lease.worktree, lease.item);
475
+ const w = await readWork(lease.worktree);
476
+ const item = w.items.get(lease.item);
477
+ if (item && item.proposedState !== null && item.state === item.proposedState) {
478
+ await amend(lease.worktree, inWorktree(w.kindFile, await checkoutRoot(cwd), lease.worktree), lease.item, { [w.stateField]: item.openState });
479
+ }
480
+ // An ask's builder writes its plan as the item's acceptance criteria and changes nothing else in it
481
+ // (#3406, studio#382): the item is kept as it was before the builder ran, and put back if it changed.
482
+ const { isAsk } = await import("../../workspace/factory-rules");
483
+ const opened = (await readWork(lease.worktree)).items.get(lease.item);
484
+ const acceptance = w.work.acceptance?.field ?? "acceptance";
485
+ const guarded = opened && isAsk(opened.data) ? { path: join(lease.worktree, ...(await fromTop(lease.worktree, opened.path)).split("/")), rel: await fromTop(lease.worktree, opened.path), data: opened.data } : null;
486
+ const { readFileSync, writeFileSync: write } = await import("node:fs");
487
+ const bytes = guarded ? readFileSync(guarded.path) : null;
488
+ const r = await run(await words(args.builder), lease.worktree, {
489
+ FACTORY_ITEM: lease.item,
490
+ FACTORY_TIER: args.ask.tier,
491
+ FACTORY_TOKEN: lease.token,
492
+ FACTORY_HOLDER: lease.holder,
493
+ FACTORY_WORKTREE: lease.worktree,
494
+ ...(args.context ? { FACTORY_CONTEXT: args.context } : {}),
495
+ });
496
+ // The builder's report: `reverted` lists what its guard put back, and `ok: false` says it did not finish though it exited 0.
497
+ const report = lastJson(r.stdout);
498
+ const reverted = Array.isArray(report?.reverted) ? (report!.reverted as unknown[]).filter((x): x is string => typeof x === "string") : [];
499
+ if (guarded && bytes) {
500
+ const now = (await readWork(lease.worktree)).items.get(lease.item);
501
+ const rest = (data: Record<string, unknown> | null | undefined) => Object.fromEntries(Object.entries(data ?? {}).filter(([k]) => k !== acceptance).sort(([a], [b]) => a.localeCompare(b)));
502
+ const before = rest(guarded.data);
503
+ const after = now ? rest(now.data) : null;
504
+ if (!after || JSON.stringify(after) !== JSON.stringify(before)) {
505
+ const changed = after ? [...new Set([...Object.keys(before), ...Object.keys(after)])].filter((k) => JSON.stringify(before[k]) !== JSON.stringify(after[k])) : [];
506
+ write(guarded.path, bytes);
507
+ reverted.push(`${guarded.rel} (${after ? `it changed ${changed.join(", ")}, and only ${acceptance} is the builder's` : "chant no longer reads it"})`);
508
+ }
509
+ }
510
+ const finished = r.code === 0 && report?.ok !== false;
511
+ const note = typeof report?.note === "string" ? report.note : finished ? "the builder finished" : r.code === 0 ? "the builder reported it did not finish" : `the builder exited ${r.code}: ${r.stderr.trim().split("\n").slice(-3).join(" ")}`;
512
+ return { ran: true, finished, exitCode: r.code, reverted, note, report };
513
+ }
514
+
515
+ export interface FactoryCheckArgs {
516
+ lease: FactoryLease;
517
+ build: FactoryBuildResult;
518
+ /** The check hook: a command run in the worktree, whose exit code is the verdict. The box's factory.check when left out. */
519
+ check?: string;
520
+ cwd?: string;
521
+ }
522
+
523
+ /** Run the check and attach its result as evidence to each criterion the factory ticks (#3406 rule 5). */
524
+ export async function factoryCheck(args: FactoryCheckArgs): Promise<FactoryCheckResult> {
525
+ const lease = leaseOf(args.lease, "factoryCheck");
526
+ if (!args.build.ran || !args.build.finished) return { ran: false, ok: false, command: null, evidence: [], log: null, report: null };
527
+ let command = args.check ?? null;
528
+ if (command === null) {
529
+ const { readDeclaration } = await import("../../workspace/declaration");
530
+ const { locateWorkspace } = await import("../../workspace/which-chant");
531
+ command = readDeclaration(locateWorkspace(lease.worktree).tree).members.find((m) => m.box?.factory?.check)?.box?.factory?.check?.run ?? null;
532
+ }
533
+ if (command === null) return { ran: false, ok: false, command: null, evidence: [], log: null, report: null };
534
+ const r = await run(await words(command), lease.worktree, {
535
+ FACTORY_ITEM: lease.item,
536
+ FACTORY_TOKEN: lease.token,
537
+ FACTORY_HOLDER: lease.holder,
538
+ FACTORY_WORKTREE: lease.worktree,
539
+ FACTORY_BUILD: JSON.stringify(args.build.report ?? {}),
540
+ });
541
+ // A check may report each criterion's own result as its last JSON line, { "criteria": { "AC-1": "pass", ... } }:
542
+ // then each criterion is ticked by its own result, and one it names no result for gets none.
543
+ const report = lastJson(r.stdout);
544
+ const ok = r.code === 0 && report?.ok !== false;
545
+ const per = report?.criteria && typeof report.criteria === "object" ? (report.criteria as Record<string, unknown>) : null;
546
+ const log = `.chant/factory/${lease.item}/check.log`;
547
+ const abs = join(lease.worktree, ...log.split("/"));
548
+ mkdirSync(dirname(abs), { recursive: true });
549
+ writeFileSync(abs, `$ ${command}\nexit ${r.code}\n\n${r.stdout}${r.stderr ? `\n--- stderr ---\n${r.stderr}` : ""}`);
550
+ const w = await readWork(lease.worktree);
551
+ const item = w.items.get(lease.item);
552
+ const evidence: string[] = [];
553
+ const { attachWorkEvidence } = await import("../../workspace/work-evidence");
554
+ for (const c of item?.acceptance ?? []) {
555
+ if (c.verification === "manual" || c.verification === "runtime") continue;
556
+ const own = per ? per[c.id] : undefined;
557
+ if (per && own !== "pass" && own !== "fail") continue;
558
+ const result = per ? (own as "pass" | "fail") : ok ? "pass" : "fail";
559
+ const out = await attachWorkEvidence({ cwd: lease.worktree, item: lease.item, holder: lease.holder, token: lease.token, criterion: c.id, result, title: `factory check: ${command}`, path: log });
560
+ if (!("error" in out)) evidence.push(c.id);
561
+ }
562
+ return { ran: true, ok, command, evidence, log, report };
563
+ }
564
+
565
+ export interface FactoryRecordArgs {
566
+ lease: FactoryLease;
567
+ /** The after hook: a command run in the worktree once the outcome is recorded, with FACTORY_OUTCOME, FACTORY_COMMIT, FACTORY_BUILD and FACTORY_CHECK set, such as ending the build's run record. A failure is reported and changes nothing. */
568
+ after?: string;
569
+ ask: FactoryAskResult;
570
+ build: FactoryBuildResult;
571
+ check: FactoryCheckResult;
572
+ cwd?: string;
573
+ }
574
+
575
+ /** The decisions a done build proposes it implements, from the intent graph of each path it changed (studio#243). */
576
+ async function proposals(worktree: string, base: string, already: string[]): Promise<{ decision: string; paths: string[] }[]> {
577
+ const { proposeImplements } = await import("../../workspace/factory-rules");
578
+ const changed = (await gitOut(["diff", "--name-only", base], worktree)).out.split("\n").filter((p) => p && !p.startsWith(".chant/"));
579
+ const { intentGraph } = await import("../../workspace/intent");
580
+ const rows: { path: string; decisions: { id: string; state: string | null; granularity: string }[] }[] = [];
581
+ for (const path of changed.slice(0, 20)) {
582
+ const { doc } = await intentGraph({ cwd: worktree, region: path });
583
+ if ("error" in doc) continue;
584
+ const decisions = new Map(doc.nodes.filter((n) => n.kind === "decision").map((n) => [n.id, n as unknown as { record: string; state: string | null }]));
585
+ const out: { id: string; state: string | null; granularity: string }[] = [];
586
+ for (const e of doc.edges as unknown as { kind: string; from: string; to: string; granularity?: string }[]) {
587
+ if (e.kind !== "constrains") continue;
588
+ const d = decisions.get(e.from);
589
+ if (d) out.push({ id: d.record, state: d.state, granularity: e.granularity ?? "" });
590
+ }
591
+ rows.push({ path, decisions: out });
592
+ }
593
+ return proposeImplements(rows, already);
594
+ }
595
+
596
+ /** Record the outcome on the item's branch and name it for the lease's release (#3406 rules 4 to 6, 8). */
597
+ export async function factoryRecord(args: FactoryRecordArgs): Promise<FactoryRecordResult> {
598
+ const result = await recordOutcome(args);
599
+ if (args.after) {
600
+ const lease = leaseOf(args.lease, "factoryRecord");
601
+ const r = await run(await words(args.after), lease.worktree, {
602
+ FACTORY_ITEM: lease.item,
603
+ FACTORY_TOKEN: lease.token,
604
+ FACTORY_HOLDER: lease.holder,
605
+ FACTORY_WORKTREE: lease.worktree,
606
+ FACTORY_OUTCOME: result.outcome,
607
+ FACTORY_COMMIT: result.commit ?? "",
608
+ FACTORY_REASON: result.reason ?? "",
609
+ FACTORY_BUILD: JSON.stringify(args.build?.report ?? {}),
610
+ FACTORY_CHECK: JSON.stringify(args.check?.report ?? {}),
611
+ });
612
+ if (r.code !== 0) console.error(`factoryRecord: the after hook exited ${r.code}: ${r.stderr.trim().split("\n").slice(-3).join(" ")}`);
613
+ }
614
+ return result;
615
+ }
616
+
617
+ /**
618
+ * What the hooks' reports add to the done commit's trailers (ws-075): `chantAgent`, the agent session
619
+ * a builder ran as, for Chant-Agent, and `records`, more `<kind>:<id>` records the build carries, such
620
+ * as the contract it built and the evidence its check wrote, from the builder's and the check's reports.
621
+ */
622
+ function trailerExtras(build: Record<string, unknown> | null | undefined, check: Record<string, unknown> | null | undefined): { agent?: string; records: string[] } {
623
+ const records: string[] = [];
624
+ for (const r of [build?.records, check?.records]) if (Array.isArray(r)) for (const x of r) if (typeof x === "string" && /^[a-z][a-z0-9-]*:[A-Za-z0-9][A-Za-z0-9._-]*$/.test(x) && !records.includes(x)) records.push(x);
625
+ const agent = typeof build?.chantAgent === "string" && build.chantAgent.trim() !== "" ? build.chantAgent.trim() : undefined;
626
+ return { ...(agent ? { agent } : {}), records };
627
+ }
628
+
629
+ /** The run id a builder's report names for the Chant-Run trailer: `run.id` or `run`, or undefined. */
630
+ function runIdOf(report: Record<string, unknown> | null | undefined): string | undefined {
631
+ const r = report?.run;
632
+ if (typeof r === "string" && r !== "") return r;
633
+ const id = r && typeof r === "object" ? (r as { id?: unknown }).id : undefined;
634
+ return typeof id === "string" && id !== "" ? id : undefined;
635
+ }
636
+
637
+ async function recordOutcome(args: FactoryRecordArgs): Promise<FactoryRecordResult> {
638
+ const lease = leaseOf(args.lease, "factoryRecord");
639
+ const cwd = args.cwd ?? process.cwd();
640
+ const root = await checkoutRoot(cwd);
641
+ const w = await readWork(lease.worktree);
642
+ const kindFile = inWorktree(w.kindFile, root, lease.worktree);
643
+ const item = w.items.get(lease.item);
644
+ if (!item) throw new Error(`no record of the work kind has id ${lease.item} in the worktree`);
645
+ const none = { commit: null, implementsProposed: [] };
646
+ if (args.ask.outcome === "redraft" || args.ask.outcome === "ask") return { outcome: args.ask.outcome, reason: `understand answered ${args.ask.understand}`, ...none };
647
+ if (args.ask.outcome === "dropped") {
648
+ await amend(lease.worktree, kindFile, lease.item, { [w.stateField]: "dropped", [w.work.closedOn]: today() });
649
+ const commit = await commitAll(lease.worktree, `${lease.item}: dropped, the understand point refused it`, lease.item, w.kindName, lease.token);
650
+ return { outcome: "dropped", reason: "understand answered refuse", commit, implementsProposed: [] };
651
+ }
652
+ const { doneVerdict } = await import("../../workspace/factory-rules");
653
+ const verdict = doneVerdict(args.build, args.check, item.acceptance);
654
+ if (!verdict.done) {
655
+ // The attempt is committed with why it is not done and chant's trailers, so the kept attempt the run
656
+ // makes of it (refs/chant/kept/<item>/<token>) says so and joins to the item and the lease.
657
+ const kept = await commitAll(lease.worktree, `${lease.item}: not done`, lease.item, w.kindName, lease.token, runIdOf(args.build.report), {
658
+ ...trailerExtras(args.build.report, args.check.report),
659
+ body: `Not done: ${verdict.reason}`,
660
+ }).catch(() => null);
661
+ return { outcome: "not_done", reason: verdict.reason, commit: kept, implementsProposed: [] };
662
+ }
663
+ const base = (await gitOut(["merge-base", "HEAD", (await gitOut(["rev-parse", "HEAD"], root)).out], lease.worktree)).out;
664
+ const already = Array.isArray(item.data?.[w.work.implements]) ? (item.data![w.work.implements] as unknown[]).filter((x): x is string => typeof x === "string") : [];
665
+ const proposed = base ? await proposals(lease.worktree, base, already) : [];
666
+ await amend(lease.worktree, kindFile, lease.item, {
667
+ [w.stateField]: w.work.done,
668
+ [w.work.closedOn]: today(),
669
+ result: { lease: lease.token },
670
+ ...(proposed.length > 0 ? { [w.work.implements]: [...already, ...proposed.map((p) => p.decision)], implements_proposed: proposed } : {}),
671
+ });
672
+ const title = typeof item.data?.title === "string" ? item.data.title : lease.item;
673
+ const commit = await commitAll(lease.worktree, `${lease.item}: ${title}`, lease.item, w.kindName, lease.token, runIdOf(args.build.report), trailerExtras(args.build.report, args.check.report));
674
+ return { outcome: "done", reason: null, commit, implementsProposed: proposed };
675
+ }