@intentius/chant 0.57.0 → 0.58.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 +20 -1
- package/dist/audit/core.d.ts.map +1 -1
- package/dist/audit/discover.d.ts +14 -8
- 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/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.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 +28 -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/registry.d.ts +26 -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 +20 -21
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/component.d.ts +3 -3
- 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 +66 -36
- 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 +9 -15
- 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/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 +104 -14
- 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 +71 -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 +89 -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 +84 -29
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/composites/apply-op.d.ts +113 -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.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 +23 -7
- 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 +184 -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 +30 -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 +79 -27
- 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/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 +61 -17
- package/src/audit/discover.test.ts +39 -0
- package/src/audit/discover.ts +91 -15
- 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 +189 -11
- package/src/cli/commands/audit.ts +73 -27
- package/src/cli/commands/build.test.ts +292 -9
- package/src/cli/commands/build.ts +156 -24
- 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 +48 -0
- package/src/cli/commands/lint.ts +123 -0
- 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 +260 -55
- package/src/cli/handlers/run.test.ts +431 -1287
- package/src/cli/handlers/run.ts +365 -915
- package/src/cli/main.test.ts +23 -15
- package/src/cli/main.ts +88 -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/registry.ts +26 -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 +3 -2
- 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 +10 -5
- package/src/components/cli-support.ts +52 -44
- package/src/components/component.schema.json +2 -2
- package/src/components/component.ts +3 -3
- package/src/components/driver-output.ts +14 -2
- package/src/components/driver.test.ts +92 -22
- package/src/components/driver.ts +193 -83
- 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/pilots-lint-clean.test.ts +11 -10
- package/src/components/run-progress.ts +6 -6
- package/src/components/verbs/run-agent.ts +11 -17
- 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/discovery/collect.test.ts +3 -3
- package/src/discovery/files.ts +4 -4
- 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 +81 -1
- 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 +2 -2
- 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 +120 -14
- 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 +143 -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/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 +1 -1
- package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +74 -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 +81 -0
- package/src/op/activities/reconcile.ts +187 -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 +123 -39
- package/src/op/composites/apply-op.ts +208 -0
- package/src/op/composites/composites.test.ts +366 -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 +107 -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 +26 -11
- package/src/op/emulator-lifecycle.ts +1 -2
- 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 +39 -6
- package/src/op/local-executor.test.ts +163 -34
- package/src/op/local-executor.ts +370 -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 +281 -0
- package/src/op/op-ir.ts +417 -0
- package/src/op/op-verb-class.ts +19 -5
- package/src/op/op.test.ts +26 -5
- package/src/op/operator.test.ts +175 -6
- package/src/op/operator.ts +63 -16
- 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 +84 -24
- 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/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
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { describe, test, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import type { OpConfig } from "../types";
|
|
3
|
+
import type { OpRunRecord, OpRunRecordInput } from "../runtime";
|
|
4
|
+
|
|
5
|
+
const loadActivitiesMock = vi.fn();
|
|
6
|
+
const loadProfilesMock = vi.fn();
|
|
7
|
+
const loadChantConfigMock = vi.fn();
|
|
8
|
+
|
|
9
|
+
vi.mock("../activity-registry", async () => {
|
|
10
|
+
const actual = await vi.importActual<typeof import("../activity-registry")>("../activity-registry");
|
|
11
|
+
return {
|
|
12
|
+
...actual,
|
|
13
|
+
loadActivities: (...args: unknown[]) => loadActivitiesMock(...args),
|
|
14
|
+
loadProfiles: (...args: unknown[]) => loadProfilesMock(...args),
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
vi.mock("../../config", async () => {
|
|
18
|
+
const actual = await vi.importActual<typeof import("../../config")>("../../config");
|
|
19
|
+
return { ...actual, loadChantConfig: (...args: unknown[]) => loadChantConfigMock(...args) };
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// The gate ledger a local run consults (#2119) is the `chant/lifecycle` orphan
|
|
23
|
+
// branch by default. Point it at memory here so a unit test never writes a
|
|
24
|
+
// fact to the real repo.
|
|
25
|
+
vi.mock("../gate", async () => {
|
|
26
|
+
const actual = await vi.importActual<typeof import("../gate")>("../gate");
|
|
27
|
+
return { ...actual, gitGateLedgerPort: () => actual.memoryGateLedgerPort() };
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
/** The run ledger, in memory — see the mock below. Cleared before each test. */
|
|
31
|
+
const runLedger: OpRunRecord[] = [];
|
|
32
|
+
|
|
33
|
+
// The run ledger this runtime appends to and answers from (#2118) is that same
|
|
34
|
+
// orphan branch. In memory here for the same reason the gate ledger is: a unit
|
|
35
|
+
// test must never leave a fact in the real repo. Everything else about the
|
|
36
|
+
// ledger path stays real, so these tests exercise the actual read-back.
|
|
37
|
+
vi.mock("../../lifecycle/run-ledger", async () => {
|
|
38
|
+
const actual = await vi.importActual<typeof import("../../lifecycle/run-ledger")>("../../lifecycle/run-ledger");
|
|
39
|
+
return {
|
|
40
|
+
...actual,
|
|
41
|
+
appendRunRecord: async (input: OpRunRecordInput) => {
|
|
42
|
+
const record: OpRunRecord = { version: 1, ...input, id: input.id ?? `run-${runLedger.length}` };
|
|
43
|
+
runLedger.push(record);
|
|
44
|
+
return { commit: "0".repeat(40), record };
|
|
45
|
+
},
|
|
46
|
+
readRunLedger: async (_env: string, op: string) => ({
|
|
47
|
+
records: runLedger.filter((r) => r.op === op),
|
|
48
|
+
malformed: 0,
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const { createLocalOpRuntime } = await import("./local");
|
|
54
|
+
|
|
55
|
+
function op(name: string, steps: unknown[]): OpConfig {
|
|
56
|
+
return {
|
|
57
|
+
name,
|
|
58
|
+
overview: `${name} overview`,
|
|
59
|
+
phases: [{ name: "main", steps }],
|
|
60
|
+
} as unknown as OpConfig;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
describe("the local op runtime", () => {
|
|
64
|
+
beforeEach(() => {
|
|
65
|
+
loadActivitiesMock.mockReset();
|
|
66
|
+
loadProfilesMock.mockReset().mockResolvedValue({ fastIdempotent: { timeout: "1m" } });
|
|
67
|
+
loadChantConfigMock.mockReset().mockResolvedValue({ config: { lexicons: ["aws"] } });
|
|
68
|
+
runLedger.length = 0;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("start runs the Op and reports it completed, with the executor's own result", async () => {
|
|
72
|
+
loadActivitiesMock.mockResolvedValue(new Map([["ok", vi.fn(async () => ({ done: true }))]]));
|
|
73
|
+
const runtime = createLocalOpRuntime();
|
|
74
|
+
|
|
75
|
+
const handle = await runtime.start(op("hello", [{ kind: "activity", fn: "ok", args: {} }]), {});
|
|
76
|
+
const status = await handle.result();
|
|
77
|
+
|
|
78
|
+
expect(runtime.name).toBe("local");
|
|
79
|
+
expect(status.state).toBe("completed");
|
|
80
|
+
expect(status.result?.status).toBe("ok");
|
|
81
|
+
expect(status.records?.map((r) => r.fn)).toEqual(["ok"]);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("the project's configured lexicons decide which appliers load", async () => {
|
|
85
|
+
loadActivitiesMock.mockResolvedValue(new Map([["ok", vi.fn(async () => ({}))]]));
|
|
86
|
+
const runtime = createLocalOpRuntime();
|
|
87
|
+
await (await runtime.start(op("hello", [{ kind: "activity", fn: "ok", args: {} }]), {})).result();
|
|
88
|
+
expect(loadActivitiesMock).toHaveBeenCalledWith(["aws"]);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("a failing step settles as failed rather than throwing out of result()", async () => {
|
|
92
|
+
loadActivitiesMock.mockResolvedValue(new Map([["boom", vi.fn(async () => { throw new Error("nope"); })]]));
|
|
93
|
+
const runtime = createLocalOpRuntime();
|
|
94
|
+
|
|
95
|
+
const handle = await runtime.start(op("bad", [{ kind: "activity", fn: "boom", args: {} }]), {});
|
|
96
|
+
const status = await handle.result();
|
|
97
|
+
|
|
98
|
+
expect(status.state).toBe("failed");
|
|
99
|
+
expect(status.result?.status).toBe("fail");
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("progress is called once per settled step", async () => {
|
|
103
|
+
loadActivitiesMock.mockResolvedValue(new Map([["ok", vi.fn(async () => ({}))]]));
|
|
104
|
+
const runtime = createLocalOpRuntime();
|
|
105
|
+
const seen: string[] = [];
|
|
106
|
+
|
|
107
|
+
const handle = await runtime.start(
|
|
108
|
+
op("hello", [
|
|
109
|
+
{ kind: "activity", fn: "ok", args: {} },
|
|
110
|
+
{ kind: "activity", fn: "ok", args: {} },
|
|
111
|
+
]),
|
|
112
|
+
{ progress: (record) => seen.push(record.fn) },
|
|
113
|
+
);
|
|
114
|
+
await handle.result();
|
|
115
|
+
|
|
116
|
+
expect(seen).toEqual(["ok", "ok"]);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("a gated Op settles as gated, naming the gate, and runs nothing after it (#2119)", async () => {
|
|
120
|
+
const after = vi.fn(async () => ({}));
|
|
121
|
+
loadActivitiesMock.mockResolvedValue(new Map([["after", after]]));
|
|
122
|
+
const runtime = createLocalOpRuntime();
|
|
123
|
+
|
|
124
|
+
const handle = await runtime.start(
|
|
125
|
+
op("gated", [
|
|
126
|
+
{ kind: "gate", signalName: "approve-prod" },
|
|
127
|
+
{ kind: "activity", fn: "after", args: {} },
|
|
128
|
+
]),
|
|
129
|
+
{},
|
|
130
|
+
);
|
|
131
|
+
const status = await handle.result();
|
|
132
|
+
|
|
133
|
+
expect(status.state).toBe("gated");
|
|
134
|
+
expect(status.gate?.name).toBe("approve-prod");
|
|
135
|
+
expect(status.result?.status).toBe("gated");
|
|
136
|
+
expect(after).not.toHaveBeenCalled();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("status, log and list answer from the run ledger (#2118)", async () => {
|
|
140
|
+
loadActivitiesMock.mockResolvedValue(new Map([["ok", vi.fn(async () => ({}))]]));
|
|
141
|
+
const runtime = createLocalOpRuntime();
|
|
142
|
+
const config = op("hello", [{ kind: "activity", fn: "ok", args: {} }]);
|
|
143
|
+
|
|
144
|
+
expect(await runtime.status("hello")).toBeUndefined();
|
|
145
|
+
expect(await runtime.log("hello")).toEqual([]);
|
|
146
|
+
|
|
147
|
+
await (await runtime.start(config, {})).result();
|
|
148
|
+
await (await runtime.start(config, {})).result();
|
|
149
|
+
|
|
150
|
+
// Two records on the ledger, not two entries in a process-local map.
|
|
151
|
+
expect(runLedger.map((r) => r.op)).toEqual(["hello", "hello"]);
|
|
152
|
+
expect((await runtime.status("hello"))?.state).toBe("completed");
|
|
153
|
+
expect(await runtime.log("hello")).toHaveLength(2);
|
|
154
|
+
expect(await runtime.log("hello", { limit: 1 })).toHaveLength(1);
|
|
155
|
+
expect((await runtime.list([config])).get("hello")?.state).toBe("completed");
|
|
156
|
+
|
|
157
|
+
// Newest first, and the ledger's own id is the run id a reader sees.
|
|
158
|
+
const [newest] = await runtime.log("hello");
|
|
159
|
+
expect(newest.id).toBe(runLedger[1].id);
|
|
160
|
+
expect((await runtime.status("hello"))?.runId).toBe(runLedger[1].id);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test("a run the ledger could not record still answers from this process", async () => {
|
|
164
|
+
loadActivitiesMock.mockResolvedValue(new Map([["ok", vi.fn(async () => ({}))]]));
|
|
165
|
+
const runtime = createLocalOpRuntime();
|
|
166
|
+
const config = op("hello", [{ kind: "activity", fn: "ok", args: {} }]);
|
|
167
|
+
|
|
168
|
+
await (await runtime.start(config, {})).result();
|
|
169
|
+
// Whatever the ledger holds is lost (an unwritable branch, a project that
|
|
170
|
+
// is not a checkout); the in-memory history is the fallback.
|
|
171
|
+
runLedger.length = 0;
|
|
172
|
+
|
|
173
|
+
expect((await runtime.status("hello"))?.state).toBe("completed");
|
|
174
|
+
expect((await runtime.list([config])).get("hello")?.state).toBe("completed");
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test("cancel says why a foreground run has nothing to cancel", async () => {
|
|
178
|
+
const runtime = createLocalOpRuntime();
|
|
179
|
+
await expect(runtime.cancel("hello", { force: true })).rejects.toThrow(/foreground/);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The built-in `local` op runtime (#2121, epic #2114).
|
|
3
|
+
*
|
|
4
|
+
* Wraps `runOpLocally` (../local-executor.ts) in the {@link OpRuntimeProvider}
|
|
5
|
+
* contract so `chant run <op>` has one dispatch path whether the run is hosted
|
|
6
|
+
* here or by a lexicon's `opRuntime`. Behaviour is the executor's, unchanged:
|
|
7
|
+
* activities and profiles come from the project's configured lexicons, a gate
|
|
8
|
+
* is decided against the gate ledger and ends the run `gated` (#2119), and
|
|
9
|
+
* Ctrl-C aborts through the caller's `AbortSignal`.
|
|
10
|
+
*
|
|
11
|
+
* Status, log and list read the run ledger (#2118): every run this provider
|
|
12
|
+
* starts appends one `OpRunRecord` to `<env>/runs__<op>.jsonl` on the
|
|
13
|
+
* lifecycle branch, so an answer here outlives the process that produced it
|
|
14
|
+
* and a run started by cron, CI or another machine is visible too. The
|
|
15
|
+
* in-memory history stays as the fallback for the case the ledger cannot cover
|
|
16
|
+
* — a project that is not a checkout, or a run whose append failed — so a
|
|
17
|
+
* `chant run` followed by `chant run status` in the same process still
|
|
18
|
+
* answers.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { loadChantConfig } from "../../config";
|
|
22
|
+
import { loadActivities, loadProfiles } from "../activity-registry";
|
|
23
|
+
import { runOpLocally, OpRunFailure, type OpRunResult } from "../local-executor";
|
|
24
|
+
import { runComponents } from "../../components/cli-support";
|
|
25
|
+
import { discoverOps } from "../discover";
|
|
26
|
+
import { readRunLedger, runEnvOf, DEFAULT_RUN_ENV } from "../../lifecycle/run-ledger";
|
|
27
|
+
import type { OpConfig } from "../types";
|
|
28
|
+
import {
|
|
29
|
+
runStateOf,
|
|
30
|
+
type OpRunHandle,
|
|
31
|
+
type OpRunRecord,
|
|
32
|
+
type OpRunStartOptions,
|
|
33
|
+
type OpRunStatus,
|
|
34
|
+
type OpRuntimeProvider,
|
|
35
|
+
} from "../runtime";
|
|
36
|
+
|
|
37
|
+
/** Every run this process has started, newest last, keyed by op name. */
|
|
38
|
+
type RunLog = Map<string, OpRunStatus[]>;
|
|
39
|
+
|
|
40
|
+
function statusFrom(
|
|
41
|
+
op: string,
|
|
42
|
+
runId: string,
|
|
43
|
+
startedAt: string,
|
|
44
|
+
result: OpRunResult,
|
|
45
|
+
): OpRunStatus {
|
|
46
|
+
return {
|
|
47
|
+
op,
|
|
48
|
+
runId,
|
|
49
|
+
state: runStateOf(result.status),
|
|
50
|
+
startedAt,
|
|
51
|
+
endedAt: new Date().toISOString(),
|
|
52
|
+
records: result.records,
|
|
53
|
+
result,
|
|
54
|
+
...(result.gate ? { gate: { name: result.gate.gate, since: result.gate.timestamp } } : {}),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* A ledger record read back as a runtime status. `records` and `result` are
|
|
60
|
+
* absent on purpose: the ledger keeps each step's verdict, not the activity
|
|
61
|
+
* return values a live `OpRunResult` carries, and inventing them would make a
|
|
62
|
+
* replayed answer look like a live one.
|
|
63
|
+
*/
|
|
64
|
+
function statusFromRecord(record: OpRunRecord): OpRunStatus {
|
|
65
|
+
return {
|
|
66
|
+
op: record.op,
|
|
67
|
+
runId: record.id,
|
|
68
|
+
state: runStateOf(record.status),
|
|
69
|
+
startedAt: record.started,
|
|
70
|
+
endedAt: record.ended,
|
|
71
|
+
...(record.gate ? { gate: record.gate } : {}),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Build the local provider. `projectPath` is where `chant.config.ts` is read
|
|
77
|
+
* from to decide which cloud appliers to load — the same best-effort read the
|
|
78
|
+
* CLI did inline before the seam existed.
|
|
79
|
+
*/
|
|
80
|
+
export function createLocalOpRuntime(opts: { projectPath?: string } = {}): OpRuntimeProvider {
|
|
81
|
+
const runs: RunLog = new Map();
|
|
82
|
+
const projectPath = opts.projectPath ?? process.cwd();
|
|
83
|
+
|
|
84
|
+
const record = (status: OpRunStatus): void => {
|
|
85
|
+
const existing = runs.get(status.op);
|
|
86
|
+
if (existing) existing.push(status);
|
|
87
|
+
else runs.set(status.op, [status]);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// A run ledger is keyed `<env>/runs__<op>.jsonl`, and `status`/`log` are
|
|
91
|
+
// handed a name rather than a config. `start` and `list` know the config and
|
|
92
|
+
// seed this; otherwise the same `*.op.ts` scan that found the Op in the
|
|
93
|
+
// first place resolves its `labels.Env`.
|
|
94
|
+
const envs = new Map<string, string>();
|
|
95
|
+
const noteEnv = (op: OpConfig): string => {
|
|
96
|
+
const env = runEnvOf(op);
|
|
97
|
+
envs.set(op.name, env);
|
|
98
|
+
return env;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const envFor = async (op: string): Promise<string> => {
|
|
102
|
+
const known = envs.get(op);
|
|
103
|
+
if (known) return known;
|
|
104
|
+
try {
|
|
105
|
+
const { ops } = await discoverOps({ cwd: projectPath });
|
|
106
|
+
for (const discovered of ops.values()) noteEnv(discovered.config);
|
|
107
|
+
} catch {
|
|
108
|
+
// Not a checkout — nothing to scan; fall through to the default env.
|
|
109
|
+
}
|
|
110
|
+
return envs.get(op) ?? DEFAULT_RUN_ENV;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/** This op's ledger history, oldest first. Empty when there is no ledger to read. */
|
|
114
|
+
const ledgerFor = async (op: string, env?: string): Promise<OpRunRecord[]> => {
|
|
115
|
+
try {
|
|
116
|
+
const { records } = await readRunLedger(env ?? (await envFor(op)), op, { cwd: projectPath });
|
|
117
|
+
return records;
|
|
118
|
+
} catch {
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
name: "local",
|
|
125
|
+
|
|
126
|
+
async start(op: OpConfig, startOpts: OpRunStartOptions): Promise<OpRunHandle> {
|
|
127
|
+
// The project's configured lexicons decide which cloud appliers to load
|
|
128
|
+
// (aws -> floci, gcp -> gcpApply, azure -> az group). Best-effort: an
|
|
129
|
+
// unreadable config just yields the base activities.
|
|
130
|
+
let lexicons: string[] = [];
|
|
131
|
+
try {
|
|
132
|
+
lexicons = (await loadChantConfig(projectPath)).config.lexicons ?? [];
|
|
133
|
+
} catch {
|
|
134
|
+
// No/invalid chant.config — base activities only.
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const [activities, profiles] = await Promise.all([loadActivities(lexicons), loadProfiles()]);
|
|
138
|
+
|
|
139
|
+
const runId = `local-${Date.now()}`;
|
|
140
|
+
const startedAt = new Date().toISOString();
|
|
141
|
+
noteEnv(op);
|
|
142
|
+
|
|
143
|
+
const settled = (async (): Promise<OpRunStatus> => {
|
|
144
|
+
try {
|
|
145
|
+
const result = await runOpLocally(
|
|
146
|
+
op,
|
|
147
|
+
activities,
|
|
148
|
+
profiles,
|
|
149
|
+
startOpts.signal,
|
|
150
|
+
{
|
|
151
|
+
runId,
|
|
152
|
+
// The run's outcome is a durable fact (#2118): the executor
|
|
153
|
+
// appends it here, at the one seam every local run passes
|
|
154
|
+
// through, rather than in the CLI handler above it.
|
|
155
|
+
ledger: { cwd: projectPath },
|
|
156
|
+
...(startOpts.progress ? { onRecord: startOpts.progress } : {}),
|
|
157
|
+
},
|
|
158
|
+
);
|
|
159
|
+
const status = statusFrom(op.name, runId, startedAt, result);
|
|
160
|
+
record(status);
|
|
161
|
+
return status;
|
|
162
|
+
} catch (err) {
|
|
163
|
+
if (err instanceof OpRunFailure) {
|
|
164
|
+
const status = statusFrom(op.name, runId, startedAt, err.result);
|
|
165
|
+
record(status);
|
|
166
|
+
return status;
|
|
167
|
+
}
|
|
168
|
+
throw err;
|
|
169
|
+
}
|
|
170
|
+
})();
|
|
171
|
+
|
|
172
|
+
return { op: op.name, runId, result: () => settled };
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
async status(op: string): Promise<OpRunStatus | undefined> {
|
|
176
|
+
const newest = (await ledgerFor(op)).at(-1);
|
|
177
|
+
if (newest) return statusFromRecord(newest);
|
|
178
|
+
const history = runs.get(op);
|
|
179
|
+
return history?.[history.length - 1];
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
async log(op: string, logOpts?: { limit?: number }): Promise<OpRunRecord[]> {
|
|
183
|
+
const history = (await ledgerFor(op)).reverse();
|
|
184
|
+
return logOpts?.limit === undefined ? history : history.slice(0, logOpts.limit);
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
async list(ops: OpConfig[]): Promise<Map<string, OpRunStatus | undefined>> {
|
|
188
|
+
const out = new Map<string, OpRunStatus | undefined>();
|
|
189
|
+
for (const op of ops) {
|
|
190
|
+
const newest = (await ledgerFor(op.name, noteEnv(op))).at(-1);
|
|
191
|
+
if (newest) {
|
|
192
|
+
out.set(op.name, statusFromRecord(newest));
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
const history = runs.get(op.name);
|
|
196
|
+
out.set(op.name, history?.[history.length - 1]);
|
|
197
|
+
}
|
|
198
|
+
return out;
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
async cancel(op: string): Promise<void> {
|
|
202
|
+
throw new Error(
|
|
203
|
+
`the local runtime runs "${op}" in the foreground — there is no detached run to cancel. ` +
|
|
204
|
+
`Press Ctrl-C in the terminal running it, or pass --on <lexicon> for a hosted run.`,
|
|
205
|
+
);
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
runComponents(path, selector, options) {
|
|
209
|
+
return runComponents(path, selector, options);
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
}
|
|
@@ -5,14 +5,16 @@
|
|
|
5
5
|
* An Op's steps run in a fixed sequence chant already knows: phases in
|
|
6
6
|
* order, and (within a non-parallel phase) steps in order. Today the only
|
|
7
7
|
* way a value escapes a step is `outcomeAttribute`, which stringifies it
|
|
8
|
-
* into a
|
|
9
|
-
* step can consume. `StepOutputRef` is the mechanism that lets a later
|
|
8
|
+
* into a named run outcome — something to read a run back by, not something a
|
|
9
|
+
* later step can consume. `StepOutputRef` is the mechanism that lets a later
|
|
10
10
|
* step's `args` hold a *reference* to an earlier step's declared return
|
|
11
11
|
* value instead.
|
|
12
12
|
*
|
|
13
13
|
* Deliberately a reference, not an expression: `diff.out.driftedStacks` is
|
|
14
|
-
* a value placeholder
|
|
15
|
-
*
|
|
14
|
+
* a value placeholder that stays inert in the Op's data until the executor
|
|
15
|
+
* substitutes the producing step's recorded result for it, just before the
|
|
16
|
+
* consuming activity is called (`../op/local-executor.ts`'s
|
|
17
|
+
* `resolveStepOutputRefs` over `resultsById`) — never `diff.out.count >
|
|
16
18
|
* 0` or a `.map()` over a reference. That property (an Op is data you can
|
|
17
19
|
* read and know what it does, not a program) is exactly what makes it safe
|
|
18
20
|
* to add this without Ops becoming programs; see the issue's "line not to
|
|
@@ -42,10 +44,10 @@
|
|
|
42
44
|
* Cross-contract type compatibility (chant #1950 pre-merge review, finding
|
|
43
45
|
* 3): `validateStepOutputRefs` checks the producer side (a registered
|
|
44
46
|
* contract with a `returns` schema, and — when `path` is set — that the path
|
|
45
|
-
* resolves on it) and, separately, `validateActivitySteps`/
|
|
47
|
+
* resolves on it) and, separately, `validateActivitySteps`/OPS012 checks a
|
|
46
48
|
* step's `args` against its own contract's `args` schema — but a
|
|
47
49
|
* {@link StepOutputRef} sitting in `args` is a placeholder object at build
|
|
48
|
-
* time, not the value it resolves to, so
|
|
50
|
+
* time, not the value it resolves to, so OPS012 skips it (see
|
|
49
51
|
* `activity-contract.ts`'s `isStepOutputRefValue` guard) rather than
|
|
50
52
|
* false-positive on it. Nothing before this compared the *consumer's*
|
|
51
53
|
* declared type at that position against the *producer's* declared type at
|
|
@@ -93,8 +95,8 @@ const STEP_OUTPUT_REF_BRAND = Symbol.for("chant.op.stepOutputRef");
|
|
|
93
95
|
* A typed reference to a prior step's declared return value. Inert by
|
|
94
96
|
* construction — it carries a producer step id and an optional dot-path
|
|
95
97
|
* into that producer's return schema, resolved by `chant build`
|
|
96
|
-
* (`validateStepOutputRefs`) and compiled by
|
|
97
|
-
* local variable holding the awaited activity result.
|
|
98
|
+
* (`validateStepOutputRefs`) and compiled by a hosting lexicon's serializer
|
|
99
|
+
* into a local variable holding the awaited activity result.
|
|
98
100
|
*/
|
|
99
101
|
export interface StepOutputRef {
|
|
100
102
|
readonly [STEP_OUTPUT_REF_BRAND]: true;
|
|
@@ -268,11 +270,11 @@ function indexById(locations: StepLocation[]): { byId: Map<string, StepLocation>
|
|
|
268
270
|
* validateStepOutputRefs}'s checks that don't depend on a contract map, kept
|
|
269
271
|
* as its own export so a caller with no contracts on hand (or that wants to
|
|
270
272
|
* defend against exactly this class of bug regardless of what contracts are
|
|
271
|
-
* registered) can still refuse a scope-invalid reference.
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
273
|
+
* registered) can still refuse a scope-invalid reference. A hosting lexicon's
|
|
274
|
+
* own Op serializer is exactly this caller: OPS013 (which calls the fuller
|
|
275
|
+
* {@link validateStepOutputRefs}) protects `chant build`, but a serializer is
|
|
276
|
+
* a public export a caller can invoke directly, bypassing that lint pass —
|
|
277
|
+
* this is its own defense-in-depth.
|
|
276
278
|
*
|
|
277
279
|
* Flags:
|
|
278
280
|
* - a reference authored inside `onFailure`, or inside an `EffectStep`'s
|
package/src/op/types.ts
CHANGED
|
@@ -1,33 +1,66 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Op type definitions — the data model for a named, phased
|
|
2
|
+
* Op type definitions — the data model for a named, phased Op.
|
|
3
3
|
*
|
|
4
|
-
* These types are intentionally free of
|
|
5
|
-
* in core without
|
|
4
|
+
* These types are intentionally free of any runtime SDK's imports, so they can
|
|
5
|
+
* live in core without core depending on a runtime.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { EffectReceiptRef } from "./receipt-store";
|
|
9
|
+
import type { ActivityProfileName } from "./activity-profiles";
|
|
9
10
|
|
|
10
11
|
export interface OpConfig {
|
|
11
|
-
/** Kebab-case identifier.
|
|
12
|
+
/** Kebab-case identifier. Names the Op's output directory (`dist/ops/<name>/`), and is the name `chant run <name>` and another Op's `depends` refer to. */
|
|
12
13
|
name: string;
|
|
13
14
|
/** Human-readable description shown in `chant run list` and deployment reports. */
|
|
14
15
|
overview: string;
|
|
15
|
-
/** Temporal task queue. Defaults to `name`. */
|
|
16
|
-
taskQueue?: string;
|
|
17
|
-
/** Temporal namespace. Defaults to chant.config.ts defaultProfile's namespace. */
|
|
18
|
-
namespace?: string;
|
|
19
16
|
/** Ordered list of execution phases. */
|
|
20
17
|
phases: PhaseDefinition[];
|
|
21
18
|
/** Other Op names that must be complete before this Op can run. */
|
|
22
19
|
depends?: string[];
|
|
23
20
|
/** Compensation phases executed on terminal failure (run in reverse order). */
|
|
24
21
|
onFailure?: PhaseDefinition[];
|
|
25
|
-
/**
|
|
26
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Discovery keys for this Op — free-form `name: value` pairs a reader
|
|
24
|
+
* filters on. `ConvergeOp` sets `Converge: "true"` and `Env`, `WatchOp`
|
|
25
|
+
* sets `Watch`, and `discoverConvergeOps` (`./operator.ts`) reads both;
|
|
26
|
+
* `chant run list` prints whatever is here.
|
|
27
|
+
*
|
|
28
|
+
* These are the discovery half of what `searchAttributes` used to carry
|
|
29
|
+
* (#2118). The other half — a run's own outcome (`Phase`, `Drift`,
|
|
30
|
+
* `Approver`, `RollbackFailed`) — is not a property of the declaration at
|
|
31
|
+
* all and now lands on the run ledger as a fact
|
|
32
|
+
* (`../lifecycle/run-ledger.ts`), written per run rather than declared once.
|
|
33
|
+
*/
|
|
34
|
+
labels?: Record<string, string>;
|
|
35
|
+
/**
|
|
36
|
+
* The cadence this Op runs on, when it has one (#2120). Runtime-neutral
|
|
37
|
+
* data, not a scheduler: the github/gitlab/forgejo lexicons render it as a
|
|
38
|
+
* CI cron ({@link ScheduledOpSpec}), `chant operator` reads it as this Op's
|
|
39
|
+
* tick cadence, a hosting lexicon hands it to its own scheduler, and the
|
|
40
|
+
* local one-shot executor ignores it.
|
|
41
|
+
*/
|
|
42
|
+
schedule?: OpSchedule;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* An Op's cadence (#2120). The cron is validated at `Op()` construction by
|
|
47
|
+
* the permissive 5-/6-field parser in `./cron.ts`, the same one a lexicon's
|
|
48
|
+
* own post-synth cron check imports.
|
|
49
|
+
*/
|
|
50
|
+
export interface OpSchedule {
|
|
51
|
+
/** 5- or 6-field cron expression, read in the running host's local time. */
|
|
52
|
+
cron: string;
|
|
53
|
+
/**
|
|
54
|
+
* What a fire does while the previous run is still going. `"skip"` is the
|
|
55
|
+
* only value — and the default — because that is what a level-triggered
|
|
56
|
+
* tick wants: the next fire re-observes everything anyway, so queueing a
|
|
57
|
+
* backlog buys nothing a single later tick does not.
|
|
58
|
+
*/
|
|
59
|
+
overlap?: "skip";
|
|
27
60
|
}
|
|
28
61
|
|
|
29
62
|
export interface PhaseDefinition {
|
|
30
|
-
/** Display name shown in progress output
|
|
63
|
+
/** Display name shown in progress output. */
|
|
31
64
|
name: string;
|
|
32
65
|
/** Ordered steps within the phase. */
|
|
33
66
|
steps: StepDefinition[];
|
|
@@ -61,23 +94,50 @@ export interface ActivityStep {
|
|
|
61
94
|
*/
|
|
62
95
|
args?: Record<string, unknown>;
|
|
63
96
|
/**
|
|
64
|
-
* Key from
|
|
97
|
+
* Key from {@link ACTIVITY_PROFILES} controlling timeout + retry.
|
|
65
98
|
* Default: "fastIdempotent"
|
|
66
99
|
*/
|
|
67
|
-
profile?:
|
|
100
|
+
profile?: ActivityProfileName;
|
|
68
101
|
/**
|
|
69
|
-
* Surface this activity's return value as a
|
|
102
|
+
* Surface this activity's return value as a named run outcome.
|
|
103
|
+
*
|
|
104
|
+
* The local executor captures it into the step's record and folds it into
|
|
105
|
+
* the run ledger's `outcomes` (`../lifecycle/run-ledger.ts`); a hosting
|
|
106
|
+
* lexicon's serializer may additionally publish it to whatever index that
|
|
107
|
+
* runtime queries by. Useful for reading back a run by outcome (e.g. `Drift:
|
|
108
|
+
* "true"/"false"` from a lifecycleDiff activity).
|
|
70
109
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
110
|
+
* An array publishes several attributes off the same result in one upsert
|
|
111
|
+
* (#2105): one activity can answer more than one question about a run, and
|
|
112
|
+
* `choudoufuLivePlan`'s drift boolean plus its unowned and adoptable counts
|
|
113
|
+
* are three attributes over a single live read that nothing would be gained
|
|
114
|
+
* by splitting into three steps. A single object is the same thing with one
|
|
115
|
+
* entry, and stays the authored form everywhere one attribute is enough.
|
|
75
116
|
*
|
|
76
117
|
* `from` is a dot-path into the return value (e.g. `"drifted"` for
|
|
77
118
|
* `{ drifted: boolean }`); when omitted, the whole return value is
|
|
78
|
-
*
|
|
119
|
+
* recorded.
|
|
79
120
|
*/
|
|
80
|
-
outcomeAttribute?:
|
|
121
|
+
outcomeAttribute?: OutcomeAttribute | OutcomeAttribute[];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** One named run outcome published off a step's return value. */
|
|
125
|
+
export interface OutcomeAttribute {
|
|
126
|
+
/** The outcome's name, as it appears in the run ledger's `outcomes`. */
|
|
127
|
+
name: string;
|
|
128
|
+
/** Dot-path into the activity's return value; the whole value when omitted. */
|
|
129
|
+
from?: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* {@link ActivityStep.outcomeAttribute} as a list, whichever form it was
|
|
134
|
+
* authored in. `[]` when the step publishes none, so every consumer can
|
|
135
|
+
* iterate without first asking which of the two shapes it is holding.
|
|
136
|
+
*/
|
|
137
|
+
export function outcomeAttributesOf(step: { outcomeAttribute?: OutcomeAttribute | OutcomeAttribute[] }): OutcomeAttribute[] {
|
|
138
|
+
const declared = step.outcomeAttribute;
|
|
139
|
+
if (!declared) return [];
|
|
140
|
+
return Array.isArray(declared) ? declared : [declared];
|
|
81
141
|
}
|
|
82
142
|
|
|
83
143
|
/**
|
|
@@ -102,19 +162,19 @@ export interface EffectStep {
|
|
|
102
162
|
expectation?: string;
|
|
103
163
|
/**
|
|
104
164
|
* Steps run when the live receipt does not match, in authored order. A gate
|
|
105
|
-
* authored here
|
|
165
|
+
* authored here is reached only when the effect will fire. Effect steps do not
|
|
106
166
|
* nest.
|
|
107
167
|
*/
|
|
108
168
|
steps: Array<ActivityStep | GateStep>;
|
|
109
|
-
/** Annotation carried into the
|
|
169
|
+
/** Annotation carried into the Op's build output as a comment. */
|
|
110
170
|
description?: string;
|
|
111
171
|
}
|
|
112
172
|
|
|
113
173
|
export interface GateStep {
|
|
114
174
|
kind: "gate";
|
|
115
|
-
/**
|
|
175
|
+
/** The gate's name — what `chant approve <op> <gate>` resolves. */
|
|
116
176
|
signalName: string;
|
|
117
|
-
/**
|
|
177
|
+
/** How long a recorded pending gate stays valid, as a duration string. Default: "48h". */
|
|
118
178
|
timeout?: string;
|
|
119
179
|
/** Human-readable description of the action required to unblock this gate. */
|
|
120
180
|
description?: string;
|
package/src/ownership.ts
CHANGED
|
@@ -44,7 +44,7 @@ export interface ChannelKeys {
|
|
|
44
44
|
/**
|
|
45
45
|
* The label-based ownership convention (`app.kubernetes.io/managed-by` +
|
|
46
46
|
* `chant.intentius.io/{stack,env}`) — the default, shared by every label-based
|
|
47
|
-
* lexicon (k8s, gcp, helm, and the
|
|
47
|
+
* lexicon (k8s, gcp, helm, and the `k8sApply` activity's `kubectl --prune`
|
|
48
48
|
* selector). AWS and Azure tag keys are defined in their own lexicons.
|
|
49
49
|
*/
|
|
50
50
|
export const LABEL_OWNERSHIP_KEYS: ChannelKeys = {
|
package/src/provenance.test.ts
CHANGED
|
@@ -155,6 +155,12 @@ describe("describePathOrigin", () => {
|
|
|
155
155
|
"composite WebService (web)",
|
|
156
156
|
);
|
|
157
157
|
expect(describePathOrigin({ kind: "build-param", params: ["region", "tier"] })).toBe("param region, tier");
|
|
158
|
+
expect(
|
|
159
|
+
describePathOrigin({ kind: "composite-parameter", composite: "WebService", parameters: ["name", "tier"] }),
|
|
160
|
+
).toBe("composite WebService parameter name, tier");
|
|
161
|
+
expect(describePathOrigin({ kind: "composite-literal", composite: "WebService" })).toBe(
|
|
162
|
+
"composite WebService literal",
|
|
163
|
+
);
|
|
158
164
|
});
|
|
159
165
|
});
|
|
160
166
|
|