@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
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect } from "vitest";
|
|
2
|
-
import { extractStepRecords, extractIndexedStepRecords, stepRecordEmitter, countActivities, queryGateState } from "./op-progress";
|
|
3
|
-
import type { StepRecord } from "../../op/local-executor";
|
|
4
|
-
import type { OpConfig } from "../../op/types";
|
|
5
|
-
import type { EffectReceiptRef } from "../../op/receipt-store";
|
|
6
|
-
import type { WorkflowHistoryRaw, HistoryEvent } from "./run-client";
|
|
7
|
-
|
|
8
|
-
// Minimal history-event builders. Field shapes match what `fetchNormalizedHistory`
|
|
9
|
-
// produces: short PascalCase `eventType`, decimal-string `eventId`/`scheduledEventId`.
|
|
10
|
-
function scheduled(eventId: string, fn: string, at: Date): HistoryEvent {
|
|
11
|
-
return {
|
|
12
|
-
eventId,
|
|
13
|
-
eventType: "ActivityTaskScheduled",
|
|
14
|
-
eventTime: at,
|
|
15
|
-
activityTaskScheduledEventAttributes: { activityId: eventId, activityType: { name: fn } },
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
function completed(scheduledEventId: string, at: Date): HistoryEvent {
|
|
19
|
-
return {
|
|
20
|
-
eventType: "ActivityTaskCompleted",
|
|
21
|
-
eventTime: at,
|
|
22
|
-
activityTaskCompletedEventAttributes: { scheduledEventId },
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
function failed(scheduledEventId: string, at: Date, message = "boom"): HistoryEvent {
|
|
26
|
-
return {
|
|
27
|
-
eventType: "ActivityTaskFailed",
|
|
28
|
-
eventTime: at,
|
|
29
|
-
activityTaskFailedEventAttributes: { scheduledEventId, failure: { message } },
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const T0 = new Date("2026-05-01T00:00:00Z");
|
|
34
|
-
const sec = (n: number) => new Date(T0.getTime() + n * 1000);
|
|
35
|
-
|
|
36
|
-
describe("extractStepRecords", () => {
|
|
37
|
-
test("joins two phases' activities to their declared phase, in order", () => {
|
|
38
|
-
const config: OpConfig = {
|
|
39
|
-
name: "op", overview: "o",
|
|
40
|
-
phases: [
|
|
41
|
-
{ name: "Build", steps: [{ kind: "activity", fn: "build" }] },
|
|
42
|
-
{ name: "Deploy", steps: [{ kind: "activity", fn: "deploy" }] },
|
|
43
|
-
],
|
|
44
|
-
};
|
|
45
|
-
const history: WorkflowHistoryRaw = {
|
|
46
|
-
events: [
|
|
47
|
-
scheduled("1", "build", sec(0)),
|
|
48
|
-
completed("1", sec(1)),
|
|
49
|
-
scheduled("2", "deploy", sec(2)),
|
|
50
|
-
completed("2", sec(4)),
|
|
51
|
-
],
|
|
52
|
-
};
|
|
53
|
-
const records = extractStepRecords(config, history);
|
|
54
|
-
expect(records).toEqual([
|
|
55
|
-
{ phase: "Build", fn: "build", status: "ok", durationMs: 1000 },
|
|
56
|
-
{ phase: "Deploy", fn: "deploy", status: "ok", durationMs: 2000 },
|
|
57
|
-
]);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test("two steps calling the same activity each get their own scheduled event (no last-wins collision)", () => {
|
|
61
|
-
const config: OpConfig = {
|
|
62
|
-
name: "op", overview: "o",
|
|
63
|
-
phases: [{ name: "P1", steps: [{ kind: "activity", fn: "dup" }, { kind: "activity", fn: "dup" }] }],
|
|
64
|
-
};
|
|
65
|
-
const history: WorkflowHistoryRaw = {
|
|
66
|
-
events: [
|
|
67
|
-
scheduled("1", "dup", sec(0)),
|
|
68
|
-
completed("1", sec(1)), // first "dup": 1000ms, ok
|
|
69
|
-
scheduled("2", "dup", sec(1)),
|
|
70
|
-
failed("2", sec(1.5), "second dup failed"), // second "dup": fails
|
|
71
|
-
],
|
|
72
|
-
};
|
|
73
|
-
const records = extractStepRecords(config, history);
|
|
74
|
-
expect(records).toEqual([
|
|
75
|
-
{ phase: "P1", fn: "dup", status: "ok", durationMs: 1000 },
|
|
76
|
-
{ phase: "P1", fn: "dup", status: "fail", durationMs: 500, error: "second dup failed" },
|
|
77
|
-
]);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("a step not yet scheduled produces no record unless final", () => {
|
|
81
|
-
const config: OpConfig = {
|
|
82
|
-
name: "op", overview: "o",
|
|
83
|
-
phases: [
|
|
84
|
-
{ name: "P1", steps: [{ kind: "activity", fn: "a" }] },
|
|
85
|
-
{ name: "P2", steps: [{ kind: "activity", fn: "b" }] },
|
|
86
|
-
],
|
|
87
|
-
};
|
|
88
|
-
const history: WorkflowHistoryRaw = { events: [scheduled("1", "a", sec(0)), completed("1", sec(1))] };
|
|
89
|
-
|
|
90
|
-
expect(extractStepRecords(config, history)).toEqual([
|
|
91
|
-
{ phase: "P1", fn: "a", status: "ok", durationMs: 1000 },
|
|
92
|
-
]);
|
|
93
|
-
expect(extractStepRecords(config, history, { final: true })).toEqual([
|
|
94
|
-
{ phase: "P1", fn: "a", status: "ok", durationMs: 1000 },
|
|
95
|
-
{ phase: "P2", fn: "b", status: "skipped", durationMs: 0 },
|
|
96
|
-
]);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
test("a scheduled-but-not-yet-settled step produces no record", () => {
|
|
100
|
-
const config: OpConfig = {
|
|
101
|
-
name: "op", overview: "o",
|
|
102
|
-
phases: [{ name: "P1", steps: [{ kind: "activity", fn: "a" }] }],
|
|
103
|
-
};
|
|
104
|
-
const history: WorkflowHistoryRaw = { events: [scheduled("1", "a", sec(0))] };
|
|
105
|
-
expect(extractStepRecords(config, history)).toEqual([]);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
test("a retried activity resolves to its last outcome (Failed attempt then eventual Completed)", () => {
|
|
109
|
-
const config: OpConfig = {
|
|
110
|
-
name: "op", overview: "o",
|
|
111
|
-
phases: [{ name: "P1", steps: [{ kind: "activity", fn: "flaky" }] }],
|
|
112
|
-
};
|
|
113
|
-
const history: WorkflowHistoryRaw = {
|
|
114
|
-
events: [
|
|
115
|
-
scheduled("1", "flaky", sec(0)),
|
|
116
|
-
failed("1", sec(1), "attempt 1 failed"),
|
|
117
|
-
completed("1", sec(3)), // eventual success
|
|
118
|
-
],
|
|
119
|
-
};
|
|
120
|
-
expect(extractStepRecords(config, history)).toEqual([
|
|
121
|
-
{ phase: "P1", fn: "flaky", status: "ok", durationMs: 3000 },
|
|
122
|
-
]);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
test("effect step: matched receipt — only receiptRead settles; nested + receiptWrite are skipped only when final", () => {
|
|
126
|
-
const receipt: EffectReceiptRef = { name: "r", effect: "e", flavor: "existence", inputs: {} };
|
|
127
|
-
const config: OpConfig = {
|
|
128
|
-
name: "op", overview: "o",
|
|
129
|
-
phases: [{
|
|
130
|
-
name: "Effect",
|
|
131
|
-
steps: [{ kind: "effect", receipt, steps: [{ kind: "activity", fn: "applyIt" }] }],
|
|
132
|
-
}],
|
|
133
|
-
};
|
|
134
|
-
const history: WorkflowHistoryRaw = {
|
|
135
|
-
events: [scheduled("1", "receiptRead", sec(0)), completed("1", sec(1))],
|
|
136
|
-
};
|
|
137
|
-
expect(extractStepRecords(config, history)).toEqual([
|
|
138
|
-
{ phase: "Effect", fn: "receiptRead", status: "ok", durationMs: 1000 },
|
|
139
|
-
]);
|
|
140
|
-
expect(extractStepRecords(config, history, { final: true })).toEqual([
|
|
141
|
-
{ phase: "Effect", fn: "receiptRead", status: "ok", durationMs: 1000 },
|
|
142
|
-
{ phase: "Effect", fn: "applyIt", status: "skipped", durationMs: 0 },
|
|
143
|
-
{ phase: "Effect", fn: "receiptWrite", status: "skipped", durationMs: 0 },
|
|
144
|
-
]);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
test("onFailure phases are matched in reverse declared order, matching how the workflow actually runs them", () => {
|
|
148
|
-
const config: OpConfig = {
|
|
149
|
-
name: "op", overview: "o",
|
|
150
|
-
phases: [{ name: "Main", steps: [{ kind: "activity", fn: "boom" }] }],
|
|
151
|
-
onFailure: [
|
|
152
|
-
{ name: "C1", steps: [{ kind: "activity", fn: "comp1" }] },
|
|
153
|
-
{ name: "C2", steps: [{ kind: "activity", fn: "comp2" }] },
|
|
154
|
-
],
|
|
155
|
-
};
|
|
156
|
-
const history: WorkflowHistoryRaw = {
|
|
157
|
-
events: [
|
|
158
|
-
scheduled("1", "boom", sec(0)),
|
|
159
|
-
failed("1", sec(1), "boom"),
|
|
160
|
-
// Compensation runs C2 then C1 (reverse of declared order).
|
|
161
|
-
scheduled("2", "comp2", sec(2)),
|
|
162
|
-
completed("2", sec(3)),
|
|
163
|
-
scheduled("3", "comp1", sec(3)),
|
|
164
|
-
completed("3", sec(4)),
|
|
165
|
-
],
|
|
166
|
-
};
|
|
167
|
-
expect(extractStepRecords(config, history)).toEqual([
|
|
168
|
-
{ phase: "Main", fn: "boom", status: "fail", durationMs: 1000, error: "boom" },
|
|
169
|
-
{ phase: "C2", fn: "comp2", status: "ok", durationMs: 1000 },
|
|
170
|
-
{ phase: "C1", fn: "comp1", status: "ok", durationMs: 1000 },
|
|
171
|
-
]);
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
describe("stepRecordEmitter", () => {
|
|
176
|
-
// chant #2032. Declared order is main phases then `onFailure` reversed, so an
|
|
177
|
-
// unreached main phase sits *before* an `onFailure` phase that ran. The live
|
|
178
|
-
// poll therefore returns [Main(fail), Comp(ok)] and the terminal `final: true`
|
|
179
|
-
// pass returns [Main(fail), Never(skipped), Comp(ok)] — an insertion, not an
|
|
180
|
-
// append. The old emitted-count watermark sliced at 2 and re-shipped Comp
|
|
181
|
-
// while dropping Never entirely. The #1676 coverage above misses this because
|
|
182
|
-
// in those configs the skipped record lands last, where insert and append are
|
|
183
|
-
// the same operation.
|
|
184
|
-
const config: OpConfig = {
|
|
185
|
-
name: "op", overview: "o",
|
|
186
|
-
phases: [
|
|
187
|
-
{ name: "Main", steps: [{ kind: "activity", fn: "boom" }] },
|
|
188
|
-
{ name: "Never", steps: [{ kind: "activity", fn: "never" }] },
|
|
189
|
-
],
|
|
190
|
-
onFailure: [{ name: "Comp", steps: [{ kind: "activity", fn: "comp" }] }],
|
|
191
|
-
};
|
|
192
|
-
// Main fails, Never is never reached, compensation runs and succeeds.
|
|
193
|
-
const history: WorkflowHistoryRaw = {
|
|
194
|
-
events: [
|
|
195
|
-
scheduled("1", "boom", sec(0)),
|
|
196
|
-
failed("1", sec(1), "boom"),
|
|
197
|
-
scheduled("2", "comp", sec(2)),
|
|
198
|
-
completed("2", sec(3)),
|
|
199
|
-
],
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
const MAIN: StepRecord = { phase: "Main", fn: "boom", status: "fail", durationMs: 1000, error: "boom" };
|
|
203
|
-
const NEVER: StepRecord = { phase: "Never", fn: "never", status: "skipped", durationMs: 0 };
|
|
204
|
-
const COMP: StepRecord = { phase: "Comp", fn: "comp", status: "ok", durationMs: 1000 };
|
|
205
|
-
|
|
206
|
-
test("the final pass inserts rather than appends, so list position is not an identity", () => {
|
|
207
|
-
expect(extractIndexedStepRecords(config, history)).toEqual([
|
|
208
|
-
{ index: 0, record: MAIN },
|
|
209
|
-
{ index: 2, record: COMP },
|
|
210
|
-
]);
|
|
211
|
-
expect(extractIndexedStepRecords(config, history, { final: true })).toEqual([
|
|
212
|
-
{ index: 0, record: MAIN },
|
|
213
|
-
{ index: 1, record: NEVER },
|
|
214
|
-
{ index: 2, record: COMP },
|
|
215
|
-
]);
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
test("each record ships exactly once across the poll passes and the final pass", () => {
|
|
219
|
-
const emitted: StepRecord[] = [];
|
|
220
|
-
const emit = stepRecordEmitter((r) => emitted.push(r));
|
|
221
|
-
|
|
222
|
-
emit(extractIndexedStepRecords(config, history)); // a poll while the workflow closes
|
|
223
|
-
emit(extractIndexedStepRecords(config, history)); // an identical re-poll adds nothing
|
|
224
|
-
emit(extractIndexedStepRecords(config, history, { final: true }));
|
|
225
|
-
|
|
226
|
-
expect(emitted).toEqual([MAIN, COMP, NEVER]);
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
test("an empty first poll does not shift what a later pass ships", () => {
|
|
230
|
-
const emitted: StepRecord[] = [];
|
|
231
|
-
const emit = stepRecordEmitter((r) => emitted.push(r));
|
|
232
|
-
|
|
233
|
-
emit(extractIndexedStepRecords(config, { events: [] }));
|
|
234
|
-
expect(emitted).toEqual([]);
|
|
235
|
-
emit(extractIndexedStepRecords(config, history, { final: true }));
|
|
236
|
-
expect(emitted).toEqual([MAIN, NEVER, COMP]);
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
describe("countActivities", () => {
|
|
241
|
-
test("counts scheduled and completed events", () => {
|
|
242
|
-
const history: WorkflowHistoryRaw = {
|
|
243
|
-
events: [scheduled("1", "a", sec(0)), scheduled("2", "b", sec(0)), completed("1", sec(1))],
|
|
244
|
-
};
|
|
245
|
-
expect(countActivities(history)).toEqual({ completed: 1, scheduled: 2 });
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
test("empty history", () => {
|
|
249
|
-
expect(countActivities({})).toEqual({ completed: 0, scheduled: 0 });
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
describe("queryGateState", () => {
|
|
254
|
-
test("returns the query result when the handle supports it", async () => {
|
|
255
|
-
const handle = { query: async () => ({ signalName: "g", since: "t" }) } as unknown as Parameters<typeof queryGateState>[0];
|
|
256
|
-
expect(await queryGateState(handle)).toEqual({ signalName: "g", since: "t" });
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
test("returns null when the workflow reports no pending gate", async () => {
|
|
260
|
-
const handle = { query: async () => null } as unknown as Parameters<typeof queryGateState>[0];
|
|
261
|
-
expect(await queryGateState(handle)).toBeNull();
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
test("returns undefined (not an error) when the query isn't registered — e.g. an Op with no gates", async () => {
|
|
265
|
-
const handle = { query: async () => { throw new Error("unregistered query"); } } as unknown as Parameters<typeof queryGateState>[0];
|
|
266
|
-
expect(await queryGateState(handle)).toBeUndefined();
|
|
267
|
-
});
|
|
268
|
-
});
|
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Per-phase progress reconstructed from a Temporal Op workflow's history
|
|
3
|
-
* (chant #1676) — the durable-path counterpart to the local executor's
|
|
4
|
-
* `StepRecord[]` (op/local-executor.ts), so `chant run <name> --temporal
|
|
5
|
-
* --progress-json` and `op-status` can report the same shape `chant run
|
|
6
|
-
* <name> --json` already does for the local path, instead of the two raw
|
|
7
|
-
* `ActivityTaskScheduled`/`ActivityTaskCompleted` counts.
|
|
8
|
-
*
|
|
9
|
-
* A step is joined to its declared (phase, fn) by position, not by name: the
|
|
10
|
-
* declared step list (`declaredStepOrder`, mirroring the serializer's own
|
|
11
|
-
* `collectActivitySteps` traversal — main phases, then `onFailure` phases
|
|
12
|
-
* *reversed*, matching how the generated workflow actually runs them) is
|
|
13
|
-
* walked in order, and each step consumes the next not-yet-consumed
|
|
14
|
-
* `ActivityTaskScheduled` event whose activity type matches its `fn` — a
|
|
15
|
-
* per-fn FIFO queue, not a global "does this name appear anywhere" scan.
|
|
16
|
-
* Two steps calling the same activity therefore each get their own
|
|
17
|
-
* scheduled event instead of the later one overwriting the earlier
|
|
18
|
-
* (the collision the prior `run-report.ts` join had). A step whose queue is
|
|
19
|
-
* empty never ran this execution — an untaken effect branch, or an
|
|
20
|
-
* `onFailure` phase on a run that succeeded.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import type { OpConfig, PhaseDefinition } from "../../op/types";
|
|
24
|
-
import type { StepRecord } from "../../op/local-executor";
|
|
25
|
-
import type { WorkflowHistoryRaw, HistoryEvent, WorkflowHandleRaw } from "./run-client";
|
|
26
|
-
|
|
27
|
-
// Synthesized step names an effect step's read-compare-run-write compiles
|
|
28
|
-
// to (lexicons/temporal/src/op/serializer.ts's RECEIPT_READ_STEP/
|
|
29
|
-
// RECEIPT_WRITE_STEP) — duplicated here rather than imported so this module
|
|
30
|
-
// stays lexicon-free, same constraint as op/local-executor.ts.
|
|
31
|
-
const RECEIPT_READ_FN = "receiptRead";
|
|
32
|
-
const RECEIPT_WRITE_FN = "receiptWrite";
|
|
33
|
-
|
|
34
|
-
interface DeclaredStep {
|
|
35
|
-
phase: string;
|
|
36
|
-
fn: string;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function flattenPhases(phases: PhaseDefinition[]): DeclaredStep[] {
|
|
40
|
-
const out: DeclaredStep[] = [];
|
|
41
|
-
for (const phase of phases) {
|
|
42
|
-
for (const step of phase.steps) {
|
|
43
|
-
if (step.kind === "activity") {
|
|
44
|
-
out.push({ phase: phase.name, fn: step.fn });
|
|
45
|
-
} else if (step.kind === "effect") {
|
|
46
|
-
out.push({ phase: phase.name, fn: RECEIPT_READ_FN });
|
|
47
|
-
for (const nested of step.steps) {
|
|
48
|
-
if (nested.kind === "activity") out.push({ phase: phase.name, fn: nested.fn });
|
|
49
|
-
}
|
|
50
|
-
out.push({ phase: phase.name, fn: RECEIPT_WRITE_FN });
|
|
51
|
-
}
|
|
52
|
-
// Gate steps schedule no activity — nothing to join them to.
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return out;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/** Declared order matching actual scheduling order: main phases, then `onFailure` reversed (compensation runs last-declared-first — serializer.ts's `renderPhases([...config.onFailure].reverse())`). */
|
|
59
|
-
function declaredStepOrder(config: OpConfig): DeclaredStep[] {
|
|
60
|
-
return [...flattenPhases(config.phases), ...flattenPhases([...(config.onFailure ?? [])].reverse())];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
interface ScheduledEntry {
|
|
64
|
-
scheduledEventId: string;
|
|
65
|
-
scheduledAt?: Date;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** Every `ActivityTaskScheduled` event, grouped by activity type name, in chronological order. */
|
|
69
|
-
function scheduledQueues(events: HistoryEvent[]): Map<string, ScheduledEntry[]> {
|
|
70
|
-
const byFn = new Map<string, ScheduledEntry[]>();
|
|
71
|
-
for (const e of events) {
|
|
72
|
-
if (e.eventType !== "ActivityTaskScheduled") continue;
|
|
73
|
-
const attrs = e.activityTaskScheduledEventAttributes;
|
|
74
|
-
if (!attrs) continue;
|
|
75
|
-
const fn = attrs.activityType?.name ?? "unknown";
|
|
76
|
-
if (!byFn.has(fn)) byFn.set(fn, []);
|
|
77
|
-
byFn.get(fn)!.push({ scheduledEventId: e.eventId ?? "", scheduledAt: e.eventTime });
|
|
78
|
-
}
|
|
79
|
-
return byFn;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
interface TerminalOutcome {
|
|
83
|
-
status: "ok" | "fail";
|
|
84
|
-
at?: Date;
|
|
85
|
-
error?: string;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* The terminal outcome of each scheduled activity, keyed by the scheduling
|
|
90
|
-
* event's own id. A retried activity emits one `ActivityTaskFailed` per
|
|
91
|
-
* attempt under the same `scheduledEventId`; walking events in order and
|
|
92
|
-
* always overwriting on a later event leaves whichever came last —
|
|
93
|
-
* `ActivityTaskCompleted` on an eventual success, otherwise the final
|
|
94
|
-
* attempt's failure.
|
|
95
|
-
*/
|
|
96
|
-
function terminalOutcomes(events: HistoryEvent[]): Map<string, TerminalOutcome> {
|
|
97
|
-
const out = new Map<string, TerminalOutcome>();
|
|
98
|
-
for (const e of events) {
|
|
99
|
-
if (e.eventType === "ActivityTaskCompleted" && e.activityTaskCompletedEventAttributes) {
|
|
100
|
-
const id = e.activityTaskCompletedEventAttributes.scheduledEventId;
|
|
101
|
-
if (id) out.set(id, { status: "ok", at: e.eventTime });
|
|
102
|
-
} else if (e.eventType === "ActivityTaskFailed" && e.activityTaskFailedEventAttributes) {
|
|
103
|
-
const id = e.activityTaskFailedEventAttributes.scheduledEventId;
|
|
104
|
-
if (id) {
|
|
105
|
-
out.set(id, {
|
|
106
|
-
status: "fail",
|
|
107
|
-
at: e.eventTime,
|
|
108
|
-
error: e.activityTaskFailedEventAttributes.failure?.message ?? "unknown error",
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return out;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* A step record paired with the position of the declared step it came from.
|
|
118
|
-
*
|
|
119
|
-
* `index` is an offset into `declaredStepOrder(config)`, which depends only
|
|
120
|
-
* on the Op config — not on the history — so it is the record's identity
|
|
121
|
-
* and is stable across polls. The record *list* is not: a mid-run poll omits
|
|
122
|
-
* every step that hasn't settled yet, and the terminal `final: true` pass
|
|
123
|
-
* inserts a `"skipped"` record at each such step's declared position, which
|
|
124
|
-
* shifts every later record's list offset (chant #2032). Anything tracking
|
|
125
|
-
* what it has already seen must key on `index`, never on how many records
|
|
126
|
-
* the previous call returned.
|
|
127
|
-
*/
|
|
128
|
-
export interface IndexedStepRecord {
|
|
129
|
-
index: number;
|
|
130
|
-
record: StepRecord;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Reconstruct per-step progress records from a workflow's history, in
|
|
135
|
-
* declared order, each tagged with its declared-step `index`. Only settled
|
|
136
|
-
* steps (matched to a scheduled event that has since completed or failed)
|
|
137
|
-
* produce a record — a step that hasn't been scheduled yet simply isn't in
|
|
138
|
-
* the result. Pass `final: true` once the workflow has reached a terminal
|
|
139
|
-
* status to also emit a `"skipped"` record for every declared step that
|
|
140
|
-
* never got a matching scheduled event (an untaken effect branch, or an
|
|
141
|
-
* `onFailure` phase on a run that succeeded) — never before, or a
|
|
142
|
-
* still-running Op would show its not-yet-reached steps as skipped.
|
|
143
|
-
*/
|
|
144
|
-
export function extractIndexedStepRecords(
|
|
145
|
-
config: OpConfig,
|
|
146
|
-
history: WorkflowHistoryRaw,
|
|
147
|
-
opts: { final?: boolean } = {},
|
|
148
|
-
): IndexedStepRecord[] {
|
|
149
|
-
const events = history.events ?? [];
|
|
150
|
-
const queues = scheduledQueues(events);
|
|
151
|
-
const terminals = terminalOutcomes(events);
|
|
152
|
-
const nextIndex = new Map<string, number>();
|
|
153
|
-
|
|
154
|
-
const records: IndexedStepRecord[] = [];
|
|
155
|
-
const declared = declaredStepOrder(config);
|
|
156
|
-
for (let index = 0; index < declared.length; index++) {
|
|
157
|
-
const step = declared[index];
|
|
158
|
-
const queue = queues.get(step.fn);
|
|
159
|
-
const idx = nextIndex.get(step.fn) ?? 0;
|
|
160
|
-
const entry = queue?.[idx];
|
|
161
|
-
if (!entry) {
|
|
162
|
-
if (opts.final) {
|
|
163
|
-
records.push({ index, record: { phase: step.phase, fn: step.fn, status: "skipped", durationMs: 0 } });
|
|
164
|
-
}
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
|
-
nextIndex.set(step.fn, idx + 1);
|
|
168
|
-
|
|
169
|
-
const terminal = terminals.get(entry.scheduledEventId);
|
|
170
|
-
if (!terminal) continue; // scheduled but not yet settled
|
|
171
|
-
|
|
172
|
-
const durationMs =
|
|
173
|
-
entry.scheduledAt && terminal.at ? terminal.at.getTime() - entry.scheduledAt.getTime() : 0;
|
|
174
|
-
records.push({
|
|
175
|
-
index,
|
|
176
|
-
record: {
|
|
177
|
-
phase: step.phase,
|
|
178
|
-
fn: step.fn,
|
|
179
|
-
status: terminal.status,
|
|
180
|
-
durationMs,
|
|
181
|
-
...(terminal.error ? { error: terminal.error } : {}),
|
|
182
|
-
},
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
return records;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/** `extractIndexedStepRecords` without the indices — the plain declared-order record list. */
|
|
189
|
-
export function extractStepRecords(
|
|
190
|
-
config: OpConfig,
|
|
191
|
-
history: WorkflowHistoryRaw,
|
|
192
|
-
opts: { final?: boolean } = {},
|
|
193
|
-
): StepRecord[] {
|
|
194
|
-
return extractIndexedStepRecords(config, history, opts).map((r) => r.record);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* A sink that forwards each declared step's record exactly once, however many
|
|
199
|
-
* times the poll loop re-derives the list.
|
|
200
|
-
*
|
|
201
|
-
* `--progress-json` calls this per poll with the whole list so far, plus once
|
|
202
|
-
* more with the terminal `final: true` list. Deduplicating by declared-step
|
|
203
|
-
* `index` is what makes that safe: an emitted-count watermark assumed the list
|
|
204
|
-
* was append-only, and the `final` pass's inserted `"skipped"` records break
|
|
205
|
-
* that assumption — with an unreached phase declared before an `onFailure`
|
|
206
|
-
* phase that ran, the insertion shifted the tail, so the last record shipped
|
|
207
|
-
* twice and the skipped one never shipped at all (chant #2032).
|
|
208
|
-
*/
|
|
209
|
-
export function stepRecordEmitter(emit: (record: StepRecord) => void): (records: IndexedStepRecord[]) => void {
|
|
210
|
-
const seen = new Set<number>();
|
|
211
|
-
return (records) => {
|
|
212
|
-
for (const { index, record } of records) {
|
|
213
|
-
if (seen.has(index)) continue;
|
|
214
|
-
seen.add(index);
|
|
215
|
-
emit(record);
|
|
216
|
-
}
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/** `{completed, scheduled}` activity counts for the summary line `chant run status`/`op-status` show alongside the full record list. */
|
|
221
|
-
export function countActivities(history: WorkflowHistoryRaw): { completed: number; scheduled: number } {
|
|
222
|
-
const events = history.events ?? [];
|
|
223
|
-
return {
|
|
224
|
-
completed: events.filter((e) => e.eventType === "ActivityTaskCompleted").length,
|
|
225
|
-
scheduled: events.filter((e) => e.eventType === "ActivityTaskScheduled").length,
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/** The `gateState` workflow query's result (op/serializer.ts's `emitGate`) — the gate currently blocking the workflow, or `null` when none is pending. */
|
|
230
|
-
export interface GateQueryResult {
|
|
231
|
-
signalName: string;
|
|
232
|
-
description?: string;
|
|
233
|
-
since: string;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* Best-effort `gateState` query. `undefined` (as opposed to `null`) means
|
|
238
|
-
* the query itself failed — an Op with no gate steps never registers a
|
|
239
|
-
* `gateState` handler, so querying it is expected to fail, not an error
|
|
240
|
-
* worth surfacing.
|
|
241
|
-
*/
|
|
242
|
-
export async function queryGateState(handle: WorkflowHandleRaw): Promise<GateQueryResult | null | undefined> {
|
|
243
|
-
try {
|
|
244
|
-
return await handle.query<GateQueryResult | null>("gateState");
|
|
245
|
-
} catch {
|
|
246
|
-
return undefined;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect } from "vitest";
|
|
2
|
-
import { fetchNormalizedHistory, type WorkflowHandleRaw } from "./run-client";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* `@temporalio/client`'s `WorkflowHandle.fetchHistory()` returns the raw
|
|
6
|
-
* Temporal wire proto: `eventType` a numeric enum, `eventId`/
|
|
7
|
-
* `scheduledEventId` protobuf `Long` instances, `eventTime` a
|
|
8
|
-
* `{seconds, nanos}` Timestamp. What turns those into the friendly
|
|
9
|
-
* `"EVENT_TYPE_ACTIVITY_TASK_SCHEDULED"` string / decimal strings is the
|
|
10
|
-
* proto message's own `toJSON()` — confirmed against a real
|
|
11
|
-
* `TestWorkflowEnvironment` run (Temporal SDK 1.17.2) during development.
|
|
12
|
-
* These fixtures simulate exactly that: plain values by default, but with a
|
|
13
|
-
* `toJSON()` on the fields that have one on the wire, so a JSON round-trip
|
|
14
|
-
* behaves the same way it does against a real server.
|
|
15
|
-
*/
|
|
16
|
-
function fakeLong(n: number) {
|
|
17
|
-
return { low: n, high: 0, unsigned: false, toJSON: () => String(n) };
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function fakeTimestamp(seconds: number, nanos = 0) {
|
|
21
|
-
return { seconds: fakeLong(seconds), nanos };
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function makeHandle(events: unknown[]): WorkflowHandleRaw {
|
|
25
|
-
return {
|
|
26
|
-
workflowId: "wf",
|
|
27
|
-
async fetchHistory() {
|
|
28
|
-
return { events } as never;
|
|
29
|
-
},
|
|
30
|
-
} as unknown as WorkflowHandleRaw;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
describe("fetchNormalizedHistory", () => {
|
|
34
|
-
test("converts the raw wire shape to short eventType, decimal eventId, and a real Date", async () => {
|
|
35
|
-
const raw = {
|
|
36
|
-
eventId: fakeLong(7),
|
|
37
|
-
eventTime: fakeTimestamp(1_788_000_000, 500_000_000),
|
|
38
|
-
eventType: "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED",
|
|
39
|
-
activityTaskScheduledEventAttributes: {
|
|
40
|
-
activityId: "1",
|
|
41
|
-
activityType: { name: "dup" },
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
const history = await fetchNormalizedHistory(makeHandle([raw]));
|
|
45
|
-
const event = history.events?.[0];
|
|
46
|
-
expect(event?.eventType).toBe("ActivityTaskScheduled");
|
|
47
|
-
expect(event?.eventId).toBe("7");
|
|
48
|
-
expect(event?.eventTime).toBeInstanceOf(Date);
|
|
49
|
-
expect(event?.eventTime?.getTime()).toBe(1_788_000_000_500);
|
|
50
|
-
expect(event?.activityTaskScheduledEventAttributes).toEqual({ activityId: "1", activityType: { name: "dup" } });
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test("ActivityTaskCompleted's scheduledEventId round-trips to a decimal string, joinable against eventId", async () => {
|
|
54
|
-
const scheduled = {
|
|
55
|
-
eventId: fakeLong(7),
|
|
56
|
-
eventType: "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED",
|
|
57
|
-
activityTaskScheduledEventAttributes: { activityId: "1", activityType: { name: "dup" } },
|
|
58
|
-
};
|
|
59
|
-
const completedEvent = {
|
|
60
|
-
eventId: fakeLong(9),
|
|
61
|
-
eventType: "EVENT_TYPE_ACTIVITY_TASK_COMPLETED",
|
|
62
|
-
activityTaskCompletedEventAttributes: { scheduledEventId: fakeLong(7) },
|
|
63
|
-
};
|
|
64
|
-
const history = await fetchNormalizedHistory(makeHandle([scheduled, completedEvent]));
|
|
65
|
-
expect(history.events?.[0].eventId).toBe(history.events?.[1].activityTaskCompletedEventAttributes?.scheduledEventId);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test("a short PascalCase eventType (already-normalized test fixture data) passes through unchanged", async () => {
|
|
69
|
-
const history = await fetchNormalizedHistory(makeHandle([{ eventType: "ActivityTaskScheduled" }]));
|
|
70
|
-
expect(history.events?.[0].eventType).toBe("ActivityTaskScheduled");
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test("an ISO eventTime string (already-normalized data) round-trips to the same instant", async () => {
|
|
74
|
-
const history = await fetchNormalizedHistory(makeHandle([{ eventTime: "2026-05-01T00:00:00.000Z" }]));
|
|
75
|
-
expect(history.events?.[0].eventTime?.toISOString()).toBe("2026-05-01T00:00:00.000Z");
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test("no events → empty array, not an error", async () => {
|
|
79
|
-
const history = await fetchNormalizedHistory(makeHandle([]));
|
|
80
|
-
expect(history.events).toEqual([]);
|
|
81
|
-
});
|
|
82
|
-
});
|