@intentius/chant 0.13.1 → 0.15.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 (450) hide show
  1. package/dist/audit/catalog.d.ts +45 -5
  2. package/dist/audit/catalog.d.ts.map +1 -1
  3. package/dist/audit/proof.d.ts +3 -0
  4. package/dist/audit/proof.d.ts.map +1 -1
  5. package/dist/audit/report-model.d.ts +4 -1
  6. package/dist/audit/report-model.d.ts.map +1 -1
  7. package/dist/audit/report.d.ts +3 -0
  8. package/dist/audit/report.d.ts.map +1 -1
  9. package/dist/audit/rules-doc.d.ts +8 -2
  10. package/dist/audit/rules-doc.d.ts.map +1 -1
  11. package/dist/cli/commands/audit.d.ts.map +1 -1
  12. package/dist/cli/commands/doctor.d.ts.map +1 -1
  13. package/dist/cli/commands/lexicon-rolling-upgrade.d.ts +37 -0
  14. package/dist/cli/commands/lexicon-rolling-upgrade.d.ts.map +1 -0
  15. package/dist/cli/commands/lexicon-surface-diff.d.ts +48 -0
  16. package/dist/cli/commands/lexicon-surface-diff.d.ts.map +1 -0
  17. package/dist/cli/commands/lint.d.ts.map +1 -1
  18. package/dist/cli/commands/pinned-upgrade.d.ts +41 -0
  19. package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -0
  20. package/dist/cli/handlers/build.d.ts.map +1 -1
  21. package/dist/cli/handlers/components.d.ts +39 -0
  22. package/dist/cli/handlers/components.d.ts.map +1 -0
  23. package/dist/cli/handlers/dev.d.ts +3 -0
  24. package/dist/cli/handlers/dev.d.ts.map +1 -1
  25. package/dist/cli/handlers/graph.d.ts +4 -2
  26. package/dist/cli/handlers/graph.d.ts.map +1 -1
  27. package/dist/cli/handlers/misc.d.ts.map +1 -1
  28. package/dist/cli/handlers/run.d.ts +49 -0
  29. package/dist/cli/handlers/run.d.ts.map +1 -1
  30. package/dist/cli/main.d.ts.map +1 -1
  31. package/dist/cli/registry.d.ts +35 -0
  32. package/dist/cli/registry.d.ts.map +1 -1
  33. package/dist/codegen/fetch.d.ts +22 -0
  34. package/dist/codegen/fetch.d.ts.map +1 -1
  35. package/dist/codegen/lexicon-regen.d.ts +110 -0
  36. package/dist/codegen/lexicon-regen.d.ts.map +1 -0
  37. package/dist/codegen/pinned-upgrade.d.ts +153 -0
  38. package/dist/codegen/pinned-upgrade.d.ts.map +1 -0
  39. package/dist/codegen/rolling-upgrade.d.ts +138 -0
  40. package/dist/codegen/rolling-upgrade.d.ts.map +1 -0
  41. package/dist/codegen/surface-snapshot.d.ts +173 -0
  42. package/dist/codegen/surface-snapshot.d.ts.map +1 -0
  43. package/dist/codegen/version-bump.d.ts +21 -0
  44. package/dist/codegen/version-bump.d.ts.map +1 -0
  45. package/dist/components/auto-release.d.ts +93 -0
  46. package/dist/components/auto-release.d.ts.map +1 -0
  47. package/dist/components/builders.d.ts +37 -0
  48. package/dist/components/builders.d.ts.map +1 -0
  49. package/dist/components/capability-plugin-loader.d.ts +111 -0
  50. package/dist/components/capability-plugin-loader.d.ts.map +1 -0
  51. package/dist/components/capability-plugin-schema.d.ts +24 -0
  52. package/dist/components/capability-plugin-schema.d.ts.map +1 -0
  53. package/dist/components/capability-plugin.d.ts +85 -0
  54. package/dist/components/capability-plugin.d.ts.map +1 -0
  55. package/dist/components/capability.d.ts +89 -0
  56. package/dist/components/capability.d.ts.map +1 -0
  57. package/dist/components/cli-support.d.ts +204 -0
  58. package/dist/components/cli-support.d.ts.map +1 -0
  59. package/dist/components/component.d.ts +179 -0
  60. package/dist/components/component.d.ts.map +1 -0
  61. package/dist/components/config-defaults.d.ts +41 -0
  62. package/dist/components/config-defaults.d.ts.map +1 -0
  63. package/dist/components/discover.d.ts +60 -0
  64. package/dist/components/discover.d.ts.map +1 -0
  65. package/dist/components/driver-output.d.ts +20 -0
  66. package/dist/components/driver-output.d.ts.map +1 -0
  67. package/dist/components/driver.d.ts +209 -0
  68. package/dist/components/driver.d.ts.map +1 -0
  69. package/dist/components/index.d.ts +22 -0
  70. package/dist/components/index.d.ts.map +1 -0
  71. package/dist/components/manifest-persistence.d.ts +79 -0
  72. package/dist/components/manifest-persistence.d.ts.map +1 -0
  73. package/dist/components/pilots/alb-ecs.pilot.d.ts +27 -0
  74. package/dist/components/pilots/alb-ecs.pilot.d.ts.map +1 -0
  75. package/dist/components/pilots/dynamodb.pilot.d.ts +22 -0
  76. package/dist/components/pilots/dynamodb.pilot.d.ts.map +1 -0
  77. package/dist/components/pilots/jar-emr.pilot.d.ts +37 -0
  78. package/dist/components/pilots/jar-emr.pilot.d.ts.map +1 -0
  79. package/dist/components/pilots/lambda.pilot.d.ts +35 -0
  80. package/dist/components/pilots/lambda.pilot.d.ts.map +1 -0
  81. package/dist/components/pilots/neo4j-fanout.pilot.d.ts +17 -0
  82. package/dist/components/pilots/neo4j-fanout.pilot.d.ts.map +1 -0
  83. package/dist/components/pilots/project.d.ts +13 -0
  84. package/dist/components/pilots/project.d.ts.map +1 -0
  85. package/dist/components/presets/ecs-fargate.d.ts +59 -0
  86. package/dist/components/presets/ecs-fargate.d.ts.map +1 -0
  87. package/dist/components/presets/index.d.ts +29 -0
  88. package/dist/components/presets/index.d.ts.map +1 -0
  89. package/dist/components/presets/lambda.d.ts +35 -0
  90. package/dist/components/presets/lambda.d.ts.map +1 -0
  91. package/dist/components/presets/single-host-compose.d.ts +43 -0
  92. package/dist/components/presets/single-host-compose.d.ts.map +1 -0
  93. package/dist/components/registry.d.ts +29 -0
  94. package/dist/components/registry.d.ts.map +1 -0
  95. package/dist/components/starter-plugin.d.ts +51 -0
  96. package/dist/components/starter-plugin.d.ts.map +1 -0
  97. package/dist/components/temporal-codegen-loader.d.ts +27 -0
  98. package/dist/components/temporal-codegen-loader.d.ts.map +1 -0
  99. package/dist/components/verbs/__tests__/mock-cloud-executor.d.ts +35 -0
  100. package/dist/components/verbs/__tests__/mock-cloud-executor.d.ts.map +1 -0
  101. package/dist/components/verbs/__tests__/mock-process-runner.d.ts +45 -0
  102. package/dist/components/verbs/__tests__/mock-process-runner.d.ts.map +1 -0
  103. package/dist/components/verbs/__tests__/mock-sbom-generator.d.ts +33 -0
  104. package/dist/components/verbs/__tests__/mock-sbom-generator.d.ts.map +1 -0
  105. package/dist/components/verbs/bom-writer.d.ts +155 -0
  106. package/dist/components/verbs/bom-writer.d.ts.map +1 -0
  107. package/dist/components/verbs/build-archive.d.ts +205 -0
  108. package/dist/components/verbs/build-archive.d.ts.map +1 -0
  109. package/dist/components/verbs/build.d.ts +150 -0
  110. package/dist/components/verbs/build.d.ts.map +1 -0
  111. package/dist/components/verbs/cloud-executor.d.ts +88 -0
  112. package/dist/components/verbs/cloud-executor.d.ts.map +1 -0
  113. package/dist/components/verbs/component-bom.d.ts +103 -0
  114. package/dist/components/verbs/component-bom.d.ts.map +1 -0
  115. package/dist/components/verbs/index.d.ts +49 -0
  116. package/dist/components/verbs/index.d.ts.map +1 -0
  117. package/dist/components/verbs/license-policy.d.ts +56 -0
  118. package/dist/components/verbs/license-policy.d.ts.map +1 -0
  119. package/dist/components/verbs/lockfile-sbom-generator.d.ts +81 -0
  120. package/dist/components/verbs/lockfile-sbom-generator.d.ts.map +1 -0
  121. package/dist/components/verbs/process-runner.d.ts +64 -0
  122. package/dist/components/verbs/process-runner.d.ts.map +1 -0
  123. package/dist/components/verbs/reproducibility.d.ts +80 -0
  124. package/dist/components/verbs/reproducibility.d.ts.map +1 -0
  125. package/dist/components/verbs/sbom-generator.d.ts +157 -0
  126. package/dist/components/verbs/sbom-generator.d.ts.map +1 -0
  127. package/dist/components/verbs/sbom.d.ts +79 -0
  128. package/dist/components/verbs/sbom.d.ts.map +1 -0
  129. package/dist/components/verbs/shell.d.ts +35 -0
  130. package/dist/components/verbs/shell.d.ts.map +1 -0
  131. package/dist/components/verbs/sign.d.ts +222 -0
  132. package/dist/components/verbs/sign.d.ts.map +1 -0
  133. package/dist/components/verbs/stub.d.ts +18 -0
  134. package/dist/components/verbs/stub.d.ts.map +1 -0
  135. package/dist/components/verbs/tool-sbom-generator.d.ts +51 -0
  136. package/dist/components/verbs/tool-sbom-generator.d.ts.map +1 -0
  137. package/dist/components/verbs/verify.d.ts +106 -0
  138. package/dist/components/verbs/verify.d.ts.map +1 -0
  139. package/dist/components/verbs/vex.d.ts +65 -0
  140. package/dist/components/verbs/vex.d.ts.map +1 -0
  141. package/dist/components/verbs/vuln-gate.d.ts +91 -0
  142. package/dist/components/verbs/vuln-gate.d.ts.map +1 -0
  143. package/dist/components/verbs/vuln-scan.d.ts +116 -0
  144. package/dist/components/verbs/vuln-scan.d.ts.map +1 -0
  145. package/dist/components/verbs/wait-verify.d.ts +85 -0
  146. package/dist/components/verbs/wait-verify.d.ts.map +1 -0
  147. package/dist/config.d.ts +205 -0
  148. package/dist/config.d.ts.map +1 -1
  149. package/dist/index.d.ts +4 -0
  150. package/dist/index.d.ts.map +1 -1
  151. package/dist/lexicon.d.ts +78 -0
  152. package/dist/lexicon.d.ts.map +1 -1
  153. package/dist/lifecycle/build-ledger-store.d.ts +121 -0
  154. package/dist/lifecycle/build-ledger-store.d.ts.map +1 -0
  155. package/dist/lifecycle/build-ledger.d.ts +225 -0
  156. package/dist/lifecycle/build-ledger.d.ts.map +1 -0
  157. package/dist/lifecycle/git.d.ts +84 -0
  158. package/dist/lifecycle/git.d.ts.map +1 -1
  159. package/dist/lifecycle/index.d.ts +5 -0
  160. package/dist/lifecycle/index.d.ts.map +1 -1
  161. package/dist/lifecycle/oras-referrer-lookup.d.ts +41 -0
  162. package/dist/lifecycle/oras-referrer-lookup.d.ts.map +1 -0
  163. package/dist/lifecycle/release-ledger.d.ts +122 -0
  164. package/dist/lifecycle/release-ledger.d.ts.map +1 -0
  165. package/dist/lifecycle/status.d.ts +150 -0
  166. package/dist/lifecycle/status.d.ts.map +1 -0
  167. package/dist/lint/component-checks.d.ts +95 -0
  168. package/dist/lint/component-checks.d.ts.map +1 -0
  169. package/dist/lint/engine.d.ts +23 -0
  170. package/dist/lint/engine.d.ts.map +1 -1
  171. package/dist/lint/presets/strict.json +8 -1
  172. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.d.ts +4 -0
  173. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.d.ts.map +1 -0
  174. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.d.ts +4 -0
  175. package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.d.ts.map +1 -0
  176. package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.d.ts +4 -0
  177. package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.d.ts.map +1 -0
  178. package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.d.ts +4 -0
  179. package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.d.ts.map +1 -0
  180. package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.d.ts +4 -0
  181. package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.d.ts.map +1 -0
  182. package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.d.ts +10 -0
  183. package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.d.ts.map +1 -0
  184. package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.d.ts +3 -0
  185. package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.d.ts.map +1 -0
  186. package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.d.ts +4 -0
  187. package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.d.ts.map +1 -0
  188. package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.d.ts +4 -0
  189. package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.d.ts.map +1 -0
  190. package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.d.ts +4 -0
  191. package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.d.ts.map +1 -0
  192. package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.d.ts +4 -0
  193. package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.d.ts.map +1 -0
  194. package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.d.ts +4 -0
  195. package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.d.ts.map +1 -0
  196. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +4 -0
  197. package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -0
  198. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +4 -0
  199. package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -0
  200. package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.d.ts +4 -0
  201. package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.d.ts.map +1 -0
  202. package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.d.ts +4 -0
  203. package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.d.ts.map +1 -0
  204. package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.d.ts +4 -0
  205. package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.d.ts.map +1 -0
  206. package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.d.ts +4 -0
  207. package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.d.ts.map +1 -0
  208. package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.d.ts +4 -0
  209. package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.d.ts.map +1 -0
  210. package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.d.ts +4 -0
  211. package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.d.ts.map +1 -0
  212. package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.d.ts +3 -0
  213. package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.d.ts.map +1 -0
  214. package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.d.ts +4 -0
  215. package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.d.ts.map +1 -0
  216. package/dist/lint/rules/comp/comp001-publishes-never-applies.d.ts +20 -0
  217. package/dist/lint/rules/comp/comp001-publishes-never-applies.d.ts.map +1 -0
  218. package/dist/lint/rules/comp/comp002-dangling-wiring-ref.d.ts +28 -0
  219. package/dist/lint/rules/comp/comp002-dangling-wiring-ref.d.ts.map +1 -0
  220. package/dist/lint/rules/comp/comp003-mutating-no-rollback.d.ts +39 -0
  221. package/dist/lint/rules/comp/comp003-mutating-no-rollback.d.ts.map +1 -0
  222. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +37 -0
  223. package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +1 -0
  224. package/dist/lint/rules/comp/comp005-capability-kind-is-noun.d.ts +43 -0
  225. package/dist/lint/rules/comp/comp005-capability-kind-is-noun.d.ts.map +1 -0
  226. package/dist/lint/rules/comp/comp006-shell-needs-reason.d.ts +22 -0
  227. package/dist/lint/rules/comp/comp006-shell-needs-reason.d.ts.map +1 -0
  228. package/dist/lint/rules/comp/comp007-composition-sprawl.d.ts +33 -0
  229. package/dist/lint/rules/comp/comp007-composition-sprawl.d.ts.map +1 -0
  230. package/dist/lint/rules/comp/index.d.ts +18 -0
  231. package/dist/lint/rules/comp/index.d.ts.map +1 -0
  232. package/dist/lint/rules/comp/support.d.ts +71 -0
  233. package/dist/lint/rules/comp/support.d.ts.map +1 -0
  234. package/dist/lsp/lexicon-providers.d.ts.map +1 -1
  235. package/dist/op/activity-registry.d.ts +11 -6
  236. package/dist/op/activity-registry.d.ts.map +1 -1
  237. package/dist/op/activity-runtime.d.ts +24 -0
  238. package/dist/op/activity-runtime.d.ts.map +1 -0
  239. package/dist/op/builders.d.ts +56 -0
  240. package/dist/op/builders.d.ts.map +1 -1
  241. package/dist/op/index.d.ts +2 -1
  242. package/dist/op/index.d.ts.map +1 -1
  243. package/dist/ownership.d.ts +20 -14
  244. package/dist/ownership.d.ts.map +1 -1
  245. package/package.json +14 -1
  246. package/src/audit/catalog.test.ts +74 -22
  247. package/src/audit/catalog.ts +74 -471
  248. package/src/audit/proof.ts +4 -2
  249. package/src/audit/report-html.test.ts +14 -7
  250. package/src/audit/report-model.ts +20 -9
  251. package/src/audit/report.test.ts +36 -13
  252. package/src/audit/report.ts +2 -0
  253. package/src/audit/rules-doc.test.ts +8 -6
  254. package/src/audit/rules-doc.ts +13 -5
  255. package/src/cli/commands/audit.ts +23 -18
  256. package/src/cli/commands/component-lint.test.ts +158 -0
  257. package/src/cli/commands/doctor.test.ts +116 -2
  258. package/src/cli/commands/doctor.ts +46 -0
  259. package/src/cli/commands/lexicon-rolling-upgrade.ts +198 -0
  260. package/src/cli/commands/lexicon-surface-diff.test.ts +104 -0
  261. package/src/cli/commands/lexicon-surface-diff.ts +185 -0
  262. package/src/cli/commands/lint.ts +142 -1
  263. package/src/cli/commands/pinned-upgrade.ts +204 -0
  264. package/src/cli/handlers/build.ts +58 -1
  265. package/src/cli/handlers/components.test.ts +504 -0
  266. package/src/cli/handlers/components.ts +404 -0
  267. package/src/cli/handlers/dev.ts +60 -1
  268. package/src/cli/handlers/graph.ts +47 -2
  269. package/src/cli/handlers/misc.ts +45 -1
  270. package/src/cli/handlers/run.test.ts +967 -3
  271. package/src/cli/handlers/run.ts +618 -11
  272. package/src/cli/main.test.ts +66 -0
  273. package/src/cli/main.ts +105 -2
  274. package/src/cli/registry.ts +35 -0
  275. package/src/codegen/fetch.test.ts +84 -3
  276. package/src/codegen/fetch.ts +76 -2
  277. package/src/codegen/lexicon-regen.test.ts +298 -0
  278. package/src/codegen/lexicon-regen.ts +545 -0
  279. package/src/codegen/pinned-upgrade.test.ts +399 -0
  280. package/src/codegen/pinned-upgrade.ts +423 -0
  281. package/src/codegen/rolling-upgrade.test.ts +333 -0
  282. package/src/codegen/rolling-upgrade.ts +320 -0
  283. package/src/codegen/surface-snapshot.test.ts +461 -0
  284. package/src/codegen/surface-snapshot.ts +546 -0
  285. package/src/codegen/version-bump.test.ts +47 -0
  286. package/src/codegen/version-bump.ts +39 -0
  287. package/src/components/README.md +130 -0
  288. package/src/components/SPRAWL-VALIDATION.md +181 -0
  289. package/src/components/__fixtures__/alb-ecs-service.json +51 -0
  290. package/src/components/__fixtures__/dynamodb-infra.json +32 -0
  291. package/src/components/__fixtures__/emr-job-consumer.json +26 -0
  292. package/src/components/__fixtures__/jar-lib-producer.json +16 -0
  293. package/src/components/__fixtures__/lambda-image-processor.json +28 -0
  294. package/src/components/__fixtures__/neo4j-fanout.json +34 -0
  295. package/src/components/__fixtures__/single-host-compose.json +29 -0
  296. package/src/components/auto-release.test.ts +217 -0
  297. package/src/components/auto-release.ts +216 -0
  298. package/src/components/builders.test.ts +45 -0
  299. package/src/components/builders.ts +71 -0
  300. package/src/components/capability-plugin-loader.ts +218 -0
  301. package/src/components/capability-plugin-schema.ts +56 -0
  302. package/src/components/capability-plugin.test.ts +235 -0
  303. package/src/components/capability-plugin.ts +108 -0
  304. package/src/components/capability.ts +117 -0
  305. package/src/components/cli-support.test.ts +579 -0
  306. package/src/components/cli-support.ts +481 -0
  307. package/src/components/component-schema.test.ts +265 -0
  308. package/src/components/component.schema.json +235 -0
  309. package/src/components/component.test.ts +251 -0
  310. package/src/components/component.ts +255 -0
  311. package/src/components/config-defaults.test.ts +263 -0
  312. package/src/components/config-defaults.ts +145 -0
  313. package/src/components/discover.test.ts +352 -0
  314. package/src/components/discover.ts +167 -0
  315. package/src/components/driver-output.ts +71 -0
  316. package/src/components/driver.test.ts +638 -0
  317. package/src/components/driver.ts +690 -0
  318. package/src/components/index.ts +113 -0
  319. package/src/components/manifest-persistence.test.ts +152 -0
  320. package/src/components/manifest-persistence.ts +164 -0
  321. package/src/components/pilots/README.md +33 -0
  322. package/src/components/pilots/alb-ecs.pilot.ts +63 -0
  323. package/src/components/pilots/dynamodb.pilot.ts +59 -0
  324. package/src/components/pilots/jar-emr.pilot.ts +69 -0
  325. package/src/components/pilots/lambda.pilot.ts +55 -0
  326. package/src/components/pilots/neo4j-fanout.pilot.ts +92 -0
  327. package/src/components/pilots/pilots-lint-clean.test.ts +78 -0
  328. package/src/components/pilots/pilots.test.ts +126 -0
  329. package/src/components/pilots/project.ts +13 -0
  330. package/src/components/presets/comp007-reduction.test.ts +122 -0
  331. package/src/components/presets/ecs-fargate.test.ts +84 -0
  332. package/src/components/presets/ecs-fargate.ts +103 -0
  333. package/src/components/presets/index.ts +32 -0
  334. package/src/components/presets/lambda.test.ts +35 -0
  335. package/src/components/presets/lambda.ts +53 -0
  336. package/src/components/presets/single-host-compose.test.ts +65 -0
  337. package/src/components/presets/single-host-compose.ts +64 -0
  338. package/src/components/registry.test.ts +112 -0
  339. package/src/components/registry.ts +37 -0
  340. package/src/components/starter-plugin.ts +105 -0
  341. package/src/components/temporal-codegen-loader.ts +41 -0
  342. package/src/components/verbs/__fixtures__/package-lock.json +45 -0
  343. package/src/components/verbs/__fixtures__/pom.xml +37 -0
  344. package/src/components/verbs/__fixtures__/schemas/cyclonedx-1.5.schema.json +3800 -0
  345. package/src/components/verbs/__fixtures__/schemas/cyclonedx-spdx-license.schema.json +621 -0
  346. package/src/components/verbs/__fixtures__/schemas/jsf-0.82.schema.json +240 -0
  347. package/src/components/verbs/__fixtures__/schemas/spdx-2.3.schema.json +740 -0
  348. package/src/components/verbs/__tests__/mock-cloud-executor.ts +102 -0
  349. package/src/components/verbs/__tests__/mock-process-runner.ts +79 -0
  350. package/src/components/verbs/__tests__/mock-sbom-generator.ts +85 -0
  351. package/src/components/verbs/bom-writer.test.ts +331 -0
  352. package/src/components/verbs/bom-writer.ts +386 -0
  353. package/src/components/verbs/build-archive.test.ts +251 -0
  354. package/src/components/verbs/build-archive.ts +296 -0
  355. package/src/components/verbs/build.test.ts +222 -0
  356. package/src/components/verbs/build.ts +252 -0
  357. package/src/components/verbs/cloud-executor.ts +181 -0
  358. package/src/components/verbs/component-bom.test.ts +219 -0
  359. package/src/components/verbs/component-bom.ts +189 -0
  360. package/src/components/verbs/index.ts +49 -0
  361. package/src/components/verbs/license-policy.ts +115 -0
  362. package/src/components/verbs/lockfile-sbom-generator.test.ts +195 -0
  363. package/src/components/verbs/lockfile-sbom-generator.ts +236 -0
  364. package/src/components/verbs/process-runner.test.ts +79 -0
  365. package/src/components/verbs/process-runner.ts +113 -0
  366. package/src/components/verbs/reproducibility.test.ts +24 -0
  367. package/src/components/verbs/reproducibility.ts +100 -0
  368. package/src/components/verbs/sbom-generator.test.ts +96 -0
  369. package/src/components/verbs/sbom-generator.ts +209 -0
  370. package/src/components/verbs/sbom.test.ts +184 -0
  371. package/src/components/verbs/sbom.ts +152 -0
  372. package/src/components/verbs/shell.test.ts +36 -0
  373. package/src/components/verbs/shell.ts +51 -0
  374. package/src/components/verbs/sign.test.ts +210 -0
  375. package/src/components/verbs/sign.ts +350 -0
  376. package/src/components/verbs/stub.ts +34 -0
  377. package/src/components/verbs/tool-sbom-generator.test.ts +194 -0
  378. package/src/components/verbs/tool-sbom-generator.ts +192 -0
  379. package/src/components/verbs/verify.test.ts +159 -0
  380. package/src/components/verbs/verify.ts +179 -0
  381. package/src/components/verbs/vex.ts +182 -0
  382. package/src/components/verbs/vuln-gate.test.ts +201 -0
  383. package/src/components/verbs/vuln-gate.ts +170 -0
  384. package/src/components/verbs/vuln-scan.test.ts +145 -0
  385. package/src/components/verbs/vuln-scan.ts +266 -0
  386. package/src/components/verbs/wait-verify.test.ts +111 -0
  387. package/src/components/verbs/wait-verify.ts +171 -0
  388. package/src/config.test.ts +74 -1
  389. package/src/config.ts +219 -0
  390. package/src/index.ts +32 -0
  391. package/src/lexicon.ts +88 -0
  392. package/src/lifecycle/build-ledger-store.test.ts +217 -0
  393. package/src/lifecycle/build-ledger-store.ts +165 -0
  394. package/src/lifecycle/build-ledger.test.ts +349 -0
  395. package/src/lifecycle/build-ledger.ts +305 -0
  396. package/src/lifecycle/git.test.ts +118 -0
  397. package/src/lifecycle/git.ts +149 -14
  398. package/src/lifecycle/index.ts +5 -0
  399. package/src/lifecycle/oras-referrer-lookup.test.ts +116 -0
  400. package/src/lifecycle/oras-referrer-lookup.ts +110 -0
  401. package/src/lifecycle/release-ledger.test.ts +209 -0
  402. package/src/lifecycle/release-ledger.ts +185 -0
  403. package/src/lifecycle/status.test.ts +330 -0
  404. package/src/lifecycle/status.ts +278 -0
  405. package/src/lint/component-checks.ts +148 -0
  406. package/src/lint/config.test.ts +21 -0
  407. package/src/lint/engine.ts +11 -2
  408. package/src/lint/presets/relaxed.json +8 -1
  409. package/src/lint/presets/strict.json +8 -1
  410. package/src/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.ts +9 -0
  411. package/src/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.ts +9 -0
  412. package/src/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.ts +11 -0
  413. package/src/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.ts +13 -0
  414. package/src/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.ts +11 -0
  415. package/src/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.ts +27 -0
  416. package/src/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.ts +10 -0
  417. package/src/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.ts +23 -0
  418. package/src/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.ts +10 -0
  419. package/src/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.ts +19 -0
  420. package/src/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.ts +10 -0
  421. package/src/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.ts +20 -0
  422. package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +23 -0
  423. package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +10 -0
  424. package/src/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.ts +14 -0
  425. package/src/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.ts +18 -0
  426. package/src/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.ts +10 -0
  427. package/src/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.ts +14 -0
  428. package/src/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.ts +13 -0
  429. package/src/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.ts +13 -0
  430. package/src/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.ts +12 -0
  431. package/src/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.ts +18 -0
  432. package/src/lint/rules/comp/comp.test.ts +378 -0
  433. package/src/lint/rules/comp/comp001-publishes-never-applies.ts +78 -0
  434. package/src/lint/rules/comp/comp002-dangling-wiring-ref.ts +94 -0
  435. package/src/lint/rules/comp/comp003-mutating-no-rollback.ts +115 -0
  436. package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +66 -0
  437. package/src/lint/rules/comp/comp005-capability-kind-is-noun.ts +113 -0
  438. package/src/lint/rules/comp/comp006-shell-needs-reason.ts +55 -0
  439. package/src/lint/rules/comp/comp007-composition-sprawl.ts +71 -0
  440. package/src/lint/rules/comp/index.ts +37 -0
  441. package/src/lint/rules/comp/support.ts +173 -0
  442. package/src/lsp/lexicon-providers.test.ts +55 -0
  443. package/src/lsp/lexicon-providers.ts +13 -3
  444. package/src/op/activity-registry.test.ts +38 -0
  445. package/src/op/activity-registry.ts +31 -12
  446. package/src/op/activity-runtime.ts +73 -0
  447. package/src/op/builders.ts +92 -0
  448. package/src/op/index.ts +3 -1
  449. package/src/ownership.test.ts +24 -26
  450. package/src/ownership.ts +26 -38
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Component-native release orchestration — capability contract, starter verb
3
+ * set, and the thin interpret driver (epic #551, #554/#556). The pilot AWS
4
+ * leaves have real implementations over an injectable `CloudExecutor` (#557);
5
+ * every other verb remains a typed stub. See https://intentius.io/chant/components/orchestration/
6
+ */
7
+
8
+ export {
9
+ type Archetype,
10
+ type Wiring,
11
+ type StackOutputReference,
12
+ type BuildSpec,
13
+ type Step,
14
+ type Gate,
15
+ type Phase,
16
+ type Component,
17
+ phase,
18
+ gate,
19
+ stackOutput,
20
+ inferArchetype,
21
+ projectToJson,
22
+ isComponent,
23
+ } from "./component";
24
+ export {
25
+ type DiscoveredComponent,
26
+ type ComponentDiscoveryResult,
27
+ discoverComponents,
28
+ } from "./discover";
29
+ export {
30
+ type ListedComponent,
31
+ type ListComponentsResult,
32
+ type DescribedComponent,
33
+ type DescribeComponentResult,
34
+ type ComponentGraphResult,
35
+ type GenerateLexicon,
36
+ type GenerateComponentsResult,
37
+ type RunComponentsOptions,
38
+ type RunComponentsResult,
39
+ type ResolvedComponentTargets,
40
+ listComponents,
41
+ describeComponent,
42
+ computeComponentGraph,
43
+ generateComponentsPipeline,
44
+ runComponents,
45
+ findComponentGate,
46
+ resolveComponentTargets,
47
+ } from "./cli-support";
48
+ export { renderDriverHuman, renderDriverJson } from "./driver-output";
49
+ export {
50
+ type Capability,
51
+ type CapabilityInput,
52
+ type CapabilityOutput,
53
+ type DeployContext,
54
+ CapabilityRegistry,
55
+ CapabilityNotImplementedError,
56
+ } from "./capability";
57
+ export { createCapabilityRegistry, STARTER_VERB_FAMILIES } from "./registry";
58
+ export {
59
+ type CapabilityPlugin,
60
+ type CapabilityManifest,
61
+ isCapabilityPlugin,
62
+ } from "./capability-plugin";
63
+ export {
64
+ CapabilityManifestSchema,
65
+ type CapabilityManifestParsed,
66
+ validateCapabilityManifest,
67
+ } from "./capability-plugin-schema";
68
+ export {
69
+ loadCapabilityPlugin,
70
+ loadCapabilityPlugins,
71
+ registerCapabilityPlugins,
72
+ buildCapabilityRegistry,
73
+ type BuildCapabilityRegistryOptions,
74
+ MalformedCapabilityPluginError,
75
+ DuplicateCapabilityKindError,
76
+ } from "./capability-plugin-loader";
77
+ export { starterCapabilityPlugin } from "./starter-plugin";
78
+ export * from "./verbs/index";
79
+ export * from "./builders";
80
+ export {
81
+ type DriverStep,
82
+ type DriverGate,
83
+ type DriverPhase,
84
+ type DriverComponent,
85
+ type DriverStepRecord,
86
+ type DriverComponentResult,
87
+ type DriverRunResult,
88
+ type ComponentGraph,
89
+ type InterpretRunOptions,
90
+ type WiringValue,
91
+ resolveComponentGraph,
92
+ resolveWiring,
93
+ resolveStepInput,
94
+ runComponentDeploy,
95
+ runInterpretDriver,
96
+ DriverGateUnsupportedError,
97
+ DependencyCycleError,
98
+ UnknownDependencyError,
99
+ DriverRunFailure,
100
+ } from "./driver";
101
+ export {
102
+ EcsFargateComponent,
103
+ type EcsFargateComponentConfig,
104
+ LambdaComponent,
105
+ type LambdaComponentConfig,
106
+ SingleHostComposeComponent,
107
+ type SingleHostComposeComponentConfig,
108
+ } from "./presets/index";
109
+ export {
110
+ type ComponentTemporalCodegen,
111
+ type ComponentTemporalCodegenOptions,
112
+ loadComponentTemporalCodegen,
113
+ } from "./temporal-codegen-loader";
@@ -0,0 +1,152 @@
1
+ import { describe, test, expect, vi, beforeEach } from "vitest";
2
+ import type { DriverStepRecord } from "./driver";
3
+ import { createBuildArchiveManifest, addArchiveEntry, type BuildArchiveManifest } from "./verbs/build-archive";
4
+
5
+ const persistBuildManifestMock = vi.fn();
6
+ const pushLifecycleMock = vi.fn();
7
+
8
+ vi.mock("../lifecycle/build-ledger-store", () => ({
9
+ persistBuildManifest: (...args: unknown[]) => persistBuildManifestMock(...args),
10
+ }));
11
+
12
+ vi.mock("../lifecycle/git", () => ({
13
+ pushLifecycle: (...args: unknown[]) => pushLifecycleMock(...args),
14
+ }));
15
+
16
+ const {
17
+ maybePersistBuildManifest,
18
+ extractRunManifest,
19
+ extractRunManifestFromPhaseOutputs,
20
+ } = await import("./manifest-persistence");
21
+
22
+ function makeManifest(component: string, digest: string): BuildArchiveManifest {
23
+ let manifest = createBuildArchiveManifest(component, { now: () => new Date("2026-01-01T00:00:00.000Z") });
24
+ manifest = addArchiveEntry(manifest, { kind: "image", path: "image.tar", digest });
25
+ return manifest;
26
+ }
27
+
28
+ function buildRecord(manifest: BuildArchiveManifest): DriverStepRecord {
29
+ return {
30
+ component: manifest.component,
31
+ phase: "Build",
32
+ kind: "docker-build",
33
+ status: "ok",
34
+ durationMs: 5,
35
+ output: { archivePath: "image.tar", digest: manifest.contents[0]!.digest, manifest },
36
+ };
37
+ }
38
+
39
+ function applyRecord(): DriverStepRecord {
40
+ return { component: "svc", phase: "Apply", kind: "cfn-deploy", status: "ok", durationMs: 5, output: { ok: true } };
41
+ }
42
+
43
+ describe("extractRunManifest", () => {
44
+ test("finds the manifest from a build-shaped step output", () => {
45
+ const manifest = makeManifest("svc", "sha256:abc");
46
+ expect(extractRunManifest([buildRecord(manifest)])).toEqual(manifest);
47
+ });
48
+
49
+ test("returns undefined when no step produced a manifest", () => {
50
+ expect(extractRunManifest([applyRecord()])).toBeUndefined();
51
+ });
52
+
53
+ test("ignores failed/skipped steps", () => {
54
+ const manifest = makeManifest("svc", "sha256:abc");
55
+ const failed: DriverStepRecord = { ...buildRecord(manifest), status: "fail", output: undefined };
56
+ expect(extractRunManifest([failed])).toBeUndefined();
57
+ });
58
+
59
+ test("takes the last (most-accumulated) manifest when multiple build steps ran", () => {
60
+ const first = makeManifest("svc", "sha256:first");
61
+ let second = makeManifest("svc", "sha256:first");
62
+ second = addArchiveEntry(second, { kind: "image", path: "second.tar", digest: "sha256:second" });
63
+
64
+ const result = extractRunManifest([buildRecord(first), buildRecord(second)]);
65
+ expect(result).toEqual(second);
66
+ expect(result?.contents).toHaveLength(2);
67
+ });
68
+ });
69
+
70
+ describe("extractRunManifestFromPhaseOutputs", () => {
71
+ test("finds the manifest across phase outputs (Temporal workflow result shape)", () => {
72
+ const manifest = makeManifest("svc", "sha256:abc");
73
+ expect(
74
+ extractRunManifestFromPhaseOutputs({
75
+ Build: { archivePath: "image.tar", digest: "sha256:abc", manifest },
76
+ Apply: { ok: true },
77
+ }),
78
+ ).toEqual(manifest);
79
+ });
80
+
81
+ test("returns undefined for undefined/empty phaseOutputs", () => {
82
+ expect(extractRunManifestFromPhaseOutputs(undefined)).toBeUndefined();
83
+ expect(extractRunManifestFromPhaseOutputs({})).toBeUndefined();
84
+ });
85
+ });
86
+
87
+ describe("maybePersistBuildManifest", () => {
88
+ beforeEach(() => {
89
+ persistBuildManifestMock.mockReset();
90
+ pushLifecycleMock.mockReset().mockResolvedValue(true);
91
+ });
92
+
93
+ test("success with a manifest in records -> persists and pushes", async () => {
94
+ const manifest = makeManifest("svc", "sha256:abc");
95
+ persistBuildManifestMock.mockResolvedValue({ commit: "a".repeat(40) });
96
+
97
+ const outcome = await maybePersistBuildManifest({ success: true, records: [buildRecord(manifest)] });
98
+
99
+ expect(outcome).toEqual({ persisted: true, commit: "a".repeat(40), manifestDigest: manifest.manifestDigest });
100
+ expect(persistBuildManifestMock).toHaveBeenCalledTimes(1);
101
+ expect(persistBuildManifestMock.mock.calls[0][0]).toEqual(manifest);
102
+ expect(pushLifecycleMock).toHaveBeenCalledTimes(1);
103
+ });
104
+
105
+ test("a pre-resolved manifest (Temporal path) takes precedence over records", async () => {
106
+ const preResolved = makeManifest("svc", "sha256:temporal");
107
+ persistBuildManifestMock.mockResolvedValue({ commit: "b".repeat(40) });
108
+
109
+ const outcome = await maybePersistBuildManifest({
110
+ success: true,
111
+ manifest: preResolved,
112
+ records: [buildRecord(makeManifest("svc", "sha256:ignored"))],
113
+ });
114
+
115
+ expect(outcome).toMatchObject({ persisted: true, manifestDigest: preResolved.manifestDigest });
116
+ expect(persistBuildManifestMock.mock.calls[0][0]).toEqual(preResolved);
117
+ });
118
+
119
+ test("failure (run.success = false) -> persists nothing (dry-run/failed-deploy safety)", async () => {
120
+ const manifest = makeManifest("svc", "sha256:abc");
121
+ const outcome = await maybePersistBuildManifest({ success: false, records: [buildRecord(manifest)] });
122
+ expect(outcome).toEqual({ persisted: false, reason: "run-not-successful" });
123
+ expect(persistBuildManifestMock).not.toHaveBeenCalled();
124
+ expect(pushLifecycleMock).not.toHaveBeenCalled();
125
+ });
126
+
127
+ test("opt-out (options.disabled) -> persists nothing, even on a successful run with a manifest", async () => {
128
+ const manifest = makeManifest("svc", "sha256:abc");
129
+ const outcome = await maybePersistBuildManifest(
130
+ { success: true, records: [buildRecord(manifest)] },
131
+ { disabled: true },
132
+ );
133
+ expect(outcome).toEqual({ persisted: false, reason: "opted-out" });
134
+ expect(persistBuildManifestMock).not.toHaveBeenCalled();
135
+ expect(pushLifecycleMock).not.toHaveBeenCalled();
136
+ });
137
+
138
+ test("no manifest in the run's records -> skipped, not an error (infra-only/apply-only component)", async () => {
139
+ const outcome = await maybePersistBuildManifest({ success: true, records: [applyRecord()] });
140
+ expect(outcome).toEqual({ persisted: false, reason: "no-manifest" });
141
+ expect(persistBuildManifestMock).not.toHaveBeenCalled();
142
+ });
143
+
144
+ test("persist failure -> reported as an error result, not thrown, and never masks the successful deploy", async () => {
145
+ const manifest = makeManifest("svc", "sha256:abc");
146
+ persistBuildManifestMock.mockRejectedValue(new Error("git write failed"));
147
+
148
+ await expect(
149
+ maybePersistBuildManifest({ success: true, records: [buildRecord(manifest)] }),
150
+ ).resolves.toMatchObject({ persisted: false, reason: "error", error: "git write failed" });
151
+ });
152
+ });
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Persist a component run's `BuildArchiveManifest` after a successful `chant
3
+ * run --components <name> --env <env>` (#609, epic #551 follow-up to
4
+ * #564/#568/#606/#613/#614). Mirrors ./auto-release.ts's shape exactly —
5
+ * same "extract from step records, then call a lifecycle-layer writer, then
6
+ * push, and never let a write failure fail an already-successful deploy"
7
+ * structure — because it is solving the same class of problem: the driver
8
+ * produces something worth recording durably, but the driver itself must
9
+ * stay capability-agnostic (../components/driver.ts takes no dependency on
10
+ * ../lifecycle/*), so the CLI performs the write as a post-run step.
11
+ *
12
+ * **Why here, not the driver.** Same reasoning as ./auto-release.ts's module
13
+ * doc: a manifest write is a git commit + push, a non-idempotent side effect
14
+ * with real-world I/O — exactly what `driver.ts` resists taking on (it is
15
+ * exercised in tests against a bare `CapabilityRegistry` with no lifecycle
16
+ * dependency at all) and what Temporal workflow code must never do directly
17
+ * (replay-safety). The CLI calls this after `runComponents`/`handle.result()`
18
+ * reports success, the same place `maybeRecordAutoRelease` is already
19
+ * called from (../cli/handlers/run.ts).
20
+ *
21
+ * **Extraction is duck-typed, not capability-specific.** `docker-build`,
22
+ * `generate-sbom`, `extract-config-bom`, and `addArchiveTemplate` (the
23
+ * build-family capabilities/helpers, ../components/verbs/build.ts,
24
+ * ./verbs/sbom.ts, ./verbs/config-bom.ts) all return `{ ..., manifest:
25
+ * BuildArchiveManifest }` — the accumulation convention documented on each of
26
+ * their inputs ("manifest to extend... same accumulation convention"). This
27
+ * module scans a run's step outputs for that shape, exactly the way
28
+ * ./auto-release.ts's `extractRunDigest` scans for a publish-shaped output,
29
+ * so a new build-family capability that follows the same `{ manifest }`
30
+ * output convention is picked up automatically — no branch here names a
31
+ * specific capability `kind`.
32
+ */
33
+ import { persistBuildManifest } from "../lifecycle/build-ledger-store";
34
+ import { pushLifecycle } from "../lifecycle/git";
35
+ import type { BuildArchiveManifest } from "./verbs/build-archive";
36
+ import type { DriverStepRecord } from "./driver";
37
+
38
+ /** A step output shaped like it carries a `BuildArchiveManifest` — duck-typed the same way ./auto-release.ts's `isPublishShaped` detects a publish result. */
39
+ function isManifestShaped(output: unknown): output is { manifest: BuildArchiveManifest } {
40
+ return (
41
+ !!output &&
42
+ typeof output === "object" &&
43
+ "manifest" in output &&
44
+ !!(output as { manifest?: unknown }).manifest &&
45
+ typeof (output as { manifest?: unknown }).manifest === "object"
46
+ );
47
+ }
48
+
49
+ /**
50
+ * Find the most fully-accumulated `BuildArchiveManifest` a component run
51
+ * produced, by scanning its step records for the last manifest-bearing
52
+ * output — mirroring `extractRunDigest`'s "last wins" convention, which is
53
+ * also the correct one here: every build-family capability's `manifest`
54
+ * input/output accumulates onto whatever manifest came before it in the same
55
+ * phase (see ../components/verbs/build.ts's `DockerBuildInput.manifest`
56
+ * doc), so the *last* manifest-bearing step output in run order is always
57
+ * the fullest one — a template + SBOM + config-BOM composition's final step
58
+ * carries every earlier entry too, not just its own.
59
+ */
60
+ export function extractRunManifest(records: DriverStepRecord[]): BuildArchiveManifest | undefined {
61
+ let found: BuildArchiveManifest | undefined;
62
+ for (const record of records) {
63
+ if (record.status !== "ok") continue;
64
+ if (isManifestShaped(record.output)) {
65
+ found = record.output.manifest;
66
+ }
67
+ }
68
+ return found;
69
+ }
70
+
71
+ /**
72
+ * Same manifest extraction as `extractRunManifest`, but over a component
73
+ * Temporal workflow's returned `phaseOutputs` (`{ [phase]: output }`) —
74
+ * mirroring ./auto-release.ts's `extractRunDigestFromPhaseOutputs`, the
75
+ * `--temporal` CLI path's counterpart, since that path never sees individual
76
+ * step records either.
77
+ */
78
+ export function extractRunManifestFromPhaseOutputs(
79
+ phaseOutputs: Record<string, Record<string, unknown>> | undefined,
80
+ ): BuildArchiveManifest | undefined {
81
+ let found: BuildArchiveManifest | undefined;
82
+ for (const output of Object.values(phaseOutputs ?? {})) {
83
+ if (isManifestShaped(output)) {
84
+ found = output.manifest;
85
+ }
86
+ }
87
+ return found;
88
+ }
89
+
90
+ /** Explicit reasons `maybePersistBuildManifest` declined to write — never a thrown error, mirroring ./auto-release.ts's `AutoReleaseSkipReason`. */
91
+ export type ManifestPersistSkipReason = "opted-out" | "run-not-successful" | "no-manifest";
92
+
93
+ export type ManifestPersistResult =
94
+ | { persisted: true; commit: string; manifestDigest: string }
95
+ | { persisted: false; reason: ManifestPersistSkipReason }
96
+ | { persisted: false; reason: "error"; error: string };
97
+
98
+ /** Input describing one component's completed run — the manifest-persistence counterpart of ./auto-release.ts's `AutoReleaseRunInfo`. */
99
+ export interface ManifestPersistRunInfo {
100
+ /** Whether the run reported overall success. A caller must not call this for a non-terminal/in-progress run — mirrors `AutoReleaseRunInfo.success`. */
101
+ success: boolean;
102
+ /** The component's step records (local executor), used to locate the accumulated manifest via `extractRunManifest`. Mutually exclusive with `manifest`. */
103
+ records?: DriverStepRecord[];
104
+ /** A manifest already resolved by the caller (e.g. a future durable/Temporal path that has its own phaseOutputs-shaped extraction). Takes precedence over `records` when both are given. */
105
+ manifest?: BuildArchiveManifest;
106
+ }
107
+
108
+ /** Opt-out knobs for manifest persistence, mirroring ./auto-release.ts's `AutoReleaseOptions`. */
109
+ export interface ManifestPersistOptions {
110
+ /** `--no-release-record` / `chant.config.ts`'s `release.autoRecord: false` also gates manifest persistence — both are "durably record this successful deploy" side effects with the same opt-out story, so one flag/config knob controls both rather than introducing a second, easy-to-forget switch. Default: persistence is ON. */
111
+ disabled?: boolean;
112
+ /** Working directory for the git plumbing calls (tests). */
113
+ cwd?: string;
114
+ }
115
+
116
+ /**
117
+ * After a successful `chant run --components <name> --env <env>` (local
118
+ * executor), persist the run's accumulated `BuildArchiveManifest` (if any)
119
+ * to the durable build-manifest store (../lifecycle/build-ledger-store.ts)
120
+ * and push it — or explain, without throwing, why it didn't. Never called
121
+ * for a failed run, matching `maybeRecordAutoRelease`'s contract exactly.
122
+ *
123
+ * Skips (returns `{ persisted: false, reason }`, never throws):
124
+ * - `options.disabled` — the opt-out flag/config was set.
125
+ * - `run.success` false — defensive; callers should not reach here on
126
+ * failure. A dry-run/failed deploy persists nothing, by construction —
127
+ * this is also what makes a dry run safe: `chant run --components` never
128
+ * calls this function at all unless the run actually completed.
129
+ * - no manifest found in the run's records — a component with no
130
+ * build-family step (an infra-only/apply-only component, or a
131
+ * build-less `Publish`-only producer that reused a prior archive) has
132
+ * nothing to persist. This is the expected common case for most deploys,
133
+ * not an error.
134
+ *
135
+ * Write/push failures (any error `persistBuildManifest`/`pushLifecycle`
136
+ * throw) are reported as `{ persisted: false, reason: "error", error }`
137
+ * rather than propagated — same "never turn a successful deploy into a
138
+ * failing CLI invocation" contract `maybeRecordAutoRelease` already
139
+ * establishes for release records.
140
+ */
141
+ export async function maybePersistBuildManifest(
142
+ run: ManifestPersistRunInfo,
143
+ options: ManifestPersistOptions = {},
144
+ ): Promise<ManifestPersistResult> {
145
+ if (options.disabled) {
146
+ return { persisted: false, reason: "opted-out" };
147
+ }
148
+ if (!run.success) {
149
+ return { persisted: false, reason: "run-not-successful" };
150
+ }
151
+
152
+ const manifest = run.manifest ?? extractRunManifest(run.records ?? []);
153
+ if (!manifest) {
154
+ return { persisted: false, reason: "no-manifest" };
155
+ }
156
+
157
+ try {
158
+ const { commit } = await persistBuildManifest(manifest, { cwd: options.cwd });
159
+ await pushLifecycle({ cwd: options.cwd });
160
+ return { persisted: true, commit, manifestDigest: manifest.manifestDigest };
161
+ } catch (err) {
162
+ return { persisted: false, reason: "error", error: err instanceof Error ? err.message : String(err) };
163
+ }
164
+ }
@@ -0,0 +1,33 @@
1
+ # Pilot component definitions
2
+
3
+ Three concrete components authored against the [Component contract](../../../../../docs/src/content/docs/components/component-contract.mdx), picked (epic [#551](https://github.com/INTENTIUS/chant/issues/551)) to be the three most-different real components chant deploys today. Each is provided as:
4
+
5
+ - a **TypeScript authoring form** (`*.pilot.ts`) — composed using the real capability `kind` verbs and typed inputs from [`../verbs`](../verbs/), against the real typed `Component`/`phase()`/`gate()`/`stackOutput()` authoring frontend (`../component.ts`, Phase 2, [#560](https://github.com/INTENTIUS/chant/issues/560)). Prior to #560 these pilots authored against a local stopgap shape (`authoring-shape.ts`, now deleted) that mirrored `component.schema.json` field-for-field as a placeholder; migrating them to import `../component` instead was a like-for-like swap since the two shapes matched 1:1 by design.
6
+ - its **JSON projection** (`project.ts` + [`pilots.test.ts`](./pilots.test.ts)) — asserted equal to the existing fixture in [`../__fixtures__/`](../__fixtures__/) that already validates against the schema ([#553](https://github.com/INTENTIUS/chant/issues/553)/[#571](https://github.com/INTENTIUS/chant/pull/571)). The fixture stays the one authoritative JSON document per pilot; this directory does not fork a second copy.
7
+
8
+ ## Mapping to the epic's axes
9
+
10
+ The epic ([#551](https://github.com/INTENTIUS/chant/issues/551)) picked these three specifically to exercise different points on each axis at once, so three components prove more than three would if they were shape-variations of each other.
11
+
12
+ | Pilot | File / fixture | build vs no-build | single vs fan-out | sticky vs simple apply | cross-stack wiring | auto vs no rollback |
13
+ |---|---|---|---|---|---|---|
14
+ | **Neo4j per-instance fan-out** | [`neo4j-fanout.pilot.ts`](./neo4j-fanout.pilot.ts) / [`neo4j-fanout.json`](../__fixtures__/neo4j-fanout.json) | no-build (`infra`, applies pre-built templates) | **fan-out** — one component composes 3 per-instance mini-compositions (`cfn-deploy` + `code-deploy` + `wait-cluster-healthy`), seed-first then rolling, gated at node 1 | simple apply (no `onReplace`/`stageGsi` — no sticky CFN concerns here) | none (self-contained cluster, no shared-stack imports) | **auto** — `code-deploy` (AWS CodeDeploy) rollback is native/automatic on failure, declared once inside the capability, never scripted per node |
15
+ | **DynamoDB table** | [`dynamodb.pilot.ts`](./dynamodb.pilot.ts) / [`dynamodb-infra.json`](../__fixtures__/dynamodb-infra.json) | no-build (`infra`, applies an existing table template) | single (one `cfn-deploy`, no fan-out) | **sticky** — `onReplace: "block"` refuses a replacing changeset (data loss guard); `stageGsi: true` stages the GSI add→backfill→remove instead of an in-place replace | none | no rollback declared — a blocked replacement is not something to compensate, it is a stop |
16
+ | **ALB/ECS target** | [`alb-ecs.pilot.ts`](./alb-ecs.pilot.ts) / [`alb-ecs-service.json`](../__fixtures__/alb-ecs-service.json) | **build** — `docker-build` → `publish-image` (promote by digest at deploy time) | single (one service, one `cfn-deploy` + `ecs-update-service`) | simple apply (no replacement-sensitive resource here) | **cross-stack** — imports `shared-alb`'s `ListenerArn`/`ClusterArn`/`Subnets` via `stackOutput()`, replacing the `describe-stacks \| jq` glue in [`examples/gitlab-aws-alb-api/src/pipeline.ts`](../../../../../examples/gitlab-aws-alb-api/src/pipeline.ts) | **no** (component-declared) — `ecs-update-service`/`cfn-deploy` have no native automatic rollback for an already-running service swap, so the component supplies an explicit `rollback` phase (`rollback-previous`) rather than relying on capability compensation |
17
+
18
+ Read together, the three cover every cell at least once: build only shows up for ALB/ECS, fan-out only for Neo4j, sticky-apply only for DynamoDB, cross-stack only for ALB/ECS, and both rollback styles (capability-native vs component-declared) appear once each.
19
+
20
+ ## A fourth component (#558): image-processor Lambda
21
+
22
+ [`lambda.pilot.ts`](./lambda.pilot.ts) / [`lambda-image-processor.json`](../__fixtures__/lambda-image-processor.json) adds a fourth component, added after the three above to validate the sprawl metric ([#551](https://github.com/INTENTIUS/chant/issues/551)#definition-of-done-the-sprawl-metric), not to re-cover the same axes. It reuses `docker-build`/`publish-image` unchanged (build + promote-by-digest is identical to ALB/ECS's) but its Apply phase dispatches to `lambda-deploy` instead of `cfn-deploy` — the first component in the set with no CloudFormation stack in its apply step at all. `lambda-deploy` was the one new capability this component needed; see [`../SPRAWL-VALIDATION.md`](../SPRAWL-VALIDATION.md) for the full accounting and the ALB/ECS pipeline-glue before/after.
23
+
24
+ ## Why the fixture is authoritative, not this directory
25
+
26
+ [#555](https://github.com/INTENTIUS/chant/issues/555) explicitly scopes "committed under an `examples/` or `fixtures/` path" — the schema's own `__fixtures__/` already holds real components drawn from this epic, including these three. Duplicating them here as a second JSON copy would immediately be the "composition copy-paste" / definition-sprawl failure mode the epic itself guards against ([#551](https://github.com/INTENTIUS/chant/issues/551)#failure-modes). Instead:
27
+
28
+ - `../__fixtures__/*.json` remains the one JSON document per pilot, already covered by [`../component-schema.test.ts`](../component-schema.test.ts).
29
+ - This directory adds the TypeScript authoring form the issue also asks for, and [`pilots.test.ts`](./pilots.test.ts) asserts the two never drift apart — if a pilot's composition changes, the fixture is the file to update, and the test fails loudly if only one side moves.
30
+
31
+ ## What's out of scope here
32
+
33
+ Per the issue: running these compositions (the [Phase 1 driver](https://github.com/INTENTIUS/chant/issues/556)) and real capability implementations ([#557](https://github.com/INTENTIUS/chant/issues/557)) are separate issues. Every capability referenced below is still a typed stub (see [`../verbs/`](../verbs/)) — `run()`/`rollback()` throw `CapabilityNotImplementedError`. Nothing here executes anything.
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Pilot: ALB/ECS target (#555, epic #551).
3
+ *
4
+ * Exercises the build + cross-stack + auto-rollback axes: `docker-build` →
5
+ * `publish-image` (promote by digest, deploy-time) → `cfn-deploy` (importing
6
+ * the shared ALB's listener/cluster/subnets as cross-stack outputs, resolved
7
+ * by `chant graph --stacks` rather than a `describe-stacks | jq` pipeline
8
+ * step — see composition-and-wiring.mdx#cross-stack-outputs) →
9
+ * `ecs-update-service` → `wait-steady-state` + `health-gate`.
10
+ *
11
+ * This is the direct component-native replacement for the hand-rolled GitLab
12
+ * pipeline in `examples/gitlab-aws-alb-api/src/pipeline.ts`: the
13
+ * `describe-stacks`/`jq` glue in that pipeline's `deployService` job is
14
+ * exactly the cross-stack `stackOutput()` wiring below, and its
15
+ * `docker build`/`docker push` steps are the `docker-build` + `publish-image`
16
+ * capabilities. `service` archetype: build → publish → apply → verify, the
17
+ * fullest of the three archetypes.
18
+ *
19
+ * The JSON projection of this pilot is authoritative at
20
+ * ../__fixtures__/alb-ecs-service.json (already schema-validated by
21
+ * component-schema.test.ts) — this module is the real typed `Component`
22
+ * authoring form (#560, ../component.ts) that composes to that same
23
+ * document; see ./pilots.test.ts, which asserts the two never diverge.
24
+ */
25
+
26
+ import type { Component } from "../component";
27
+ import { phase, stackOutput } from "../component";
28
+
29
+ /** The shared ALB stack's exported outputs this service imports — the cross-stack wiring axis. */
30
+ const sharedAlbOutputs = {
31
+ listenerArn: stackOutput("shared-alb", "ListenerArn"),
32
+ clusterArn: stackOutput("shared-alb", "ClusterArn"),
33
+ subnets: stackOutput("shared-alb", "Subnets"),
34
+ };
35
+
36
+ export const searchService: Component = {
37
+ name: "search-service",
38
+ archetype: "service",
39
+ dependsOn: ["shared-alb"],
40
+ build: { kind: "docker-build", context: ".", into: "archive" },
41
+ deploy: [
42
+ phase("Publish", [{ kind: "publish-image", from: "archive", to: "$env.registry" }]),
43
+ phase("Apply", [
44
+ {
45
+ kind: "cfn-deploy",
46
+ template: "archive:search.template.json",
47
+ imageRef: "@Publish.digest",
48
+ inputs: sharedAlbOutputs,
49
+ },
50
+ { kind: "ecs-update-service", cluster: "$env.cluster", service: "search" },
51
+ ]),
52
+ phase("Verify", [
53
+ { kind: "wait-steady-state", service: "search" },
54
+ { kind: "health-gate", path: "/healthz" },
55
+ ]),
56
+ ],
57
+ // No native `rollback` on ecs-update-service/cfn-deploy for an already-running
58
+ // service swap — the component declares an explicit compensation phase
59
+ // (auto/no-rollback axis: this is the "no automatic capability rollback,
60
+ // component supplies its own" side, contrasted with code-deploy's native
61
+ // automatic rollback in the Neo4j pilot).
62
+ rollback: [phase("Rollback", [{ kind: "rollback-previous", service: "search", cluster: "$env.cluster" }])],
63
+ };
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Pilot: DynamoDB table (#555, epic #551).
3
+ *
4
+ * Exercises the sticky-apply axis: `cfn-deploy` carries declarative safety
5
+ * options — `onReplace: "block"` refuses a changeset that would replace the
6
+ * table (losing data) rather than update it in place, and `stageGsi: true`
7
+ * stages a GSI change (add → backfill → remove) instead of an in-place
8
+ * replace. That stickiness lives inside the `cfn-deploy` capability, exposed
9
+ * as options, not scripted per component — see
10
+ * capabilities.mdx#stickiness-lives-in-the-capability. `infra` archetype: no
11
+ * build, apply → verify only. Verify fans out in parallel: the stack wait and
12
+ * a GSI backfill migration have no ordering dependency on each other.
13
+ *
14
+ * The JSON projection of this pilot is authoritative at
15
+ * ../__fixtures__/dynamodb-infra.json (already schema-validated by
16
+ * component-schema.test.ts) — this module is the real typed `Component`
17
+ * authoring form (#560, ../component.ts) that composes to that same
18
+ * document; see ./pilots.test.ts, which asserts the two never diverge.
19
+ */
20
+
21
+ import type { Component } from "../component";
22
+ import { phase } from "../component";
23
+
24
+ // `cfn-deploy`'s safety fields, kept as a plain literal here: the pilot is
25
+ // agnostic component *data* naming the `cfn-deploy` kind, so it does not import
26
+ // the AWS capability's types (those live in the aws lexicon now). The `onReplace`
27
+ // value must match `cfn-deploy`'s `CfnReplacePolicy` union.
28
+ const cfnSafetyOptions: { onReplace: "block" | "allow" | "snapshot-first"; stageGsi: boolean } = {
29
+ onReplace: "block",
30
+ stageGsi: true,
31
+ };
32
+
33
+ export const ordersTable: Component = {
34
+ name: "orders-table",
35
+ archetype: "infra",
36
+ dependsOn: [],
37
+ deploy: [
38
+ phase("Apply", [
39
+ { kind: "cfn-deploy", template: "archive:orders-table.template.json", ...cfnSafetyOptions },
40
+ ]),
41
+ phase(
42
+ "Verify",
43
+ [
44
+ { kind: "wait-for-stack", stack: "orders-table" },
45
+ {
46
+ kind: "run-migration",
47
+ script: "archive:migrations/backfill-gsi.sql",
48
+ // A GSI backfill has no clean inverse: once items are re-projected
49
+ // onto the new index, "rolling back" the migration would mean a
50
+ // second migration to undo it, not a mechanical compensation the
51
+ // capability could run automatically — see COMP003
52
+ // (lint-rules/composition.mdx) for the opt-out convention.
53
+ noRollback: "GSI backfill is forward-only; undoing it needs a second, hand-written migration, not automatic compensation",
54
+ },
55
+ ],
56
+ { parallel: true },
57
+ ),
58
+ ],
59
+ };
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Pilot pair: JAR producer -> EMR consumer, cross-component artifact outputs
3
+ * (#561, epic #551).
4
+ *
5
+ * This is the epic's worked example for cross-component wiring (#551
6
+ * §"Cross-component outputs", docs/components/composition-and-wiring.mdx
7
+ * §"Cross-component outputs"): a **producer-library** component
8
+ * (`jar-lib`) that only builds and publishes an artifact — no apply, no
9
+ * service — paired with an **infra** consumer (`emr-job`) that submits an
10
+ * EMR job run against the producer's published S3 URI.
11
+ *
12
+ * The wiring itself needs no new machinery: `dependsOn: ["jar-lib"]` orders
13
+ * the producer first (`resolveComponentGraph`, ../driver.ts), and
14
+ * `"@jar-lib.publish.uri"` is the same `@<component>.publish.uri|digest|key`
15
+ * reference form `resolveWiring` (../driver.ts) already resolves generically
16
+ * from `componentOutputs`, which `runComponentDeploy` already populates from
17
+ * any step whose output carries `uri`/`digest`/`key` (`findPublishOutput`) —
18
+ * both landed with #556/#560 and are exercised by ../driver.test.ts's
19
+ * "wires a cross-component artifact reference" case. What #561 actually adds
20
+ * is: this pair authored as real typed `Component`s (rather than only the
21
+ * hand-written JSON fixtures), and a real `emr-start-job-run`/`wait-job`
22
+ * capability implementation (../verbs/job-submission.ts,
23
+ * ../verbs/wait-verify.ts) so the pair runs to completion against a mocked
24
+ * `CloudExecutor` instead of throwing `CapabilityNotImplementedError`.
25
+ *
26
+ * The JSON projections of these two components are authoritative at
27
+ * ../__fixtures__/jar-lib-producer.json and
28
+ * ../__fixtures__/emr-job-consumer.json (pre-existing, from #560) — this
29
+ * module is the real typed `Component` authoring form that composes to those
30
+ * same documents; see ./pilots.test.ts, which asserts the two never diverge.
31
+ */
32
+
33
+ import type { Component } from "../component";
34
+ import { phase } from "../component";
35
+
36
+ /** Producer: a JAR built from a Maven project, published to S3. Publish-only deploy — no apply phase at all, the defining shape of the `producer-library` archetype. */
37
+ export const jarLib: Component = {
38
+ name: "jar-lib",
39
+ archetype: "producer-library",
40
+ dependsOn: [],
41
+ build: { kind: "jvm-build", context: ".", into: "archive" },
42
+ deploy: [
43
+ // → @jar-lib.publish.uri / @jar-lib.publish.digest, resolved by the graph
44
+ // for any downstream consumer — never known by this component itself.
45
+ phase("Publish", [{ kind: "publish-artifact", from: "archive", to: "$env.s3" }]),
46
+ ],
47
+ };
48
+
49
+ /** Consumer: an EMR job run reading the producer's published JAR by S3 URI. `dependsOn: ["jar-lib"]` orders the producer first; the graph resolves the reference into the Submit step. */
50
+ export const emrJob: Component = {
51
+ name: "emr-job",
52
+ archetype: "infra",
53
+ dependsOn: ["jar-lib"],
54
+ deploy: [
55
+ phase("Submit", [
56
+ {
57
+ kind: "emr-start-job-run",
58
+ jar: "@jar-lib.publish.uri",
59
+ args: ["--input", "$env.inputPath", "--output", "$env.outputPath"],
60
+ // A submitted EMR job run has no automatic "undo": stopping a
61
+ // running/completed job is not the same as reverting whatever it
62
+ // already wrote, so compensation is a human/runbook decision, not a
63
+ // mechanical capability rollback — see COMP003 (lint-rules/composition.mdx).
64
+ noRollback: "a submitted job run has no automatic undo; cancelling it does not revert data it already wrote",
65
+ },
66
+ ]),
67
+ phase("Verify", [{ kind: "wait-job", runId: "@Submit.runId" }]),
68
+ ],
69
+ };