@intentius/chant 0.91.0 → 0.94.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 (361) hide show
  1. package/dist/cli/commands/build.d.ts.map +1 -1
  2. package/dist/cli/commands/lint.d.ts.map +1 -1
  3. package/dist/cli/handlers/graph.d.ts.map +1 -1
  4. package/dist/cli/handlers/operator.d.ts +6 -0
  5. package/dist/cli/handlers/operator.d.ts.map +1 -1
  6. package/dist/cli/handlers/run.d.ts.map +1 -1
  7. package/dist/cli/main.d.ts.map +1 -1
  8. package/dist/cli/mcp/workspace-plugins.d.ts +6 -6
  9. package/dist/cli/mcp/workspace-tools.d.ts +2 -1
  10. package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
  11. package/dist/cli/plugins.d.ts.map +1 -1
  12. package/dist/cli/registry.d.ts +12 -2
  13. package/dist/cli/registry.d.ts.map +1 -1
  14. package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
  15. package/dist/config.d.ts +22 -0
  16. package/dist/config.d.ts.map +1 -1
  17. package/dist/lexicon-module.d.ts +22 -0
  18. package/dist/lexicon-module.d.ts.map +1 -1
  19. package/dist/lifecycle/converge-ledger.d.ts +19 -0
  20. package/dist/lifecycle/converge-ledger.d.ts.map +1 -1
  21. package/dist/lifecycle/run-ledger.d.ts +2 -0
  22. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  23. package/dist/lifecycle/symptoms.d.ts +51 -0
  24. package/dist/lifecycle/symptoms.d.ts.map +1 -1
  25. package/dist/lint/rules/index.d.ts +4 -2
  26. package/dist/lint/rules/index.d.ts.map +1 -1
  27. package/dist/lint/rules/op/index.d.ts +14 -3
  28. package/dist/lint/rules/op/index.d.ts.map +1 -1
  29. package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -1
  30. package/dist/lint/rules/op/sys010-key-over-plain-http.d.ts +29 -0
  31. package/dist/lint/rules/op/sys010-key-over-plain-http.d.ts.map +1 -0
  32. package/dist/lint/rules/sys001-no-literal-key.d.ts +3 -0
  33. package/dist/lint/rules/sys001-no-literal-key.d.ts.map +1 -0
  34. package/dist/op/__fixtures__/decide-stub-backend.d.ts +53 -0
  35. package/dist/op/__fixtures__/decide-stub-backend.d.ts.map +1 -0
  36. package/dist/op/activities/activity-contracts.d.ts +201 -0
  37. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  38. package/dist/op/activities/apply.d.ts.map +1 -1
  39. package/dist/op/activities/change-coverage.d.ts +44 -0
  40. package/dist/op/activities/change-coverage.d.ts.map +1 -0
  41. package/dist/op/activities/converge.d.ts +24 -1
  42. package/dist/op/activities/converge.d.ts.map +1 -1
  43. package/dist/op/activities/decide.d.ts +107 -0
  44. package/dist/op/activities/decide.d.ts.map +1 -0
  45. package/dist/op/activities/index.d.ts +10 -0
  46. package/dist/op/activities/index.d.ts.map +1 -1
  47. package/dist/op/activities/shell.d.ts +32 -0
  48. package/dist/op/activities/shell.d.ts.map +1 -1
  49. package/dist/op/activities/source-release.d.ts +86 -0
  50. package/dist/op/activities/source-release.d.ts.map +1 -0
  51. package/dist/op/activities/source-rollback.d.ts +100 -0
  52. package/dist/op/activities/source-rollback.d.ts.map +1 -0
  53. package/dist/op/activities/work-evidence.d.ts +42 -0
  54. package/dist/op/activities/work-evidence.d.ts.map +1 -0
  55. package/dist/op/activity-contract.d.ts +1 -0
  56. package/dist/op/activity-contract.d.ts.map +1 -1
  57. package/dist/op/activity-profiles.d.ts +16 -0
  58. package/dist/op/activity-profiles.d.ts.map +1 -1
  59. package/dist/op/builders.d.ts +84 -2
  60. package/dist/op/builders.d.ts.map +1 -1
  61. package/dist/op/composites/converge-op.d.ts +31 -4
  62. package/dist/op/composites/converge-op.d.ts.map +1 -1
  63. package/dist/op/decide-backend.d.ts +116 -0
  64. package/dist/op/decide-backend.d.ts.map +1 -0
  65. package/dist/op/decide-config.d.ts +120 -0
  66. package/dist/op/decide-config.d.ts.map +1 -0
  67. package/dist/op/decide-read-inputs.d.ts +40 -0
  68. package/dist/op/decide-read-inputs.d.ts.map +1 -0
  69. package/dist/op/gate-wait.d.ts +43 -0
  70. package/dist/op/gate-wait.d.ts.map +1 -0
  71. package/dist/op/gate.d.ts +5 -2
  72. package/dist/op/gate.d.ts.map +1 -1
  73. package/dist/op/index.d.ts +11 -4
  74. package/dist/op/index.d.ts.map +1 -1
  75. package/dist/op/local-executor.d.ts +29 -4
  76. package/dist/op/local-executor.d.ts.map +1 -1
  77. package/dist/op/local-output.d.ts +2 -0
  78. package/dist/op/local-output.d.ts.map +1 -1
  79. package/dist/op/op-ir.d.ts +2 -0
  80. package/dist/op/op-ir.d.ts.map +1 -1
  81. package/dist/op/op-verb-class.d.ts.map +1 -1
  82. package/dist/op/operator.d.ts +97 -1
  83. package/dist/op/operator.d.ts.map +1 -1
  84. package/dist/op/runtime.d.ts +37 -5
  85. package/dist/op/runtime.d.ts.map +1 -1
  86. package/dist/op/runtimes/local.d.ts.map +1 -1
  87. package/dist/op/source-archive.d.ts +63 -0
  88. package/dist/op/source-archive.d.ts.map +1 -0
  89. package/dist/op/steward-points.d.ts +136 -0
  90. package/dist/op/steward-points.d.ts.map +1 -0
  91. package/dist/op/steward-turn.d.ts +53 -0
  92. package/dist/op/steward-turn.d.ts.map +1 -0
  93. package/dist/op/steward.d.ts +22 -1
  94. package/dist/op/steward.d.ts.map +1 -1
  95. package/dist/op/types.d.ts +7 -0
  96. package/dist/op/types.d.ts.map +1 -1
  97. package/dist/op/work-lease-run.d.ts +1 -1
  98. package/dist/op/work-lease-run.d.ts.map +1 -1
  99. package/dist/workspace/__fixtures__/decide-workspace.d.ts +100 -0
  100. package/dist/workspace/__fixtures__/decide-workspace.d.ts.map +1 -0
  101. package/dist/workspace/answers-ledger.d.ts +76 -0
  102. package/dist/workspace/answers-ledger.d.ts.map +1 -0
  103. package/dist/workspace/box-intent.d.ts +85 -0
  104. package/dist/workspace/box-intent.d.ts.map +1 -0
  105. package/dist/workspace/changes-cli.d.ts +16 -0
  106. package/dist/workspace/changes-cli.d.ts.map +1 -0
  107. package/dist/workspace/changes.d.ts +200 -0
  108. package/dist/workspace/changes.d.ts.map +1 -0
  109. package/dist/workspace/chant-migrations/chud-lexicon-exit-fly-site.d.ts +59 -0
  110. package/dist/workspace/chant-migrations/chud-lexicon-exit-fly-site.d.ts.map +1 -0
  111. package/dist/workspace/chant-migrations/chud-lexicon-exit-live-names.d.ts +51 -0
  112. package/dist/workspace/chant-migrations/chud-lexicon-exit-live-names.d.ts.map +1 -0
  113. package/dist/workspace/chant-migrations/chud-lexicon-exit-rollback.d.ts +26 -0
  114. package/dist/workspace/chant-migrations/chud-lexicon-exit-rollback.d.ts.map +1 -0
  115. package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-inputs.d.ts +59 -0
  116. package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-inputs.d.ts.map +1 -0
  117. package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-policy.d.ts +22 -0
  118. package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-policy.d.ts.map +1 -0
  119. package/dist/workspace/chant-migrations/chud-lexicon-exit.d.ts +71 -0
  120. package/dist/workspace/chant-migrations/chud-lexicon-exit.d.ts.map +1 -0
  121. package/dist/workspace/chant-migrations.d.ts +104 -0
  122. package/dist/workspace/chant-migrations.d.ts.map +1 -0
  123. package/dist/workspace/checks/boxes.d.ts +47 -1
  124. package/dist/workspace/checks/boxes.d.ts.map +1 -1
  125. package/dist/workspace/checks/diagrams.d.ts +31 -0
  126. package/dist/workspace/checks/diagrams.d.ts.map +1 -0
  127. package/dist/workspace/checks/records.d.ts +7 -0
  128. package/dist/workspace/checks/records.d.ts.map +1 -1
  129. package/dist/workspace/checks.d.ts +7 -0
  130. package/dist/workspace/checks.d.ts.map +1 -1
  131. package/dist/workspace/compose-graph.d.ts +2 -0
  132. package/dist/workspace/compose-graph.d.ts.map +1 -1
  133. package/dist/workspace/conformance/index.d.ts.map +1 -1
  134. package/dist/workspace/decide.d.ts +49 -4
  135. package/dist/workspace/decide.d.ts.map +1 -1
  136. package/dist/workspace/decision-points.schema.json +3 -3
  137. package/dist/workspace/declaration.d.ts +58 -0
  138. package/dist/workspace/declaration.d.ts.map +1 -1
  139. package/dist/workspace/declaration.schema.json +119 -1
  140. package/dist/workspace/declared-kinds.d.ts +20 -0
  141. package/dist/workspace/declared-kinds.d.ts.map +1 -1
  142. package/dist/workspace/generated-files.d.ts +7 -0
  143. package/dist/workspace/generated-files.d.ts.map +1 -1
  144. package/dist/workspace/intent-joins.d.ts +5 -5
  145. package/dist/workspace/intent.d.ts.map +1 -1
  146. package/dist/workspace/lineage-check.d.ts +3 -0
  147. package/dist/workspace/lineage-check.d.ts.map +1 -1
  148. package/dist/workspace/lineage-upgrade.d.ts +6 -1
  149. package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
  150. package/dist/workspace/ls.d.ts +39 -1
  151. package/dist/workspace/ls.d.ts.map +1 -1
  152. package/dist/workspace/point-answer.schema.json +95 -0
  153. package/dist/workspace/points-cli.d.ts +2 -0
  154. package/dist/workspace/points-cli.d.ts.map +1 -1
  155. package/dist/workspace/points.d.ts +4 -6
  156. package/dist/workspace/points.d.ts.map +1 -1
  157. package/dist/workspace/reason-codes.d.ts +16 -2
  158. package/dist/workspace/reason-codes.d.ts.map +1 -1
  159. package/dist/workspace/records-cli.d.ts +11 -1
  160. package/dist/workspace/records-cli.d.ts.map +1 -1
  161. package/dist/workspace/records-close.d.ts +1 -1
  162. package/dist/workspace/records-close.d.ts.map +1 -1
  163. package/dist/workspace/records-write.d.ts +11 -5
  164. package/dist/workspace/records-write.d.ts.map +1 -1
  165. package/dist/workspace/records.d.ts +34 -4
  166. package/dist/workspace/records.d.ts.map +1 -1
  167. package/dist/workspace/status-gates.d.ts +7 -2
  168. package/dist/workspace/status-gates.d.ts.map +1 -1
  169. package/dist/workspace/status-stewards.d.ts +65 -1
  170. package/dist/workspace/status-stewards.d.ts.map +1 -1
  171. package/dist/workspace/status.d.ts +24 -0
  172. package/dist/workspace/status.d.ts.map +1 -1
  173. package/dist/workspace/work-cli.d.ts +113 -2
  174. package/dist/workspace/work-cli.d.ts.map +1 -1
  175. package/dist/workspace/work-evidence.d.ts +74 -0
  176. package/dist/workspace/work-evidence.d.ts.map +1 -0
  177. package/dist/workspace/work.d.ts +43 -1
  178. package/dist/workspace/work.d.ts.map +1 -1
  179. package/package.json +1 -1
  180. package/src/cli/commands/audit.test.ts +9 -1
  181. package/src/cli/commands/build.ts +3 -2
  182. package/src/cli/commands/lint.ts +7 -1
  183. package/src/cli/handlers/graph.test.ts +20 -0
  184. package/src/cli/handlers/graph.ts +16 -2
  185. package/src/cli/handlers/operator.ts +34 -2
  186. package/src/cli/handlers/run.test.ts +154 -2
  187. package/src/cli/handlers/run.ts +121 -2
  188. package/src/cli/main.test.ts +10 -0
  189. package/src/cli/main.ts +23 -3
  190. package/src/cli/mcp/workspace-plugins.ts +6 -6
  191. package/src/cli/mcp/workspace-tools.test.ts +35 -19
  192. package/src/cli/mcp/workspace-tools.ts +62 -4
  193. package/src/cli/plugins.ts +11 -3
  194. package/src/cli/registry.ts +12 -2
  195. package/src/cli/serve-mcp-workspace.test.ts +6 -6
  196. package/src/codegen/pinned-upgrade.ts +2 -1
  197. package/src/codegen/release-wiring.test.ts +49 -2
  198. package/src/components/capability-plugin-loader.ts +3 -3
  199. package/src/components/cli-support.ts +2 -2
  200. package/src/config.ts +11 -0
  201. package/src/lexicon-module.ts +56 -1
  202. package/src/lexicon-package.test.ts +96 -0
  203. package/src/lifecycle/converge-ledger.ts +20 -0
  204. package/src/lifecycle/run-ledger.ts +6 -0
  205. package/src/lifecycle/symptoms.ts +95 -0
  206. package/src/lint/rules/index.ts +6 -2
  207. package/src/lint/rules/op/index.ts +17 -4
  208. package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +23 -1
  209. package/src/lint/rules/op/ops014-converge-rule-refusals.ts +10 -6
  210. package/src/lint/rules/op/sys010-key-over-plain-http.test.ts +52 -0
  211. package/src/lint/rules/op/sys010-key-over-plain-http.ts +100 -0
  212. package/src/lint/rules/sys001-no-literal-key.test.ts +31 -0
  213. package/src/lint/rules/sys001-no-literal-key.ts +67 -0
  214. package/src/op/__fixtures__/decide-stub-backend.ts +143 -0
  215. package/src/op/activities/activity-contracts.ts +190 -1
  216. package/src/op/activities/apply.ts +7 -6
  217. package/src/op/activities/change-coverage.ts +60 -0
  218. package/src/op/activities/converge.test.ts +55 -1
  219. package/src/op/activities/converge.ts +208 -29
  220. package/src/op/activities/decide.live.test.ts +78 -0
  221. package/src/op/activities/decide.test.ts +308 -0
  222. package/src/op/activities/decide.ts +267 -0
  223. package/src/op/activities/index.ts +21 -0
  224. package/src/op/activities/shell.test.ts +91 -1
  225. package/src/op/activities/shell.ts +91 -2
  226. package/src/op/activities/source-release.test.ts +118 -0
  227. package/src/op/activities/source-release.ts +168 -0
  228. package/src/op/activities/source-rollback.test.ts +131 -0
  229. package/src/op/activities/source-rollback.ts +239 -0
  230. package/src/op/activities/work-evidence.ts +62 -0
  231. package/src/op/activity-contract-registry.test.ts +2 -0
  232. package/src/op/activity-contract-registry.ts +2 -2
  233. package/src/op/activity-contract.test.ts +12 -0
  234. package/src/op/activity-contract.ts +6 -1
  235. package/src/op/activity-profiles.ts +29 -0
  236. package/src/op/activity-registry.test.ts +1 -1
  237. package/src/op/activity-registry.ts +2 -2
  238. package/src/op/builders.ts +119 -5
  239. package/src/op/command-gate.test.ts +192 -0
  240. package/src/op/composites/converge-op.test.ts +27 -1
  241. package/src/op/composites/converge-op.ts +69 -15
  242. package/src/op/decide-backend.test.ts +44 -0
  243. package/src/op/decide-backend.ts +212 -0
  244. package/src/op/decide-config.test.ts +52 -0
  245. package/src/op/decide-config.ts +80 -0
  246. package/src/op/decide-read-inputs.ts +117 -0
  247. package/src/op/gate-approval.ts +2 -2
  248. package/src/op/gate-wait.ts +57 -0
  249. package/src/op/gate.ts +8 -3
  250. package/src/op/generate-pipeline.ts +2 -2
  251. package/src/op/index.ts +18 -3
  252. package/src/op/local-executor.ts +151 -15
  253. package/src/op/local-output.test.ts +33 -0
  254. package/src/op/local-output.ts +20 -2
  255. package/src/op/op-ir.test.ts +10 -0
  256. package/src/op/op-ir.ts +4 -0
  257. package/src/op/op-verb-class.ts +1 -0
  258. package/src/op/operator.ts +290 -11
  259. package/src/op/runtime.ts +31 -8
  260. package/src/op/runtimes/local.ts +3 -1
  261. package/src/op/source-archive.ts +161 -0
  262. package/src/op/steward-points.test.ts +364 -0
  263. package/src/op/steward-points.ts +194 -0
  264. package/src/op/steward-turn.ts +79 -0
  265. package/src/op/steward.test.ts +87 -3
  266. package/src/op/steward.ts +25 -1
  267. package/src/op/types.ts +7 -0
  268. package/src/op/work-lease-run.test.ts +20 -1
  269. package/src/op/work-lease-run.ts +2 -2
  270. package/src/workspace/__fixtures__/decide-workspace.ts +129 -0
  271. package/src/workspace/__fixtures__/studio-template-84c8b21.json +67 -0
  272. package/src/workspace/answers-ledger.ts +118 -0
  273. package/src/workspace/box-intent.test.ts +205 -0
  274. package/src/workspace/box-intent.ts +159 -0
  275. package/src/workspace/changes-cli.ts +56 -0
  276. package/src/workspace/changes.schema.json +472 -0
  277. package/src/workspace/changes.test.ts +315 -0
  278. package/src/workspace/changes.ts +512 -0
  279. package/src/workspace/chant-migrations/chud-lexicon-exit-fly-site.ts +234 -0
  280. package/src/workspace/chant-migrations/chud-lexicon-exit-live-names.ts +164 -0
  281. package/src/workspace/chant-migrations/chud-lexicon-exit-rollback.ts +223 -0
  282. package/src/workspace/chant-migrations/chud-lexicon-exit-ship-inputs.ts +195 -0
  283. package/src/workspace/chant-migrations/chud-lexicon-exit-ship-policy.ts +108 -0
  284. package/src/workspace/chant-migrations/chud-lexicon-exit.ts +882 -0
  285. package/src/workspace/chant-migrations.e2e.test.ts +1089 -0
  286. package/src/workspace/chant-migrations.ts +169 -0
  287. package/src/workspace/check-contract.test.ts +4 -2
  288. package/src/workspace/check.schema.json +19 -5
  289. package/src/workspace/checks/boxes.test.ts +82 -2
  290. package/src/workspace/checks/boxes.ts +202 -1
  291. package/src/workspace/checks/diagrams.test.ts +134 -0
  292. package/src/workspace/checks/diagrams.ts +108 -0
  293. package/src/workspace/checks/records.ts +47 -0
  294. package/src/workspace/checks.ts +20 -2
  295. package/src/workspace/compose-graph.ts +2 -0
  296. package/src/workspace/conformance/__fixture__/decisions/decision.kind.mjs +10 -0
  297. package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +26 -0
  298. package/src/workspace/conformance/index.ts +5 -0
  299. package/src/workspace/decide.test.ts +1 -1
  300. package/src/workspace/decide.ts +156 -23
  301. package/src/workspace/decision-points.schema.json +3 -3
  302. package/src/workspace/declaration.schema.json +119 -1
  303. package/src/workspace/declaration.test.ts +58 -0
  304. package/src/workspace/declaration.ts +112 -0
  305. package/src/workspace/declared-kinds.test.ts +31 -5
  306. package/src/workspace/declared-kinds.ts +46 -1
  307. package/src/workspace/generated-files.ts +14 -0
  308. package/src/workspace/graph-cli.ts +1 -1
  309. package/src/workspace/graph.schema.json +9 -1
  310. package/src/workspace/intent-joins.test.ts +5 -5
  311. package/src/workspace/intent-joins.ts +5 -5
  312. package/src/workspace/intent.schema.json +8 -2
  313. package/src/workspace/intent.ts +3 -10
  314. package/src/workspace/lineage-check.ts +16 -1
  315. package/src/workspace/lineage-upgrade-cli.ts +1 -1
  316. package/src/workspace/lineage-upgrade.test.ts +70 -0
  317. package/src/workspace/lineage-upgrade.ts +81 -10
  318. package/src/workspace/ls-contract.test.ts +57 -0
  319. package/src/workspace/ls.schema.json +46 -1
  320. package/src/workspace/ls.ts +62 -3
  321. package/src/workspace/points-cli.ts +17 -3
  322. package/src/workspace/points-write.schema.json +11 -1
  323. package/src/workspace/points.schema.json +51 -0
  324. package/src/workspace/points.test.ts +16 -15
  325. package/src/workspace/points.ts +5 -17
  326. package/src/workspace/read-contract.test.ts +9 -1
  327. package/src/workspace/reason-codes.test.ts +18 -8
  328. package/src/workspace/reason-codes.ts +21 -2
  329. package/src/workspace/records-amend.schema.json +2 -0
  330. package/src/workspace/records-cli.ts +27 -4
  331. package/src/workspace/records-close.schema.json +2 -0
  332. package/src/workspace/records-formats.test.ts +15 -15
  333. package/src/workspace/records-new.schema.json +2 -0
  334. package/src/workspace/records-review.schema.json +2 -0
  335. package/src/workspace/records-sessions-write.e2e.test.ts +77 -0
  336. package/src/workspace/records-sessions-write.test.ts +2 -34
  337. package/src/workspace/records-since.test.ts +8 -7
  338. package/src/workspace/records-write.e2e.test.ts +108 -0
  339. package/src/workspace/records-write.test.ts +32 -41
  340. package/src/workspace/records-write.ts +33 -15
  341. package/src/workspace/records.schema.json +36 -2
  342. package/src/workspace/records.test.ts +49 -4
  343. package/src/workspace/records.ts +109 -3
  344. package/src/workspace/status-contract.test.ts +14 -8
  345. package/src/workspace/status-gates.ts +9 -4
  346. package/src/workspace/status-stewards.ts +155 -5
  347. package/src/workspace/status.schema.json +129 -8
  348. package/src/workspace/status.ts +46 -1
  349. package/src/workspace/work-acceptance.test.ts +274 -0
  350. package/src/workspace/{work-cli.test.ts → work-cli.e2e.test.ts} +1 -1
  351. package/src/workspace/work-cli.ts +193 -10
  352. package/src/workspace/work-evidence.schema.json +212 -0
  353. package/src/workspace/work-evidence.ts +169 -0
  354. package/src/workspace/work-history.schema.json +349 -0
  355. package/src/workspace/work-history.test.ts +156 -0
  356. package/src/workspace/{work-readiness-chud.test.ts → work-readiness.test.ts} +30 -32
  357. package/src/workspace/work.test.ts +20 -2
  358. package/src/workspace/work.ts +100 -1
  359. /package/src/cli/{discovery-skip.test.ts → discovery-skip.e2e.test.ts} +0 -0
  360. /package/src/workspace/conformance/{conformance.test.ts → conformance.e2e.test.ts} +0 -0
  361. /package/src/workspace/{which-chant.test.ts → which-chant.e2e.test.ts} +0 -0
