@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
|
@@ -22,7 +22,6 @@ vi.mock("../lifecycle/release-ledger", async () => {
|
|
|
22
22
|
const {
|
|
23
23
|
maybeRecordAutoRelease,
|
|
24
24
|
extractRunDigest,
|
|
25
|
-
extractRunDigestFromPhaseOutputs,
|
|
26
25
|
} = await import("./auto-release");
|
|
27
26
|
|
|
28
27
|
function publishRecord(digest: string): DriverStepRecord {
|
|
@@ -64,21 +63,6 @@ describe("extractRunDigest", () => {
|
|
|
64
63
|
});
|
|
65
64
|
});
|
|
66
65
|
|
|
67
|
-
describe("extractRunDigestFromPhaseOutputs", () => {
|
|
68
|
-
test("finds the digest across phase outputs (Temporal workflow result shape)", () => {
|
|
69
|
-
expect(extractRunDigestFromPhaseOutputs({ Publish: { digest: "sha256:abc", uri: "repo@sha256:abc" }, Apply: { ok: true } })).toBe("sha256:abc");
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test("returns undefined for undefined/empty phaseOutputs", () => {
|
|
73
|
-
expect(extractRunDigestFromPhaseOutputs(undefined)).toBeUndefined();
|
|
74
|
-
expect(extractRunDigestFromPhaseOutputs({})).toBeUndefined();
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test("ignores a phase output carrying only a content digest (SBOM, #665)", () => {
|
|
78
|
-
expect(extractRunDigestFromPhaseOutputs({ Sbom: { digest: "sha256:sbombytes" } })).toBeUndefined();
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
66
|
describe("maybeRecordAutoRelease", () => {
|
|
83
67
|
beforeEach(() => {
|
|
84
68
|
getHeadCommitMock.mockReset().mockResolvedValue("abc123headsha");
|
|
@@ -111,19 +95,19 @@ describe("maybeRecordAutoRelease", () => {
|
|
|
111
95
|
expect(pushLifecycleMock).toHaveBeenCalledTimes(1);
|
|
112
96
|
});
|
|
113
97
|
|
|
114
|
-
test("a pre-resolved digest
|
|
98
|
+
test("a pre-resolved digest takes precedence and is used directly", async () => {
|
|
115
99
|
appendReleaseRecordMock.mockResolvedValue({
|
|
116
100
|
commit: "b".repeat(40),
|
|
117
|
-
record: { version: 1, component: "svc", env: "prod", digest: "sha256:
|
|
101
|
+
record: { version: 1, component: "svc", env: "prod", digest: "sha256:preresolved", gitSha: "x", runId: "r", timestamp: "t", actor: "a" },
|
|
118
102
|
});
|
|
119
103
|
|
|
120
104
|
await maybeRecordAutoRelease(
|
|
121
|
-
{ component: "svc", env: "prod", success: true, digest: "sha256:
|
|
105
|
+
{ component: "svc", env: "prod", success: true, digest: "sha256:preresolved", records: [publishRecord("sha256:ignored")], runId: "run-1" },
|
|
122
106
|
{ actor: "alice" },
|
|
123
107
|
);
|
|
124
108
|
|
|
125
109
|
const [input] = appendReleaseRecordMock.mock.calls[0];
|
|
126
|
-
expect(input.digest).toBe("sha256:
|
|
110
|
+
expect(input.digest).toBe("sha256:preresolved");
|
|
127
111
|
});
|
|
128
112
|
|
|
129
113
|
test("failure (run.success = false) -> writes nothing", async () => {
|
|
@@ -4,23 +4,19 @@
|
|
|
4
4
|
* release ledger (../lifecycle/release-ledger.ts) was only populated by the
|
|
5
5
|
* standalone `chant components release <env>` command — a deploy that never
|
|
6
6
|
* called it left the ledger silently empty. This module makes recording
|
|
7
|
-
* happen *by construction*: the CLI post-run step
|
|
8
|
-
*
|
|
9
|
-
* (`runComponentTemporal`) calls `maybeRecordAutoRelease` after the run
|
|
10
|
-
* reports success.
|
|
7
|
+
* happen *by construction*: the CLI's post-run step (`runOpComponents`)
|
|
8
|
+
* calls `maybeRecordAutoRelease` after the run reports success.
|
|
11
9
|
*
|
|
12
10
|
* Deliberately CLI-side, not driver-side or workflow-side:
|
|
13
11
|
* - `../components/driver.ts` stays capability-agnostic — it already
|
|
14
12
|
* resists per-component/per-capability branching, and "write to git"
|
|
15
13
|
* is exactly the kind of side effect that doesn't belong in a step
|
|
16
14
|
* dispatcher tests exercise against a bare `CapabilityRegistry`.
|
|
17
|
-
* -
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* reports a terminal COMPLETED status, the same place `runOpTemporal`
|
|
23
|
-
* already writes its deployment report post-run.
|
|
15
|
+
* - A ledger write is a non-idempotent git push with real-world side
|
|
16
|
+
* effects (network, `Date.now()`, file writes) — the kind of thing that
|
|
17
|
+
* belongs at the edge of a run rather than inside a step a retry may run
|
|
18
|
+
* a second time. It happens in the CLI, once the run has reported a
|
|
19
|
+
* terminal outcome.
|
|
24
20
|
*
|
|
25
21
|
* Reuses ../lifecycle/release-ledger.ts's `appendReleaseRecord` verbatim —
|
|
26
22
|
* this module only decides *whether* to call it and *what digest* to record,
|
|
@@ -72,27 +68,6 @@ export function extractRunDigest(records: DriverStepRecord[]): string | undefine
|
|
|
72
68
|
return found;
|
|
73
69
|
}
|
|
74
70
|
|
|
75
|
-
/**
|
|
76
|
-
* Same digest extraction as `extractRunDigest`, but over a component
|
|
77
|
-
* Temporal workflow's returned `phaseOutputs` (`{ [phase]: output }`) instead
|
|
78
|
-
* of a `DriverStepRecord[]` — the shape `handle.result()` resolves to for a
|
|
79
|
-
* COMPLETED component workflow (see lexicons/temporal/src/component-op/
|
|
80
|
-
* serializer.ts's generated `return { phaseOutputs, componentOutputs }`).
|
|
81
|
-
* Used by the `--temporal` CLI path, which never sees individual step
|
|
82
|
-
* records (those exist only inside the workflow/activities).
|
|
83
|
-
*/
|
|
84
|
-
export function extractRunDigestFromPhaseOutputs(
|
|
85
|
-
phaseOutputs: Record<string, Record<string, unknown>> | undefined,
|
|
86
|
-
): string | undefined {
|
|
87
|
-
let found: string | undefined;
|
|
88
|
-
for (const output of Object.values(phaseOutputs ?? {})) {
|
|
89
|
-
if (isPromotedArtifact(output) && typeof output.digest === "string") {
|
|
90
|
-
found = output.digest;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return found;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
71
|
/** Explicit reasons `maybeRecordAutoRelease` declined to write a record — never a thrown error, since "nothing to record" (or "opted out") is an expected, common outcome. */
|
|
97
72
|
export type AutoReleaseSkipReason =
|
|
98
73
|
| "opted-out"
|
|
@@ -105,19 +80,19 @@ export type AutoReleaseResult =
|
|
|
105
80
|
| { recorded: false; reason: AutoReleaseSkipReason; detail?: string }
|
|
106
81
|
| { recorded: false; reason: "error"; error: string };
|
|
107
82
|
|
|
108
|
-
/** Input describing one component's completed run
|
|
83
|
+
/** Input describing one component's completed run. */
|
|
109
84
|
export interface AutoReleaseRunInfo {
|
|
110
85
|
component: string;
|
|
111
86
|
env: string;
|
|
112
|
-
/** Whether the run reported overall success
|
|
87
|
+
/** Whether the run reported overall success (`DriverRunResult.ok`). A caller must not call this for a non-terminal/in-progress run. */
|
|
113
88
|
success: boolean;
|
|
114
89
|
/** The component's step records (local executor), used to locate the published digest via `extractRunDigest`. Mutually exclusive with `digest` — pass whichever the caller already has. */
|
|
115
90
|
records?: DriverStepRecord[];
|
|
116
|
-
/** A digest
|
|
91
|
+
/** A digest the caller already resolved by its own means. Takes precedence over `records` when both are given. */
|
|
117
92
|
digest?: string;
|
|
118
|
-
/** Orchestrator run identifier — a
|
|
93
|
+
/** Orchestrator run identifier — a hosting runtime's own run id, or a locally generated one (mirrors `runComponentsReleaseRecord`'s `--run-id` default). */
|
|
119
94
|
runId: string;
|
|
120
|
-
/** The id space `runId` lives in (#2045) — `{ forge: "op" }` for a
|
|
95
|
+
/** The id space `runId` lives in (#2045) — `{ forge: "op" }` for a hosted run, `{ forge: "local" }` for a local-executor mint. Recorded verbatim as the release record's `runOrigin`. */
|
|
121
96
|
runOrigin?: RunOrigin;
|
|
122
97
|
/** The bypassed capability-profile divergences, when the caller deliberately overrode a deploy-time profile assertion (chant #1244) — recorded verbatim as the release record's `profileOverride`. */
|
|
123
98
|
profileOverride?: string;
|
|
@@ -142,11 +117,11 @@ function resolveActor(override?: string): string | undefined {
|
|
|
142
117
|
}
|
|
143
118
|
|
|
144
119
|
/**
|
|
145
|
-
* After a successful `chant run --components <name> --env <env
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
120
|
+
* After a successful `chant run --components <name> --env <env>`, append
|
|
121
|
+
* exactly one immutable release record to the ledger and push it — or
|
|
122
|
+
* explain, without throwing, why it didn't. Never called for a failed run
|
|
123
|
+
* (`run.success` must be true before the caller invokes this at all; see
|
|
124
|
+
* `runOpComponents`) — a failed
|
|
150
125
|
* deploy writes nothing, by construction, since this function is simply
|
|
151
126
|
* never reached on that path.
|
|
152
127
|
*
|
|
@@ -50,10 +50,10 @@ export interface Capability<In = unknown, Out = unknown> {
|
|
|
50
50
|
* returned (#1944, epic #1564 phase 4) — a serializable identity channel a
|
|
51
51
|
* capability can use to recover state `rollback` needs when it cannot rely
|
|
52
52
|
* on in-process object identity between its `run`/`rollback` calls. The
|
|
53
|
-
* local interpret driver (../driver.ts) always threads it through;
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
53
|
+
* local interpret driver (../driver.ts) always threads it through; a
|
|
54
|
+
* hosting runtime that splits a run across process boundaries threads it
|
|
55
|
+
* across as plain JSON, which is exactly the case this exists for — see
|
|
56
|
+
* ./verbs/run-agent.ts's "Rollback identity" doc
|
|
57
57
|
* comment for the motivating gap (a fresh sprite's checkpoint id, recorded
|
|
58
58
|
* only in an in-process `WeakMap` keyed by `run()`'s `input` object, never
|
|
59
59
|
* survives to a `rollback()` call that runs as a separate Activity with its
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
generateComponentsPipeline,
|
|
26
26
|
} from "./cli-support";
|
|
27
27
|
import { CapabilityRegistry, type DeployContext } from "./capability";
|
|
28
|
+
import { memoryGateLedgerPort } from "../op/gate";
|
|
28
29
|
import type { DriverComponent, RunProgressEvent } from "./driver";
|
|
29
30
|
|
|
30
31
|
// A minimal stand-in for the real gitlab lexicon plugin, satisfying
|
|
@@ -427,9 +428,9 @@ describe("findComponentGate", () => {
|
|
|
427
428
|
const component: DriverComponent = {
|
|
428
429
|
name: "svc",
|
|
429
430
|
dependsOn: [],
|
|
430
|
-
deploy: [{ phase: "Approve", steps: [{ kind: "gate",
|
|
431
|
+
deploy: [{ phase: "Approve", steps: [{ kind: "gate", gate: "release-approval" }] }],
|
|
431
432
|
};
|
|
432
|
-
expect(findComponentGate(component)).toEqual({
|
|
433
|
+
expect(findComponentGate(component)).toEqual({ gate: "release-approval" });
|
|
433
434
|
});
|
|
434
435
|
|
|
435
436
|
test("finds a gate nested inside a fan-out phase", () => {
|
|
@@ -442,13 +443,13 @@ describe("findComponentGate", () => {
|
|
|
442
443
|
steps: [
|
|
443
444
|
{
|
|
444
445
|
phase: "instance-2",
|
|
445
|
-
steps: [{ kind: "gate",
|
|
446
|
+
steps: [{ kind: "gate", gate: "instance-2-approval" }],
|
|
446
447
|
},
|
|
447
448
|
],
|
|
448
449
|
},
|
|
449
450
|
],
|
|
450
451
|
};
|
|
451
|
-
expect(findComponentGate(component)?.
|
|
452
|
+
expect(findComponentGate(component)?.gate).toBe("instance-2-approval");
|
|
452
453
|
});
|
|
453
454
|
|
|
454
455
|
test("finds a gate in a component's rollback phases", () => {
|
|
@@ -456,9 +457,20 @@ describe("findComponentGate", () => {
|
|
|
456
457
|
name: "svc",
|
|
457
458
|
dependsOn: [],
|
|
458
459
|
deploy: [{ phase: "Apply", steps: [{ kind: "deploy-thing" }] }],
|
|
459
|
-
rollback: [{ phase: "Rollback", steps: [{ kind: "gate",
|
|
460
|
+
rollback: [{ phase: "Rollback", steps: [{ kind: "gate", gate: "rollback-approval" }] }],
|
|
461
|
+
};
|
|
462
|
+
expect(findComponentGate(component)?.gate).toBe("rollback-approval");
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
// #2202: the name comes back on `gate` whichever key the component spelled
|
|
466
|
+
// it with, so no caller has to know about the deprecated one.
|
|
467
|
+
test("normalizes a gate step's deprecated `signalName` key onto `gate`", () => {
|
|
468
|
+
const component = {
|
|
469
|
+
name: "svc",
|
|
470
|
+
dependsOn: [],
|
|
471
|
+
deploy: [{ phase: "Approve", steps: [{ kind: "gate", signalName: "release-approval" }] }],
|
|
460
472
|
};
|
|
461
|
-
expect(findComponentGate(component)
|
|
473
|
+
expect(findComponentGate(component)).toEqual({ gate: "release-approval" });
|
|
462
474
|
});
|
|
463
475
|
});
|
|
464
476
|
|
|
@@ -587,11 +599,11 @@ describe("runComponents", () => {
|
|
|
587
599
|
expect(result.error).toContain("svc");
|
|
588
600
|
});
|
|
589
601
|
|
|
590
|
-
test("a gate in the selected component
|
|
602
|
+
test("a gate in the selected component ends the run pending approval (#2119)", async () => {
|
|
591
603
|
await writeFile(
|
|
592
604
|
join(testDir, "svc.component.ts"),
|
|
593
605
|
`export const svc = { name: "svc", dependsOn: [], deploy: [
|
|
594
|
-
{ phase: "Approve", steps: [{ kind: "gate",
|
|
606
|
+
{ phase: "Approve", steps: [{ kind: "gate", gate: "release-approval" }] },
|
|
595
607
|
{ phase: "Apply", steps: [{ kind: "deploy-thing" }] },
|
|
596
608
|
] };`,
|
|
597
609
|
);
|
|
@@ -600,11 +612,15 @@ describe("runComponents", () => {
|
|
|
600
612
|
const registry = new CapabilityRegistry();
|
|
601
613
|
registry.register(capability);
|
|
602
614
|
|
|
603
|
-
const
|
|
615
|
+
const gates = memoryGateLedgerPort();
|
|
616
|
+
const result = await runComponents(testDir, "svc", { registry, gates });
|
|
604
617
|
|
|
605
618
|
expect(result.success).toBe(false);
|
|
606
|
-
expect(result.
|
|
607
|
-
|
|
619
|
+
expect(result.gated?.component).toBe("svc");
|
|
620
|
+
expect(result.gated?.gate.gate).toBe("release-approval");
|
|
621
|
+
expect(result.run?.status).toBe("gated");
|
|
622
|
+
expect(gates.appended).toHaveLength(1);
|
|
623
|
+
// Nothing after the gate ran.
|
|
608
624
|
expect(capability.calls).toHaveLength(0);
|
|
609
625
|
});
|
|
610
626
|
|
|
@@ -844,7 +860,7 @@ describe("resolveComponentTargets — buildParams (chant #1108)", () => {
|
|
|
844
860
|
await rm(testDir, { recursive: true, force: true });
|
|
845
861
|
});
|
|
846
862
|
|
|
847
|
-
test("forwards buildParams into discovery — the
|
|
863
|
+
test("forwards buildParams into discovery — the selector-resolution entrypoint", async () => {
|
|
848
864
|
await writeFile(
|
|
849
865
|
join(testDir, "svc.component.ts"),
|
|
850
866
|
`
|
|
@@ -31,12 +31,15 @@ import {
|
|
|
31
31
|
runComponentDeploy,
|
|
32
32
|
UnknownDependencyError,
|
|
33
33
|
DependencyCycleError,
|
|
34
|
-
DriverGateUnsupportedError,
|
|
35
34
|
DriverRunFailure,
|
|
36
35
|
type DriverComponent,
|
|
36
|
+
type DriverGate,
|
|
37
37
|
type DriverPhase,
|
|
38
38
|
type DriverRunResult,
|
|
39
39
|
} from "./driver";
|
|
40
|
+
import type { PendingGateRecord } from "../lifecycle/gate-ledger";
|
|
41
|
+
import type { GateLedgerPort } from "../op/gate";
|
|
42
|
+
import { gateName } from "../op/gate-name";
|
|
40
43
|
import { isLexiconPlugin, type LexiconPlugin, type ComponentPipelineOptions } from "../lexicon";
|
|
41
44
|
import type { RunProgressEvent } from "./run-progress";
|
|
42
45
|
import { relative } from "node:path";
|
|
@@ -313,18 +316,21 @@ function toDriverComponent(component: { name: string; dependsOn: string[]; deplo
|
|
|
313
316
|
|
|
314
317
|
/**
|
|
315
318
|
* Find the first `gate` step anywhere in a component's `deploy`/`rollback`
|
|
316
|
-
* composition (including nested fan-out phases)
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
319
|
+
* composition (including nested fan-out phases).
|
|
320
|
+
*
|
|
321
|
+
* A declaration-time question, not a pre-flight refusal: since #2119 the
|
|
322
|
+
* driver decides a gate against the ledger when it reaches one, so nothing
|
|
323
|
+
* needs to know up front that a component has one.
|
|
324
|
+
*
|
|
325
|
+
* The name comes back on `gate` whichever key the component spelled it with,
|
|
326
|
+
* so a caller never has to know about the deprecated `signalName` (#2202).
|
|
321
327
|
*/
|
|
322
|
-
export function findComponentGate(component: DriverComponent): {
|
|
323
|
-
const search = (phases: DriverPhase[] | undefined): {
|
|
328
|
+
export function findComponentGate(component: DriverComponent): { gate: string } | undefined {
|
|
329
|
+
const search = (phases: DriverPhase[] | undefined): { gate: string } | undefined => {
|
|
324
330
|
for (const phaseDef of phases ?? []) {
|
|
325
331
|
for (const entry of phaseDef.steps) {
|
|
326
332
|
if ((entry as { kind?: unknown }).kind === "gate") {
|
|
327
|
-
return
|
|
333
|
+
return { gate: gateName(entry as DriverGate) };
|
|
328
334
|
}
|
|
329
335
|
if (typeof (entry as DriverPhase).phase === "string" && Array.isArray((entry as DriverPhase).steps)) {
|
|
330
336
|
const nested = search([entry as DriverPhase]);
|
|
@@ -406,6 +412,8 @@ export interface RunComponentsOptions {
|
|
|
406
412
|
* every test in `cli-support.test.ts`) that doesn't supply this.
|
|
407
413
|
*/
|
|
408
414
|
buildParams?: BuildParamProvenance[];
|
|
415
|
+
/** 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`. */
|
|
416
|
+
gates?: GateLedgerPort;
|
|
409
417
|
}
|
|
410
418
|
|
|
411
419
|
/** Result of `chant run --components <name|all>`. */
|
|
@@ -416,8 +424,8 @@ export interface RunComponentsResult {
|
|
|
416
424
|
/** Component names actually dispatched to the driver, in run order. */
|
|
417
425
|
selected: string[];
|
|
418
426
|
error?: string;
|
|
419
|
-
/** Set when
|
|
420
|
-
|
|
427
|
+
/** Set when the run stopped at a `gate` nobody has approved (#2119): the component it stopped at and the pending fact recorded for it. */
|
|
428
|
+
gated?: { component: string; gate: PendingGateRecord };
|
|
421
429
|
/** This run's resolved build-time parameters (chant #1108) — the component-driver counterpart of `../cli/commands/build.ts`'s `BuildResult.buildParams`. Present only once the run actually reached dispatch (mirrors `BuildResult.buildParams`, which is likewise absent on an early-error return). */
|
|
422
430
|
buildParams?: BuildParamProvenance[];
|
|
423
431
|
}
|
|
@@ -428,8 +436,7 @@ export interface RunComponentsResult {
|
|
|
428
436
|
* local in-process executor — the CLI entrypoint the driver never had (#585,
|
|
429
437
|
* follow-up to #556). Discovers the full component set first, then either:
|
|
430
438
|
* - `selector === "all"`: resolves the whole set's dependency order/waves
|
|
431
|
-
* and dispatches every component through `runInterpretDriver`,
|
|
432
|
-
* what the generated orchestrator Op will eventually do — the same
|
|
439
|
+
* and dispatches every component through `runInterpretDriver`, in the same
|
|
433
440
|
* order `chant graph --components` reports.
|
|
434
441
|
* - a single name: dispatches just that component via `runComponentDeploy`,
|
|
435
442
|
* without requiring the rest of its `dependsOn` graph to be present in
|
|
@@ -441,14 +448,12 @@ export interface RunComponentsResult {
|
|
|
441
448
|
* infra outside the discovered set (e.g. a shared stack, per the
|
|
442
449
|
* `search-service` pilot), which is exactly the common case.
|
|
443
450
|
*
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
* `
|
|
447
|
-
*
|
|
448
|
-
* component execution to what already exists for Ops; the epic tracks
|
|
449
|
-
* graduating a gated component to `--temporal` separately).
|
|
451
|
+
* A `gate` no longer refuses the run up front (#2119). The driver decides each
|
|
452
|
+
* one against the gate ledger as it reaches it; a gate nobody has approved
|
|
453
|
+
* stops the run there with `gated` set, which the CLI turns into exit code 3
|
|
454
|
+
* and the `chant approve` line.
|
|
450
455
|
*/
|
|
451
|
-
/** Result of resolving a `<name|all>` selector against discovered components
|
|
456
|
+
/** Result of resolving a `<name|all>` selector against discovered components. */
|
|
452
457
|
export interface ResolvedComponentTargets {
|
|
453
458
|
success: boolean;
|
|
454
459
|
targets: DriverComponent[];
|
|
@@ -459,10 +464,8 @@ export interface ResolvedComponentTargets {
|
|
|
459
464
|
* Discover every component under `path` and resolve `selector` (`"all"` or a
|
|
460
465
|
* single component name) to the `DriverComponent`(s) to run, with no gate
|
|
461
466
|
* check and no dispatch — just discovery + selection, factored out of
|
|
462
|
-
* `runComponents` so
|
|
463
|
-
*
|
|
464
|
-
* without also inheriting the local executor's pre-flight gate rejection
|
|
465
|
-
* (gates are exactly what the durable path exists to support).
|
|
467
|
+
* `runComponents` so another entrypoint can reuse the exact same selection
|
|
468
|
+
* semantics without inheriting the run itself.
|
|
466
469
|
*/
|
|
467
470
|
export async function resolveComponentTargets(
|
|
468
471
|
path: string,
|
|
@@ -526,17 +529,6 @@ export async function runComponents(
|
|
|
526
529
|
}
|
|
527
530
|
const targets = resolved.targets;
|
|
528
531
|
|
|
529
|
-
for (const component of targets) {
|
|
530
|
-
const gate = findComponentGate(component);
|
|
531
|
-
if (gate) {
|
|
532
|
-
return {
|
|
533
|
-
success: false,
|
|
534
|
-
selected: targets.map((c) => c.name),
|
|
535
|
-
gateUnsupported: { component: component.name, signalName: gate.signalName },
|
|
536
|
-
};
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
532
|
// (#629) Resolve `chant.config.ts`'s `sbom`/`signing`/`vulnPolicy` sections
|
|
541
533
|
// and fill their defaults into every recognized step (`generate-sbom`,
|
|
542
534
|
// `sign`/`attest-provenance`, `verify`, `vuln-gate`) that didn't already
|
|
@@ -563,10 +555,25 @@ export async function runComponents(
|
|
|
563
555
|
const seedOutputs = options.componentOutputs ?? {};
|
|
564
556
|
const { onProgress } = options;
|
|
565
557
|
|
|
558
|
+
const gates = options.gates;
|
|
559
|
+
|
|
566
560
|
try {
|
|
567
561
|
if (selector === "all") {
|
|
568
|
-
const run = await runInterpretDriver(resolvedTargets, registry, {
|
|
569
|
-
|
|
562
|
+
const run = await runInterpretDriver(resolvedTargets, registry, {
|
|
563
|
+
env,
|
|
564
|
+
componentOutputs: seedOutputs,
|
|
565
|
+
onProgress,
|
|
566
|
+
...(gates ? { gates } : {}),
|
|
567
|
+
});
|
|
568
|
+
return {
|
|
569
|
+
success: run.status === "ok",
|
|
570
|
+
run,
|
|
571
|
+
selected,
|
|
572
|
+
buildParams: options.buildParams,
|
|
573
|
+
...(run.status === "gated" && run.gate
|
|
574
|
+
? { gated: { component: run.gatedComponent ?? selected[0], gate: run.gate } }
|
|
575
|
+
: {}),
|
|
576
|
+
};
|
|
570
577
|
}
|
|
571
578
|
|
|
572
579
|
// Single-component invocation: run just this component, bypassing
|
|
@@ -592,8 +599,9 @@ export async function runComponents(
|
|
|
592
599
|
registry,
|
|
593
600
|
componentOutputs,
|
|
594
601
|
onProgress,
|
|
602
|
+
gates ? { port: gates } : undefined,
|
|
595
603
|
);
|
|
596
|
-
const status
|
|
604
|
+
const status = componentResult.status === "fail" ? "failed" : componentResult.status;
|
|
597
605
|
onProgress?.({ type: "component-done", wave: 1, component: componentName, status });
|
|
598
606
|
onProgress?.({ type: "wave-done", wave: 1, status });
|
|
599
607
|
onProgress?.({ type: "run-done", status });
|
|
@@ -602,21 +610,26 @@ export async function runComponents(
|
|
|
602
610
|
waves: [selected],
|
|
603
611
|
results: [componentResult],
|
|
604
612
|
ok: componentResult.ok,
|
|
605
|
-
|
|
613
|
+
status: componentResult.status,
|
|
614
|
+
failedComponent: componentResult.status === "fail" ? componentResult.component : undefined,
|
|
615
|
+
...(componentResult.status === "gated"
|
|
616
|
+
? { gatedComponent: componentResult.component, gate: componentResult.gate }
|
|
617
|
+
: {}),
|
|
606
618
|
componentOutputs,
|
|
607
619
|
};
|
|
608
|
-
return {
|
|
620
|
+
return {
|
|
621
|
+
success: componentResult.ok,
|
|
622
|
+
run,
|
|
623
|
+
selected,
|
|
624
|
+
buildParams: options.buildParams,
|
|
625
|
+
...(componentResult.status === "gated" && componentResult.gate
|
|
626
|
+
? { gated: { component: componentResult.component, gate: componentResult.gate } }
|
|
627
|
+
: {}),
|
|
628
|
+
};
|
|
609
629
|
} catch (err) {
|
|
610
630
|
if (err instanceof DriverRunFailure) {
|
|
611
631
|
return { success: false, run: err.result, selected, error: err.message };
|
|
612
632
|
}
|
|
613
|
-
if (err instanceof DriverGateUnsupportedError) {
|
|
614
|
-
return {
|
|
615
|
-
success: false,
|
|
616
|
-
selected,
|
|
617
|
-
gateUnsupported: { component: err.component, signalName: err.signalName },
|
|
618
|
-
};
|
|
619
|
-
}
|
|
620
633
|
if (err instanceof UnknownDependencyError || err instanceof DependencyCycleError) {
|
|
621
634
|
return { success: false, selected, error: err.message };
|
|
622
635
|
}
|
|
@@ -192,14 +192,14 @@ describe("Component JSON Schema", () => {
|
|
|
192
192
|
deploy: [
|
|
193
193
|
{
|
|
194
194
|
phase: "Approve",
|
|
195
|
-
steps: [{ kind: "gate",
|
|
195
|
+
steps: [{ kind: "gate", gate: "approve-gated", description: "confirm", timeout: "24h" }],
|
|
196
196
|
},
|
|
197
197
|
],
|
|
198
198
|
};
|
|
199
199
|
expect(validate(withGate)).toBe(true);
|
|
200
200
|
});
|
|
201
201
|
|
|
202
|
-
it("rejects a gate step
|
|
202
|
+
it("rejects a gate step naming neither `gate` nor `signalName`", () => {
|
|
203
203
|
const invalid = {
|
|
204
204
|
name: "gated",
|
|
205
205
|
dependsOn: [],
|
|
@@ -208,6 +208,22 @@ describe("Component JSON Schema", () => {
|
|
|
208
208
|
expect(validate(invalid)).toBe(false);
|
|
209
209
|
});
|
|
210
210
|
|
|
211
|
+
// The gate step's name key was renamed from `signalName` to `gate` in #2202.
|
|
212
|
+
// The schema takes either one and exactly one, through 0.59.0.
|
|
213
|
+
const gated = (step: Record<string, unknown>): Record<string, unknown> => ({
|
|
214
|
+
name: "gated",
|
|
215
|
+
dependsOn: [],
|
|
216
|
+
deploy: [{ phase: "Approve", steps: [step] }],
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("still accepts the deprecated `signalName` key on a gate step", () => {
|
|
220
|
+
expect(validate(gated({ kind: "gate", signalName: "approve-gated" }))).toBe(true);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("rejects a gate step carrying both `gate` and `signalName`", () => {
|
|
224
|
+
expect(validate(gated({ kind: "gate", gate: "approve-gated", signalName: "approve-gated" }))).toBe(false);
|
|
225
|
+
});
|
|
226
|
+
|
|
211
227
|
it("accepts a stackOutput cross-stack reference", () => {
|
|
212
228
|
const withStackOutput = {
|
|
213
229
|
name: "svc",
|
|
@@ -160,17 +160,30 @@
|
|
|
160
160
|
}
|
|
161
161
|
},
|
|
162
162
|
|
|
163
|
+
"GateName": {
|
|
164
|
+
"type": "string",
|
|
165
|
+
"minLength": 1,
|
|
166
|
+
"description": "A gate's name, on either of the two keys that may carry it."
|
|
167
|
+
},
|
|
168
|
+
|
|
163
169
|
"Gate": {
|
|
164
170
|
"type": "object",
|
|
165
|
-
"description": "
|
|
166
|
-
"required": ["kind"
|
|
171
|
+
"description": "Ends the run pending human approval. The driver decides a gate against the gate ledger when it reaches one; a gate nobody has approved stops the run there, and `chant approve <component> <gate>` records the resolution the next run reads.",
|
|
172
|
+
"required": ["kind"],
|
|
173
|
+
"oneOf": [
|
|
174
|
+
{ "required": ["gate"], "properties": { "gate": { "$ref": "#/$defs/GateName" } } },
|
|
175
|
+
{ "required": ["signalName"], "properties": { "signalName": { "$ref": "#/$defs/GateName" } } }
|
|
176
|
+
],
|
|
167
177
|
"additionalProperties": false,
|
|
168
178
|
"properties": {
|
|
169
179
|
"kind": { "type": "string", "const": "gate" },
|
|
180
|
+
"gate": {
|
|
181
|
+
"$ref": "#/$defs/GateName",
|
|
182
|
+
"description": "The gate's name — what `chant approve <component> <gate>` resolves."
|
|
183
|
+
},
|
|
170
184
|
"signalName": {
|
|
171
|
-
"
|
|
172
|
-
"
|
|
173
|
-
"description": "Signal name the generated workflow waits for before continuing."
|
|
185
|
+
"$ref": "#/$defs/GateName",
|
|
186
|
+
"description": "Deprecated spelling of `gate` (chant #2202), accepted through 0.59.0 and removed in 0.60.0. Exactly one of `gate` and `signalName` may be present."
|
|
174
187
|
},
|
|
175
188
|
"timeout": {
|
|
176
189
|
"type": "string",
|
|
@@ -37,13 +37,13 @@ describe("phase()", () => {
|
|
|
37
37
|
|
|
38
38
|
describe("gate()", () => {
|
|
39
39
|
it("builds a minimal Gate", () => {
|
|
40
|
-
expect(gate("approve-x")).toEqual({ kind: "gate",
|
|
40
|
+
expect(gate("approve-x")).toEqual({ kind: "gate", gate: "approve-x" });
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
it("carries optional timeout/description", () => {
|
|
44
44
|
expect(gate("approve-x", { timeout: "24h", description: "confirm" })).toEqual({
|
|
45
45
|
kind: "gate",
|
|
46
|
-
|
|
46
|
+
gate: "approve-x",
|
|
47
47
|
timeout: "24h",
|
|
48
48
|
description: "confirm",
|
|
49
49
|
});
|
|
@@ -77,16 +77,36 @@ export interface Step {
|
|
|
77
77
|
[param: string]: unknown;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
/**
|
|
81
|
-
export interface
|
|
80
|
+
/** Everything on a component gate step except the key that names it. */
|
|
81
|
+
export interface GateBase {
|
|
82
82
|
kind: "gate";
|
|
83
|
-
|
|
84
|
-
/** Duration string bounding the wait, e.g. "48h". Default: "48h". */
|
|
83
|
+
/** How long a recorded pending gate stays valid, as a duration string. Default: "48h". */
|
|
85
84
|
timeout?: string;
|
|
86
85
|
/** Human-readable description of the action required to unblock this gate. */
|
|
87
86
|
description?: string;
|
|
88
87
|
}
|
|
89
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Mirrors `$defs.Gate` — a human approval decided against the gate ledger; the
|
|
91
|
+
* run stops here with status `gated` until `chant approve` has answered it.
|
|
92
|
+
* The name lives on `gate`; `signalName` is the key it carried through 0.58.0
|
|
93
|
+
* and is still accepted (#2202). Read both through `gateName()`.
|
|
94
|
+
*/
|
|
95
|
+
export type Gate = GateBase &
|
|
96
|
+
(
|
|
97
|
+
| {
|
|
98
|
+
/** The gate's name — what `chant approve <component> <gate>` resolves. */
|
|
99
|
+
gate: string;
|
|
100
|
+
/** @deprecated Renamed to `gate` in #2202. Accepted through 0.59.0, removed in 0.60.0. */
|
|
101
|
+
signalName?: string;
|
|
102
|
+
}
|
|
103
|
+
| {
|
|
104
|
+
gate?: undefined;
|
|
105
|
+
/** @deprecated Renamed to `gate` in #2202. Accepted through 0.59.0, removed in 0.60.0. */
|
|
106
|
+
signalName: string;
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
|
|
90
110
|
/**
|
|
91
111
|
* Mirrors `$defs.Phase` — one named phase of a deploy composition. A step may
|
|
92
112
|
* itself be a nested `Phase`, which is how a fan-out unit becomes a mini-
|
|
@@ -170,9 +190,9 @@ export function phase(name: string, steps: Array<Step | Gate | Phase>, opts?: {
|
|
|
170
190
|
return { phase: name, steps, ...(opts?.parallel ? { parallel: true } : {}) };
|
|
171
191
|
}
|
|
172
192
|
|
|
173
|
-
/** Author a gate step —
|
|
174
|
-
export function gate(
|
|
175
|
-
return { kind: "gate",
|
|
193
|
+
/** Author a gate step — a human approval the driver decides against the gate ledger, stopping the run `gated` when nothing has answered it. */
|
|
194
|
+
export function gate(name: string, opts?: { timeout?: string; description?: string }): Gate {
|
|
195
|
+
return { kind: "gate", gate: name, ...opts };
|
|
176
196
|
}
|
|
177
197
|
|
|
178
198
|
/**
|
|
@@ -257,11 +257,11 @@ describe("applyConfigDefaults", () => {
|
|
|
257
257
|
test("leaves gate steps untouched", () => {
|
|
258
258
|
const config: ChantConfig = { sbom: { format: "cyclonedx" } };
|
|
259
259
|
const comp = component([
|
|
260
|
-
{ phase: "Approve", steps: [{ kind: "gate",
|
|
260
|
+
{ phase: "Approve", steps: [{ kind: "gate", gate: "release-approval" }] },
|
|
261
261
|
]);
|
|
262
262
|
|
|
263
263
|
const result = applyConfigDefaults(comp, config);
|
|
264
|
-
expect(result.deploy[0]!.steps[0]).toEqual({ kind: "gate",
|
|
264
|
+
expect(result.deploy[0]!.steps[0]).toEqual({ kind: "gate", gate: "release-approval" });
|
|
265
265
|
});
|
|
266
266
|
|
|
267
267
|
test("applies defaults to rollback phases too", () => {
|