@intentius/chant 0.57.0 → 0.59.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.
- package/dist/audit/catalog.d.ts +51 -1
- package/dist/audit/catalog.d.ts.map +1 -1
- package/dist/audit/core.d.ts +36 -1
- package/dist/audit/core.d.ts.map +1 -1
- package/dist/audit/discover.d.ts +26 -9
- package/dist/audit/discover.d.ts.map +1 -1
- package/dist/audit/lineage.d.ts +10 -0
- package/dist/audit/lineage.d.ts.map +1 -0
- package/dist/audit/prior-art.d.ts +385 -0
- package/dist/audit/prior-art.d.ts.map +1 -0
- package/dist/audit/proof.d.ts +16 -0
- package/dist/audit/proof.d.ts.map +1 -1
- package/dist/audit/report-html.d.ts.map +1 -1
- package/dist/audit/report-model.d.ts +8 -1
- package/dist/audit/report-model.d.ts.map +1 -1
- package/dist/audit/report.d.ts.map +1 -1
- package/dist/audit/rules-doc.d.ts +3 -0
- package/dist/audit/rules-doc.d.ts.map +1 -1
- package/dist/audit/secrets.d.ts +15 -0
- package/dist/audit/secrets.d.ts.map +1 -1
- package/dist/audit/terraform-state.d.ts +46 -0
- package/dist/audit/terraform-state.d.ts.map +1 -0
- package/dist/build.d.ts +17 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/claimed-fields.d.ts +161 -0
- package/dist/claimed-fields.d.ts.map +1 -0
- package/dist/cli/build-params-cli.d.ts +2 -2
- package/dist/cli/command-group.d.ts +14 -0
- package/dist/cli/command-group.d.ts.map +1 -1
- package/dist/cli/commands/audit.d.ts +17 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/carve-bridge.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-docs.d.ts +1 -1
- package/dist/cli/commands/check-lexicon-examples.d.ts +16 -6
- package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/codegen.d.ts +1 -0
- package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/project.d.ts +7 -0
- package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/lint.d.ts +13 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/onboard.d.ts +2 -0
- package/dist/cli/commands/onboard.d.ts.map +1 -1
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/operator.d.ts +82 -16
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts +49 -42
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/main.d.ts +12 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/mcp/op-tools.d.ts +16 -1
- package/dist/cli/mcp/op-tools.d.ts.map +1 -1
- package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
- package/dist/cli/mcp/resources/context.d.ts.map +1 -1
- package/dist/cli/plugins.d.ts +22 -0
- package/dist/cli/plugins.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +40 -9
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/generate-post-synth-barrel.d.ts +1 -1
- package/dist/components/auto-release.d.ts +10 -20
- package/dist/components/auto-release.d.ts.map +1 -1
- package/dist/components/capability.d.ts +4 -4
- package/dist/components/cli-support.d.ts +24 -22
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/component.d.ts +21 -6
- package/dist/components/component.d.ts.map +1 -1
- package/dist/components/driver-output.d.ts.map +1 -1
- package/dist/components/driver.d.ts +73 -37
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/manifest-persistence.d.ts +1 -9
- package/dist/components/manifest-persistence.d.ts.map +1 -1
- package/dist/components/run-progress.d.ts +6 -6
- package/dist/components/run-progress.d.ts.map +1 -1
- package/dist/components/verbs/run-agent.d.ts +10 -22
- package/dist/components/verbs/run-agent.d.ts.map +1 -1
- package/dist/components/verbs/verify.d.ts +2 -2
- package/dist/deep-observation.d.ts +17 -0
- package/dist/deep-observation.d.ts.map +1 -1
- package/dist/detectLexicon.d.ts +13 -0
- package/dist/detectLexicon.d.ts.map +1 -1
- package/dist/discovery/files.d.ts +4 -4
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/param-deps.d.ts +33 -0
- package/dist/discovery/param-deps.d.ts.map +1 -1
- package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
- package/dist/discovery/sandbox/config-wire.d.ts +2 -2
- package/dist/fold/foldable-helpers.d.ts +5 -1
- package/dist/fold/foldable-helpers.d.ts.map +1 -1
- package/dist/fold-provenance.d.ts +236 -0
- package/dist/fold-provenance.d.ts.map +1 -0
- package/dist/graph-ops.d.ts +1 -1
- package/dist/held-elsewhere.d.ts +85 -0
- package/dist/held-elsewhere.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/kubectl-context.d.ts +3 -3
- package/dist/lexicon-config.d.ts +4 -4
- package/dist/lexicon-plugin-helpers.d.ts +1 -1
- package/dist/lexicon.d.ts +273 -16
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/change-set.d.ts +13 -0
- package/dist/lifecycle/change-set.d.ts.map +1 -1
- package/dist/lifecycle/deep-diff.d.ts +133 -6
- package/dist/lifecycle/deep-diff.d.ts.map +1 -1
- package/dist/lifecycle/deep-observe.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +79 -3
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/index.d.ts +1 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/release-ledger.d.ts +2 -2
- package/dist/lifecycle/run-ledger.d.ts +53 -0
- package/dist/lifecycle/run-ledger.d.ts.map +1 -0
- package/dist/lifecycle/symptoms.d.ts +3 -3
- package/dist/lifecycle/symptoms.d.ts.map +1 -1
- package/dist/lint/config.d.ts +81 -2
- package/dist/lint/config.d.ts.map +1 -1
- package/dist/lint/post-synth.d.ts +55 -2
- package/dist/lint/post-synth.d.ts.map +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -1
- package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts +44 -0
- package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts.map +1 -0
- package/dist/lint/rules/comp/index.d.ts +1 -1
- package/dist/lint/rules/comp/index.d.ts.map +1 -1
- package/dist/lint/rules/op/index.d.ts +16 -0
- package/dist/lint/rules/op/index.d.ts.map +1 -0
- package/dist/lint/rules/op/ops012-activity-contract.d.ts +27 -0
- package/dist/lint/rules/op/ops012-activity-contract.d.ts.map +1 -0
- package/dist/lint/rules/op/ops013-step-output-ref.d.ts +61 -0
- package/dist/lint/rules/op/ops013-step-output-ref.d.ts.map +1 -0
- package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts +55 -0
- package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -0
- package/dist/lint/rules/op/support.d.ts +12 -0
- package/dist/lint/rules/op/support.d.ts.map +1 -0
- package/dist/lint/suppressions.d.ts +108 -0
- package/dist/lint/suppressions.d.ts.map +1 -0
- package/dist/live-endpoint.d.ts +1 -1
- package/dist/op/activities/activity-contracts.d.ts +54 -0
- package/dist/op/activities/activity-contracts.d.ts.map +1 -0
- package/dist/op/activities/apply.d.ts +262 -0
- package/dist/op/activities/apply.d.ts.map +1 -0
- package/dist/op/activities/build.d.ts +13 -0
- package/dist/op/activities/build.d.ts.map +1 -0
- package/dist/op/activities/converge.d.ts +110 -0
- package/dist/op/activities/converge.d.ts.map +1 -0
- package/dist/op/activities/env-teardown.d.ts +76 -0
- package/dist/op/activities/env-teardown.d.ts.map +1 -0
- package/dist/op/activities/guard-validate.d.ts +64 -0
- package/dist/op/activities/guard-validate.d.ts.map +1 -0
- package/dist/op/activities/http-check.d.ts +34 -0
- package/dist/op/activities/http-check.d.ts.map +1 -0
- package/dist/op/activities/index.d.ts +31 -0
- package/dist/op/activities/index.d.ts.map +1 -0
- package/dist/op/activities/lexicon-upgrade.d.ts +182 -0
- package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -0
- package/dist/op/activities/lifecycle.d.ts +42 -0
- package/dist/op/activities/lifecycle.d.ts.map +1 -0
- package/dist/op/activities/pipeline-audit.d.ts +84 -0
- package/dist/op/activities/pipeline-audit.d.ts.map +1 -0
- package/dist/op/activities/policy.d.ts +17 -0
- package/dist/op/activities/policy.d.ts.map +1 -0
- package/dist/op/activities/reconcile.d.ts +149 -0
- package/dist/op/activities/reconcile.d.ts.map +1 -0
- package/dist/op/activities/shell.d.ts +13 -0
- package/dist/op/activities/shell.d.ts.map +1 -0
- package/dist/op/activities/teardown.d.ts +10 -0
- package/dist/op/activities/teardown.d.ts.map +1 -0
- package/dist/op/activities/util.d.ts +7 -0
- package/dist/op/activities/util.d.ts.map +1 -0
- package/dist/op/activities/wait.d.ts +28 -0
- package/dist/op/activities/wait.d.ts.map +1 -0
- package/dist/op/activities/workflow-audit.d.ts +92 -0
- package/dist/op/activities/workflow-audit.d.ts.map +1 -0
- package/dist/op/activity-contract-registry.d.ts +76 -0
- package/dist/op/activity-contract-registry.d.ts.map +1 -0
- package/dist/op/activity-contract.d.ts +25 -18
- package/dist/op/activity-contract.d.ts.map +1 -1
- package/dist/op/activity-failure.d.ts +28 -0
- package/dist/op/activity-failure.d.ts.map +1 -0
- package/dist/op/activity-profiles.d.ts +118 -0
- package/dist/op/activity-profiles.d.ts.map +1 -0
- package/dist/op/activity-registry.d.ts +22 -38
- package/dist/op/activity-registry.d.ts.map +1 -1
- package/dist/op/activity-runtime.d.ts +3 -14
- package/dist/op/activity-runtime.d.ts.map +1 -1
- package/dist/op/builders.d.ts +85 -30
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/change-signal.d.ts +91 -0
- package/dist/op/change-signal.d.ts.map +1 -0
- package/dist/op/composites/apply-op.d.ts +118 -0
- package/dist/op/composites/apply-op.d.ts.map +1 -0
- package/dist/op/composites/converge-op.d.ts +120 -0
- package/dist/op/composites/converge-op.d.ts.map +1 -0
- package/dist/op/composites/index.d.ts +26 -0
- package/dist/op/composites/index.d.ts.map +1 -0
- package/dist/op/composites/lexicon-upgrade-op.d.ts +78 -0
- package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -0
- package/dist/op/composites/pipeline-audit-op.d.ts +50 -0
- package/dist/op/composites/pipeline-audit-op.d.ts.map +1 -0
- package/dist/op/composites/reconcile-op.d.ts +57 -0
- package/dist/op/composites/reconcile-op.d.ts.map +1 -0
- package/dist/op/composites/watch-op.d.ts +60 -0
- package/dist/op/composites/watch-op.d.ts.map +1 -0
- package/dist/op/composites/workflow-audit-op.d.ts +57 -0
- package/dist/op/composites/workflow-audit-op.d.ts.map +1 -0
- package/dist/op/converge-rule.d.ts +12 -10
- package/dist/op/converge-rule.d.ts.map +1 -1
- package/dist/op/cron.d.ts +51 -0
- package/dist/op/cron.d.ts.map +1 -0
- package/dist/op/discover.d.ts +9 -0
- package/dist/op/discover.d.ts.map +1 -1
- package/dist/op/duration.d.ts +11 -0
- package/dist/op/duration.d.ts.map +1 -0
- package/dist/op/emulator-lifecycle.d.ts.map +1 -1
- package/dist/op/gate-name.d.ts +40 -0
- package/dist/op/gate-name.d.ts.map +1 -0
- package/dist/op/gate-summary.d.ts +43 -0
- package/dist/op/gate-summary.d.ts.map +1 -0
- package/dist/op/gate.d.ts +90 -0
- package/dist/op/gate.d.ts.map +1 -0
- package/dist/op/generate-pipeline.d.ts +9 -0
- package/dist/op/generate-pipeline.d.ts.map +1 -1
- package/dist/op/index.d.ts +29 -9
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/local-executor.d.ts +114 -28
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-output.d.ts +11 -1
- package/dist/op/local-output.d.ts.map +1 -1
- package/dist/op/op-ir.d.ts +185 -0
- package/dist/op/op-ir.d.ts.map +1 -0
- package/dist/op/op-verb-class.d.ts +10 -2
- package/dist/op/op-verb-class.d.ts.map +1 -1
- package/dist/op/operator.d.ts +93 -5
- package/dist/op/operator.d.ts.map +1 -1
- package/dist/op/receipt-store.d.ts +1 -1
- package/dist/op/receipt-store.d.ts.map +1 -1
- package/dist/op/resource.d.ts +15 -1
- package/dist/op/resource.d.ts.map +1 -1
- package/dist/op/runtime.d.ts +200 -0
- package/dist/op/runtime.d.ts.map +1 -0
- package/dist/op/runtimes/local.d.ts +29 -0
- package/dist/op/runtimes/local.d.ts.map +1 -0
- package/dist/op/step-output-ref.d.ts +15 -13
- package/dist/op/step-output-ref.d.ts.map +1 -1
- package/dist/op/types.d.ts +96 -29
- package/dist/op/types.d.ts.map +1 -1
- package/dist/ownership.d.ts +1 -1
- package/dist/provenance.d.ts +21 -0
- package/dist/provenance.d.ts.map +1 -1
- package/dist/serializer-walker.d.ts.map +1 -1
- package/dist/terraform/bridge.d.ts +26 -7
- package/dist/terraform/bridge.d.ts.map +1 -1
- package/dist/terraform/carve-provider.d.ts +28 -2
- package/dist/terraform/carve-provider.d.ts.map +1 -1
- package/dist/terraform/data-source-shape.d.ts +77 -0
- package/dist/terraform/data-source-shape.d.ts.map +1 -0
- package/dist/terraform/graph.d.ts.map +1 -1
- package/dist/terraform/providers/kubernetes.d.ts +5 -0
- package/dist/terraform/providers/kubernetes.d.ts.map +1 -1
- package/dist/terraform/tier-map.d.ts +16 -4
- package/dist/terraform/tier-map.d.ts.map +1 -1
- package/dist/terraform/types.d.ts +8 -0
- package/dist/terraform/types.d.ts.map +1 -1
- package/package.json +6 -1
- package/src/audit/catalog.test.ts +79 -3
- package/src/audit/catalog.ts +111 -13
- package/src/audit/core.test.ts +26 -0
- package/src/audit/core.ts +84 -18
- package/src/audit/discover.test.ts +39 -0
- package/src/audit/discover.ts +202 -18
- package/src/audit/lineage.ts +100 -0
- package/src/audit/prior-art.ts +153 -0
- package/src/audit/proof.test.ts +67 -0
- package/src/audit/proof.ts +70 -0
- package/src/audit/report-html.ts +9 -4
- package/src/audit/report-model.ts +16 -2
- package/src/audit/report.test.ts +33 -0
- package/src/audit/report.ts +5 -3
- package/src/audit/rules-doc.test.ts +34 -2
- package/src/audit/rules-doc.ts +82 -9
- package/src/audit/secrets.ts +15 -3
- package/src/audit/terraform-state.test.ts +144 -0
- package/src/audit/terraform-state.ts +131 -0
- package/src/build.ts +31 -1
- package/src/claimed-fields.test.ts +145 -0
- package/src/claimed-fields.ts +208 -0
- package/src/cli/build-params-cli.ts +2 -2
- package/src/cli/command-group.ts +14 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/.terraform/providers/lock.txt +1 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/main.tf +1 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/modules/foo/main.tf +1 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/variables.tf +3 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +13 -4
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs-cli.ts +4 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +1 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/package-cli.ts +21 -0
- package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +1 -0
- package/src/cli/commands/audit.test.ts +191 -11
- package/src/cli/commands/audit.ts +78 -28
- package/src/cli/commands/build.test.ts +330 -9
- package/src/cli/commands/build.ts +170 -24
- package/src/cli/commands/carve-bridge.test.ts +237 -14
- package/src/cli/commands/carve-bridge.ts +21 -17
- package/src/cli/commands/carve-emit-k8s.test.ts +17 -10
- package/src/cli/commands/check-lexicon-docs.ts +1 -1
- package/src/cli/commands/check-lexicon-examples.test.ts +29 -1
- package/src/cli/commands/check-lexicon-examples.ts +42 -10
- package/src/cli/commands/init-lexicon/templates/codegen.ts +9 -0
- package/src/cli/commands/init-lexicon/templates/project.ts +44 -4
- package/src/cli/commands/init-lexicon.test.ts +97 -2
- package/src/cli/commands/init-lexicon.ts +4 -2
- package/src/cli/commands/init.test.ts +35 -1
- package/src/cli/commands/init.ts +14 -3
- package/src/cli/commands/lint.test.ts +194 -1
- package/src/cli/commands/lint.ts +205 -7
- package/src/cli/commands/onboard.test.ts +75 -0
- package/src/cli/commands/onboard.ts +54 -23
- package/src/cli/handlers/build.test.ts +81 -1
- package/src/cli/handlers/build.ts +15 -1
- package/src/cli/handlers/graph.test.ts +3 -3
- package/src/cli/handlers/lifecycle.test.ts +195 -12
- package/src/cli/handlers/lifecycle.ts +123 -6
- package/src/cli/handlers/misc.ts +1 -1
- package/src/cli/handlers/operator.test.ts +183 -11
- package/src/cli/handlers/operator.ts +341 -55
- package/src/cli/handlers/run.test.ts +568 -1295
- package/src/cli/handlers/run.ts +446 -912
- package/src/cli/main.test.ts +22 -16
- package/src/cli/main.ts +66 -33
- package/src/cli/mcp/op-tools.ts +147 -88
- package/src/cli/mcp/resource-handlers.ts +10 -37
- package/src/cli/mcp/resources/context.ts +11 -12
- package/src/cli/mcp/server.test.ts +25 -27
- package/src/cli/mcp/server.ts +2 -2
- package/src/cli/plugins.test.ts +68 -2
- package/src/cli/plugins.ts +39 -0
- package/src/cli/registry.ts +40 -9
- package/src/codegen/docs.ts +1 -1
- package/src/codegen/generate-post-synth-barrel.test.ts +1 -1
- package/src/codegen/generate-post-synth-barrel.ts +1 -1
- package/src/components/README.md +4 -3
- package/src/components/__fixtures__/neo4j-fanout.json +1 -1
- package/src/components/auto-release.test.ts +4 -20
- package/src/components/auto-release.ts +17 -42
- package/src/components/capability.ts +4 -4
- package/src/components/cli-support.test.ts +28 -12
- package/src/components/cli-support.ts +60 -47
- package/src/components/component-schema.test.ts +18 -2
- package/src/components/component.schema.json +18 -5
- package/src/components/component.test.ts +2 -2
- package/src/components/component.ts +27 -7
- package/src/components/config-defaults.test.ts +2 -2
- package/src/components/driver-output.ts +14 -2
- package/src/components/driver.test.ts +109 -20
- package/src/components/driver.ts +201 -84
- package/src/components/index.ts +1 -6
- package/src/components/manifest-persistence.test.ts +2 -20
- package/src/components/manifest-persistence.ts +4 -24
- package/src/components/pilots/neo4j-fanout.pilot.ts +3 -3
- package/src/components/pilots/pilots-lint-clean.test.ts +11 -10
- package/src/components/run-progress.ts +6 -6
- package/src/components/verbs/run-agent.test.ts +19 -0
- package/src/components/verbs/run-agent.ts +12 -24
- package/src/components/verbs/verify.ts +2 -2
- package/src/deep-observation.test.ts +75 -0
- package/src/deep-observation.ts +48 -0
- package/src/detectLexicon.ts +18 -1
- package/src/discovery/collect.test.ts +3 -3
- package/src/discovery/files.ts +4 -4
- package/src/discovery/fold-import.test.ts +1 -1
- package/src/discovery/fold-import.ts +105 -2
- package/src/discovery/param-deps.test.ts +112 -1
- package/src/discovery/param-deps.ts +193 -0
- package/src/discovery/sandbox/bundle.ts +15 -1
- package/src/discovery/sandbox/config-wire.test.ts +2 -2
- package/src/discovery/sandbox/config-wire.ts +2 -2
- package/src/fold/fold.test.ts +56 -0
- package/src/fold/foldable-helpers.ts +82 -2
- package/src/fold-provenance-exclusion.test.ts +186 -0
- package/src/fold-provenance.test.ts +495 -0
- package/src/fold-provenance.ts +441 -0
- package/src/graph-ops.test.ts +3 -3
- package/src/graph-ops.ts +1 -1
- package/src/held-elsewhere.test.ts +102 -0
- package/src/held-elsewhere.ts +114 -0
- package/src/index.ts +3 -0
- package/src/kubectl-context.ts +3 -3
- package/src/lexicon-config.test.ts +5 -5
- package/src/lexicon-config.ts +4 -4
- package/src/lexicon-plugin-helpers.ts +1 -1
- package/src/lexicon.ts +296 -16
- package/src/lifecycle/change-set.test.ts +49 -0
- package/src/lifecycle/change-set.ts +67 -0
- package/src/lifecycle/converge-ledger.ts +1 -1
- package/src/lifecycle/deep-diff.test.ts +267 -14
- package/src/lifecycle/deep-diff.ts +217 -14
- package/src/lifecycle/deep-observe.test.ts +3 -1
- package/src/lifecycle/deep-observe.ts +16 -6
- package/src/lifecycle/gate-ledger.test.ts +74 -2
- package/src/lifecycle/gate-ledger.ts +154 -36
- package/src/lifecycle/index.ts +1 -0
- package/src/lifecycle/release-ledger.ts +2 -2
- package/src/lifecycle/run-ledger.test.ts +268 -0
- package/src/lifecycle/run-ledger.ts +201 -0
- package/src/lifecycle/symptoms.ts +3 -3
- package/src/lint/config.test.ts +82 -1
- package/src/lint/config.ts +112 -3
- package/src/lint/pipeline-change-gate.test.ts +2 -2
- package/src/lint/policy.test.ts +1 -1
- package/src/lint/post-synth.test.ts +31 -0
- package/src/lint/post-synth.ts +54 -1
- package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +2 -2
- package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +1 -1
- package/src/lint/rules/comp/comp.test.ts +27 -1
- package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +76 -0
- package/src/lint/rules/comp/index.ts +3 -3
- package/src/lint/rules/op/index.ts +23 -0
- package/src/lint/rules/op/ops012-activity-contract.test.ts +161 -0
- package/src/lint/rules/op/ops012-activity-contract.ts +64 -0
- package/src/lint/rules/op/ops013-step-output-ref.test.ts +237 -0
- package/src/lint/rules/op/ops013-step-output-ref.ts +98 -0
- package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +263 -0
- package/src/lint/rules/op/ops014-converge-rule-refusals.ts +179 -0
- package/src/lint/rules/op/support.ts +11 -0
- package/src/lint/suppressions.test.ts +163 -0
- package/src/lint/suppressions.ts +204 -0
- package/src/live-endpoint.ts +1 -1
- package/src/op/activities/activity-contracts.ts +66 -0
- package/src/op/activities/apply.test.ts +567 -0
- package/src/op/activities/apply.ts +662 -0
- package/src/op/activities/build.ts +26 -0
- package/src/op/activities/converge.test.ts +330 -0
- package/src/op/activities/converge.ts +449 -0
- package/src/op/activities/env-teardown.test.ts +187 -0
- package/src/op/activities/env-teardown.ts +171 -0
- package/src/op/activities/guard-validate.test.ts +139 -0
- package/src/op/activities/guard-validate.ts +223 -0
- package/src/op/activities/http-check.test.ts +48 -0
- package/src/op/activities/http-check.ts +55 -0
- package/src/op/activities/index.ts +119 -0
- package/src/op/activities/lexicon-upgrade.test.ts +492 -0
- package/src/op/activities/lexicon-upgrade.ts +673 -0
- package/src/op/activities/lifecycle.ts +85 -0
- package/src/op/activities/pipeline-audit.test.ts +67 -0
- package/src/op/activities/pipeline-audit.ts +201 -0
- package/src/op/activities/policy.test.ts +19 -0
- package/src/op/activities/policy.ts +37 -0
- package/src/op/activities/reconcile.test.ts +161 -0
- package/src/op/activities/reconcile.ts +354 -0
- package/src/op/activities/shell.ts +26 -0
- package/src/op/activities/teardown.ts +22 -0
- package/src/op/activities/util.ts +6 -0
- package/src/op/activities/wait.ts +69 -0
- package/src/op/activities/workflow-audit.test.ts +90 -0
- package/src/op/activities/workflow-audit.ts +203 -0
- package/src/op/activity-contract-registry.test.ts +98 -0
- package/src/op/activity-contract-registry.ts +114 -0
- package/src/op/activity-contract.test.ts +1 -1
- package/src/op/activity-contract.ts +37 -33
- package/src/op/activity-failure.ts +34 -0
- package/src/op/activity-profiles.test.ts +56 -0
- package/src/op/activity-profiles.ts +116 -0
- package/src/op/activity-registry.test.ts +37 -28
- package/src/op/activity-registry.ts +27 -56
- package/src/op/activity-runtime.ts +3 -47
- package/src/op/builders-exports.test.ts +0 -49
- package/src/op/builders-typed.test.ts +164 -0
- package/src/op/builders.ts +125 -41
- package/src/op/change-signal.test.ts +117 -0
- package/src/op/change-signal.ts +169 -0
- package/src/op/composites/apply-op.ts +218 -0
- package/src/op/composites/composites.test.ts +379 -0
- package/src/op/composites/converge-op.test.ts +168 -0
- package/src/op/composites/converge-op.ts +214 -0
- package/src/op/composites/index.ts +26 -0
- package/src/op/composites/lexicon-upgrade-op.test.ts +68 -0
- package/src/op/composites/lexicon-upgrade-op.ts +134 -0
- package/src/op/composites/pipeline-audit-op.test.ts +25 -0
- package/src/op/composites/pipeline-audit-op.ts +78 -0
- package/src/op/composites/reconcile-op.test.ts +51 -0
- package/src/op/composites/reconcile-op.ts +110 -0
- package/src/op/composites/watch-op.ts +108 -0
- package/src/op/composites/workflow-audit-op.test.ts +25 -0
- package/src/op/composites/workflow-audit-op.ts +88 -0
- package/src/op/converge-rule.ts +12 -10
- package/src/op/cron.test.ts +128 -0
- package/src/op/cron.ts +149 -0
- package/src/op/discover-root.test.ts +105 -1
- package/src/op/discover.test.ts +6 -2
- package/src/op/discover.ts +84 -16
- package/src/op/duration.ts +21 -0
- package/src/op/effect-step.test.ts +29 -14
- package/src/op/emulator-lifecycle.ts +1 -2
- package/src/op/gate-name.test.ts +65 -0
- package/src/op/gate-name.ts +60 -0
- package/src/op/gate-summary.ts +84 -0
- package/src/op/gate.ts +155 -0
- package/src/op/generate-pipeline.test.ts +65 -3
- package/src/op/generate-pipeline.ts +19 -2
- package/src/op/index.ts +48 -8
- package/src/op/local-executor.test.ts +178 -34
- package/src/op/local-executor.ts +371 -102
- package/src/op/local-output.test.ts +95 -11
- package/src/op/local-output.ts +33 -4
- package/src/op/op-ir.test.ts +292 -0
- package/src/op/op-ir.ts +419 -0
- package/src/op/op-verb-class.test.ts +2 -2
- package/src/op/op-verb-class.ts +19 -5
- package/src/op/op.test.ts +28 -7
- package/src/op/operator.test.ts +543 -6
- package/src/op/operator.ts +203 -20
- package/src/op/receipt-store.ts +1 -1
- package/src/op/resource.ts +20 -2
- package/src/op/runtime.ts +203 -0
- package/src/op/runtimes/local.test.ts +181 -0
- package/src/op/runtimes/local.ts +212 -0
- package/src/op/step-output-ref.ts +15 -13
- package/src/op/types.ts +106 -26
- package/src/ownership.ts +1 -1
- package/src/provenance.test.ts +6 -0
- package/src/provenance.ts +21 -1
- package/src/serializer-walker.test.ts +42 -0
- package/src/serializer-walker.ts +21 -2
- package/src/terraform/aws-resources.test.ts +13 -4
- package/src/terraform/bridge.test.ts +22 -9
- package/src/terraform/bridge.ts +89 -28
- package/src/terraform/carve-provider.ts +38 -2
- package/src/terraform/data-source-shape.ts +95 -0
- package/src/terraform/graph.ts +35 -7
- package/src/terraform/providers/kubernetes.ts +48 -2
- package/src/terraform/tier-map.ts +21 -6
- package/src/terraform/types.ts +8 -0
- package/dist/cli/handlers/op-progress.d.ts +0 -90
- package/dist/cli/handlers/op-progress.d.ts.map +0 -1
- package/dist/cli/handlers/run-client.d.ts +0 -127
- package/dist/cli/handlers/run-client.d.ts.map +0 -1
- package/dist/cli/handlers/run-report.d.ts +0 -5
- package/dist/cli/handlers/run-report.d.ts.map +0 -1
- package/dist/components/temporal-codegen-loader.d.ts +0 -27
- package/dist/components/temporal-codegen-loader.d.ts.map +0 -1
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +0 -37
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +0 -1
- package/src/cli/handlers/op-progress.test.ts +0 -268
- package/src/cli/handlers/op-progress.ts +0 -248
- package/src/cli/handlers/run-client.test.ts +0 -82
- package/src/cli/handlers/run-client.ts +0 -219
- package/src/cli/handlers/run-report.test.ts +0 -62
- package/src/cli/handlers/run-report.ts +0 -122
- package/src/components/temporal-codegen-loader.ts +0 -41
- package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +0 -66
package/src/components/driver.ts
CHANGED
|
@@ -11,11 +11,18 @@
|
|
|
11
11
|
* component.schema.json (`@Phase.field` prior-step references,
|
|
12
12
|
* `@<component>.publish.<field>` cross-component artifact references, and
|
|
13
13
|
* passes through `$env.*`/`stackOutput` values as opaque env config), runs
|
|
14
|
-
* `parallel` phases concurrently,
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
14
|
+
* `parallel` phases concurrently, decides a `gate` against the gate ledger
|
|
15
|
+
* (#2119 — the same `../op/gate.ts` the Op executor uses, so `chant run
|
|
16
|
+
* --components` and `chant run <op>` can never disagree about what a gate
|
|
17
|
+
* means), and on terminal failure unwinds every executed step in reverse via
|
|
18
|
+
* that step's capability `rollback`, then runs `onFailure` phases in reverse
|
|
19
|
+
* order (best-effort), mirroring the Op local executor's saga semantics.
|
|
20
|
+
*
|
|
21
|
+
* A gate nobody has approved is not a failure: the component stops there with
|
|
22
|
+
* status `gated`, the pending fact is on the ledger, and no rollback and no
|
|
23
|
+
* `onFailure` phase runs — nothing failed and the steps that did run are the
|
|
24
|
+
* steps the author meant to run before the approval. The next run re-reads the
|
|
25
|
+
* ledger and continues past the gate if `chant approve` has answered it.
|
|
19
26
|
*
|
|
20
27
|
* A step whose capability declares no `rollback` is never silently passed
|
|
21
28
|
* over during unwind: it gets a `"rollback-opted-out"` record (see
|
|
@@ -25,15 +32,13 @@
|
|
|
25
32
|
* already requires at author time — the driver reports the same fact the
|
|
26
33
|
* lint rule already made a component author state.
|
|
27
34
|
*
|
|
28
|
-
* This unwind runs entirely in-process: if the process crashes mid-rollback
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* progress* is Temporal-only, the same boundary that already applies to
|
|
36
|
-
* forward `onFailure` compensation on an Op.
|
|
35
|
+
* This unwind runs entirely in-process: if the process crashes mid-rollback,
|
|
36
|
+
* nothing resumes it — there is no persisted run state to resume from (see
|
|
37
|
+
* docs/components/orchestration.mdx#rollback-comes-free). The *mechanism*
|
|
38
|
+
* (reverse-order unwind calling each capability's `rollback`) is
|
|
39
|
+
* capability-agnostic; *durable resume of a rollback already in progress*
|
|
40
|
+
* would be a hosting runtime's to offer, the same boundary that already
|
|
41
|
+
* applies to forward `onFailure` compensation on an Op.
|
|
37
42
|
*
|
|
38
43
|
* Contains zero per-component logic: nothing in this module branches on a
|
|
39
44
|
* component or capability `kind`/name. All behavior is either generic
|
|
@@ -42,8 +47,11 @@
|
|
|
42
47
|
*/
|
|
43
48
|
|
|
44
49
|
import { topoSort } from "../codegen/topo-sort";
|
|
50
|
+
import { evaluateGate, gitGateLedgerPort, type GateLedgerPort } from "../op/gate";
|
|
51
|
+
import { gateName } from "../op/gate-name";
|
|
52
|
+
import type { PendingGateRecord } from "../lifecycle/gate-ledger";
|
|
45
53
|
import type { CapabilityRegistry, DeployContext } from "./capability";
|
|
46
|
-
import type { RunProgressEvent } from "./run-progress";
|
|
54
|
+
import type { RunProgressEvent, RunProgressStatus } from "./run-progress";
|
|
47
55
|
|
|
48
56
|
export type { RunProgressEvent } from "./run-progress";
|
|
49
57
|
|
|
@@ -61,10 +69,16 @@ export interface DriverStep {
|
|
|
61
69
|
[param: string]: unknown;
|
|
62
70
|
}
|
|
63
71
|
|
|
64
|
-
/**
|
|
72
|
+
/**
|
|
73
|
+
* A gate step — a human approval, decided against the gate ledger when the run
|
|
74
|
+
* reaches it (schema `Gate`). The name is on `gate`; `signalName` is the
|
|
75
|
+
* deprecated spelling (#2202), so read the name through `gateName()`.
|
|
76
|
+
*/
|
|
65
77
|
export interface DriverGate {
|
|
66
78
|
kind: "gate";
|
|
67
|
-
|
|
79
|
+
gate?: string;
|
|
80
|
+
/** @deprecated Renamed to `gate` in #2202. Accepted through 0.59.0, removed in 0.60.0. */
|
|
81
|
+
signalName?: string;
|
|
68
82
|
timeout?: string;
|
|
69
83
|
description?: string;
|
|
70
84
|
}
|
|
@@ -96,20 +110,6 @@ function isPhaseStep(step: DriverStep | DriverGate | DriverPhase): step is Drive
|
|
|
96
110
|
|
|
97
111
|
// ── Errors ────────────────────────────────────────────────────────────────
|
|
98
112
|
|
|
99
|
-
/** Thrown when a component's composition contains a `gate` — gates need a durable runtime, matching chant's Op local executor. */
|
|
100
|
-
export class DriverGateUnsupportedError extends Error {
|
|
101
|
-
constructor(
|
|
102
|
-
public readonly component: string,
|
|
103
|
-
public readonly signalName: string,
|
|
104
|
-
) {
|
|
105
|
-
super(
|
|
106
|
-
`component "${component}": gate "${signalName}" is not supported on the local executor — ` +
|
|
107
|
-
`gates need a durable runtime. Re-run with a durable (Temporal) backend.`,
|
|
108
|
-
);
|
|
109
|
-
this.name = "DriverGateUnsupportedError";
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
113
|
/** Thrown when a dependency cycle is found among `dependsOn` edges. */
|
|
114
114
|
export class DependencyCycleError extends Error {
|
|
115
115
|
constructor(public readonly cycle: string[]) {
|
|
@@ -147,12 +147,18 @@ export interface DriverStepRecord {
|
|
|
147
147
|
durationMs: number;
|
|
148
148
|
output?: unknown;
|
|
149
149
|
error?: string;
|
|
150
|
+
/** Set on a `gate` step that passed (#2119): who resolved it, when, and at what address. */
|
|
151
|
+
approval?: { gate: string; resolvedBy: string; timestamp: string; url?: string };
|
|
150
152
|
}
|
|
151
153
|
|
|
152
154
|
export interface DriverComponentResult {
|
|
153
155
|
component: string;
|
|
154
156
|
ok: boolean;
|
|
157
|
+
/** Three-state outcome (#2119) — `gated` is `ok: false` without being a failure: the component stopped at a gate awaiting `chant approve`, and nothing was rolled back. */
|
|
158
|
+
status: "ok" | "fail" | "gated";
|
|
155
159
|
records: DriverStepRecord[];
|
|
160
|
+
/** Present when `status === "gated"`: the pending fact this component stopped on. */
|
|
161
|
+
gate?: PendingGateRecord;
|
|
156
162
|
}
|
|
157
163
|
|
|
158
164
|
export interface DriverRunResult {
|
|
@@ -162,8 +168,14 @@ export interface DriverRunResult {
|
|
|
162
168
|
waves: string[][];
|
|
163
169
|
results: DriverComponentResult[];
|
|
164
170
|
ok: boolean;
|
|
171
|
+
/** Three-state outcome (#2119), matching `OpRunResult.status`. */
|
|
172
|
+
status: "ok" | "fail" | "gated";
|
|
165
173
|
/** Name of the component that terminated the run, if any. */
|
|
166
174
|
failedComponent?: string;
|
|
175
|
+
/** Name of the component the run stopped at for approval, when `status === "gated"`. */
|
|
176
|
+
gatedComponent?: string;
|
|
177
|
+
/** The pending fact the run stopped on, when `status === "gated"`. */
|
|
178
|
+
gate?: PendingGateRecord;
|
|
167
179
|
/**
|
|
168
180
|
* The accumulated cross-component/cross-stack outputs after the run — each
|
|
169
181
|
* component's `publish` output and, for an applied stack, its `cfn-deploy`
|
|
@@ -285,12 +297,11 @@ export function resolveWiring(
|
|
|
285
297
|
* Deep-walk an object, resolving every string/stackOutput wiring value found.
|
|
286
298
|
* Arrays and nested objects are walked too.
|
|
287
299
|
*
|
|
288
|
-
* Exported (not just used internally) so
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
*
|
|
293
|
-
* place so local and durable execution can never silently diverge.
|
|
300
|
+
* Exported (not just used internally) so a hosting runtime that runs steps
|
|
301
|
+
* out of process can resolve a step's wiring the same way — the orchestrator
|
|
302
|
+
* only accumulates `phaseOutputs`/`componentOutputs` and passes them through;
|
|
303
|
+
* resolution logic stays in one place so local and hosted execution can never
|
|
304
|
+
* silently diverge.
|
|
294
305
|
*/
|
|
295
306
|
export function resolveStepInput(
|
|
296
307
|
input: Record<string, unknown>,
|
|
@@ -338,6 +349,29 @@ class StepFailure extends Error {
|
|
|
338
349
|
}
|
|
339
350
|
}
|
|
340
351
|
|
|
352
|
+
/** Internal: a phase stopped at an unapproved gate (#2119). Carries what ran before it, so the records survive; not a failure, so no unwind follows. */
|
|
353
|
+
class GateStop extends Error {
|
|
354
|
+
constructor(
|
|
355
|
+
public readonly records: DriverStepRecord[],
|
|
356
|
+
public readonly executed: ExecutedStep[],
|
|
357
|
+
public readonly pending: PendingGateRecord,
|
|
358
|
+
) {
|
|
359
|
+
super(`gate "${pending.gate}" is pending approval`);
|
|
360
|
+
this.name = "GateStop";
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/** A result status as the progress stream spells it — the only difference is `fail` vs `failed`, which the two vocabularies have always disagreed on. */
|
|
365
|
+
function progressStatus(status: DriverComponentResult["status"]): RunProgressStatus {
|
|
366
|
+
return status === "fail" ? "failed" : status;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/** How a component's run reaches the gate ledger — see `../op/gate.ts`. */
|
|
370
|
+
export interface GateContext {
|
|
371
|
+
port: GateLedgerPort;
|
|
372
|
+
now?: string;
|
|
373
|
+
}
|
|
374
|
+
|
|
341
375
|
/** Run a single capability step. Never throws for a capability-run failure; returns a fail record instead. */
|
|
342
376
|
async function runCapabilityStep(
|
|
343
377
|
step: DriverStep,
|
|
@@ -381,11 +415,16 @@ async function runCapabilityStep(
|
|
|
381
415
|
}
|
|
382
416
|
|
|
383
417
|
/**
|
|
384
|
-
* Run a phase's steps. A step may be a `Gate` (
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
*
|
|
388
|
-
* `
|
|
418
|
+
* Run a phase's steps. A step may be a `Gate` (decided against the gate
|
|
419
|
+
* ledger, in authored order — a resolution newer than the gate's newest
|
|
420
|
+
* pending fact lets it pass carrying the approver, anything else records the
|
|
421
|
+
* fact and stops the component) or a nested `Phase` (a fan-out unit; recursed
|
|
422
|
+
* into, inheriting `parallel` from its own definition, not its parent's).
|
|
423
|
+
* Steps run sequentially unless `phase.parallel` is set, in which case they run
|
|
424
|
+
* via `Promise.all`, matching ../op/local-executor.ts's phase semantics — and
|
|
425
|
+
* as there, a gate in a parallel phase is decided before the fan-out, since a
|
|
426
|
+
* gate is a read of the ledger rather than work, and starting activities a
|
|
427
|
+
* pending gate is about to strand defeats the point of stopping at it.
|
|
389
428
|
*
|
|
390
429
|
* `onProgress`, when supplied, is called with a `phase-start` event before any
|
|
391
430
|
* step runs, a `step` event around each capability invocation (`"running"`
|
|
@@ -402,22 +441,60 @@ async function runPhase(
|
|
|
402
441
|
registry: CapabilityRegistry,
|
|
403
442
|
phaseOutputs: Record<string, Record<string, unknown>>,
|
|
404
443
|
componentOutputs: Record<string, Record<string, unknown>>,
|
|
444
|
+
gates: GateContext,
|
|
405
445
|
onProgress?: (event: RunProgressEvent) => void,
|
|
406
446
|
): Promise<{ records: DriverStepRecord[]; executed: ExecutedStep[] }> {
|
|
407
|
-
|
|
408
|
-
|
|
447
|
+
/** Decide this phase's gates against the ledger, in authored order, before any of its work starts. Throws `GateStop` at the first one nobody has approved. */
|
|
448
|
+
const decideGates = async (): Promise<DriverStepRecord[]> => {
|
|
449
|
+
const gateRecords: DriverStepRecord[] = [];
|
|
450
|
+
for (const gate of phaseDef.steps.filter(isGateStep)) {
|
|
451
|
+
const start = Date.now();
|
|
452
|
+
const check = await evaluateGate(gates.port, {
|
|
453
|
+
op: ctx.component,
|
|
454
|
+
gate: gateName(gate),
|
|
455
|
+
...(gate.description ? { description: gate.description } : {}),
|
|
456
|
+
...(gate.timeout ? { timeout: gate.timeout } : {}),
|
|
457
|
+
...(gates.now ? { now: gates.now } : {}),
|
|
458
|
+
});
|
|
459
|
+
const base = { component: ctx.component, phase: phaseDef.phase, kind: `gate:${gateName(gate)}` };
|
|
460
|
+
if (!check.satisfied) {
|
|
461
|
+
gateRecords.push({ ...base, status: "skipped" as const, durationMs: Date.now() - start });
|
|
462
|
+
for (const skipped of phaseDef.steps.filter((s): s is DriverStep | DriverPhase => !isGateStep(s))) {
|
|
463
|
+
gateRecords.push(skippedRecord(skipped));
|
|
464
|
+
}
|
|
465
|
+
throw new GateStop(gateRecords, [], check.pending);
|
|
466
|
+
}
|
|
467
|
+
gateRecords.push({
|
|
468
|
+
...base,
|
|
469
|
+
status: "ok" as const,
|
|
470
|
+
durationMs: Date.now() - start,
|
|
471
|
+
approval: {
|
|
472
|
+
gate: gateName(gate),
|
|
473
|
+
resolvedBy: check.resolution.resolvedBy,
|
|
474
|
+
timestamp: check.resolution.timestamp,
|
|
475
|
+
...(check.resolution.url ? { url: check.resolution.url } : {}),
|
|
476
|
+
},
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
return gateRecords;
|
|
480
|
+
};
|
|
409
481
|
|
|
410
482
|
const entries = phaseDef.steps.filter((s): s is DriverStep | DriverPhase => !isGateStep(s));
|
|
411
483
|
|
|
412
484
|
const runEntry = async (
|
|
413
485
|
entry: DriverStep | DriverPhase,
|
|
414
|
-
): Promise<{ records: DriverStepRecord[]; executed: ExecutedStep[]; failed: boolean }> => {
|
|
486
|
+
): Promise<{ records: DriverStepRecord[]; executed: ExecutedStep[]; failed: boolean; pending?: PendingGateRecord }> => {
|
|
415
487
|
if (isPhaseStep(entry)) {
|
|
416
488
|
try {
|
|
417
|
-
const nested = await runPhase(entry, ctx, registry, phaseOutputs, componentOutputs, onProgress);
|
|
489
|
+
const nested = await runPhase(entry, ctx, registry, phaseOutputs, componentOutputs, gates, onProgress);
|
|
418
490
|
return { ...nested, failed: false };
|
|
419
491
|
} catch (err) {
|
|
420
492
|
if (err instanceof StepFailure) return { records: err.records, executed: err.executed, failed: true };
|
|
493
|
+
// A nested fan-out phase's gate stops the whole component, but the
|
|
494
|
+
// records it produced before the gate still belong in the run.
|
|
495
|
+
if (err instanceof GateStop) {
|
|
496
|
+
return { records: err.records, executed: err.executed, failed: false, pending: err.pending };
|
|
497
|
+
}
|
|
421
498
|
throw err;
|
|
422
499
|
}
|
|
423
500
|
}
|
|
@@ -448,32 +525,38 @@ async function runPhase(
|
|
|
448
525
|
};
|
|
449
526
|
};
|
|
450
527
|
|
|
528
|
+
const skippedRecord = (entry: DriverStep | DriverPhase): DriverStepRecord => ({
|
|
529
|
+
component: ctx.component,
|
|
530
|
+
phase: phaseDef.phase,
|
|
531
|
+
kind: isPhaseStep(entry) ? entry.phase : (entry as DriverStep).kind,
|
|
532
|
+
status: "skipped",
|
|
533
|
+
durationMs: 0,
|
|
534
|
+
});
|
|
535
|
+
|
|
451
536
|
const runEntries = async (): Promise<{ records: DriverStepRecord[]; executed: ExecutedStep[] }> => {
|
|
537
|
+
const gateRecords = await decideGates();
|
|
452
538
|
if (phaseDef.parallel) {
|
|
453
539
|
const results = await Promise.all(entries.map(runEntry));
|
|
454
|
-
const records = results.flatMap((r) => r.records);
|
|
540
|
+
const records = gateRecords.concat(results.flatMap((r) => r.records));
|
|
455
541
|
const executed = results.flatMap((r) => r.executed);
|
|
542
|
+
const pending = results.find((r) => r.pending)?.pending;
|
|
543
|
+
if (pending) throw new GateStop(records, executed, pending);
|
|
456
544
|
if (results.some((r) => r.failed)) throw new StepFailure(records, executed);
|
|
457
545
|
return { records, executed };
|
|
458
546
|
}
|
|
459
547
|
|
|
460
|
-
const records: DriverStepRecord[] = [];
|
|
548
|
+
const records: DriverStepRecord[] = [...gateRecords];
|
|
461
549
|
const executed: ExecutedStep[] = [];
|
|
462
550
|
for (let i = 0; i < entries.length; i++) {
|
|
463
551
|
const result = await runEntry(entries[i]);
|
|
464
552
|
records.push(...result.records);
|
|
465
553
|
executed.push(...result.executed);
|
|
554
|
+
if (result.pending) {
|
|
555
|
+
for (const skipped of entries.slice(i + 1)) records.push(skippedRecord(skipped));
|
|
556
|
+
throw new GateStop(records, executed, result.pending);
|
|
557
|
+
}
|
|
466
558
|
if (result.failed) {
|
|
467
|
-
for (const skipped of entries.slice(i + 1))
|
|
468
|
-
const skippedKind = isPhaseStep(skipped) ? skipped.phase : (skipped as DriverStep).kind;
|
|
469
|
-
records.push({
|
|
470
|
-
component: ctx.component,
|
|
471
|
-
phase: phaseDef.phase,
|
|
472
|
-
kind: skippedKind,
|
|
473
|
-
status: "skipped",
|
|
474
|
-
durationMs: 0,
|
|
475
|
-
});
|
|
476
|
-
}
|
|
559
|
+
for (const skipped of entries.slice(i + 1)) records.push(skippedRecord(skipped));
|
|
477
560
|
throw new StepFailure(records, executed);
|
|
478
561
|
}
|
|
479
562
|
}
|
|
@@ -486,7 +569,9 @@ async function runPhase(
|
|
|
486
569
|
onProgress?.({ type: "phase-done", component: ctx.component, phase: phaseDef.phase, status: "ok" });
|
|
487
570
|
return result;
|
|
488
571
|
} catch (err) {
|
|
489
|
-
if (err instanceof
|
|
572
|
+
if (err instanceof GateStop) {
|
|
573
|
+
onProgress?.({ type: "phase-done", component: ctx.component, phase: phaseDef.phase, status: "gated" });
|
|
574
|
+
} else if (err instanceof StepFailure) {
|
|
490
575
|
onProgress?.({ type: "phase-done", component: ctx.component, phase: phaseDef.phase, status: "failed" });
|
|
491
576
|
}
|
|
492
577
|
throw err;
|
|
@@ -577,6 +662,7 @@ export async function runComponentDeploy(
|
|
|
577
662
|
registry: CapabilityRegistry,
|
|
578
663
|
componentOutputs: Record<string, Record<string, unknown>>,
|
|
579
664
|
onProgress?: (event: RunProgressEvent) => void,
|
|
665
|
+
gates: GateContext = { port: gitGateLedgerPort() },
|
|
580
666
|
): Promise<DriverComponentResult> {
|
|
581
667
|
const phaseOutputs: Record<string, Record<string, unknown>> = {};
|
|
582
668
|
const records: DriverStepRecord[] = [];
|
|
@@ -584,11 +670,20 @@ export async function runComponentDeploy(
|
|
|
584
670
|
|
|
585
671
|
try {
|
|
586
672
|
for (const phaseDef of component.deploy) {
|
|
587
|
-
const result = await runPhase(phaseDef, ctx, registry, phaseOutputs, componentOutputs, onProgress);
|
|
673
|
+
const result = await runPhase(phaseDef, ctx, registry, phaseOutputs, componentOutputs, gates, onProgress);
|
|
588
674
|
records.push(...result.records);
|
|
589
675
|
allExecuted.push(...result.executed);
|
|
590
676
|
}
|
|
591
677
|
} catch (err) {
|
|
678
|
+
// A pending gate stops the component where it stands (#2119): no saga
|
|
679
|
+
// unwind and no `rollback` phase. The steps before the gate ran on
|
|
680
|
+
// purpose and are meant to survive the wait for an approval — undoing
|
|
681
|
+
// them would make every gated run a no-op with a rollback attached.
|
|
682
|
+
if (err instanceof GateStop) {
|
|
683
|
+
records.push(...err.records);
|
|
684
|
+
return { component: component.name, ok: false, status: "gated", records, gate: err.pending };
|
|
685
|
+
}
|
|
686
|
+
|
|
592
687
|
if (err instanceof StepFailure) {
|
|
593
688
|
records.push(...err.records);
|
|
594
689
|
allExecuted.push(...err.executed);
|
|
@@ -600,24 +695,24 @@ export async function runComponentDeploy(
|
|
|
600
695
|
|
|
601
696
|
for (const phaseDef of [...(component.rollback ?? [])].reverse()) {
|
|
602
697
|
try {
|
|
603
|
-
const result = await runPhase(phaseDef, ctx, registry, phaseOutputs, componentOutputs, onProgress);
|
|
698
|
+
const result = await runPhase(phaseDef, ctx, registry, phaseOutputs, componentOutputs, gates, onProgress);
|
|
604
699
|
records.push(...result.records);
|
|
605
700
|
} catch (compErr) {
|
|
606
|
-
if (compErr instanceof StepFailure) records.push(...compErr.records);
|
|
701
|
+
if (compErr instanceof StepFailure || compErr instanceof GateStop) records.push(...compErr.records);
|
|
607
702
|
else throw compErr;
|
|
608
703
|
}
|
|
609
704
|
}
|
|
610
705
|
|
|
611
|
-
return { component: component.name, ok: false, records };
|
|
706
|
+
return { component: component.name, ok: false, status: "fail", records };
|
|
612
707
|
}
|
|
613
708
|
|
|
614
709
|
// Publish-family and stack outputs become this component's entry in
|
|
615
|
-
// `componentOutputs` — through the same exported accumulator
|
|
616
|
-
//
|
|
617
|
-
//
|
|
710
|
+
// `componentOutputs` — through the same exported accumulator a hosted
|
|
711
|
+
// runtime calls (#700), so local and hosted runs can never diverge on what
|
|
712
|
+
// downstream references see.
|
|
618
713
|
accumulateComponentOutputs(componentOutputs, component.name, phaseOutputs);
|
|
619
714
|
|
|
620
|
-
return { component: component.name, ok: true, records };
|
|
715
|
+
return { component: component.name, ok: true, status: "ok", records };
|
|
621
716
|
}
|
|
622
717
|
|
|
623
718
|
/**
|
|
@@ -641,9 +736,8 @@ export async function runComponentDeploy(
|
|
|
641
736
|
* the driver free of per-capability branching. Returns `undefined` when the
|
|
642
737
|
* component exposed nothing.
|
|
643
738
|
*
|
|
644
|
-
* Exported, like `resolveStepInput`, so
|
|
645
|
-
* (
|
|
646
|
-
* this exact function rather than re-deriving it (#700). The resolver and the
|
|
739
|
+
* Exported, like `resolveStepInput`, so a hosting runtime accumulates outputs
|
|
740
|
+
* via this exact function rather than re-deriving it (#700). The resolver and the
|
|
647
741
|
* accumulator are the two halves of one contract; sharing only the resolver
|
|
648
742
|
* is how the cross-stack gap #699 closed locally could reopen durably.
|
|
649
743
|
*/
|
|
@@ -659,11 +753,11 @@ export function collectComponentOutputs(
|
|
|
659
753
|
/**
|
|
660
754
|
* Record a finished component's outputs (`collectComponentOutputs`) into the
|
|
661
755
|
* shared `componentOutputs` map under the component's own name, merging over
|
|
662
|
-
* any seeded entry (`--seed-outputs`, or a
|
|
663
|
-
* thread-through). Mutates and returns `componentOutputs`, so
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
*
|
|
756
|
+
* any seeded entry (`--seed-outputs`, or a parent orchestrator's
|
|
757
|
+
* thread-through). Mutates and returns `componentOutputs`, so an out-of-process
|
|
758
|
+
* step can hand the updated map back over a JSON boundary — every value in it
|
|
759
|
+
* is plain result data, so the map is serializable by construction. A no-op
|
|
760
|
+
* when the component exposed nothing.
|
|
667
761
|
*/
|
|
668
762
|
export function accumulateComponentOutputs(
|
|
669
763
|
componentOutputs: Record<string, Record<string, unknown>>,
|
|
@@ -736,6 +830,10 @@ export interface InterpretRunOptions {
|
|
|
736
830
|
* byte-for-byte the same as before this option existed.
|
|
737
831
|
*/
|
|
738
832
|
onProgress?: (event: RunProgressEvent) => void;
|
|
833
|
+
/** Where a `gate` step's facts are read and written (#2119). Defaults to the `chant/lifecycle` orphan branch; a test passes `memoryGateLedgerPort()` from `../op/gate.ts`. */
|
|
834
|
+
gates?: GateLedgerPort;
|
|
835
|
+
/** ISO-8601 "now" for gate decisions, so a test is deterministic. */
|
|
836
|
+
now?: string;
|
|
739
837
|
}
|
|
740
838
|
|
|
741
839
|
/**
|
|
@@ -748,6 +846,11 @@ export interface InterpretRunOptions {
|
|
|
748
846
|
* a result with `ok: false`; throws `DriverRunFailure` carrying that result
|
|
749
847
|
* so callers can choose to inspect or propagate it.
|
|
750
848
|
*
|
|
849
|
+
* A component that stops at an unapproved gate (#2119) ends the run the same
|
|
850
|
+
* way, with `status: "gated"` and the pending fact on `gate` — but it is
|
|
851
|
+
* *returned*, never thrown, because nothing failed. Downstream waves do not
|
|
852
|
+
* run: a gate is the author saying a human decides before the rest happens.
|
|
853
|
+
*
|
|
751
854
|
* Zero per-component logic: this function and everything it calls dispatches
|
|
752
855
|
* purely on the generic `Component`/`Phase`/`Step` shapes and the registry —
|
|
753
856
|
* no branch anywhere names a specific component or capability.
|
|
@@ -761,11 +864,16 @@ export async function runInterpretDriver(
|
|
|
761
864
|
const byName = new Map(components.map((c) => [c.name, c]));
|
|
762
865
|
const componentOutputs: Record<string, Record<string, unknown>> = { ...(options.componentOutputs ?? {}) };
|
|
763
866
|
const { onProgress } = options;
|
|
867
|
+
const gates: GateContext = {
|
|
868
|
+
port: options.gates ?? gitGateLedgerPort(),
|
|
869
|
+
...(options.now ? { now: options.now } : {}),
|
|
870
|
+
};
|
|
764
871
|
|
|
765
872
|
onProgress?.({ type: "run-start", waves });
|
|
766
873
|
|
|
767
874
|
const results: DriverComponentResult[] = [];
|
|
768
875
|
let failedComponent: string | undefined;
|
|
876
|
+
let gated: DriverComponentResult | undefined;
|
|
769
877
|
|
|
770
878
|
waveLoop: for (const [waveIndex, wave] of waves.entries()) {
|
|
771
879
|
const waveNum = waveIndex + 1;
|
|
@@ -780,23 +888,32 @@ export async function runInterpretDriver(
|
|
|
780
888
|
registry,
|
|
781
889
|
componentOutputs,
|
|
782
890
|
onProgress,
|
|
891
|
+
gates,
|
|
783
892
|
);
|
|
784
|
-
onProgress?.({ type: "component-done", wave: waveNum, component: component.name, status: result.
|
|
893
|
+
onProgress?.({ type: "component-done", wave: waveNum, component: component.name, status: progressStatus(result.status) });
|
|
785
894
|
return result;
|
|
786
895
|
}),
|
|
787
896
|
);
|
|
788
897
|
results.push(...waveResults);
|
|
789
|
-
const
|
|
790
|
-
onProgress?.({ type: "wave-done", wave: waveNum, status:
|
|
791
|
-
if (
|
|
792
|
-
|
|
898
|
+
const stopped = waveResults.find((r) => r.status !== "ok");
|
|
899
|
+
onProgress?.({ type: "wave-done", wave: waveNum, status: progressStatus(stopped?.status ?? "ok") });
|
|
900
|
+
if (stopped) {
|
|
901
|
+
// A failure in the same wave outranks a gate: something is actually
|
|
902
|
+
// broken, and reporting the run as "waiting on a human" would hide it.
|
|
903
|
+
const failure = waveResults.find((r) => r.status === "fail");
|
|
904
|
+
if (failure) failedComponent = failure.component;
|
|
905
|
+
else gated = stopped;
|
|
793
906
|
break waveLoop;
|
|
794
907
|
}
|
|
795
908
|
}
|
|
796
909
|
|
|
797
|
-
const
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
910
|
+
const status: DriverRunResult["status"] = failedComponent ? "fail" : gated ? "gated" : "ok";
|
|
911
|
+
const ok = status === "ok";
|
|
912
|
+
onProgress?.({ type: "run-done", status: progressStatus(status) });
|
|
913
|
+
const result: DriverRunResult = {
|
|
914
|
+
order, waves, results, ok, status, failedComponent, componentOutputs,
|
|
915
|
+
...(gated ? { gatedComponent: gated.component, gate: gated.gate } : {}),
|
|
916
|
+
};
|
|
917
|
+
if (status === "fail") throw new DriverRunFailure(result);
|
|
801
918
|
return result;
|
|
802
919
|
}
|
package/src/components/index.ts
CHANGED
|
@@ -95,7 +95,7 @@ export {
|
|
|
95
95
|
accumulateComponentOutputs,
|
|
96
96
|
runComponentDeploy,
|
|
97
97
|
runInterpretDriver,
|
|
98
|
-
|
|
98
|
+
type GateContext,
|
|
99
99
|
DependencyCycleError,
|
|
100
100
|
UnknownDependencyError,
|
|
101
101
|
DriverRunFailure,
|
|
@@ -108,8 +108,3 @@ export {
|
|
|
108
108
|
SingleHostComposeComponent,
|
|
109
109
|
type SingleHostComposeComponentConfig,
|
|
110
110
|
} from "./presets/index";
|
|
111
|
-
export {
|
|
112
|
-
type ComponentTemporalCodegen,
|
|
113
|
-
type ComponentTemporalCodegenOptions,
|
|
114
|
-
loadComponentTemporalCodegen,
|
|
115
|
-
} from "./temporal-codegen-loader";
|
|
@@ -16,7 +16,6 @@ vi.mock("../lifecycle/git", () => ({
|
|
|
16
16
|
const {
|
|
17
17
|
maybePersistBuildManifest,
|
|
18
18
|
extractRunManifest,
|
|
19
|
-
extractRunManifestFromPhaseOutputs,
|
|
20
19
|
} = await import("./manifest-persistence");
|
|
21
20
|
|
|
22
21
|
function makeManifest(component: string, digest: string): BuildArchiveManifest {
|
|
@@ -67,23 +66,6 @@ describe("extractRunManifest", () => {
|
|
|
67
66
|
});
|
|
68
67
|
});
|
|
69
68
|
|
|
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
69
|
describe("maybePersistBuildManifest", () => {
|
|
88
70
|
beforeEach(() => {
|
|
89
71
|
persistBuildManifestMock.mockReset();
|
|
@@ -102,8 +84,8 @@ describe("maybePersistBuildManifest", () => {
|
|
|
102
84
|
expect(pushLifecycleMock).toHaveBeenCalledTimes(1);
|
|
103
85
|
});
|
|
104
86
|
|
|
105
|
-
test("a pre-resolved manifest
|
|
106
|
-
const preResolved = makeManifest("svc", "sha256:
|
|
87
|
+
test("a pre-resolved manifest takes precedence over records", async () => {
|
|
88
|
+
const preResolved = makeManifest("svc", "sha256:preresolved");
|
|
107
89
|
persistBuildManifestMock.mockResolvedValue({ commit: "b".repeat(40) });
|
|
108
90
|
|
|
109
91
|
const outcome = await maybePersistBuildManifest({
|
|
@@ -13,10 +13,9 @@
|
|
|
13
13
|
* doc: a manifest write is a git commit + push, a non-idempotent side effect
|
|
14
14
|
* with real-world I/O — exactly what `driver.ts` resists taking on (it is
|
|
15
15
|
* exercised in tests against a bare `CapabilityRegistry` with no lifecycle
|
|
16
|
-
* dependency at all)
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* called from (../cli/handlers/run.ts).
|
|
16
|
+
* dependency at all). The CLI calls this after `runComponents` reports
|
|
17
|
+
* success, the same place `maybeRecordAutoRelease` is already called from
|
|
18
|
+
* (../cli/handlers/run.ts).
|
|
20
19
|
*
|
|
21
20
|
* **Extraction is duck-typed, not capability-specific.** `docker-build`,
|
|
22
21
|
* `generate-sbom`, `extract-config-bom`, and `addArchiveTemplate` (the
|
|
@@ -68,25 +67,6 @@ export function extractRunManifest(records: DriverStepRecord[]): BuildArchiveMan
|
|
|
68
67
|
return found;
|
|
69
68
|
}
|
|
70
69
|
|
|
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
70
|
/** Explicit reasons `maybePersistBuildManifest` declined to write — never a thrown error, mirroring ./auto-release.ts's `AutoReleaseSkipReason`. */
|
|
91
71
|
export type ManifestPersistSkipReason = "opted-out" | "run-not-successful" | "no-manifest";
|
|
92
72
|
|
|
@@ -101,7 +81,7 @@ export interface ManifestPersistRunInfo {
|
|
|
101
81
|
success: boolean;
|
|
102
82
|
/** The component's step records (local executor), used to locate the accumulated manifest via `extractRunManifest`. Mutually exclusive with `manifest`. */
|
|
103
83
|
records?: DriverStepRecord[];
|
|
104
|
-
/** A manifest
|
|
84
|
+
/** A manifest the caller already resolved by its own means. Takes precedence over `records` when both are given. */
|
|
105
85
|
manifest?: BuildArchiveManifest;
|
|
106
86
|
}
|
|
107
87
|
|
|
@@ -31,7 +31,7 @@ interface Neo4jInstanceConfig {
|
|
|
31
31
|
*/
|
|
32
32
|
health: { size: number } | { quorum: true };
|
|
33
33
|
/** Optional human gate placed before this instance's steps (rolling instances only, never the seed). */
|
|
34
|
-
approval?: {
|
|
34
|
+
approval?: { gate: string; description: string; timeout: string };
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
const SEED: Neo4jInstanceConfig = {
|
|
@@ -55,7 +55,7 @@ const FOLLOWERS: Neo4jInstanceConfig[] = [
|
|
|
55
55
|
template: "archive:neo4j-1.template.json",
|
|
56
56
|
health: { quorum: true },
|
|
57
57
|
approval: {
|
|
58
|
-
|
|
58
|
+
gate: "approve-neo4j-node-1",
|
|
59
59
|
description: "Confirm the seed node is healthy before rolling to node 1",
|
|
60
60
|
timeout: "24h",
|
|
61
61
|
},
|
|
@@ -71,7 +71,7 @@ const FOLLOWERS: Neo4jInstanceConfig[] = [
|
|
|
71
71
|
/** Build one instance's mini-composition phase — the unit that repeats N times for an N-node cluster. */
|
|
72
72
|
function instancePhase(instance: Neo4jInstanceConfig): Phase {
|
|
73
73
|
const steps = [
|
|
74
|
-
...(instance.approval ? [gate(instance.approval.
|
|
74
|
+
...(instance.approval ? [gate(instance.approval.gate, instance.approval)] : []),
|
|
75
75
|
{ kind: "cfn-deploy", template: instance.template },
|
|
76
76
|
{ kind: "code-deploy", instance: instance.index, revision: "@Seed.templateUri" },
|
|
77
77
|
{ kind: "wait-cluster-healthy", ...instance.health },
|