@@ -25,6 +25,7 @@
25
25
 
26
26
  import { z } from "zod";
27
27
  import { activityContract } from "../activity-contract";
28
+ import { backendSchema } from "../decide-config";
28
29
 
29
30
  export const lifecycleSnapshotContract = activityContract(
30
31
  "lifecycleSnapshot",
@@ -54,8 +55,14 @@ export const shellCmdContract = activityContract(
54
55
  env: z.record(z.string(), z.string()).optional(),
55
56
  cwd: z.string().optional(),
56
57
  okExit: z.array(z.number()).optional(),
58
+ gatedExit: z.number().optional(),
59
+ gate: z.strictObject({ op: z.string(), gate: z.string() }).optional(),
60
+ json: z.boolean().optional(),
57
61
  }),
58
- z.object({ stdout: z.string(), stderr: z.string(), exitCode: z.number() }),
62
+ // `json` is stdout parsed, when the step sets `json` (#2787): whatever the
63
+ // command printed, so its shape is the author's and only the whole value is
64
+ // a reference target (`sh.out.json`).
65
+ z.object({ stdout: z.string(), stderr: z.string(), exitCode: z.number(), json: z.unknown().optional() }),
59
66
  );
60
67
 
61
68
  export const httpCheckContract = activityContract(
@@ -166,3 +173,185 @@ export const proposeWorkspaceUpgradeContract = activityContract(
166
173
  summary: z.string(),
167
174
  }),
