@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
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The gate step's name field, and the one-version bridge for the key it used
|
|
3
|
+
* to carry (chant #2202).
|
|
4
|
+
*
|
|
5
|
+
* A gate is a fact on the gate ledger, not a channel: since #2119 nothing is
|
|
6
|
+
* running and nothing is signalled, so the field that names a gate is called
|
|
7
|
+
* `gate` — the same word `chant approve <op> <gate>` takes on the command
|
|
8
|
+
* line. It was called `signalName` through 0.58.0.
|
|
9
|
+
*
|
|
10
|
+
* `signalName` is still read, on `GateStep`, on the component `Gate` step and
|
|
11
|
+
* on the composites' gate options, and a build that sees only the old key
|
|
12
|
+
* warns once. It goes away in 0.60.0: delete this module's
|
|
13
|
+
* {@link DEPRECATED_GATE_KEY_WARNING}, {@link usesDeprecatedGateKey}, the
|
|
14
|
+
* `signalName` branch of {@link gateName}, the optional `signalName` fields
|
|
15
|
+
* that call it, and the schema's `oneOf` once that release is out, leaving
|
|
16
|
+
* `gate` as the only key.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import type { OpConfig, PhaseDefinition, StepDefinition } from "./types";
|
|
20
|
+
|
|
21
|
+
/** Either spelling of a gate step's name. `gate` since #2202; `signalName` through 0.59.0. */
|
|
22
|
+
export interface GateNamed {
|
|
23
|
+
gate?: string;
|
|
24
|
+
/** @deprecated Renamed to `gate` in #2202. Accepted through 0.59.0, removed in 0.60.0. */
|
|
25
|
+
signalName?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The gate's name, from whichever key carries it. One place reads the old key,
|
|
30
|
+
* so removing the bridge is a one-file edit rather than a sweep.
|
|
31
|
+
*/
|
|
32
|
+
export function gateName(step: GateNamed): string {
|
|
33
|
+
return step.gate ?? step.signalName ?? "";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** True when a step names its gate only with the deprecated key. */
|
|
37
|
+
export function usesDeprecatedGateKey(step: GateNamed): boolean {
|
|
38
|
+
return step.gate === undefined && typeof step.signalName === "string";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** What a build prints once when it finds a gate step still using the old key. */
|
|
42
|
+
export const DEPRECATED_GATE_KEY_WARNING =
|
|
43
|
+
'Gate steps still using "signalName": the key is now "gate" (chant #2202). ' +
|
|
44
|
+
'"signalName" is accepted through 0.59.0 and removed in 0.60.0.';
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* True when any gate step in an Op's phases (main or `onFailure`, at any
|
|
48
|
+
* nesting depth inside an `effect()`) names itself only with the deprecated
|
|
49
|
+
* key. `chant build` calls this to warn once per build.
|
|
50
|
+
*/
|
|
51
|
+
export function opUsesDeprecatedGateKey(config: OpConfig): boolean {
|
|
52
|
+
const inStep = (step: StepDefinition): boolean => {
|
|
53
|
+
if (step.kind === "gate") return usesDeprecatedGateKey(step);
|
|
54
|
+
if (step.kind === "effect") return step.steps.some(inStep);
|
|
55
|
+
return false;
|
|
56
|
+
};
|
|
57
|
+
const inPhases = (phases: PhaseDefinition[] | undefined): boolean =>
|
|
58
|
+
(phases ?? []).some((p) => p.steps.some(inStep));
|
|
59
|
+
return inPhases(config.phases) || inPhases(config.onFailure);
|
|
60
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pending-gate block a CI run leaves where people actually look (#2243).
|
|
3
|
+
*
|
|
4
|
+
* A gated run already prints the gate, the approve command and the expiry to
|
|
5
|
+
* stderr (`./local-output.ts`'s `renderHuman`). In CI that lands in a log
|
|
6
|
+
* nobody opens unless the run is red, which is exactly the run this stops
|
|
7
|
+
* being red. GitHub Actions, Forgejo Actions and Gitea all give a step a
|
|
8
|
+
* markdown scratchpad through `GITHUB_STEP_SUMMARY`, rendered at the top of
|
|
9
|
+
* the run page; anything else that sets the variable gets the same block.
|
|
10
|
+
*
|
|
11
|
+
* That is the whole forge coupling: one environment variable, appended to
|
|
12
|
+
* when it is set, and nothing at all when it is not. No API call, no token,
|
|
13
|
+
* no flag to turn it on.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { appendFileSync } from "node:fs";
|
|
17
|
+
import { gateLedgerPath } from "../lifecycle/gate-ledger";
|
|
18
|
+
import { approveCommand } from "./gate";
|
|
19
|
+
|
|
20
|
+
/** What a gated run knows about the gate it stopped on. */
|
|
21
|
+
export interface GatedRunSummary {
|
|
22
|
+
/** The Op (or component) the gate belongs to. */
|
|
23
|
+
op: string;
|
|
24
|
+
/** The gate's name — the second argument to `chant approve`. */
|
|
25
|
+
gate: string;
|
|
26
|
+
/** The gate's authored description, when it has one. */
|
|
27
|
+
description?: string;
|
|
28
|
+
/** ISO-8601 instant the pending fact ages out at. */
|
|
29
|
+
expiresAt?: string;
|
|
30
|
+
/** The approval surface the run resolved, when it knew one. */
|
|
31
|
+
url?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The markdown block itself. Pure, so a test reads what CI would render
|
|
36
|
+
* without touching a file: op, gate, the exact `chant approve` line, and the
|
|
37
|
+
* ledger path the pending fact was appended to.
|
|
38
|
+
*/
|
|
39
|
+
export function gatedRunSummaryMarkdown(summary: GatedRunSummary): string {
|
|
40
|
+
const lines = [
|
|
41
|
+
`### Waiting on gate \`${summary.gate}\``,
|
|
42
|
+
"",
|
|
43
|
+
`Op \`${summary.op}\` reached a gate nobody has approved, recorded the pending fact, and stopped. Nothing failed.`,
|
|
44
|
+
"",
|
|
45
|
+
];
|
|
46
|
+
if (summary.description) {
|
|
47
|
+
lines.push(summary.description, "");
|
|
48
|
+
}
|
|
49
|
+
lines.push(
|
|
50
|
+
"Approve it, then re-run this workflow:",
|
|
51
|
+
"",
|
|
52
|
+
"```",
|
|
53
|
+
`${approveCommand(summary.op, summary.gate)} --approver <you>`,
|
|
54
|
+
"```",
|
|
55
|
+
"",
|
|
56
|
+
`Ledger: \`${gateLedgerPath(summary.op)}\` on the \`chant/lifecycle\` branch.`,
|
|
57
|
+
);
|
|
58
|
+
if (summary.expiresAt) lines.push(`Expires: ${summary.expiresAt}`);
|
|
59
|
+
if (summary.url) lines.push(`Approve at: ${summary.url}`);
|
|
60
|
+
lines.push("");
|
|
61
|
+
return lines.join("\n");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Append {@link gatedRunSummaryMarkdown} to the file `GITHUB_STEP_SUMMARY`
|
|
66
|
+
* names, when the variable is set and the file can be written.
|
|
67
|
+
*
|
|
68
|
+
* Returns the path written, or `undefined` when there was nothing to write to.
|
|
69
|
+
* A write that fails is swallowed: a run that already decided its outcome must
|
|
70
|
+
* not turn into a different one because a CI scratchpad was read-only.
|
|
71
|
+
*/
|
|
72
|
+
export function writeGatedRunSummary(
|
|
73
|
+
summary: GatedRunSummary,
|
|
74
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
75
|
+
): string | undefined {
|
|
76
|
+
const path = env.GITHUB_STEP_SUMMARY;
|
|
77
|
+
if (!path) return undefined;
|
|
78
|
+
try {
|
|
79
|
+
appendFileSync(path, gatedRunSummaryMarkdown(summary));
|
|
80
|
+
return path;
|
|
81
|
+
} catch {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
}
|
package/src/op/gate.ts
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate-as-fact (#2119, epic #2114) — the one place that decides what happens
|
|
3
|
+
* when a run reaches a `gate`, shared by the Op executor
|
|
4
|
+
* (`./local-executor.ts`) and the component driver
|
|
5
|
+
* (`../components/driver.ts`) so the two can never drift.
|
|
6
|
+
*
|
|
7
|
+
* A gate used to be a wait, which meant a runtime that cannot wait had to
|
|
8
|
+
* refuse the whole op before its first step (`LocalGateUnsupportedError`,
|
|
9
|
+
* deleted with this). It is a fact now: the run reads the gate ledger
|
|
10
|
+
* (`../lifecycle/gate-ledger.ts`) for a resolution someone wrote with `chant
|
|
11
|
+
* approve`, and either walks through carrying the approver, or records a
|
|
12
|
+
* pending fact and ends. Nothing blocks, nothing is queued, nothing has to be
|
|
13
|
+
* resumed — the next run re-evaluates from the ledger, which is exactly the
|
|
14
|
+
* level-triggered shape a converge tick already has.
|
|
15
|
+
*
|
|
16
|
+
* The staleness rule is the same one `chant operator status` has applied since
|
|
17
|
+
* #1485: a resolution counts only if it is newer than the newest pending fact
|
|
18
|
+
* for that gate. Approving before the gate was ever reached does not
|
|
19
|
+
* pre-authorize a future run's gate that has since been recorded pending; a
|
|
20
|
+
* resolution from last month does not answer the fact this run just wrote.
|
|
21
|
+
*
|
|
22
|
+
* Ledger access goes through {@link GateLedgerPort} rather than straight to
|
|
23
|
+
* git, so a test (and the operator's own in-memory paths) can drive the
|
|
24
|
+
* decision without an orphan branch on disk.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import {
|
|
28
|
+
appendPendingGate,
|
|
29
|
+
isPendingGateExpired,
|
|
30
|
+
latestPendingGate,
|
|
31
|
+
latestResolutionSince,
|
|
32
|
+
readGateLedger,
|
|
33
|
+
resolveApprovalUrl,
|
|
34
|
+
DEFAULT_GATE_EXPIRY,
|
|
35
|
+
type GateResolutionRecord,
|
|
36
|
+
type PendingGateInput,
|
|
37
|
+
type PendingGateRecord,
|
|
38
|
+
} from "../lifecycle/gate-ledger";
|
|
39
|
+
import { pushLifecycle } from "../lifecycle/git";
|
|
40
|
+
import { parseDuration } from "./duration";
|
|
41
|
+
|
|
42
|
+
/** The gate ledger, as the two executors need it: read both kinds of line, append a pending fact. */
|
|
43
|
+
export interface GateLedgerPort {
|
|
44
|
+
read(op: string): Promise<{ resolutions: GateResolutionRecord[]; pending: PendingGateRecord[] }>;
|
|
45
|
+
appendPending(input: PendingGateInput): Promise<PendingGateRecord>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The real port: the `chant/lifecycle` orphan branch. Pushes best-effort after
|
|
50
|
+
* appending, the same two-step-collapsed-into-one shape `chant approve` uses
|
|
51
|
+
* (`../cli/handlers/operator.ts` calls `pushLifecycle().catch(...)` right after
|
|
52
|
+
* its append) — a pending fact that only ever reaches the local branch is still
|
|
53
|
+
* a correct local answer, so a missing remote never fails the run.
|
|
54
|
+
*/
|
|
55
|
+
export function gitGateLedgerPort(opts?: { cwd?: string }): GateLedgerPort {
|
|
56
|
+
return {
|
|
57
|
+
async read(op) {
|
|
58
|
+
const { resolutions, pending } = await readGateLedger(op, opts);
|
|
59
|
+
return { resolutions, pending };
|
|
60
|
+
},
|
|
61
|
+
async appendPending(input) {
|
|
62
|
+
const { record } = await appendPendingGate(input, opts);
|
|
63
|
+
await pushLifecycle(opts).catch(() => undefined);
|
|
64
|
+
return record;
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** A gate ledger held in memory — what a test, or a caller that has already read the ledger, hands {@link evaluateGate}. */
|
|
70
|
+
export function memoryGateLedgerPort(
|
|
71
|
+
seed: { resolutions?: GateResolutionRecord[]; pending?: PendingGateRecord[] } = {},
|
|
72
|
+
): GateLedgerPort & { appended: PendingGateRecord[] } {
|
|
73
|
+
const resolutions = [...(seed.resolutions ?? [])];
|
|
74
|
+
const pending = [...(seed.pending ?? [])];
|
|
75
|
+
const appended: PendingGateRecord[] = [];
|
|
76
|
+
return {
|
|
77
|
+
appended,
|
|
78
|
+
async read() {
|
|
79
|
+
return { resolutions: [...resolutions], pending: [...pending] };
|
|
80
|
+
},
|
|
81
|
+
async appendPending(input) {
|
|
82
|
+
const record: PendingGateRecord = { version: 1, kind: "pending", ...input };
|
|
83
|
+
pending.push(record);
|
|
84
|
+
appended.push(record);
|
|
85
|
+
return record;
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** What a caller has to say about the gate it just reached. */
|
|
91
|
+
export interface GateCheckInput {
|
|
92
|
+
/** The op the gate belongs to — the component's name, on the driver. */
|
|
93
|
+
op: string;
|
|
94
|
+
/** The gate's signal name. */
|
|
95
|
+
gate: string;
|
|
96
|
+
description?: string;
|
|
97
|
+
/** The gate's authored `timeout`, which becomes the pending fact's expiry. Default {@link DEFAULT_GATE_EXPIRY}. */
|
|
98
|
+
timeout?: string;
|
|
99
|
+
/** Identifies the run that reached the gate, when the caller has one. */
|
|
100
|
+
runId?: string;
|
|
101
|
+
/** ISO-8601 "now" — supplied by the caller, so the decision is deterministic under test. */
|
|
102
|
+
now?: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Either the gate is answered, or it is a standing fact. */
|
|
106
|
+
export type GateCheck =
|
|
107
|
+
| { satisfied: true; resolution: GateResolutionRecord }
|
|
108
|
+
| { satisfied: false; pending: PendingGateRecord; recorded: boolean };
|
|
109
|
+
|
|
110
|
+
/** The beginning of time — the anchor for a gate that has never been recorded pending, so any resolution for it counts. */
|
|
111
|
+
const EPOCH = new Date(0).toISOString();
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Decide a gate against the ledger, recording the pending fact when it isn't
|
|
115
|
+
* answered.
|
|
116
|
+
*
|
|
117
|
+
* - A resolution newer than the newest pending fact satisfies the gate.
|
|
118
|
+
* - Otherwise, a pending fact that hasn't expired stands as it is: the run
|
|
119
|
+
* ends `gated` and the ledger is left alone, so an operator ticking every
|
|
120
|
+
* minute against an unapproved gate does not append a line a minute.
|
|
121
|
+
* - Otherwise (no pending fact, or the newest one has expired) a fresh pending
|
|
122
|
+
* fact is appended and the run ends `gated`. `recorded` says which of the
|
|
123
|
+
* two happened, so a renderer can tell "just recorded" from "still standing".
|
|
124
|
+
*/
|
|
125
|
+
export async function evaluateGate(port: GateLedgerPort, input: GateCheckInput): Promise<GateCheck> {
|
|
126
|
+
const now = input.now ?? new Date().toISOString();
|
|
127
|
+
const { resolutions, pending } = await port.read(input.op);
|
|
128
|
+
|
|
129
|
+
const standing = latestPendingGate(pending, input.gate);
|
|
130
|
+
const resolution = latestResolutionSince(resolutions, input.gate, standing?.timestamp ?? EPOCH);
|
|
131
|
+
if (resolution) return { satisfied: true, resolution };
|
|
132
|
+
|
|
133
|
+
if (standing && !isPendingGateExpired(standing, now)) {
|
|
134
|
+
return { satisfied: false, pending: standing, recorded: false };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const url = resolveApprovalUrl();
|
|
138
|
+
const record = await port.appendPending({
|
|
139
|
+
op: input.op,
|
|
140
|
+
gate: input.gate,
|
|
141
|
+
timestamp: now,
|
|
142
|
+
expiresAt: new Date(
|
|
143
|
+
new Date(now).getTime() + parseDuration(input.timeout ?? DEFAULT_GATE_EXPIRY),
|
|
144
|
+
).toISOString(),
|
|
145
|
+
...(input.description ? { description: input.description } : {}),
|
|
146
|
+
...(input.runId ? { runId: input.runId } : {}),
|
|
147
|
+
...(url ? { url } : {}),
|
|
148
|
+
});
|
|
149
|
+
return { satisfied: false, pending: record, recorded: true };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** The line every renderer prints to say how a pending gate is cleared. */
|
|
153
|
+
export function approveCommand(op: string, gate: string): string {
|
|
154
|
+
return `chant approve ${op} ${gate}`;
|
|
155
|
+
}
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { describe, test, expect, vi } from "vitest";
|
|
12
|
-
import { generateOpsPipeline } from "./generate-pipeline";
|
|
12
|
+
import { generateOpsPipeline, withOpSchedules } from "./generate-pipeline";
|
|
13
|
+
import type { DiscoveredOp } from "./discover";
|
|
14
|
+
import type { OpConfig } from "./types";
|
|
13
15
|
import type { ScheduledOpSpec, OpPipelineResult } from "../lexicon";
|
|
14
16
|
|
|
15
17
|
vi.mock("@intentius/chant-lexicon-gitlab", () => ({
|
|
@@ -22,7 +24,12 @@ vi.mock("@intentius/chant-lexicon-gitlab", () => ({
|
|
|
22
24
|
package: () => "gitlab",
|
|
23
25
|
generateOpPipeline: (ops: ScheduledOpSpec[]): OpPipelineResult => ({
|
|
24
26
|
files: ops.map((o) => ({ name: `${o.name}.yml`, yaml: `# ${o.name} @ ${o.schedule}` })),
|
|
25
|
-
jobs: ops.map((o) => ({
|
|
27
|
+
jobs: ops.map((o) => ({
|
|
28
|
+
jobName: o.name,
|
|
29
|
+
op: o.name,
|
|
30
|
+
trigger: o.trigger ?? { kind: "cron" as const, schedule: o.schedule! },
|
|
31
|
+
findingMode: o.findingMode ?? "report",
|
|
32
|
+
})),
|
|
26
33
|
}),
|
|
27
34
|
},
|
|
28
35
|
}));
|
|
@@ -48,6 +55,61 @@ describe("generateOpsPipeline", () => {
|
|
|
48
55
|
const result = await generateOpsPipeline(specs, "gitlab");
|
|
49
56
|
expect(result.success).toBe(true);
|
|
50
57
|
expect(result.files).toEqual([{ name: "alb-deploy.yml", yaml: "# alb-deploy @ 0 6 * * *" }]);
|
|
51
|
-
expect(result.jobs).toEqual([
|
|
58
|
+
expect(result.jobs).toEqual([
|
|
59
|
+
{ jobName: "alb-deploy", op: "alb-deploy", trigger: { kind: "cron", schedule: "0 6 * * *" }, findingMode: "issue" },
|
|
60
|
+
]);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// #2084: `trigger` is new and optional — a spec built the old way (`schedule`
|
|
64
|
+
// only, no `trigger`) must still round-trip through `generateOpsPipeline`
|
|
65
|
+
// unchanged, since every pre-#2084 caller (`WorkflowAuditOp`,
|
|
66
|
+
// `PipelineAuditOp`, `ReconcileOp`) only ever sets `schedule`.
|
|
67
|
+
test("a legacy `{ schedule }` spec with no `trigger` round-trips unchanged", async () => {
|
|
68
|
+
const specs: ScheduledOpSpec[] = [{ name: "alb-deploy", schedule: "0 6 * * *" }];
|
|
69
|
+
const result = await generateOpsPipeline(specs, "gitlab");
|
|
70
|
+
expect(result.success).toBe(true);
|
|
71
|
+
expect(result.files).toEqual([{ name: "alb-deploy.yml", yaml: "# alb-deploy @ 0 6 * * *" }]);
|
|
72
|
+
expect(result.jobs).toEqual([
|
|
73
|
+
{ jobName: "alb-deploy", op: "alb-deploy", trigger: { kind: "cron", schedule: "0 6 * * *" }, findingMode: "report" },
|
|
74
|
+
]);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe("withOpSchedules — the Op's own cadence reaches the CI generator (#2120)", () => {
|
|
79
|
+
function discovered(entries: Array<[string, OpConfig]>): Map<string, DiscoveredOp> {
|
|
80
|
+
return new Map(entries.map(([name, config]) => [name, { config, filePath: `${name}.op.ts`, exportName: "default" }]));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const scheduled: OpConfig = {
|
|
84
|
+
name: "prod-watch",
|
|
85
|
+
overview: "watch prod",
|
|
86
|
+
phases: [],
|
|
87
|
+
schedule: { cron: "*/10 * * * *", overlap: "skip" },
|
|
88
|
+
};
|
|
89
|
+
const unscheduled: OpConfig = { name: "one-shot", overview: "no cadence", phases: [] };
|
|
90
|
+
|
|
91
|
+
test("a scheduled Op's cadence lands on its spec as opSchedule", () => {
|
|
92
|
+
const [spec] = withOpSchedules([{ name: "prod-watch" }], discovered([["prod-watch", scheduled]]));
|
|
93
|
+
expect(spec.opSchedule).toEqual({ cron: "*/10 * * * *", overlap: "skip" });
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("an Op with no cadence leaves its spec untouched", () => {
|
|
97
|
+
const input: ScheduledOpSpec[] = [{ name: "one-shot", schedule: "0 6 * * *" }];
|
|
98
|
+
expect(withOpSchedules(input, discovered([["one-shot", unscheduled]]))).toEqual(input);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("an explicit trigger or schedule on the spec is preserved alongside it — resolveOpTrigger picks", () => {
|
|
102
|
+
const [spec] = withOpSchedules(
|
|
103
|
+
[{ name: "prod-watch", trigger: { kind: "push", branches: ["main"] } }],
|
|
104
|
+
discovered([["prod-watch", scheduled]]),
|
|
105
|
+
);
|
|
106
|
+
expect(spec.trigger).toEqual({ kind: "push", branches: ["main"] });
|
|
107
|
+
expect(spec.opSchedule).toEqual({ cron: "*/10 * * * *", overlap: "skip" });
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("the input specs are not mutated", () => {
|
|
111
|
+
const input: ScheduledOpSpec[] = [{ name: "prod-watch" }];
|
|
112
|
+
withOpSchedules(input, discovered([["prod-watch", scheduled]]));
|
|
113
|
+
expect(input[0].opSchedule).toBeUndefined();
|
|
52
114
|
});
|
|
53
115
|
});
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* `resolveComponentGraph`; each `ScheduledOpSpec` is generated independently.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import { discoverOps } from "./discover";
|
|
19
|
+
import { discoverOps, type DiscoveredOp } from "./discover";
|
|
20
20
|
import {
|
|
21
21
|
isLexiconPlugin,
|
|
22
22
|
type LexiconPlugin,
|
|
@@ -46,6 +46,23 @@ async function loadLexiconPlugin(name: string): Promise<LexiconPlugin | null> {
|
|
|
46
46
|
return null;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Copy each discovered Op's own `schedule` (#2120) onto its spec, so a CI
|
|
51
|
+
* generator can render the cron the Op already declares — `WatchOp({ name,
|
|
52
|
+
* schedule })` then needs no second cron in the `generateOpsPipeline` call.
|
|
53
|
+
* The spec's own `trigger`/`schedule` still win; `resolveOpTrigger` reads
|
|
54
|
+
* `opSchedule` last. Specs for Ops with no cadence pass through untouched.
|
|
55
|
+
*/
|
|
56
|
+
export function withOpSchedules(
|
|
57
|
+
specs: ScheduledOpSpec[],
|
|
58
|
+
discovered: Map<string, DiscoveredOp>,
|
|
59
|
+
): ScheduledOpSpec[] {
|
|
60
|
+
return specs.map((spec) => {
|
|
61
|
+
const schedule = discovered.get(spec.name)?.config.schedule;
|
|
62
|
+
return schedule ? { ...spec, opSchedule: schedule } : spec;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
49
66
|
/** Result of generating scheduled CI for a set of Ops (generate mode's Op counterpart, #927). */
|
|
50
67
|
export interface GenerateOpsPipelineResult {
|
|
51
68
|
success: boolean;
|
|
@@ -94,6 +111,6 @@ export async function generateOpsPipeline(
|
|
|
94
111
|
};
|
|
95
112
|
}
|
|
96
113
|
|
|
97
|
-
const { files, jobs } = plugin.generateOpPipeline(ops, options);
|
|
114
|
+
const { files, jobs } = plugin.generateOpPipeline(withOpSchedules(ops, discovered.ops), options);
|
|
98
115
|
return { success: true, files, jobs };
|
|
99
116
|
}
|
package/src/op/index.ts
CHANGED
|
@@ -3,18 +3,34 @@ export { Op, phase, activity, gate, effect, build, kubectlApply, helmInstall, he
|
|
|
3
3
|
k3sInstall, k3sUninstall, flociUp, flociDown,
|
|
4
4
|
flociAzUp, flociAzDown, flociGcpUp, flociGcpDown, httpCheck,
|
|
5
5
|
azGroupEnsure, azGroupDelete, azApply, azDelete, awsApply, awsDelete, gcpApply, gcpDelete, policyGate,
|
|
6
|
+
guardValidate,
|
|
6
7
|
spriteCreate, spriteExec, spriteCheckpoint, spriteRestore, listCheckpoints, spriteDestroy,
|
|
7
8
|
spriteWriteFile, spriteReadFile, spriteListDir, spriteRemove,
|
|
8
9
|
spriteApplyNetworkPolicy, spriteApplyServices,
|
|
9
10
|
spriteTaskCreate, spriteTaskRefresh, spriteTaskRelease,
|
|
10
11
|
spritesUp, spritesDown } from "./builders";
|
|
11
12
|
export { OpResource } from "./resource";
|
|
12
|
-
export {
|
|
13
|
+
export { sleep } from "./activity-runtime";
|
|
13
14
|
export { emulatorLifecycle, emulatorsOf, endpointEnvVars } from "./emulator-lifecycle";
|
|
14
15
|
export type { EmulatorSpec, EmulatorCapability, EmulatorDeclaration, EmulatorUpArgs, EmulatorLifecycle } from "./emulator-lifecycle";
|
|
15
16
|
export { checkFreshness, compare, formatResult, latestRelease, parseVersion, unpinned } from "./emulator-freshness";
|
|
16
17
|
export type { FreshnessResult } from "./emulator-freshness";
|
|
17
|
-
export type { OpConfig, PhaseDefinition, StepDefinition, ActivityStep, GateStep, EffectStep } from "./types";
|
|
18
|
+
export type { OpConfig, OpSchedule, PhaseDefinition, StepDefinition, ActivityStep, GateStep, EffectStep, OutcomeAttribute } from "./types";
|
|
19
|
+
export { outcomeAttributesOf } from "./types";
|
|
20
|
+
export { isValidCronExpression, cronSyntaxMessage, cronMatches, cronDueBetween } from "./cron";
|
|
21
|
+
export {
|
|
22
|
+
WatchOp, ReconcileOp, ApplyOp, ConvergeOp,
|
|
23
|
+
WorkflowAuditOp, PipelineAuditOp, LexiconUpgradeOp, IN_SCOPE_LEXICONS,
|
|
24
|
+
} from "./composites";
|
|
25
|
+
export type {
|
|
26
|
+
WatchOpConfig, WatchOpResources,
|
|
27
|
+
ReconcileOpConfig, ReconcileOpResources,
|
|
28
|
+
ApplyOpConfig, ApplyOpResources,
|
|
29
|
+
ConvergeOpConfig, ConvergeOpResources, ConvergeDial,
|
|
30
|
+
WorkflowAuditOpConfig, WorkflowAuditOpResources,
|
|
31
|
+
PipelineAuditOpConfig, PipelineAuditOpResources,
|
|
32
|
+
LexiconUpgradeOpConfig, LexiconUpgradeOpResources,
|
|
33
|
+
} from "./composites";
|
|
18
34
|
export { receiptActivities, receiptCheckInput } from "./receipt-store";
|
|
19
35
|
export type {
|
|
20
36
|
ReceiptStore, EffectReceiptRef, ReceiptCheckInput, ReceiptActivities, ReceiptActivityOptions,
|
|
@@ -23,12 +39,31 @@ export type {
|
|
|
23
39
|
} from "./receipt-store";
|
|
24
40
|
export { discoverOps } from "./discover";
|
|
25
41
|
export type { DiscoveredOp, OpDiscoveryResult } from "./discover";
|
|
26
|
-
export { generateOpsPipeline } from "./generate-pipeline";
|
|
42
|
+
export { generateOpsPipeline, withOpSchedules } from "./generate-pipeline";
|
|
27
43
|
export type { GenerateOpsPipelineResult } from "./generate-pipeline";
|
|
28
44
|
export { loadActivities, loadProfiles, resolveActivity } from "./activity-registry";
|
|
29
|
-
export type { ActivityFn
|
|
30
|
-
export {
|
|
31
|
-
export type {
|
|
45
|
+
export type { ActivityFn } from "./activity-registry";
|
|
46
|
+
export { loadActivityContracts, mergeActivityContracts } from "./activity-contract-registry";
|
|
47
|
+
export type { LexiconActivityContractContributor } from "./activity-contract-registry";
|
|
48
|
+
export { ACTIVITY_PROFILES, ACTIVITY_PROFILE_NAMES } from "./activity-profiles";
|
|
49
|
+
export type { ActivityProfile, ActivityProfileName } from "./activity-profiles";
|
|
50
|
+
export { NonRetryableActivityError, nonRetryableFailure } from "./activity-failure";
|
|
51
|
+
export { runOpLocally, parseDuration, OpRunFailure } from "./local-executor";
|
|
52
|
+
export type { StepRecord, OpRunResult, RunOpOptions } from "./local-executor";
|
|
53
|
+
export { evaluateGate, gitGateLedgerPort, memoryGateLedgerPort, approveCommand } from "./gate";
|
|
54
|
+
export type { GateLedgerPort, GateCheck, GateCheckInput } from "./gate";
|
|
55
|
+
export { gateName, usesDeprecatedGateKey, DEPRECATED_GATE_KEY_WARNING } from "./gate-name";
|
|
56
|
+
export type { GateNamed } from "./gate-name";
|
|
57
|
+
export { createLocalOpRuntime } from "./runtimes/local";
|
|
58
|
+
export { runStateOf } from "./runtime";
|
|
59
|
+
export type {
|
|
60
|
+
OpRuntimeProvider, OpRunHandle, OpRunStartOptions, OpRunState, OpRunStatus,
|
|
61
|
+
OpRunRecord, OpRunRecordInput, OpRunPhaseRecord, OpRunStepRecord,
|
|
62
|
+
} from "./runtime";
|
|
63
|
+
export { buildOpIR, serializeOpIR, opConfigFromIR, OP_IR_FORMAT_VERSION } from "./op-ir";
|
|
64
|
+
export type {
|
|
65
|
+
OpIR, OpIRPhase, OpIRStep, OpIRActivityStep, OpIRGateStep, OpIREffectStep, OpIRActivityContract,
|
|
66
|
+
} from "./op-ir";
|
|
32
67
|
export { renderHuman, renderJson } from "./local-output";
|
|
33
68
|
export {
|
|
34
69
|
activityContract, isActivityContract, collectActivityContracts, validateActivitySteps, KNOWN_ACTIVITY_PROFILES,
|
|
@@ -52,9 +87,14 @@ export type {
|
|
|
52
87
|
} from "./converge-rule";
|
|
53
88
|
export {
|
|
54
89
|
discoverConvergeOps, runOperatorRound, runOperatorForever, formatRoundLine,
|
|
55
|
-
DEFAULT_OPERATOR_INTERVAL_MS,
|
|
90
|
+
formatSignalLine, DEFAULT_OPERATOR_INTERVAL_MS,
|
|
91
|
+
} from "./operator";
|
|
92
|
+
export type {
|
|
93
|
+
OperatorTickEvent, OperatorRoundOptions, OperatorLoopOptions,
|
|
94
|
+
ChangeSubscriber, OperatorSignalEvent,
|
|
56
95
|
} from "./operator";
|
|
57
|
-
export
|
|
96
|
+
export { createChangeSignalGate, DEFAULT_SIGNAL_FLOOR_MS } from "./change-signal";
|
|
97
|
+
export type { ChangeSignalGate, ChangeSignalGateOptions, WakeReason } from "./change-signal";
|
|
58
98
|
export { classifyOpVerbClass, isGated } from "./op-verb-class";
|
|
59
99
|
export type { OpVerbClass } from "./op-verb-class";
|
|
60
100
|
export { takeProfileAndId } from "./builders";
|