@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
|
@@ -20,13 +20,19 @@ import {
|
|
|
20
20
|
} from "../../op/operator";
|
|
21
21
|
import { readLease, DEFAULT_LEASE_TTL_MS } from "../../lifecycle/lease";
|
|
22
22
|
import { readConvergeLedger, type ConvergeTickRecord } from "../../lifecycle/converge-ledger";
|
|
23
|
-
import
|
|
24
|
-
import {
|
|
23
|
+
import { readRunLedger } from "../../lifecycle/run-ledger";
|
|
24
|
+
import type { OpRunRecord } from "../../op/runtime";
|
|
25
|
+
import type { GateResolutionRecord, PendingGateRecord } from "../../lifecycle/gate-ledger";
|
|
26
|
+
import {
|
|
27
|
+
appendGateResolution, appendPendingGate, readGateResolutions, readGateLedger,
|
|
28
|
+
latestResolutionSince, latestPendingGate, isPendingGateExpired,
|
|
29
|
+
resolveApprovalUrl, isApprovalUrl,
|
|
30
|
+
} from "../../lifecycle/gate-ledger";
|
|
25
31
|
import { pushLifecycle } from "../../lifecycle/git";
|
|
26
32
|
import { formatError, formatWarning, formatSuccess, formatBold, formatInfo } from "../format";
|
|
27
33
|
import type { CommandContext } from "../registry";
|
|
28
34
|
|
|
29
|
-
/** Load the activities a local tick needs, the same way
|
|
35
|
+
/** Load the activities a local tick needs, the same way a local run does: core's base activities plus whatever the project's configured lexicons contribute. Best-effort on the lexicon list — an unreadable `chant.config.ts` falls back to base activities only. */
|
|
30
36
|
async function loadOperatorActivities() {
|
|
31
37
|
let lexicons: string[] = [];
|
|
32
38
|
try {
|
|
@@ -42,7 +48,7 @@ async function loadOperatorActivities() {
|
|
|
42
48
|
/**
|
|
43
49
|
* `chant operator [--env <env>] [--interval <duration>] [--lease-ttl
|
|
44
50
|
* <duration>] [--once]` — run scheduled ticks for this project's discovered
|
|
45
|
-
* ConvergeOps, locally, with no
|
|
51
|
+
* ConvergeOps, locally, with no service to install (issue's own worked
|
|
46
52
|
* example). `--once` runs a single round and exits (also the offline test
|
|
47
53
|
* story, and what a cron/systemd-timer/k8s-CronJob invoker uses instead of
|
|
48
54
|
* leaving the daemon running); omitted, the daemon loops until Ctrl-C.
|
|
@@ -113,11 +119,37 @@ interface OpStatusLine {
|
|
|
113
119
|
op: string;
|
|
114
120
|
env: string;
|
|
115
121
|
lastTick?: ConvergeTickRecord;
|
|
116
|
-
/** `url` (#2028) is the gate's approval surface, when
|
|
117
|
-
pendingGates: { rule
|
|
122
|
+
/** `url` (#2028) is the gate's approval surface, when whatever recorded it knew one — what a renderer points its approve affordance at instead of a shell command. `rule` is present only for a gate a converge rule's dispatch reached; a gate an ordinary `chant run` stopped at has none. */
|
|
123
|
+
pendingGates: { rule?: string; op?: string; gate: string; url?: string; expiresAt?: string; description?: string }[];
|
|
118
124
|
lease?: { holder: string; expiresAt: string };
|
|
119
125
|
}
|
|
120
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Every gate an op is currently standing at, read from its own gate ledger
|
|
129
|
+
* (#2119) — a live (unexpired) pending fact with no resolution newer than it.
|
|
130
|
+
*
|
|
131
|
+
* Ledger-first, so `chant operator status` sees a gate any run recorded, not
|
|
132
|
+
* only one a converge tick's dispatch reached. Before this, a plain `chant run
|
|
133
|
+
* <op>` could not produce a pending gate at all (the executor refused the op
|
|
134
|
+
* outright), so reading the converge ledger's `gated` outcomes was the whole
|
|
135
|
+
* story; now it is one source among the ops' own.
|
|
136
|
+
*/
|
|
137
|
+
export async function pendingGatesFor(
|
|
138
|
+
opName: string,
|
|
139
|
+
opts: { cwd?: string; now?: string } = {},
|
|
140
|
+
): Promise<PendingGateRecord[]> {
|
|
141
|
+
const now = opts.now ?? new Date().toISOString();
|
|
142
|
+
const { resolutions, pending } = await readGateLedger(opName, { cwd: opts.cwd });
|
|
143
|
+
const standing: PendingGateRecord[] = [];
|
|
144
|
+
for (const gate of new Set(pending.map((p) => p.gate))) {
|
|
145
|
+
const latest = latestPendingGate(pending, gate);
|
|
146
|
+
if (!latest || isPendingGateExpired(latest, now)) continue;
|
|
147
|
+
if (latestResolutionSince(resolutions, gate, latest.timestamp)) continue;
|
|
148
|
+
standing.push(latest);
|
|
149
|
+
}
|
|
150
|
+
return standing.sort((a, b) => a.gate.localeCompare(b.gate));
|
|
151
|
+
}
|
|
152
|
+
|
|
121
153
|
async function statusFor(opName: string, env: string, cwd?: string): Promise<OpStatusLine> {
|
|
122
154
|
const [{ records }, { record: lease }] = await Promise.all([
|
|
123
155
|
readConvergeLedger(env, { cwd }),
|
|
@@ -127,19 +159,47 @@ async function statusFor(opName: string, env: string, cwd?: string): Promise<OpS
|
|
|
127
159
|
const lastTick = ownRecords.at(-1);
|
|
128
160
|
|
|
129
161
|
const pendingGates: OpStatusLine["pendingGates"] = [];
|
|
162
|
+
const seen = new Set<string>();
|
|
163
|
+
|
|
164
|
+
// The dispatched ops this ConvergeOp's last tick recorded as gated, plus the
|
|
165
|
+
// ConvergeOp itself — a gate can sit on either.
|
|
166
|
+
const gateOps = new Set<string>([opName]);
|
|
167
|
+
const ruleFor = new Map<string, string>();
|
|
168
|
+
for (const outcome of lastTick?.outcomes ?? []) {
|
|
169
|
+
if (outcome.action !== "gated" || !outcome.gateName || !outcome.op) continue;
|
|
170
|
+
gateOps.add(outcome.op);
|
|
171
|
+
ruleFor.set(`${outcome.op}\0${outcome.gateName}`, outcome.ruleId);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
for (const gateOp of [...gateOps].sort()) {
|
|
175
|
+
for (const record of await pendingGatesFor(gateOp, { cwd })) {
|
|
176
|
+
seen.add(`${gateOp}\0${record.gate}`);
|
|
177
|
+
pendingGates.push({
|
|
178
|
+
op: gateOp,
|
|
179
|
+
gate: record.gate,
|
|
180
|
+
expiresAt: record.expiresAt,
|
|
181
|
+
...(ruleFor.get(`${gateOp}\0${record.gate}`) ? { rule: ruleFor.get(`${gateOp}\0${record.gate}`) } : {}),
|
|
182
|
+
...(record.description ? { description: record.description } : {}),
|
|
183
|
+
...(record.url ? { url: record.url } : {}),
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// A tick that recorded a `gated` outcome before the executor started writing
|
|
189
|
+
// pending facts (#2119) still has nothing in `_gates` to read; fall back to
|
|
190
|
+
// the outcome itself so an in-flight gate isn't dropped on upgrade.
|
|
130
191
|
if (lastTick) {
|
|
131
192
|
for (const outcome of lastTick.outcomes) {
|
|
132
193
|
if (outcome.action !== "gated" || !outcome.gateName || !outcome.op) continue;
|
|
194
|
+
if (seen.has(`${outcome.op}\0${outcome.gateName}`)) continue;
|
|
133
195
|
const { records: resolutions } = await readGateResolutions(outcome.op, { cwd });
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
});
|
|
142
|
-
}
|
|
196
|
+
if (latestResolutionSince(resolutions, outcome.gateName, lastTick.timestamp)) continue;
|
|
197
|
+
pendingGates.push({
|
|
198
|
+
rule: outcome.ruleId,
|
|
199
|
+
op: outcome.op,
|
|
200
|
+
gate: outcome.gateName,
|
|
201
|
+
...(outcome.url ? { url: outcome.url } : {}),
|
|
202
|
+
});
|
|
143
203
|
}
|
|
144
204
|
}
|
|
145
205
|
|
|
@@ -152,6 +212,15 @@ async function statusFor(opName: string, env: string, cwd?: string): Promise<OpS
|
|
|
152
212
|
};
|
|
153
213
|
}
|
|
154
214
|
|
|
215
|
+
/** One op standing at a gate that no ConvergeOp row above already reported (#2119) — an ordinary `chant run <op>` records these now, so they belong on this page even where no converge tick was ever involved. */
|
|
216
|
+
export interface StandaloneGateLine {
|
|
217
|
+
op: string;
|
|
218
|
+
gate: string;
|
|
219
|
+
description?: string;
|
|
220
|
+
expiresAt: string;
|
|
221
|
+
url?: string;
|
|
222
|
+
}
|
|
223
|
+
|
|
155
224
|
/**
|
|
156
225
|
* `chant operator status [--env <env>] [--json]` — last tick, outcome
|
|
157
226
|
* counts, and pending gates, read from the `chant/lifecycle` orphan branch
|
|
@@ -159,22 +228,46 @@ async function statusFor(opName: string, env: string, cwd?: string): Promise<OpS
|
|
|
159
228
|
* running: everything here was already durably recorded by whichever
|
|
160
229
|
* process (this operator, a bare `chant run <op>`, or another machine's
|
|
161
230
|
* operator) ran the last tick.
|
|
231
|
+
*
|
|
232
|
+
* Pending gates are read from every discovered op's own gate ledger, not only
|
|
233
|
+
* from a converge tick's `gated` outcomes (#2119) — a gate an ordinary `chant
|
|
234
|
+
* run <op>` stopped at is the same standing fact and shows up the same way,
|
|
235
|
+
* under "pending gates" for ops with no converge tick behind them.
|
|
162
236
|
*/
|
|
163
237
|
export async function runOperatorStatus(ctx: CommandContext): Promise<number> {
|
|
164
238
|
const { ops, errors } = await discoverConvergeOps({ env: ctx.args.env });
|
|
165
239
|
for (const err of errors) console.error(formatWarning({ message: err }));
|
|
166
240
|
|
|
167
|
-
|
|
241
|
+
const rows = await Promise.all(
|
|
242
|
+
ops.map((d) => statusFor(d.config.name, d.config.labels?.Env ?? "unknown")),
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
// Every other discovered op that is standing at a gate. `discoverOps` sees
|
|
246
|
+
// the whole project, so an ApplyOp someone ran by hand this morning is here
|
|
247
|
+
// even though no ConvergeOp ever dispatched it.
|
|
248
|
+
const covered = new Set(rows.flatMap((r) => r.pendingGates.map((g) => `${g.op ?? r.op} ${g.gate}`)));
|
|
249
|
+
const { ops: allOps } = await discoverOps();
|
|
250
|
+
const standalone: StandaloneGateLine[] = [];
|
|
251
|
+
for (const opName of [...allOps.keys()].sort()) {
|
|
252
|
+
for (const record of await pendingGatesFor(opName)) {
|
|
253
|
+
if (covered.has(`${opName} ${record.gate}`)) continue;
|
|
254
|
+
standalone.push({
|
|
255
|
+
op: opName,
|
|
256
|
+
gate: record.gate,
|
|
257
|
+
expiresAt: record.expiresAt,
|
|
258
|
+
...(record.description ? { description: record.description } : {}),
|
|
259
|
+
...(record.url ? { url: record.url } : {}),
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (ops.length === 0 && standalone.length === 0) {
|
|
168
265
|
console.error(formatWarning({ message: "No ConvergeOp declarations found" }));
|
|
169
266
|
return 0;
|
|
170
267
|
}
|
|
171
268
|
|
|
172
|
-
const rows = await Promise.all(
|
|
173
|
-
ops.map((d) => statusFor(d.config.name, d.config.searchAttributes?.Env ?? "unknown")),
|
|
174
|
-
);
|
|
175
|
-
|
|
176
269
|
if (ctx.args.json) {
|
|
177
|
-
console.log(JSON.stringify(rows, null, 2));
|
|
270
|
+
console.log(JSON.stringify(standalone.length > 0 ? { rows, pendingGates: standalone } : rows, null, 2));
|
|
178
271
|
return 0;
|
|
179
272
|
}
|
|
180
273
|
|
|
@@ -190,13 +283,28 @@ export async function runOperatorStatus(ctx: CommandContext): Promise<number> {
|
|
|
190
283
|
if (row.pendingGates.length > 0) {
|
|
191
284
|
console.log(` pending gates:`);
|
|
192
285
|
for (const g of row.pendingGates) {
|
|
193
|
-
|
|
286
|
+
const op = g.op ?? row.op;
|
|
287
|
+
console.log(
|
|
288
|
+
` - ${op} gate "${g.gate}"${g.rule ? ` (rule ${g.rule})` : ""} — resolve: chant approve ${op} ${g.gate}`,
|
|
289
|
+
);
|
|
290
|
+
if (g.expiresAt) console.log(` expires: ${g.expiresAt}`);
|
|
194
291
|
if (g.url) console.log(` approve at: ${g.url}`);
|
|
195
292
|
}
|
|
196
293
|
}
|
|
197
294
|
console.log("");
|
|
198
295
|
}
|
|
199
296
|
|
|
297
|
+
if (standalone.length > 0) {
|
|
298
|
+
console.log(formatBold("pending gates (no converge tick)"));
|
|
299
|
+
for (const g of standalone) {
|
|
300
|
+
console.log(` - ${g.op} gate "${g.gate}" — resolve: chant approve ${g.op} ${g.gate}`);
|
|
301
|
+
if (g.description) console.log(` ${g.description}`);
|
|
302
|
+
console.log(` expires: ${g.expiresAt}`);
|
|
303
|
+
if (g.url) console.log(` approve at: ${g.url}`);
|
|
304
|
+
}
|
|
305
|
+
console.log("");
|
|
306
|
+
}
|
|
307
|
+
|
|
200
308
|
return 0;
|
|
201
309
|
}
|
|
202
310
|
|
|
@@ -205,17 +313,20 @@ export async function runOperatorStatus(ctx: CommandContext): Promise<number> {
|
|
|
205
313
|
/** One entry of the merged tick/gate timeline `chant operator log` prints. */
|
|
206
314
|
export type OperatorLogEntry =
|
|
207
315
|
| { kind: "tick"; timestamp: string; record: ConvergeTickRecord }
|
|
208
|
-
| { kind: "gate-resolution"; timestamp: string; record: GateResolutionRecord }
|
|
316
|
+
| { kind: "gate-resolution"; timestamp: string; record: GateResolutionRecord }
|
|
317
|
+
/** One Op run (#2118), timestamped at the instant it ended — the tick that dispatched it precedes it. */
|
|
318
|
+
| { kind: "run"; timestamp: string; record: OpRunRecord };
|
|
209
319
|
|
|
210
320
|
export interface OperatorLogResult {
|
|
211
321
|
entries: OperatorLogEntry[];
|
|
212
322
|
/**
|
|
213
|
-
* Unreadable lines behind this answer, per ledger. `readConvergeLedger
|
|
214
|
-
* `readGateResolutions`
|
|
215
|
-
* throwing, so a corrupted ledger renders a shorter
|
|
216
|
-
* consumer could not tell that from a genuinely
|
|
323
|
+
* Unreadable lines behind this answer, per ledger. `readConvergeLedger`,
|
|
324
|
+
* `readGateResolutions` and `readRunLedger` all skip a malformed line and
|
|
325
|
+
* count it rather than throwing, so a corrupted ledger renders a shorter
|
|
326
|
+
* timeline; without this a consumer could not tell that from a genuinely
|
|
327
|
+
* quiet environment.
|
|
217
328
|
*/
|
|
218
|
-
malformed: { converge: number; gates: number };
|
|
329
|
+
malformed: { converge: number; gates: number; runs: number };
|
|
219
330
|
}
|
|
220
331
|
|
|
221
332
|
/**
|
|
@@ -234,7 +345,7 @@ export async function collectOperatorLog(
|
|
|
234
345
|
const sinceMs = opts.since ? new Date(opts.since).getTime() : undefined;
|
|
235
346
|
|
|
236
347
|
const entries: OperatorLogEntry[] = [];
|
|
237
|
-
const malformed = { converge: 0, gates: 0 };
|
|
348
|
+
const malformed = { converge: 0, gates: 0, runs: 0 };
|
|
238
349
|
|
|
239
350
|
// One read per distinct environment — several ConvergeOps can share one
|
|
240
351
|
// `<env>/converge.jsonl`, and re-reading it per op would both cost more and
|
|
@@ -263,11 +374,23 @@ export async function collectOperatorLog(
|
|
|
263
374
|
}
|
|
264
375
|
}
|
|
265
376
|
|
|
377
|
+
// The runs each discovered Op recorded (#2118). Keyed `<env>/runs__<op>`,
|
|
378
|
+
// so unlike the converge ledger this is one read per (env, op) pair rather
|
|
379
|
+
// than per env — a ConvergeOp's own ticks and its own runs interleave here.
|
|
380
|
+
for (const { name, env } of wanted) {
|
|
381
|
+
const { records, malformed: bad } = await readRunLedger(env, name, { cwd: opts.cwd });
|
|
382
|
+
malformed.runs += bad;
|
|
383
|
+
for (const record of records) {
|
|
384
|
+
entries.push({ kind: "run", timestamp: record.ended, record });
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Within one instant: the tick first (it is what dispatched anything else),
|
|
389
|
+
// then the run it dispatched, then the gate resolution against that run.
|
|
390
|
+
const rank: Record<OperatorLogEntry["kind"], number> = { tick: 0, run: 1, "gate-resolution": 2 };
|
|
266
391
|
let merged = entries.sort((a, b) => {
|
|
267
392
|
const delta = new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime();
|
|
268
|
-
|
|
269
|
-
// the tick is what made the gate pending in the first place.
|
|
270
|
-
return delta !== 0 ? delta : (a.kind === b.kind ? 0 : a.kind === "tick" ? -1 : 1);
|
|
393
|
+
return delta !== 0 ? delta : rank[a.kind] - rank[b.kind];
|
|
271
394
|
});
|
|
272
395
|
if (sinceMs !== undefined) merged = merged.filter((e) => new Date(e.timestamp).getTime() >= sinceMs);
|
|
273
396
|
if (opts.limit !== undefined && merged.length > opts.limit) merged = merged.slice(-opts.limit);
|
|
@@ -276,6 +399,17 @@ export async function collectOperatorLog(
|
|
|
276
399
|
}
|
|
277
400
|
|
|
278
401
|
function renderLogEntry(entry: OperatorLogEntry): string[] {
|
|
402
|
+
if (entry.kind === "run") {
|
|
403
|
+
const { record } = entry;
|
|
404
|
+
const id = `[${record.id.slice(0, 8)}]`;
|
|
405
|
+
const outcomes = Object.entries(record.outcomes).map(([k, v]) => `${k}=${String(v)}`).join(" ");
|
|
406
|
+
const steps = record.phases.reduce((n, p) => n + p.steps.length, 0);
|
|
407
|
+
return [
|
|
408
|
+
`${record.ended} ${record.op}@${record.env} ${id} run ${record.status} ` +
|
|
409
|
+
`phases=${record.phases.length} steps=${steps}${outcomes ? ` ${outcomes}` : ""}`,
|
|
410
|
+
];
|
|
411
|
+
}
|
|
412
|
+
|
|
279
413
|
if (entry.kind === "gate-resolution") {
|
|
280
414
|
const { record } = entry;
|
|
281
415
|
return [
|
|
@@ -335,7 +469,7 @@ export async function runOperatorLog(ctx: CommandContext): Promise<number> {
|
|
|
335
469
|
}
|
|
336
470
|
|
|
337
471
|
const { entries, malformed } = await collectOperatorLog(
|
|
338
|
-
ops.map((d) => ({ name: d.config.name, env: d.config.
|
|
472
|
+
ops.map((d) => ({ name: d.config.name, env: d.config.labels?.Env ?? "unknown" })),
|
|
339
473
|
{ op: ctx.args.op, since: ctx.args.since, limit: ctx.args.limit },
|
|
340
474
|
);
|
|
341
475
|
|
|
@@ -344,16 +478,16 @@ export async function runOperatorLog(ctx: CommandContext): Promise<number> {
|
|
|
344
478
|
return 0;
|
|
345
479
|
}
|
|
346
480
|
|
|
347
|
-
const unreadable = malformed.converge + malformed.gates;
|
|
481
|
+
const unreadable = malformed.converge + malformed.gates + malformed.runs;
|
|
348
482
|
if (unreadable > 0) {
|
|
349
483
|
console.error(formatWarning({
|
|
350
484
|
message: `${unreadable} ledger line(s) were unreadable and are missing from this timeline ` +
|
|
351
|
-
`(converge: ${malformed.converge}, gates: ${malformed.gates})`,
|
|
485
|
+
`(converge: ${malformed.converge}, gates: ${malformed.gates}, runs: ${malformed.runs})`,
|
|
352
486
|
}));
|
|
353
487
|
}
|
|
354
488
|
|
|
355
489
|
if (entries.length === 0) {
|
|
356
|
-
console.error(formatWarning({ message: "No converge ticks recorded yet" }));
|
|
490
|
+
console.error(formatWarning({ message: "No converge ticks or Op runs recorded yet" }));
|
|
357
491
|
return 0;
|
|
358
492
|
}
|
|
359
493
|
|
|
@@ -366,16 +500,22 @@ export async function runOperatorLog(ctx: CommandContext): Promise<number> {
|
|
|
366
500
|
// ── chant approve <op> <gate> ───────────────────────────────────────────────
|
|
367
501
|
|
|
368
502
|
/**
|
|
369
|
-
* `chant approve <op> <gate> [--actor <name>] [--note <text>] [--url <url>]
|
|
370
|
-
* — record the
|
|
371
|
-
*
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
*
|
|
503
|
+
* `chant approve <op> <gate> [--actor <name>] [--note <text>] [--url <url>]
|
|
504
|
+
* [--expire]` — record the out-of-band resolution fact for a gate a run
|
|
505
|
+
* stopped at (issue #1485: "resolution is an out-of-band act that writes the
|
|
506
|
+
* counterpart fact"). Per that issue's leaning on open question 3 ("local
|
|
507
|
+
* trust in v1"), this performs no authorization check beyond "you can run
|
|
508
|
+
* `chant approve` locally".
|
|
509
|
+
*
|
|
510
|
+
* Since #2119 this closes the loop rather than just narrating it: the next
|
|
511
|
+
* `chant run <op>` reads the resolution, finds it newer than the gate's
|
|
512
|
+
* pending fact, and walks through.
|
|
513
|
+
*
|
|
514
|
+
* `--expire` is the other half — clear a standing pending fact *without*
|
|
515
|
+
* approving anything, for a gate that was recorded against a run nobody
|
|
516
|
+
* intends to finish. It writes no resolution; it appends a pending fact that
|
|
517
|
+
* is already expired, which supersedes the standing one on an append-only
|
|
518
|
+
* ledger, so the next run decides the gate from scratch.
|
|
379
519
|
*/
|
|
380
520
|
export async function runApprove(ctx: CommandContext): Promise<number> {
|
|
381
521
|
const opName = ctx.args.path;
|
|
@@ -385,6 +525,75 @@ export async function runApprove(ctx: CommandContext): Promise<number> {
|
|
|
385
525
|
return 1;
|
|
386
526
|
}
|
|
387
527
|
|
|
528
|
+
if (ctx.args.expire) {
|
|
529
|
+
const now = new Date().toISOString();
|
|
530
|
+
const standing = latestPendingGate((await readGateLedger(opName)).pending, gate);
|
|
531
|
+
if (!standing || isPendingGateExpired(standing, now)) {
|
|
532
|
+
console.error(formatWarning({
|
|
533
|
+
message: `Gate "${gate}" on "${opName}" has no standing pending fact — nothing to expire`,
|
|
534
|
+
}));
|
|
535
|
+
return 0;
|
|
536
|
+
}
|
|
537
|
+
await appendPendingGate({
|
|
538
|
+
op: opName,
|
|
539
|
+
gate,
|
|
540
|
+
timestamp: now,
|
|
541
|
+
expiresAt: now,
|
|
542
|
+
...(standing.description ? { description: standing.description } : {}),
|
|
543
|
+
});
|
|
544
|
+
await pushLifecycle().catch(() => undefined);
|
|
545
|
+
console.error(formatSuccess(`Gate "${gate}" on "${opName}" expired at ${now} — not approved`));
|
|
546
|
+
console.error(formatInfo(
|
|
547
|
+
`The next \`chant run ${opName}\` decides this gate from scratch and records a fresh pending fact.`,
|
|
548
|
+
));
|
|
549
|
+
return 0;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// `--approver` wins over `--actor`, the same precedence `chant run approve`
|
|
553
|
+
// has applied since #2126 (`../handlers/run.ts`'s `runOpApprove`). Reading
|
|
554
|
+
// only `--actor` here meant every README that teaches `--approver you`
|
|
555
|
+
// recorded the shell user instead (#2192).
|
|
556
|
+
const outcome = await recordGateApproval(opName, gate, {
|
|
557
|
+
actor: ctx.args.approver ?? ctx.args.actor,
|
|
558
|
+
note: ctx.args.note,
|
|
559
|
+
url: ctx.args.url,
|
|
560
|
+
});
|
|
561
|
+
if (!outcome.ok) return 1;
|
|
562
|
+
|
|
563
|
+
console.error(formatInfo(
|
|
564
|
+
`This records the resolution as a fact; it does not itself re-run anything. ` +
|
|
565
|
+
`Run \`chant run ${opName}\` and it walks through gate "${gate}".`,
|
|
566
|
+
));
|
|
567
|
+
return 0;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/** What a caller supplies alongside the op and gate names. */
|
|
571
|
+
export interface GateApprovalOptions {
|
|
572
|
+
/** `--actor`/`--approver`; falls back to the CI or shell identity. */
|
|
573
|
+
actor?: string;
|
|
574
|
+
/** `--note` — free-text prose. */
|
|
575
|
+
note?: string;
|
|
576
|
+
/** `--url` — the approval surface, validated as absolute http/https. */
|
|
577
|
+
url?: string;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
export type GateApprovalOutcome =
|
|
581
|
+
| { ok: true; record: GateResolutionRecord }
|
|
582
|
+
| { ok: false };
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* The ledger write behind `chant approve` — extracted so `chant run approve`
|
|
586
|
+
* (#2121) records the identical fact before waking the runtime that hosts the
|
|
587
|
+
* gated run, instead of growing a second, drifting writer.
|
|
588
|
+
*
|
|
589
|
+
* Prints the same warning for an undiscovered op and the same success line as
|
|
590
|
+
* `chant approve` always did; the caller adds whatever it does next.
|
|
591
|
+
*/
|
|
592
|
+
export async function recordGateApproval(
|
|
593
|
+
opName: string,
|
|
594
|
+
gate: string,
|
|
595
|
+
opts: GateApprovalOptions,
|
|
596
|
+
): Promise<GateApprovalOutcome> {
|
|
388
597
|
const { ops } = await discoverOps();
|
|
389
598
|
if (!ops.has(opName)) {
|
|
390
599
|
console.error(formatWarning({
|
|
@@ -392,18 +601,18 @@ export async function runApprove(ctx: CommandContext): Promise<number> {
|
|
|
392
601
|
}));
|
|
393
602
|
}
|
|
394
603
|
|
|
395
|
-
const resolvedBy =
|
|
604
|
+
const resolvedBy = opts.actor ?? process.env.GITHUB_ACTOR ?? process.env.GITLAB_USER_LOGIN ?? process.env.USER ?? "unknown";
|
|
396
605
|
|
|
397
606
|
// #2028: the resolution's link is typed. `--url` wins; otherwise, running
|
|
398
607
|
// inside the PR/MR job that carries the change is itself the address, the
|
|
399
608
|
// same env fallback `--actor` uses. `--note` stays free-text prose.
|
|
400
|
-
const url =
|
|
609
|
+
const url = opts.url ?? resolveApprovalUrl();
|
|
401
610
|
if (url && !isApprovalUrl(url)) {
|
|
402
611
|
console.error(formatError({
|
|
403
612
|
message: `--url must be an absolute http/https URL (got "${url}")`,
|
|
404
613
|
hint: "Pass the PR/MR link, or omit --url and put prose in --note.",
|
|
405
614
|
}));
|
|
406
|
-
return
|
|
615
|
+
return { ok: false };
|
|
407
616
|
}
|
|
408
617
|
|
|
409
618
|
const { record } = await appendGateResolution({
|
|
@@ -411,7 +620,7 @@ export async function runApprove(ctx: CommandContext): Promise<number> {
|
|
|
411
620
|
gate,
|
|
412
621
|
resolvedBy,
|
|
413
622
|
timestamp: new Date().toISOString(),
|
|
414
|
-
...(
|
|
623
|
+
...(opts.note ? { note: opts.note } : {}),
|
|
415
624
|
...(url ? { url } : {}),
|
|
416
625
|
});
|
|
417
626
|
await pushLifecycle().catch(() => undefined);
|
|
@@ -420,9 +629,5 @@ export async function runApprove(ctx: CommandContext): Promise<number> {
|
|
|
420
629
|
`Gate "${gate}" on "${opName}" resolved by ${record.resolvedBy} at ${record.timestamp}` +
|
|
421
630
|
(record.url ? ` (${record.url})` : ""),
|
|
422
631
|
));
|
|
423
|
-
|
|
424
|
-
"This records the resolution as a fact; it does not itself re-run the gated dispatch — " +
|
|
425
|
-
"the local executor still refuses any op with a gate. Re-run it with --temporal, or via the PR that carries the change.",
|
|
426
|
-
));
|
|
427
|
-
return 0;
|
|
632
|
+
return { ok: true, record };
|
|
428
633
|
}
|