168
175
  );
176
+
177
+ /**
178
+ * The forward coverage check over an Op's own diff (#2773). `args` mirrors
179
+ * `ChangeCoverageArgs`. `returns` names what a step reads: whether the check
180
+ * passed, the range and work item checked, and each finding with the
181
+ * `triage` a work item seeded from it takes as its `source`.
182
+ */
183
+ export const changeCoverageContract = activityContract(
184
+ "changeCoverage",
185
+ z.strictObject({
186
+ cwd: z.string().optional(),
187
+ range: z.string().optional(),
188
+ work: z.string().optional(),
189
+ severity: z.enum(["off", "warn", "fail"]).optional(),
190
+ }),
191
+ z.object({
192
+ ok: z.boolean(),
193
+ range: z.object({ spec: z.string(), base: z.string(), head: z.string() }),
194
+ work: z.string().nullable(),
195
+ severity: z.enum(["off", "warn", "fail"]),
196
+ findings: z.array(
197
+ z.object({
198
+ code: z.enum(["change-uncovered", "change-out-of-scope"]),
199
+ path: z.string(),
200
+ message: z.string(),
201
+ severity: z.enum(["warn", "fail"]),
202
+ records: z.array(z.string()),
203
+ triage: z.object({ finding: z.enum(["change-uncovered", "change-out-of-scope"]), region: z.string() }),
204
+ }),
205
+ ),
206
+ summary: z.object({
207
+ paths: z.number(),
208
+ covered: z.number(),
209
+ uncovered: z.number(),
210
+ outOfScope: z.number(),
211
+ ignored: z.number(),
212
+ records: z.number(),
213
+ }),
214
+ }),
215
+ );
216
+
217
+ /**
218
+ * Evidence for an acceptance criterion, under the run's work lease (#2772).
219
+ * `lease` is the run's lease, a reference the builder fills in, so it is not
220
+ * checked here. `returns` names what a step reads: the item, the record's
221
+ * path, the entry appended and the criteria counted with it.
222
+ */
223
+ export const workEvidenceContract = activityContract(
224
+ "workEvidence",
225
+ z.strictObject({
226
+ lease: z.unknown(),
227
+ criterion: z.string(),
228
+ result: z.enum(["pass", "fail"]),
229
+ title: z.string(),
230
+ url: z.string().optional(),
231
+ path: z.string().optional(),
232
+ kind: z.string().optional(),
233
+ cwd: z.string().optional(),
234
+ }),
235
+ z.object({
236
+ item: z.string(),
237
+ path: z.string(),
238
+ evidence: z.record(z.string(), z.unknown()),
239
+ acceptance: z.object({ met: z.number(), total: z.number(), criteria: z.array(z.object({ id: z.string(), verification: z.string(), met: z.boolean() })) }),
240
+ }),
241
+ );
242
+
243
+ /**
244
+ * The source-release activities (#2782, ./source-release.ts). A release Op
245
+ * reads `archive.out.digest` into its plan, `plan.out.digest` into its gate
246
+ * and its ship step, and `plan.out.file` into its record step.
247
+ */
248
+ export const sourceArchiveContract = activityContract(
249
+ "sourceArchive",
250
+ z.strictObject({ path: z.string(), ref: z.string().optional(), out: z.string().optional(), cwd: z.string().optional() }),
251
+ z.object({ digest: z.string(), archive: z.string(), commit: z.string(), dir: z.string(), files: z.number(), bytes: z.number() }),
252
+ );
253
+
254
+ export const releasePlanContract = activityContract(
255
+ "releasePlan",
256
+ z.strictObject({
257
+ component: z.string(),
258
+ env: z.string(),
259
+ gitSha: z.string(),
260
+ content: z.record(z.string(), z.unknown()),
261
+ dir: z.string().optional(),
262
+ cwd: z.string().optional(),
263
+ }),
264
+ z.object({ digest: z.string(), file: z.string(), gitSha: z.string() }),
265
+ );
266
+
267
+ export const releaseRecordContract = activityContract(
268
+ "releaseRecord",
269
+ z.strictObject({
270
+ plan: z.string(),
271
+ digest: z.string().optional(),
272
+ approval: z.strictObject({ op: z.string(), gate: z.string() }).optional(),
273
+ actor: z.string().optional(),
274
+ runId: z.string().optional(),
275
+ cwd: z.string().optional(),
276
+ }),
277
+ z.object({ recorded: z.boolean(), digest: z.string(), env: z.string(), component: z.string(), approver: z.string().nullable() }),
278
+ );
279
+
280
+ /**
281
+ * `decide` (#2740, core's since #2828). OPS012 checks a step's args against
282
+ * it and OPS013 a later step's reference into its result, so a misspelled
283
+ * `point` or a key written as a literal string fails `chant build` rather
284
+ * than a run.
285
+ */
286
+ const decideEscalation = z.object({ kind: z.enum(["table", "model"]), reason: z.string() }).loose();
287
+
288
+ export const decideContract = activityContract(
289
+ "decide",
290
+ z.strictObject({
291
+ point: z.string().min(1),
292
+ inputs: z.record(z.string(), z.unknown()).optional(),
293
+ read: z.record(z.string(), z.string()).optional(),
294
+ subject: z.string().optional(),
295
+ kind: z.string().optional(),
296
+ cwd: z.string().optional(),
297
+ backends: z.record(z.string(), backendSchema).optional(),
298
+ dryRun: z.boolean().optional(),
299
+ }),
300
+ z.strictObject({
301
+ id: z.string(),
302
+ path: z.string(),
303
+ state: z.enum(["escalated", "proposed", "answered"]),
304
+ open: z.boolean(),
305
+ answer: z.union([z.string(), z.boolean(), z.null()]),
306
+ decider: z.string(),
307
+ model: z.string().nullable(),
308
+ backend: z.string().nullable(),
309
+ confidence: z.number().nullable(),
310
+ threshold: z.number().nullable(),
311
+ answeredBy: z.array(z.string()),
312
+ escalations: z.array(decideEscalation),
313
+ missing: z.array(z.string()),
314
+ }),
315
+ { entities: ["point"] },
316
+ );
317
+
318
+ /**
319
+ * The rollback activities for a source release (#2800, ./source-rollback.ts).
320
+ * A rollback Op reads `plan.out.digest` into its gate, `plan.out.to` and the
321
+ * archive fields into the step that restores the Machine, and
322
+ * `plan.out.file` into its record step.
323
+ */
324
+ export const releaseRollbackPlanContract = activityContract(
325
+ "releaseRollbackPlan",
326
+ z.strictObject({
327
+ component: z.string(),
328
+ env: z.string(),
329
+ to: z.string().optional(),
330
+ path: z.string().optional(),
331
+ dir: z.string().optional(),
332
+ cwd: z.string().optional(),
333
+ }),
334
+ z.object({
335
+ digest: z.string(),
336
+ file: z.string(),
337
+ to: z.string(),
338
+ from: z.string(),
339
+ gitSha: z.string(),
340
+ archive: z.string(),
341
+ archiveDigest: z.string(),
342
+ dir: z.string(),
343
+ }),
344
+ );
345
+
346
+ export const releaseRollbackRecordContract = activityContract(
347
+ "releaseRollbackRecord",
348
+ z.strictObject({
349
+ plan: z.string(),
350
+ digest: z.string().optional(),
351
+ approval: z.strictObject({ op: z.string(), gate: z.string() }).optional(),
352
+ actor: z.string().optional(),
353
+ runId: z.string().optional(),
354
+ cwd: z.string().optional(),
355
+ }),
356
+ z.object({ recorded: z.boolean(), digest: z.string(), env: z.string(), component: z.string(), approver: z.string().nullable() }),
357
+ );
@@ -35,6 +35,7 @@
35
35
  import { exec } from "node:child_process";
36
36
  import { promisify } from "node:util";
37
37
  import { normalizeApply, type ApplyResult } from "../../apply";
38
+ import { importLexiconPackage } from "../../lexicon-module";
38
39
 
39
40
  const execAsync = promisify(exec);
40
41
 
@@ -241,7 +242,7 @@ async function loadK8sApplier(): Promise<K8sApplier> {
241
242
  const spec = "@intentius/chant-lexicon-k8s/op/activities";
242
243
  let mod: { applyManifest?: K8sApplier };
243
244
  try {
244
- mod = (await import(spec)) as { applyManifest?: K8sApplier };
245
+ mod = (await importLexiconPackage(spec)) as { applyManifest?: K8sApplier };
245
246
  } catch (err) {
246
247
  throw new Error(
247
248
  `apply target "kubectl" needs @intentius/chant-lexicon-k8s, which could not be loaded ` +
@@ -269,7 +270,7 @@ async function loadAzureApplier(): Promise<AzureApplier> {
269
270
  };
270
271
  let mod: AzureModule;
271
272
  try {
272
- mod = (await import(spec)) as AzureModule;
273
+ mod = (await importLexiconPackage(spec)) as AzureModule;
273
274
  } catch (err) {
274
275
  throw new Error(
275
276
  `apply target "arm" needs @intentius/chant-lexicon-azure, which could not be loaded ` +
@@ -304,7 +305,7 @@ async function loadGcpApplier(): Promise<GcpApplier> {
304
305
  };
305
306
  let mod: GcpModule;
306
307
  try {
307
- mod = (await import(spec)) as GcpModule;
308
+ mod = (await importLexiconPackage(spec)) as GcpModule;
308
309
  } catch (err) {
309
310
  throw new Error(
310
311
  `apply target "gcp" needs @intentius/chant-lexicon-gcp, which could not be loaded ` +
@@ -339,7 +340,7 @@ async function loadFlyApplier(): Promise<FlyApplier> {
339
340
  };
340
341
  let mod: FlyModule;
341
342
  try {
342
- mod = (await import(spec)) as FlyModule;
343
+ mod = (await importLexiconPackage(spec)) as FlyModule;
343
344
  } catch (err) {
344
345
  throw new Error(
345
346
  `apply target "fly" needs @intentius/chant-lexicon-fly, which could not be loaded ` +
@@ -370,7 +371,7 @@ async function loadAwsApplier(): Promise<AwsApplier> {
370
371
  const spec = "@intentius/chant-lexicon-aws/op/activities";
371
372
  let mod: { awsApply?: AwsApplier };
372
373
  try {
373
- mod = (await import(spec)) as { awsApply?: AwsApplier };
374
+ mod = (await importLexiconPackage(spec)) as { awsApply?: AwsApplier };
374
375
  } catch (err) {
375
376
  throw new Error(
376
377
  `apply target "cloudformation" needs @intentius/chant-lexicon-aws, which could not be loaded ` +
@@ -395,7 +396,7 @@ async function loadAwsRollback(): Promise<AwsRollback> {
395
396
  const spec = "@intentius/chant-lexicon-aws/op/activities";
396
397
  let mod: { rollbackStack?: AwsRollback };
397
398
  try {
398
- mod = (await import(spec)) as { rollbackStack?: AwsRollback };
399
+ mod = (await importLexiconPackage(spec)) as { rollbackStack?: AwsRollback };
399
400
  } catch (err) {
400
401
  throw new Error(
401
402
  `rollback for target "cloudformation" needs @intentius/chant-lexicon-aws, which could not be ` +
@@ -0,0 +1,60 @@
1
+ /**
2
+ * changeCoverage — the forward coverage check (#2773) as an Op activity, for
3
+ * an Op that changes the checkout (#2748) to run on its own diff.
4
+ *
5
+ * Such an Op's leased steps work in a worktree of their own on
6
+ * `chant/work/[<member>/]<item>`. Given that worktree as `cwd`
7
+ * (`workLeaseOutput("worktree")`) and no `range`, the activity checks the
8
+ * commits the branch holds beyond the main worktree's HEAD, with the branch's
9
+ * item as the work item in hand, exactly as `chant workspace check --changes
10
+ * <base>..HEAD --work <item>` would. A `range` or `work` given replaces what
11
+ * the branch says.
12
+ *
13
+ * The step fails when the check's severity is `fail` and it has a finding,
14
+ * or when the check can't run; otherwise it returns the document's findings
15
+ * and summary for later steps. The workspace code loads on first call, so
16
+ * importing core's activities loads nothing under `workspace/` (#2525 rule 5).
17
+ */
18
+
19
+ import type { ChangeFinding, ChangesDocument } from "../../workspace/changes";
20
+
21
+ export interface ChangeCoverageArgs {
22
+ /** The checkout to check: the Op's worktree. Default: the working directory. */
23
+ cwd?: string;
24
+ /** `<base>..<head>`, `<base>...<head>` or `<base>`. Default: the work branch's own commits. */
25
+ range?: string;
26
+ /** The work item in hand. Default: the work branch's item. */
27
+ work?: string;
28
+ /** In place of the declaration's `changes.severity`. */
29
+ severity?: "off" | "warn" | "fail";
30
+ }
31
+
32
+ export interface ChangeCoverageResult {
33
+ ok: boolean;
34
+ range: { spec: string; base: string; head: string };
35
+ work: string | null;
36
+ severity: "off" | "warn" | "fail";
37
+ findings: Pick<ChangeFinding, "code" | "path" | "message" | "severity" | "records" | "triage">[];
38
+ summary: Exclude<ChangesDocument, { error: unknown }>["summary"];
39
+ }
40
+
41
+ export async function changeCoverage(args: ChangeCoverageArgs = {}): Promise<ChangeCoverageResult> {
42
+ const { checkChanges, workBranchChanges } = await import("../../workspace/changes");
43
+ const cwd = args.cwd ?? process.cwd();
44
+ const branch = args.range === undefined ? workBranchChanges(cwd) : undefined;
45
+ const range = args.range ?? branch?.range;
46
+ if (range === undefined) throw new Error(`changeCoverage: ${cwd} is not on a chant/work/ branch, so give the range to check`);
47
+ const work = args.work ?? branch?.work;
48
+ const { doc } = await checkChanges({ cwd, range, ...(work !== undefined ? { work } : {}), ...(args.severity ? { severity: args.severity } : {}) });
49
+ if ("error" in doc) throw new Error(`changeCoverage: ${doc.error.code}: ${doc.error.message}`);
50
+ const result: ChangeCoverageResult = {
51
+ ok: doc.ok,
52
+ range: doc.range,
53
+ work: doc.work?.record ?? null,
54
+ severity: doc.severity,
55
+ findings: doc.findings.map(({ code, path, message, severity, records, triage }) => ({ code, path, message, severity, records, triage })),
56
+ summary: doc.summary,
57
+ };
58
+ if (!doc.ok) throw new Error(`changeCoverage: ${doc.findings.length} change ${doc.findings.length === 1 ? "finding" : "findings"} at severity fail: ${doc.findings.map((f) => `${f.code} ${f.path}`).join(", ")}`);
59
+ return result;
60
+ }
@@ -1,9 +1,11 @@
1
1
  import { describe, test, expect } from "vitest";
2
2
  import { eq, gt, run, report, when } from "../converge-rule";
3
- import type { ConvergeSymptom } from "../../lifecycle/symptoms";
3
+ import { parseResourceObservation, type ConvergeSymptom, type ObservedResource, type ResourceSymptom } from "../../lifecycle/symptoms";
4
4
  import type { ConvergeTickRecord, ConvergeRuleOutcome } from "../../lifecycle/converge-ledger";
5
5
  import {
6
6
  planConvergeTick,
7
+ planResourceTick,
8
+ consecutiveResourceFires,
7
9
  verbClassAllowedToDispatch,
8
10
  enforceVerbClassAtDispatch,
9
11
  sanitizeOneLine,
@@ -354,3 +356,55 @@ describe("classifyDispatchFailure", () => {
354
356
  expect(classifyDispatchFailure("")).toBeUndefined();
355
357
  });
356
358
  });
359
+
360
+ describe("planResourceTick — rules evaluated once per observed resource (#2778)", () => {
361
+ const restart = when<ResourceSymptom>(eq("status", "drifted"), run("restart-service"), { id: "restart-drifted", why: "Restart a drifted service." });
362
+ const unknownR = when<ResourceSymptom>(eq("status", "unknown"), report("not observed"), { id: "report-unknown", why: "unknown never remediates." });
363
+ const resources: ObservedResource[] = [
364
+ { name: "app", status: "drifted", detail: "stopped" },
365
+ { name: "hud", status: "in-sync" },
366
+ { name: "door", status: "drifted" },
367
+ { name: "site", status: "unknown", detail: "no health" },
368
+ ];
369
+
370
+ test("a fired run() is planned for each drifted resource, and names it", () => {
371
+ const plan = planResourceTick("box", resources, [restart, unknownR], [], "box-converge", "apply", 3);
372
+ expect(plan.firedRuleIds).toEqual(["restart-drifted", "report-unknown"]);
373
+ expect(plan.outcomes).toEqual([
374
+ { ruleId: "restart-drifted", resource: "app", action: "ran", op: "restart-service" },
375
+ { ruleId: "restart-drifted", resource: "door", action: "ran", op: "restart-service" },
376
+ { ruleId: "report-unknown", resource: "site", action: "reported", reason: "not observed" },
377
+ ]);
378
+ });
379
+
380
+ test("unknown never remediates, the dial and the budget hold per tick", () => {
381
+ const anyStatus = when<ResourceSymptom>(eq("env", "box"), run("restart-service"), { id: "restart-all", why: "x" });
382
+ const plan = planResourceTick("box", [{ name: "site", status: "unknown" }], [anyStatus], [], "box-converge", "apply", 3);
383
+ expect(plan.outcomes[0]).toMatchObject({ action: "reported", resource: "site", reason: expect.stringMatching(/unknown never remediates/) });
384
+ expect(planResourceTick("box", resources, [restart], [], "box-converge", "observe", 3).outcomes.map((o) => o.action)).toEqual(["reported", "reported"]);
385
+ expect(planResourceTick("box", resources, [restart], [], "box-converge", "apply", 1).outcomes.map((o) => o.action)).toEqual(["ran", "skipped-budget"]);
386
+ });
387
+
388
+ test("flap damping counts one rule's fires for one resource, on this op's ticks", () => {
389
+ const fired = (resource: string, op = "box-converge") =>
390
+ tick({ op, firedRuleIds: ["restart-drifted"], outcomes: [{ ruleId: "restart-drifted", action: "ran", op: "restart-service", resource }] });
391
+ const prior = [fired("app"), fired("app"), fired("hud", "other-converge"), fired("app")];
392
+ expect(consecutiveResourceFires(prior, "box-converge", "restart-drifted", "app")).toBe(3);
393
+ expect(consecutiveResourceFires(prior, "box-converge", "restart-drifted", "door")).toBe(0);
394
+ const plan = planResourceTick("box", resources, [restart], prior, "box-converge", "apply", 3);
395
+ expect(plan.outcomes.map((o) => [o.resource, o.action])).toEqual([["app", "skipped-flap"], ["door", "ran"]]);
396
+ });
397
+ });
398
+
399
+ describe("parseResourceObservation (#2778)", () => {
400
+ test("reads an observation, or a shell result that prints one, and refuses anything else", () => {
401
+ const observation = { resources: [{ name: "app", status: "drifted", detail: "stopped" }] };
402
+ expect(parseResourceObservation(observation)).toEqual(observation);
403
+ expect(parseResourceObservation({ stdout: JSON.stringify(observation), stderr: "", exitCode: 0 })).toEqual(observation);
404
+ expect(() => parseResourceObservation({ stdout: "nope", stderr: "", exitCode: 0 })).toThrow(/not JSON/);
405
+ expect(() => parseResourceObservation({})).toThrow(/no `resources` array/);
406
+ expect(() => parseResourceObservation({ resources: [{ name: "app", status: "down" }] })).toThrow(/in-sync, drifted or unknown/);
407
+ expect(() => parseResourceObservation({ resources: [{ status: "drifted" }] })).toThrow(/has no name/);
408
+ expect(() => parseResourceObservation({ resources: [{ name: "a", status: "drifted" }, { name: "a", status: "in-sync" }] })).toThrow(/twice/);
409
+ });
410
+ });