@intentius/chant 0.101.0 → 0.104.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/agents/checks.d.ts.map +1 -1
- package/dist/attrref.d.ts.map +1 -1
- package/dist/audit/core.d.ts +2 -0
- package/dist/audit/core.d.ts.map +1 -1
- package/dist/audit/discover.d.ts.map +1 -1
- package/dist/audit/nginx.d.ts.map +1 -1
- package/dist/audit/prior-art.d.ts +48 -0
- package/dist/audit/prior-art.d.ts.map +1 -1
- package/dist/behaviour-kinds.d.ts.map +1 -1
- package/dist/builder.d.ts.map +1 -1
- package/dist/change-set.d.ts +232 -0
- package/dist/change-set.d.ts.map +1 -0
- package/dist/cli/commands/audit.d.ts +7 -0
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/carve-emit.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon.d.ts +16 -0
- package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/import.d.ts +8 -0
- package/dist/cli/commands/import.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/init.d.ts +19 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/onboard.d.ts +9 -0
- package/dist/cli/commands/onboard.d.ts.map +1 -1
- package/dist/cli/commands/pinned-upgrade.d.ts +19 -5
- package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -1
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/change-set.d.ts +11 -0
- package/dist/cli/handlers/change-set.d.ts.map +1 -0
- package/dist/cli/handlers/dev.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.d.ts +33 -0
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/operator.d.ts +16 -0
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/pr.d.ts +31 -0
- package/dist/cli/handlers/pr.d.ts.map +1 -0
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/lsp/server.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/mcp/op-tools.d.ts.map +1 -1
- package/dist/cli/mcp/server.d.ts.map +1 -1
- package/dist/cli/mcp/tools/build.d.ts.map +1 -1
- package/dist/cli/mcp/tools/composites.d.ts.map +1 -1
- package/dist/cli/mcp/tools/explain.d.ts.map +1 -1
- package/dist/cli/mcp/tools/import.d.ts.map +1 -1
- package/dist/cli/mcp/tools/lint.d.ts.map +1 -1
- package/dist/cli/mcp/tools/scaffold.d.ts.map +1 -1
- package/dist/cli/mcp/tools/search.d.ts.map +1 -1
- package/dist/cli/mcp/workspace-tools.d.ts +4 -3
- package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +74 -3
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/fetch.d.ts.map +1 -1
- package/dist/codegen/naming.d.ts.map +1 -1
- package/dist/codegen/pinned-upgrade.d.ts +67 -3
- package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
- package/dist/codegen/registry.d.ts.map +1 -1
- package/dist/components/auto-release.d.ts +16 -0
- package/dist/components/auto-release.d.ts.map +1 -1
- package/dist/components/capability-plugin-loader.d.ts.map +1 -1
- package/dist/components/capability.d.ts +53 -0
- package/dist/components/capability.d.ts.map +1 -1
- package/dist/components/changed-files.d.ts +31 -0
- package/dist/components/changed-files.d.ts.map +1 -0
- package/dist/components/cli-support.d.ts +9 -1
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/component.d.ts +24 -0
- package/dist/components/component.d.ts.map +1 -1
- package/dist/components/deploy-units.d.ts.map +1 -1
- package/dist/components/driver.d.ts +13 -0
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/fan-out-output.d.ts +6 -0
- package/dist/components/fan-out-output.d.ts.map +1 -1
- package/dist/components/fan-out-record.d.ts +41 -0
- package/dist/components/fan-out-record.d.ts.map +1 -0
- package/dist/components/fan-out-run.d.ts +65 -0
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-support.d.ts +2 -0
- package/dist/components/fan-out-support.d.ts.map +1 -1
- package/dist/components/fan-out.d.ts +6 -0
- package/dist/components/fan-out.d.ts.map +1 -1
- package/dist/components/gated-wave-pipeline.d.ts +50 -0
- package/dist/components/gated-wave-pipeline.d.ts.map +1 -0
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/layers.d.ts +25 -0
- package/dist/components/layers.d.ts.map +1 -0
- package/dist/components/pr-pipeline.d.ts +61 -0
- package/dist/components/pr-pipeline.d.ts.map +1 -0
- package/dist/components/pr-run.d.ts +119 -0
- package/dist/components/pr-run.d.ts.map +1 -0
- package/dist/components/promote.d.ts.map +1 -1
- package/dist/components/starter-plugin.d.ts.map +1 -1
- package/dist/components/verbs/process-runner.d.ts.map +1 -1
- package/dist/components/verbs/r2-sync.d.ts.map +1 -1
- package/dist/components/verbs/run-agent.d.ts.map +1 -1
- package/dist/components/verbs/sbom-generator.d.ts.map +1 -1
- package/dist/components/verbs/shell.d.ts.map +1 -1
- package/dist/components/verbs/sign.d.ts.map +1 -1
- package/dist/components/verbs/verify.d.ts.map +1 -1
- package/dist/components/verbs/vuln-gate.d.ts.map +1 -1
- package/dist/components/verbs/vuln-scan.d.ts.map +1 -1
- package/dist/components/verbs/wrangler.d.ts.map +1 -1
- package/dist/components/wave-plan.d.ts +49 -0
- package/dist/components/wave-plan.d.ts.map +1 -0
- package/dist/composite.d.ts.map +1 -1
- package/dist/config.d.ts +19 -7
- package/dist/config.d.ts.map +1 -1
- package/dist/declarable.d.ts +16 -0
- package/dist/declarable.d.ts.map +1 -1
- package/dist/discovery/cache.d.ts.map +1 -1
- package/dist/discovery/fold-import.d.ts +15 -5
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/param-deps.d.ts +16 -0
- package/dist/discovery/param-deps.d.ts.map +1 -1
- package/dist/discovery/sandbox/policy-wire.d.ts.map +1 -1
- package/dist/discovery/specifier-resolve.d.ts +37 -0
- package/dist/discovery/specifier-resolve.d.ts.map +1 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/fold/fold.d.ts +3 -1
- package/dist/fold/fold.d.ts.map +1 -1
- package/dist/gated-waves.d.ts +147 -0
- package/dist/gated-waves.d.ts.map +1 -0
- package/dist/graph-detail.d.ts.map +1 -1
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-layout.d.ts.map +1 -1
- package/dist/import/base-parser.d.ts.map +1 -1
- package/dist/import/embedded.d.ts +7 -0
- package/dist/import/embedded.d.ts.map +1 -1
- package/dist/import/parser-options.d.ts +14 -0
- package/dist/import/parser-options.d.ts.map +1 -0
- package/dist/import/parser.d.ts +17 -0
- package/dist/import/parser.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/kubectl-context.d.ts.map +1 -1
- package/dist/lexicon-output.d.ts.map +1 -1
- package/dist/lexicon-schema.d.ts +3 -3
- package/dist/lexicon.d.ts +103 -3
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/assert-live.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +22 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/git.d.ts +46 -1
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/member-ledger.d.ts.map +1 -1
- package/dist/lifecycle/observe.d.ts.map +1 -1
- package/dist/lifecycle/plan-ledger.d.ts.map +1 -1
- package/dist/lifecycle/release-ledger.d.ts.map +1 -1
- package/dist/lifecycle/scenario.d.ts.map +1 -1
- package/dist/lifecycle/status.d.ts.map +1 -1
- package/dist/lifecycle/work-lease.d.ts +61 -2
- package/dist/lifecycle/work-lease.d.ts.map +1 -1
- package/dist/lint/config.d.ts +8 -8
- package/dist/lint/engine.d.ts +6 -0
- package/dist/lint/engine.d.ts.map +1 -1
- package/dist/lint/post-synth.d.ts +18 -0
- package/dist/lint/post-synth.d.ts.map +1 -1
- package/dist/lsp/lexicon-providers.d.ts.map +1 -1
- package/dist/op/activities/activity-contracts.d.ts +137 -11
- package/dist/op/activities/activity-contracts.d.ts.map +1 -1
- package/dist/op/activities/apply.d.ts +79 -9
- package/dist/op/activities/apply.d.ts.map +1 -1
- package/dist/op/activities/change-set.d.ts +62 -0
- package/dist/op/activities/change-set.d.ts.map +1 -0
- package/dist/op/activities/decide.d.ts +2 -0
- package/dist/op/activities/decide.d.ts.map +1 -1
- package/dist/op/activities/factory.d.ts +137 -0
- package/dist/op/activities/factory.d.ts.map +1 -0
- package/dist/op/activities/index.d.ts +5 -1
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/lexicon-upgrade.d.ts +44 -12
- package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -1
- package/dist/op/activity-contract.d.ts +1 -1
- package/dist/op/activity-contract.d.ts.map +1 -1
- package/dist/op/activity-failure.d.ts.map +1 -1
- package/dist/op/activity-profiles.d.ts.map +1 -1
- package/dist/op/builders.d.ts +11 -0
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/composites/apply-op.d.ts +12 -5
- package/dist/op/composites/apply-op.d.ts.map +1 -1
- package/dist/op/composites/lexicon-upgrade-op.d.ts +22 -6
- package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -1
- package/dist/op/decide-backend.d.ts +5 -1
- package/dist/op/decide-backend.d.ts.map +1 -1
- package/dist/op/decide-read-inputs.d.ts +4 -2
- package/dist/op/decide-read-inputs.d.ts.map +1 -1
- package/dist/op/emulator-lifecycle.d.ts +21 -2
- package/dist/op/emulator-lifecycle.d.ts.map +1 -1
- package/dist/op/factory.d.ts +83 -0
- package/dist/op/factory.d.ts.map +1 -0
- package/dist/op/gate-approval.d.ts +5 -1
- package/dist/op/gate-approval.d.ts.map +1 -1
- package/dist/op/gate-wait.d.ts.map +1 -1
- package/dist/op/gate.d.ts +19 -3
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/index.d.ts +6 -1
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/local-executor.d.ts +6 -0
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/op-ir.d.ts +2 -0
- package/dist/op/op-ir.d.ts.map +1 -1
- package/dist/op/op-verb-class.d.ts.map +1 -1
- package/dist/op/operator.d.ts.map +1 -1
- package/dist/op/run-context.d.ts +39 -0
- package/dist/op/run-context.d.ts.map +1 -0
- package/dist/op/run-live.d.ts.map +1 -1
- package/dist/op/runtimes/local.d.ts.map +1 -1
- package/dist/op/source-archive.d.ts.map +1 -1
- package/dist/op/steward-beside.d.ts.map +1 -1
- package/dist/op/steward-points.d.ts.map +1 -1
- package/dist/op/steward.d.ts.map +1 -1
- package/dist/op/types.d.ts +16 -3
- package/dist/op/types.d.ts.map +1 -1
- package/dist/op/work-lease-run.d.ts +24 -4
- package/dist/op/work-lease-run.d.ts.map +1 -1
- package/dist/plan-summary.d.ts +207 -0
- package/dist/plan-summary.d.ts.map +1 -0
- package/dist/pr-forge.d.ts +105 -0
- package/dist/pr-forge.d.ts.map +1 -0
- package/dist/pr-loop.d.ts +178 -0
- package/dist/pr-loop.d.ts.map +1 -0
- package/dist/project-root.d.ts.map +1 -1
- package/dist/provenance.d.ts +21 -0
- package/dist/provenance.d.ts.map +1 -1
- package/dist/pseudo-parameter.d.ts.map +1 -1
- package/dist/reconcile.d.ts.map +1 -1
- package/dist/secret-materialization.d.ts.map +1 -1
- package/dist/telemetry-attribution.d.ts +31 -0
- package/dist/telemetry-attribution.d.ts.map +1 -1
- package/dist/terraform/emit-source.d.ts.map +1 -1
- package/dist/terraform/hcl2json.d.ts +45 -0
- package/dist/terraform/hcl2json.d.ts.map +1 -0
- package/dist/terraform/parse.d.ts +4 -40
- package/dist/terraform/parse.d.ts.map +1 -1
- package/dist/testing.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/decide-workspace.d.ts +1 -1
- package/dist/workspace/__fixtures__/decide-workspace.d.ts.map +1 -1
- package/dist/workspace/agent-cli.d.ts +5 -0
- package/dist/workspace/agent-cli.d.ts.map +1 -1
- package/dist/workspace/box-cli.d.ts +12 -0
- package/dist/workspace/box-cli.d.ts.map +1 -0
- package/dist/workspace/box-factory.d.ts +97 -0
- package/dist/workspace/box-factory.d.ts.map +1 -0
- package/dist/workspace/box-listing.d.ts +85 -0
- package/dist/workspace/box-listing.d.ts.map +1 -0
- package/dist/workspace/box-publish.d.ts +147 -0
- package/dist/workspace/box-publish.d.ts.map +1 -0
- package/dist/workspace/broker-protocol.d.ts +190 -0
- package/dist/workspace/broker-protocol.d.ts.map +1 -0
- package/dist/workspace/changes.d.ts.map +1 -1
- package/dist/workspace/chant-migrations/chud-lexicon-exit.d.ts.map +1 -1
- package/dist/workspace/checks/boxes.d.ts.map +1 -1
- package/dist/workspace/checks.d.ts +5 -0
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/compose-graph.d.ts +10 -0
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/composites.d.ts +2 -2
- package/dist/workspace/composites.d.ts.map +1 -1
- package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts +17 -0
- package/dist/workspace/conformance/__fixtures__/reference-broker.d.ts.map +1 -0
- package/dist/workspace/conformance/broker.d.ts +202 -0
- package/dist/workspace/conformance/broker.d.ts.map +1 -0
- package/dist/workspace/conformance/index.d.ts +68 -6
- package/dist/workspace/conformance/index.d.ts.map +1 -1
- package/dist/workspace/conformance/vitest.d.ts +19 -3
- package/dist/workspace/conformance/vitest.d.ts.map +1 -1
- package/dist/workspace/conformance/writer.d.ts +462 -0
- package/dist/workspace/conformance/writer.d.ts.map +1 -0
- package/dist/workspace/decide.d.ts +126 -12
- package/dist/workspace/decide.d.ts.map +1 -1
- package/dist/workspace/decision-points.schema.json +11 -4
- package/dist/workspace/declaration.d.ts +156 -4
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.schema.json +383 -5
- package/dist/workspace/environments.d.ts +36 -10
- package/dist/workspace/environments.d.ts.map +1 -1
- package/dist/workspace/factory-rules.d.ts +180 -0
- package/dist/workspace/factory-rules.d.ts.map +1 -0
- package/dist/workspace/generated-files.d.ts.map +1 -1
- package/dist/workspace/graph-cache.d.ts.map +1 -1
- package/dist/workspace/graph-cli.d.ts +2 -0
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/identity.d.ts +111 -0
- package/dist/workspace/identity.d.ts.map +1 -0
- package/dist/workspace/init.d.ts +21 -0
- package/dist/workspace/init.d.ts.map +1 -1
- package/dist/workspace/intent-cli.d.ts +7 -4
- package/dist/workspace/intent-cli.d.ts.map +1 -1
- package/dist/workspace/intent-record.d.ts +36 -2
- package/dist/workspace/intent-record.d.ts.map +1 -1
- package/dist/workspace/intent.d.ts +249 -8
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/json-edit.d.ts +24 -0
- package/dist/workspace/json-edit.d.ts.map +1 -0
- package/dist/workspace/jsonc.d.ts +11 -0
- package/dist/workspace/jsonc.d.ts.map +1 -1
- package/dist/workspace/kinds.d.ts +66 -4
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/lexicon-symbols.d.ts +29 -0
- package/dist/workspace/lexicon-symbols.d.ts.map +1 -0
- package/dist/workspace/lineage-hash-index.d.ts.map +1 -1
- package/dist/workspace/lineage-lock.d.ts +2 -2
- package/dist/workspace/lineage-lock.d.ts.map +1 -1
- package/dist/workspace/lineage-upgrade.d.ts +31 -2
- package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
- package/dist/workspace/links.d.ts.map +1 -1
- package/dist/workspace/point-answer.schema.json +42 -2
- package/dist/workspace/points-cli.d.ts +10 -3
- package/dist/workspace/points-cli.d.ts.map +1 -1
- package/dist/workspace/points.d.ts +66 -5
- package/dist/workspace/points.d.ts.map +1 -1
- package/dist/workspace/principal-classes.d.ts +114 -0
- package/dist/workspace/principal-classes.d.ts.map +1 -0
- package/dist/workspace/reason-codes.d.ts +53 -4
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/record-assets.d.ts.map +1 -1
- package/dist/workspace/record-sessions.d.ts +5 -7
- package/dist/workspace/record-sessions.d.ts.map +1 -1
- package/dist/workspace/records-checkout.d.ts +54 -0
- package/dist/workspace/records-checkout.d.ts.map +1 -0
- package/dist/workspace/records-cli.d.ts +34 -1
- package/dist/workspace/records-cli.d.ts.map +1 -1
- package/dist/workspace/records-close.d.ts +7 -3
- package/dist/workspace/records-close.d.ts.map +1 -1
- package/dist/workspace/records-since.d.ts.map +1 -1
- package/dist/workspace/records-write.d.ts +68 -7
- package/dist/workspace/records-write.d.ts.map +1 -1
- package/dist/workspace/records.d.ts +43 -9
- package/dist/workspace/records.d.ts.map +1 -1
- package/dist/workspace/runs-cli.d.ts +296 -0
- package/dist/workspace/runs-cli.d.ts.map +1 -0
- package/dist/workspace/runs.d.ts +544 -0
- package/dist/workspace/runs.d.ts.map +1 -0
- package/dist/workspace/session-kinds.d.ts +1 -1
- package/dist/workspace/session-kinds.d.ts.map +1 -1
- package/dist/workspace/source-block.d.ts +1 -1
- package/dist/workspace/source-block.d.ts.map +1 -1
- package/dist/workspace/squash.d.ts +80 -0
- package/dist/workspace/squash.d.ts.map +1 -0
- package/dist/workspace/status-gates.d.ts +17 -3
- package/dist/workspace/status-gates.d.ts.map +1 -1
- package/dist/workspace/status.d.ts +64 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/symbols.d.ts +63 -0
- package/dist/workspace/symbols.d.ts.map +1 -0
- package/dist/workspace/trailer-joins.d.ts +46 -0
- package/dist/workspace/trailer-joins.d.ts.map +1 -0
- package/dist/workspace/trailers.d.ts +89 -0
- package/dist/workspace/trailers.d.ts.map +1 -0
- package/dist/workspace/trust/attestor.d.ts.map +1 -1
- package/dist/workspace/trust/rotation.d.ts.map +1 -1
- package/dist/workspace/trust/run-commits.d.ts +46 -0
- package/dist/workspace/trust/run-commits.d.ts.map +1 -0
- package/dist/workspace/trust/run-statement.d.ts +128 -0
- package/dist/workspace/trust/run-statement.d.ts.map +1 -0
- package/dist/workspace/trust/seal.d.ts +38 -0
- package/dist/workspace/trust/seal.d.ts.map +1 -1
- package/dist/workspace/trust/test-repo.d.ts.map +1 -1
- package/dist/workspace/trust/verify-cli.d.ts +1 -1
- package/dist/workspace/trust/verify.d.ts +16 -2
- package/dist/workspace/trust/verify.d.ts.map +1 -1
- package/dist/workspace/wip-cli.d.ts +21 -0
- package/dist/workspace/wip-cli.d.ts.map +1 -0
- package/dist/workspace/wip.d.ts +268 -0
- package/dist/workspace/wip.d.ts.map +1 -0
- package/dist/workspace/work-cli.d.ts +39 -3
- package/dist/workspace/work-cli.d.ts.map +1 -1
- package/dist/workspace/work-evidence.d.ts +1 -1
- package/dist/workspace/work-evidence.d.ts.map +1 -1
- package/dist/workspace/work-size.d.ts +55 -0
- package/dist/workspace/work-size.d.ts.map +1 -0
- package/dist/workspace/work.d.ts +26 -1
- package/dist/workspace/work.d.ts.map +1 -1
- package/dist/workspace/workspace-kinds.schema.json +122 -0
- package/dist/workspace/workspace-principals.schema.json +60 -0
- package/dist/workspace/write-lock-cli.d.ts +60 -0
- package/dist/workspace/write-lock-cli.d.ts.map +1 -0
- package/dist/workspace/write-lock.d.ts +152 -0
- package/dist/workspace/write-lock.d.ts.map +1 -0
- package/dist/workspace/write-scope.d.ts +83 -19
- package/dist/workspace/write-scope.d.ts.map +1 -1
- package/dist/yaml.d.ts +21 -39
- package/dist/yaml.d.ts.map +1 -1
- package/package.json +7 -2
- package/src/__fixtures__/change-set/lifecycle-plan.floci.json +59 -0
- package/src/__fixtures__/change-set/lifecycle-v1.ts.txt +4 -0
- package/src/__fixtures__/change-set/lifecycle-v2.ts.txt +4 -0
- package/src/__fixtures__/change-set/lifecycle.change-set.golden.json +95 -0
- package/src/__fixtures__/change-set/warden.change-set.golden.json +106 -0
- package/src/__fixtures__/change-set/warden.plan.json +44 -0
- package/src/__fixtures__/plan-summary/normalization-vectors.json +1593 -0
- package/src/__fixtures__/pr-loop/pr-apply-applied.note.golden.md +31 -0
- package/src/__fixtures__/pr-loop/pr-apply-refused.note.golden.md +31 -0
- package/src/__fixtures__/pr-loop/pr-plan.golden.json +127 -0
- package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +37 -0
- package/src/audit/core.test.ts +15 -0
- package/src/audit/core.ts +8 -2
- package/src/audit/discover.test.ts +11 -0
- package/src/audit/discover.ts +7 -2
- package/src/audit/prior-art.ts +15 -0
- package/src/change-set-bundle.test.ts +57 -0
- package/src/change-set.test.ts +215 -0
- package/src/change-set.ts +445 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +1 -1
- package/src/cli/commands/audit-opt-in.test.ts +54 -0
- package/src/cli/commands/audit.ts +29 -2
- package/src/cli/commands/build.test.ts +19 -0
- package/src/cli/commands/build.ts +3 -2
- package/src/cli/commands/carve-emit-state.test.ts +4 -0
- package/src/cli/commands/carve-emit.ts +5 -19
- package/src/cli/commands/check-lexicon.test.ts +62 -1
- package/src/cli/commands/check-lexicon.ts +36 -6
- package/src/cli/commands/import-live.test.ts +18 -0
- package/src/cli/commands/import-parser-options.test.ts +133 -0
- package/src/cli/commands/import.ts +21 -3
- package/src/cli/commands/init-lexicon/templates/project.ts +1 -1
- package/src/cli/commands/init.test.ts +8 -1
- package/src/cli/commands/init.ts +23 -8
- package/src/cli/commands/lint.test.ts +37 -0
- package/src/cli/commands/onboard.test.ts +53 -3
- package/src/cli/commands/onboard.ts +52 -4
- package/src/cli/commands/pinned-upgrade.ts +73 -33
- package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +2 -2
- package/src/cli/handlers/build.ts +13 -1
- package/src/cli/handlers/change-set.test.ts +56 -0
- package/src/cli/handlers/change-set.ts +44 -0
- package/src/cli/handlers/components.ts +2 -2
- package/src/cli/handlers/dev.ts +8 -6
- package/src/cli/handlers/fan-out.test.ts +221 -2
- package/src/cli/handlers/fan-out.ts +165 -75
- package/src/cli/handlers/graph.ts +3 -0
- package/src/cli/handlers/lifecycle.test.ts +67 -0
- package/src/cli/handlers/lifecycle.ts +6 -5
- package/src/cli/handlers/misc.ts +2 -0
- package/src/cli/handlers/operator.test.ts +21 -0
- package/src/cli/handlers/operator.ts +121 -6
- package/src/cli/handlers/pr.ts +373 -0
- package/src/cli/handlers/run.test.ts +111 -0
- package/src/cli/handlers/run.ts +86 -24
- package/src/cli/handlers/scenario.ts +2 -2
- package/src/cli/main.test.ts +21 -0
- package/src/cli/main.ts +246 -30
- package/src/cli/mcp/never-over-mcp.test.ts +101 -0
- package/src/cli/mcp/op-tools.ts +24 -2
- package/src/cli/mcp/workspace-tools.test.ts +5 -2
- package/src/cli/mcp/workspace-tools.ts +62 -7
- package/src/cli/registry.ts +74 -3
- package/src/codegen/pinned-upgrade-multi.test.ts +157 -0
- package/src/codegen/pinned-upgrade-tags.test.ts +112 -0
- package/src/codegen/pinned-upgrade.test.ts +104 -0
- package/src/codegen/pinned-upgrade.ts +250 -56
- package/src/codegen/testdata/postgres-tags.json +242 -0
- package/src/components/auto-release.ts +1 -1
- package/src/components/capability.ts +55 -0
- package/src/components/changed-files.ts +66 -0
- package/src/components/cli-support.ts +28 -5
- package/src/components/component.schema.json +17 -0
- package/src/components/component.ts +25 -0
- package/src/components/deploy-units.ts +3 -0
- package/src/components/driver.test.ts +52 -0
- package/src/components/driver.ts +31 -13
- package/src/components/fan-out-output.ts +42 -1
- package/src/components/fan-out-record.ts +69 -0
- package/src/components/fan-out-run.test.ts +17 -0
- package/src/components/fan-out-run.ts +304 -1
- package/src/components/fan-out-support.ts +3 -0
- package/src/components/fan-out-waves.test.ts +375 -0
- package/src/components/fan-out.ts +18 -17
- package/src/components/gated-wave-pipeline.ts +82 -0
- package/src/components/index.ts +1 -0
- package/src/components/layers.ts +30 -0
- package/src/components/pr-pipeline.ts +91 -0
- package/src/components/pr-run.test.ts +205 -0
- package/src/components/pr-run.ts +280 -0
- package/src/components/promote.ts +5 -0
- package/src/components/verbs/shell.test.ts +11 -0
- package/src/components/verbs/shell.ts +7 -3
- package/src/components/wave-plan.ts +124 -0
- package/src/config.test.ts +21 -0
- package/src/config.ts +15 -0
- package/src/declarable.test.ts +21 -0
- package/src/declarable.ts +19 -0
- package/src/discovery/fold-composite.test.ts +41 -5
- package/src/discovery/fold-import.test.ts +129 -0
- package/src/discovery/fold-import.ts +643 -131
- package/src/discovery/fold-package-composite.test.ts +264 -0
- package/src/discovery/fold-specifiers.test.ts +191 -0
- package/src/discovery/param-deps.test.ts +66 -1
- package/src/discovery/param-deps.ts +45 -0
- package/src/discovery/sandbox/bundle.ts +1 -1
- package/src/discovery/specifier-resolve.ts +344 -0
- package/src/fold/fold.test.ts +39 -1
- package/src/fold/fold.ts +83 -9
- package/src/fold-provenance.test.ts +140 -0
- package/src/gated-waves-bundle.test.ts +62 -0
- package/src/gated-waves.test.ts +118 -0
- package/src/gated-waves.ts +240 -0
- package/src/graph-ir.test.ts +83 -0
- package/src/graph-ir.ts +29 -0
- package/src/import/embedded.test.ts +20 -0
- package/src/import/embedded.ts +13 -0
- package/src/import/parser-options.ts +46 -0
- package/src/import/parser.ts +20 -0
- package/src/index.ts +1 -0
- package/src/lexicon.ts +106 -3
- package/src/lifecycle/gate-ledger.ts +23 -0
- package/src/lifecycle/git.ts +102 -16
- package/src/lifecycle/observe.test.ts +18 -0
- package/src/lifecycle/observe.ts +6 -4
- package/src/lifecycle/snapshot.ts +2 -2
- package/src/lifecycle/work-lease.test.ts +1 -1
- package/src/lifecycle/work-lease.ts +93 -2
- package/src/lint/engine.test.ts +55 -0
- package/src/lint/engine.ts +30 -4
- package/src/lint/output-docs.test.ts +59 -56
- package/src/lint/post-synth.test.ts +19 -0
- package/src/lint/post-synth.ts +19 -1
- package/src/meta/declared-imports.test.ts +1 -1
- package/src/op/activities/activity-contracts.ts +84 -0
- package/src/op/activities/apply.test.ts +189 -5
- package/src/op/activities/apply.ts +230 -8
- package/src/op/activities/change-set.ts +114 -0
- package/src/op/activities/decide.ts +3 -0
- package/src/op/activities/factory.ts +675 -0
- package/src/op/activities/index.ts +9 -0
- package/src/op/activities/lexicon-upgrade.test.ts +160 -6
- package/src/op/activities/lexicon-upgrade.ts +154 -51
- package/src/op/activity-contract.test.ts +21 -1
- package/src/op/activity-contract.ts +19 -9
- package/src/op/builders.ts +23 -0
- package/src/op/composites/apply-op.ts +12 -5
- package/src/op/composites/composites.test.ts +30 -3
- package/src/op/composites/lexicon-upgrade-op.test.ts +7 -2
- package/src/op/composites/lexicon-upgrade-op.ts +29 -8
- package/src/op/decide-backend.ts +5 -1
- package/src/op/decide-read-inputs.ts +33 -5
- package/src/op/emulator-lifecycle.test.ts +23 -0
- package/src/op/emulator-lifecycle.ts +52 -14
- package/src/op/factory.e2e.test.ts +232 -0
- package/src/op/factory.ts +118 -0
- package/src/op/gate-approval.test.ts +74 -0
- package/src/op/gate-approval.ts +5 -1
- package/src/op/gate.ts +31 -5
- package/src/op/index.ts +11 -1
- package/src/op/local-executor.test.ts +15 -0
- package/src/op/local-executor.ts +40 -12
- package/src/op/local-output.ts +1 -1
- package/src/op/op-ir.test.ts +9 -0
- package/src/op/op-ir.ts +4 -0
- package/src/op/op-verb-class.ts +3 -0
- package/src/op/operator.ts +4 -0
- package/src/op/run-context.test.ts +141 -0
- package/src/op/run-context.ts +51 -0
- package/src/op/runtimes/local.test.ts +14 -0
- package/src/op/runtimes/local.ts +2 -0
- package/src/op/steward-beside.ts +2 -0
- package/src/op/types.ts +16 -3
- package/src/op/work-lease-run.test.ts +47 -0
- package/src/op/work-lease-run.ts +76 -11
- package/src/plan-summary.test.ts +263 -0
- package/src/plan-summary.ts +845 -0
- package/src/pr-forge.test.ts +237 -0
- package/src/pr-forge.ts +332 -0
- package/src/pr-loop-bundle.test.ts +46 -0
- package/src/pr-loop.test.ts +171 -0
- package/src/pr-loop.ts +324 -0
- package/src/provenance.ts +35 -0
- package/src/telemetry-attribution.test.ts +23 -1
- package/src/telemetry-attribution.ts +51 -0
- package/src/terraform/hcl2json.test.ts +21 -0
- package/src/terraform/hcl2json.ts +81 -0
- package/src/terraform/parse.ts +11 -74
- package/src/workspace/agent-cli.ts +7 -3
- package/src/workspace/agent.schema.json +22 -0
- package/src/workspace/app-kind.test.ts +196 -0
- package/src/workspace/box-cli.ts +113 -0
- package/src/workspace/box-factory.test.ts +323 -0
- package/src/workspace/box-factory.ts +136 -0
- package/src/workspace/box-listing-write.schema.json +204 -0
- package/src/workspace/box-listing.test.ts +234 -0
- package/src/workspace/box-listing.ts +324 -0
- package/src/workspace/box-publish.schema.json +498 -0
- package/src/workspace/box-publish.test.ts +204 -0
- package/src/workspace/box-publish.ts +420 -0
- package/src/workspace/box-ship.test.ts +96 -0
- package/src/workspace/broker-protocol.schema.json +186 -0
- package/src/workspace/broker-protocol.test.ts +122 -0
- package/src/workspace/broker-protocol.ts +317 -0
- package/src/workspace/builder-tiers.test.ts +146 -0
- package/src/workspace/change-set.schema.json +460 -0
- package/src/workspace/changes.schema.json +12 -20
- package/src/workspace/changes.ts +4 -1
- package/src/workspace/chant-migrations.e2e.test.ts +17 -5
- package/src/workspace/checks/boxes.test.ts +5 -0
- package/src/workspace/checks.ts +39 -8
- package/src/workspace/component-environments.test.ts +105 -0
- package/src/workspace/compose-graph.ts +7 -0
- package/src/workspace/composites.schema.json +23 -4
- package/src/workspace/composites.test.ts +8 -8
- package/src/workspace/composites.ts +13 -2
- package/src/workspace/conformance/__fixture__/decisions/decision.schema.json +2 -2
- package/src/workspace/conformance/__fixtures__/reference-broker.ts +207 -0
- package/src/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +32 -0
- package/src/workspace/conformance/__writer_fixture__/answers/answer.schema.json +135 -0
- package/src/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
- package/src/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
- package/src/workspace/conformance/__writer_fixture__/decisions/points.json +228 -0
- package/src/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
- package/src/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
- package/src/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +54 -0
- package/src/workspace/conformance/__writer_fixture__/sessions/session.schema.json +289 -0
- package/src/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
- package/src/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
- package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +603 -0
- package/src/workspace/conformance/broker.test.ts +122 -0
- package/src/workspace/conformance/broker.ts +792 -0
- package/src/workspace/conformance/conformance.e2e.test.ts +36 -3
- package/src/workspace/conformance/index.mjs +51 -3
- package/src/workspace/conformance/index.ts +107 -15
- package/src/workspace/conformance/vitest.ts +76 -2
- package/src/workspace/conformance/writer-conformance.e2e.test.ts +177 -0
- package/src/workspace/conformance/writer.test.ts +186 -0
- package/src/workspace/conformance/writer.ts +1191 -0
- package/src/workspace/decide.test.ts +208 -4
- package/src/workspace/decide.ts +433 -73
- package/src/workspace/decision-points.schema.json +11 -4
- package/src/workspace/declaration.schema.json +383 -5
- package/src/workspace/declaration.ts +315 -10
- package/src/workspace/environments.ts +66 -14
- package/src/workspace/factory-rules.test.ts +62 -0
- package/src/workspace/factory-rules.ts +218 -0
- package/src/workspace/graph-cli.ts +6 -3
- package/src/workspace/graph.schema.json +314 -0
- package/src/workspace/identity.test.ts +219 -0
- package/src/workspace/identity.ts +186 -0
- package/src/workspace/init.ts +82 -2
- package/src/workspace/intent-cli.ts +84 -13
- package/src/workspace/intent-patch-id.test.ts +162 -0
- package/src/workspace/intent-record.schema.json +336 -1
- package/src/workspace/intent-record.ts +96 -16
- package/src/workspace/intent-reviews.test.ts +76 -0
- package/src/workspace/intent-squash.test.ts +213 -0
- package/src/workspace/intent-why.test.ts +274 -0
- package/src/workspace/intent.schema.json +950 -9
- package/src/workspace/intent.test.ts +11 -2
- package/src/workspace/intent.ts +722 -65
- package/src/workspace/json-edit.test.ts +121 -0
- package/src/workspace/json-edit.ts +142 -0
- package/src/workspace/jsonc.ts +20 -0
- package/src/workspace/kinds.ts +201 -39
- package/src/workspace/lexicon-symbols.test.ts +148 -0
- package/src/workspace/lexicon-symbols.ts +125 -0
- package/src/workspace/lineage-upgrade.test.ts +63 -0
- package/src/workspace/lineage-upgrade.ts +146 -5
- package/src/workspace/plan-summary.schema.json +155 -0
- package/src/workspace/point-answer.schema.json +42 -2
- package/src/workspace/points-cli.ts +42 -16
- package/src/workspace/points-write.schema.json +163 -4
- package/src/workspace/points.schema.json +157 -2
- package/src/workspace/points.test.ts +13 -1
- package/src/workspace/points.ts +118 -12
- package/src/workspace/pr-report.schema.json +95 -0
- package/src/workspace/principal-classes.test.ts +175 -0
- package/src/workspace/principal-classes.ts +307 -0
- package/src/workspace/profiles.test.ts +159 -0
- package/src/workspace/read-contract.test.ts +2 -2
- package/src/workspace/reason-codes.test.ts +23 -3
- package/src/workspace/reason-codes.ts +61 -4
- package/src/workspace/record-sessions.ts +9 -8
- package/src/workspace/records-amend.schema.json +80 -0
- package/src/workspace/records-checkout.ts +106 -0
- package/src/workspace/records-cli.ts +123 -17
- package/src/workspace/records-close.schema.json +79 -0
- package/src/workspace/records-close.ts +31 -7
- package/src/workspace/records-concurrent.e2e.test.ts +135 -0
- package/src/workspace/records-concurrent.test.ts +145 -0
- package/src/workspace/records-formats.test.ts +46 -10
- package/src/workspace/records-new.schema.json +9 -0
- package/src/workspace/records-review.schema.json +80 -0
- package/src/workspace/records-sessions-write.test.ts +69 -0
- package/src/workspace/records-sessions.test.ts +22 -0
- package/src/workspace/records-uncommitted.test.ts +171 -0
- package/src/workspace/records-write.ts +219 -30
- package/src/workspace/records.schema.json +88 -1
- package/src/workspace/records.ts +76 -8
- package/src/workspace/reference-kinds/app/package.json +10 -0
- package/src/workspace/reference-kinds/app/workspace-kinds.json +45 -0
- package/src/workspace/run-statement.schema.json +622 -0
- package/src/workspace/runs-cli.ts +710 -0
- package/src/workspace/runs-statement.test.ts +239 -0
- package/src/workspace/runs-write.schema.json +994 -0
- package/src/workspace/runs.schema.json +1257 -0
- package/src/workspace/runs.test.ts +281 -0
- package/src/workspace/runs.ts +970 -0
- package/src/workspace/session-kinds.ts +3 -3
- package/src/workspace/squash.ts +198 -0
- package/src/workspace/status-contract.test.ts +10 -2
- package/src/workspace/status-gates.ts +25 -9
- package/src/workspace/status.schema.json +252 -4
- package/src/workspace/status.ts +110 -1
- package/src/workspace/symbols.ts +191 -0
- package/src/workspace/trailer-joins.test.ts +171 -0
- package/src/workspace/trailer-joins.ts +82 -0
- package/src/workspace/trailers.ts +148 -0
- package/src/workspace/trust/run-commits.ts +115 -0
- package/src/workspace/trust/run-statement.ts +226 -0
- package/src/workspace/trust/seal.ts +58 -1
- package/src/workspace/trust/verify-cli.ts +6 -5
- package/src/workspace/trust/verify.ts +39 -6
- package/src/workspace/wip-cli.ts +97 -0
- package/src/workspace/wip-write.schema.json +504 -0
- package/src/workspace/wip.schema.json +334 -0
- package/src/workspace/wip.test.ts +294 -0
- package/src/workspace/wip.ts +753 -0
- package/src/workspace/work-cli.e2e.test.ts +28 -1
- package/src/workspace/work-cli.ts +136 -8
- package/src/workspace/work-evidence.schema.json +5 -0
- package/src/workspace/work-history.schema.json +73 -1
- package/src/workspace/work-history.test.ts +48 -5
- package/src/workspace/work-kind-fields.test.ts +154 -0
- package/src/workspace/work-lease.schema.json +14 -1
- package/src/workspace/work-size.test.ts +77 -0
- package/src/workspace/work-size.ts +93 -0
- package/src/workspace/work.ts +82 -0
- package/src/workspace/workspace-kinds.schema.json +122 -0
- package/src/workspace/workspace-principals.schema.json +60 -0
- package/src/workspace/write-lock-cli.ts +131 -0
- package/src/workspace/write-lock.schema.json +172 -0
- package/src/workspace/write-lock.test.ts +189 -0
- package/src/workspace/write-lock.ts +474 -0
- package/src/workspace/write-scope.test.ts +144 -3
- package/src/workspace/write-scope.ts +192 -45
- package/src/yaml.test.ts +111 -1
- package/src/yaml.ts +141 -549
|
@@ -150,14 +150,22 @@ function isStepOutputRefValue(value: unknown): boolean {
|
|
|
150
150
|
return typeof value === "object" && value !== null && (value as Record<symbol, unknown>)[STEP_OUTPUT_REF_BRAND] === true;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
/**
|
|
154
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Does any prefix of `path` (a zod issue's `.path`) inside `obj` land on a
|
|
155
|
+
* step-output reference? A reference stands in for the whole value at its
|
|
156
|
+
* position, so an issue at or below it describes the placeholder, not the
|
|
157
|
+
* value it resolves to. "Below" matters for a whole-value reference in a
|
|
158
|
+
* record-typed arg (`inputs: step.out.json`, #3299): zod walks the
|
|
159
|
+
* reference's own keys, brand symbol included, and reports issues inside it.
|
|
160
|
+
*/
|
|
161
|
+
function pathCrossesStepOutputRef(obj: unknown, path: ReadonlyArray<PropertyKey>): boolean {
|
|
155
162
|
let current = obj;
|
|
156
163
|
for (const segment of path) {
|
|
157
|
-
if (current === null || typeof current !== "object") return
|
|
164
|
+
if (current === null || typeof current !== "object") return false;
|
|
158
165
|
current = (current as Record<PropertyKey, unknown>)[segment];
|
|
166
|
+
if (isStepOutputRefValue(current)) return true;
|
|
159
167
|
}
|
|
160
|
-
return
|
|
168
|
+
return false;
|
|
161
169
|
}
|
|
162
170
|
|
|
163
171
|
/** Unwrap `ZodOptional`/`ZodNullable`/`ZodDefault` (and similar) down to the schema they wrap. */
|
|
@@ -270,16 +278,18 @@ export function validateActivitySteps(
|
|
|
270
278
|
const parsed = contract.args.safeParse(step.args ?? {});
|
|
271
279
|
if (!parsed.success) {
|
|
272
280
|
for (const issue of parsed.error.issues) {
|
|
273
|
-
// A step-output reference (#1290) sitting at this path
|
|
274
|
-
// placeholder object at build time, not the value it
|
|
275
|
-
// resolve to — so an args-schema
|
|
281
|
+
// A step-output reference (#1290) sitting at this path, or above
|
|
282
|
+
// it, is a placeholder object at build time, not the value it
|
|
283
|
+
// will resolve to — so an args-schema issue there is a false
|
|
276
284
|
// positive; OPS013 (`validateStepOutputRefs`) is what validates
|
|
277
285
|
// a reference, against the *producer's* declared return schema.
|
|
278
286
|
// An unrecognized-key issue's path is the parent object (`[]`
|
|
279
287
|
// for a top-level extra key), which is never itself a reference,
|
|
280
288
|
// so a genuinely misspelled key is still caught either way.
|
|
281
|
-
if (
|
|
282
|
-
|
|
289
|
+
if (pathCrossesStepOutputRef(step.args, issue.path)) continue;
|
|
290
|
+
// String(), not join(): a zod path can hold a symbol key, and
|
|
291
|
+
// join() throws converting one (#3299).
|
|
292
|
+
const path = issue.path.length > 0 ? issue.path.map((segment) => String(segment)).join(".") : "(args)";
|
|
283
293
|
issues.push({ opName: config.name, phase: phase.name, fn: step.fn, message: `args.${path}: ${issue.message}` });
|
|
284
294
|
}
|
|
285
295
|
}
|
package/src/op/builders.ts
CHANGED
|
@@ -18,6 +18,7 @@ import type { PolicyGateArgs } from "./activities/policy";
|
|
|
18
18
|
import type { GuardValidateArgs } from "./activities/guard-validate";
|
|
19
19
|
import type { WorkEvidenceArgs } from "./activities/work-evidence";
|
|
20
20
|
import type { DecideArgs } from "./activities/decide";
|
|
21
|
+
import type { ComposeChangeSetArgs, LifecyclePlanChangeSetArgs, ReadChangeSetPartArgs } from "./activities/change-set";
|
|
21
22
|
import { isValidCronExpression, cronSyntaxMessage } from "./cron";
|
|
22
23
|
|
|
23
24
|
/** An `activity()` result — the plain `ActivityStep` shape plus the `.out` reference sugar (#1290). */
|
|
@@ -398,6 +399,28 @@ export const releasePlan = (args: WithStepRefs<ReleasePlanArgs> & StepOpts): Nam
|
|
|
398
399
|
return activity("releasePlan", rest, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
|
|
399
400
|
};
|
|
400
401
|
|
|
402
|
+
/**
|
|
403
|
+
* Join members' change-set parts into one document (#3181). Its `digest` is
|
|
404
|
+
* what a combined run's gate binds: `gate("approve", { plan:
|
|
405
|
+
* changeSet.out.digest })`. Defaults to the `fastIdempotent` profile.
|
|
406
|
+
*/
|
|
407
|
+
export const composeChangeSet = (args: WithStepRefs<ComposeChangeSetArgs> & StepOpts): NamedActivityStep => {
|
|
408
|
+
const { args: rest, profile, id } = takeProfileAndId(args as Record<string, unknown>);
|
|
409
|
+
return activity("composeChangeSet", rest, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
/** A chant member's change-set part, from `chant lifecycle plan <env> --json` (#3181). Its `part` feeds {@link composeChangeSet}. */
|
|
413
|
+
export const lifecyclePlanChangeSet = (args: WithStepRefs<LifecyclePlanChangeSetArgs> & StepOpts): NamedActivityStep => {
|
|
414
|
+
const { args: rest, profile, id } = takeProfileAndId(args as Record<string, unknown>);
|
|
415
|
+
return activity("lifecyclePlanChangeSet", rest, { profile: profile ?? "longInfra", ...(id ? { id } : {}) });
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
/** A member's change-set part from a plan file a chant or warden run wrote (#3181). Its `part` feeds {@link composeChangeSet}. */
|
|
419
|
+
export const readChangeSetPart = (args: WithStepRefs<ReadChangeSetPartArgs> & StepOpts): NamedActivityStep => {
|
|
420
|
+
const { args: rest, profile, id } = takeProfileAndId(args as Record<string, unknown>);
|
|
421
|
+
return activity("readChangeSetPart", rest, { profile: profile ?? "fastIdempotent", ...(id ? { id } : {}) });
|
|
422
|
+
};
|
|
423
|
+
|
|
401
424
|
/**
|
|
402
425
|
* Record a release in the release ledger with its plan (#2782, ws-055), once:
|
|
403
426
|
* a retry whose release the ledger already names records nothing. Defaults to
|
|
@@ -10,8 +10,11 @@
|
|
|
10
10
|
* the ownership tag on `arm` (chant #1448 — previously `--mode Complete`, which
|
|
11
11
|
* removed resources chant never applied), the ownership label on `gcp`
|
|
12
12
|
* (chant #1449), the metadata marker (machines) and managed app
|
|
13
|
-
* (volumes/ips/certs/secrets) on `fly` (chant #1449),
|
|
14
|
-
* `
|
|
13
|
+
* (volumes/ips/certs/secrets) on `fly` (chant #1449), the ownership labels on
|
|
14
|
+
* `grafana` (chant #3011), the comment marker on `clickhouse` (chant #3208)
|
|
15
|
+
* and `postgres` (chant #3280),
|
|
16
|
+
* and the stack itself on `cloudformation`, which a
|
|
17
|
+
* resource CFN did not create is not in. All of
|
|
15
18
|
* them are owned-only. See {@link DeleteMode}.
|
|
16
19
|
*
|
|
17
20
|
* A gate is a fact, not a wait (#2119): the local executor reads the gate
|
|
@@ -52,14 +55,18 @@ import { defaultOutput, hasNativeRollback, type ApplyTarget, type DeleteMode } f
|
|
|
52
55
|
export interface ApplyOpConfig {
|
|
53
56
|
/** Op name (kebab-case). */
|
|
54
57
|
name: string;
|
|
55
|
-
/** Environment — CFN stack name / ARM resource group / kube context env
|
|
56
|
-
*
|
|
58
|
+
/** Environment — CFN stack name / ARM resource group / kube context env /
|
|
59
|
+
* the `grafana.profiles.<env>` entry on `grafana` / the `sql.profiles.<env>`
|
|
60
|
+
* entry on `clickhouse` and `postgres`; a log label on `gcp` and
|
|
61
|
+
* `fly`. */
|
|
57
62
|
env: string;
|
|
58
63
|
/** Native apply mechanism. Default: "kubectl". */
|
|
59
64
|
target?: ApplyTarget;
|
|
60
65
|
/** Built manifest/template path. Default per target: `dist` (dir) for kubectl,
|
|
61
66
|
* `template.json` (file) for CloudFormation/ARM, `dist/gcp.yaml` for gcp,
|
|
62
|
-
* `dist/fly.json` for fly.
|
|
67
|
+
* `dist/fly.json` for fly, `dist/grafana.json` (the build index) for
|
|
68
|
+
* grafana, `dist/schema.json` for clickhouse and postgres. Must match your
|
|
69
|
+
* build output. */
|
|
63
70
|
output?: string;
|
|
64
71
|
/** Project directory to build. Default: ".". */
|
|
65
72
|
path?: string;
|
|
@@ -157,6 +157,33 @@ describe("ApplyOp: shape", () => {
|
|
|
157
157
|
expect(applyStep.fn).toBe("nativeApply");
|
|
158
158
|
expect(applyStep.args).toEqual({ target: "kubectl", env: "prod", output: "dist", deleteMode: "never" });
|
|
159
159
|
});
|
|
160
|
+
|
|
161
|
+
test("target clickhouse applies the sql build output, dist/schema.json by default (#3208)", () => {
|
|
162
|
+
const { op } = ApplyOp({ name: "p", env: "prod", target: "clickhouse", delete: "owned-only" });
|
|
163
|
+
const phases = getProps(op).phases as Array<Record<string, unknown>>;
|
|
164
|
+
const applyStep = (phases[2].steps as Array<Record<string, unknown>>)[0];
|
|
165
|
+
expect(applyStep.fn).toBe("nativeApply");
|
|
166
|
+
expect(applyStep.args).toEqual({ target: "clickhouse", env: "prod", output: "dist/schema.json", deleteMode: "owned-only" });
|
|
167
|
+
expect(getProps(op).onFailure).toBeUndefined();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("target postgres applies the sql build output, dist/schema.json by default (#3280)", () => {
|
|
171
|
+
const { op } = ApplyOp({ name: "p", env: "prod", target: "postgres", delete: "owned-only" });
|
|
172
|
+
const phases = getProps(op).phases as Array<Record<string, unknown>>;
|
|
173
|
+
const applyStep = (phases[2].steps as Array<Record<string, unknown>>)[0];
|
|
174
|
+
expect(applyStep.fn).toBe("nativeApply");
|
|
175
|
+
expect(applyStep.args).toEqual({ target: "postgres", env: "prod", output: "dist/schema.json", deleteMode: "owned-only" });
|
|
176
|
+
expect(getProps(op).onFailure).toBeUndefined();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test("target grafana applies the build index, dist/grafana.json by default (#3011)", () => {
|
|
180
|
+
const { op } = ApplyOp({ name: "p", env: "prod", target: "grafana", delete: "owned-only" });
|
|
181
|
+
const phases = getProps(op).phases as Array<Record<string, unknown>>;
|
|
182
|
+
const applyStep = (phases[2].steps as Array<Record<string, unknown>>)[0];
|
|
183
|
+
expect(applyStep.fn).toBe("nativeApply");
|
|
184
|
+
expect(applyStep.args).toEqual({ target: "grafana", env: "prod", output: "dist/grafana.json", deleteMode: "owned-only" });
|
|
185
|
+
expect(getProps(op).onFailure).toBeUndefined();
|
|
186
|
+
});
|
|
160
187
|
});
|
|
161
188
|
|
|
162
189
|
describe("ApplyOp: gating + deletes", () => {
|
|
@@ -274,7 +301,7 @@ describe("ApplyOp: compensation (#125, total-or-refused in #1449)", () => {
|
|
|
274
301
|
});
|
|
275
302
|
|
|
276
303
|
test("compensate: true is refused at build time for every rollback-less target (#1449)", () => {
|
|
277
|
-
for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly"] as const) {
|
|
304
|
+
for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly", "grafana", "clickhouse", "postgres"] as const) {
|
|
278
305
|
expect(() => ApplyOp({ name: "p", env: "prod", target, compensate: true })).toThrow(
|
|
279
306
|
new RegExp(`ApplyOp "p": compensate is enabled, but target "${target}" has no automatic rollback`),
|
|
280
307
|
);
|
|
@@ -296,7 +323,7 @@ describe("ApplyOp: compensation (#125, total-or-refused in #1449)", () => {
|
|
|
296
323
|
});
|
|
297
324
|
|
|
298
325
|
test("an object without a command is refused the same way as true", () => {
|
|
299
|
-
for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly"] as const) {
|
|
326
|
+
for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly", "grafana", "clickhouse", "postgres"] as const) {
|
|
300
327
|
expect(() => ApplyOp({ name: "p", env: "prod", target, compensate: {} })).toThrow(
|
|
301
328
|
/has no automatic rollback/,
|
|
302
329
|
);
|
|
@@ -304,7 +331,7 @@ describe("ApplyOp: compensation (#125, total-or-refused in #1449)", () => {
|
|
|
304
331
|
});
|
|
305
332
|
|
|
306
333
|
test("a command lifts the refusal on every target", () => {
|
|
307
|
-
for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly", "cloudformation"] as const) {
|
|
334
|
+
for (const target of ["kubectl", "kustomize", "arm", "gcp", "fly", "grafana", "clickhouse", "postgres", "cloudformation"] as const) {
|
|
308
335
|
const { op } = ApplyOp({
|
|
309
336
|
name: "p",
|
|
310
337
|
env: "prod",
|
|
@@ -49,17 +49,22 @@ describe("LexiconUpgradeOp composite (#527)", () => {
|
|
|
49
49
|
expect(phases[0].steps[0].outcomeAttribute).toEqual({ name: "HasUpgrade", from: "hasUpgrade" });
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
test("
|
|
52
|
+
test("known set is exactly the 11 lexicons (helm/forgejo excluded)", () => {
|
|
53
53
|
// cedar joined with #1650: it pins `CEDAR_WASM_VERSION`, a dependency
|
|
54
54
|
// rather than a downloaded spec, but the pinned-constant machinery the Op
|
|
55
55
|
// drives is identical. helm/forgejo still have no upstream at all.
|
|
56
56
|
expect([...IN_SCOPE_LEXICONS].sort()).toEqual(
|
|
57
|
-
["aws", "azure", "cedar", "docker", "fly", "gcp", "github", "gitlab", "k8s"].sort(),
|
|
57
|
+
["aws", "azure", "cedar", "docker", "fly", "gcp", "github", "gitlab", "k3s", "k8s", "sql"].sort(),
|
|
58
58
|
);
|
|
59
59
|
expect(IN_SCOPE_LEXICONS).not.toContain("helm");
|
|
60
60
|
expect(IN_SCOPE_LEXICONS).not.toContain("forgejo");
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
+
test("accepts a pinned lexicon by name, discovered at run time", () => {
|
|
64
|
+
expect(() => LexiconUpgradeOp({ lexicon: "sql" })).not.toThrow();
|
|
65
|
+
expect(() => LexiconUpgradeOp({ lexicon: "k3s" })).not.toThrow();
|
|
66
|
+
});
|
|
67
|
+
|
|
63
68
|
test("rejects out-of-scope lexicons at construction", () => {
|
|
64
69
|
for (const l of ["helm", "forgejo"]) {
|
|
65
70
|
expect(() => LexiconUpgradeOp({ lexicon: l as never })).toThrow(/not in scope/);
|
|
@@ -13,9 +13,13 @@
|
|
|
13
13
|
* lands on the Op itself (#2120).
|
|
14
14
|
*
|
|
15
15
|
* Lexicon classification (which check the activity dispatches to):
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* ROLLING {aws, azure, github, fly} → checkRollingUpgrade
|
|
17
|
+
* PINNED any other lexicon whose plugin declares `upstreamPin`
|
|
18
|
+
* (k8s, k3s, gcp, docker, gitlab, cedar, sql, ...) → checkPinnedUpgrade
|
|
19
|
+
* The pinned set is discovered from the plugin at run time, the way `chant dev
|
|
20
|
+
* pinned-upgrade` does. A pin that moves with other constants (`alsoMoves`, as
|
|
21
|
+
* sql's version plus digest) is report-only. helm / forgejo are excluded: no
|
|
22
|
+
* upstream spec.
|
|
19
23
|
*
|
|
20
24
|
* Finding-modes mirror ReconcileOp: `report` (default, no external services)
|
|
21
25
|
* | `issue` | `pull-request`. For the epic goal, `pull-request` opens/updates a
|
|
@@ -43,9 +47,15 @@ import { Op, phase } from "../builders";
|
|
|
43
47
|
import type { OpResource } from "../resource";
|
|
44
48
|
import type { LexiconUpgradeMode, SupportedLexicon } from "../activities/lexicon-upgrade";
|
|
45
49
|
|
|
46
|
-
/**
|
|
50
|
+
/**
|
|
51
|
+
* The lexicons known to be in scope. This is not a gate: a lexicon that declares
|
|
52
|
+
* `upstreamPin` is dispatched without being listed. helm / forgejo are excluded
|
|
53
|
+
* (no upstream spec).
|
|
54
|
+
*/
|
|
47
55
|
export const IN_SCOPE_LEXICONS: readonly SupportedLexicon[] = [
|
|
48
56
|
"k8s",
|
|
57
|
+
"k3s",
|
|
58
|
+
"sql",
|
|
49
59
|
"gcp",
|
|
50
60
|
"docker",
|
|
51
61
|
"gitlab",
|
|
@@ -74,6 +84,12 @@ export interface LexiconUpgradeOpConfig {
|
|
|
74
84
|
* `<cwd>/lexicons/<lexicon>` at run time.
|
|
75
85
|
*/
|
|
76
86
|
lexiconDir?: string;
|
|
87
|
+
/**
|
|
88
|
+
* Label of one pin to check, for a lexicon whose plugin declares several
|
|
89
|
+
* (`upstreamPins`; sql has `clickhouse` and `postgres-14` to `postgres-18`).
|
|
90
|
+
* Omit to check every pin.
|
|
91
|
+
*/
|
|
92
|
+
pin?: string;
|
|
77
93
|
/**
|
|
78
94
|
* What to produce on findings. Default: "report".
|
|
79
95
|
* @default "report"
|
|
@@ -86,15 +102,19 @@ export interface LexiconUpgradeOpResources {
|
|
|
86
102
|
op: InstanceType<typeof OpResource>;
|
|
87
103
|
}
|
|
88
104
|
|
|
105
|
+
const EXCLUDED_LEXICONS: ReadonlySet<string> = new Set(["helm", "forgejo"]);
|
|
106
|
+
|
|
89
107
|
/**
|
|
90
|
-
* Build a LexiconUpgradeOp for one lexicon. Rejects
|
|
91
|
-
* construction time
|
|
108
|
+
* Build a LexiconUpgradeOp for one lexicon. Rejects the lexicons with no
|
|
109
|
+
* upstream spec at construction time. Whether any other name declares a pin is
|
|
110
|
+
* only known by loading its plugin, so the activity checks that at run time and
|
|
111
|
+
* fails with a clear message for a name that has none.
|
|
92
112
|
*/
|
|
93
113
|
export function LexiconUpgradeOp(config: LexiconUpgradeOpConfig): LexiconUpgradeOpResources {
|
|
94
|
-
if (
|
|
114
|
+
if (EXCLUDED_LEXICONS.has(config.lexicon)) {
|
|
95
115
|
throw new Error(
|
|
96
116
|
`LexiconUpgradeOp: "${config.lexicon}" is not in scope. ` +
|
|
97
|
-
`
|
|
117
|
+
`Known lexicons: ${IN_SCOPE_LEXICONS.join(", ")}, and any lexicon declaring upstreamPin ` +
|
|
98
118
|
`(helm, forgejo have no upstream spec).`,
|
|
99
119
|
);
|
|
100
120
|
}
|
|
@@ -119,6 +139,7 @@ export function LexiconUpgradeOp(config: LexiconUpgradeOpConfig): LexiconUpgrade
|
|
|
119
139
|
args: {
|
|
120
140
|
lexicon: config.lexicon,
|
|
121
141
|
...(config.lexiconDir ? { lexiconDir: config.lexiconDir } : {}),
|
|
142
|
+
...(config.pin ? { pin: config.pin } : {}),
|
|
122
143
|
mode: onFinding,
|
|
123
144
|
},
|
|
124
145
|
// Surface whether a PR-worthy upgrade was found as the run's
|
package/src/op/decide-backend.ts
CHANGED
|
@@ -6,9 +6,13 @@
|
|
|
6
6
|
* POST <url>/v1/systemone Authorization: Bearer <key>
|
|
7
7
|
* { "model": "jev-1.13.0", "state": {...}, "questions": { "<name>": { "type": "noul" | "choice" | "score", "instructions": ..., "criteria": ... } } }
|
|
8
8
|
*
|
|
9
|
-
* { "model": "jev-1.13.0", "answers": { "<name>": { "type": "noul", "noul": 0.22 } | { "type": "choice", "choice": ..., "probabilities": {...}, "confidence": ... } | { "type": "score", ... } } }
|
|
9
|
+
* { "model": "jev-1.13.0", "answers": { "<name>": { "type": "noul", "noul": 0.22, "reason"?: ... } | { "type": "choice", "choice": ..., "probabilities": {...}, "confidence": ..., "reason"?: ... } | { "type": "score", ..., "reason"?: ... } } }
|
|
10
10
|
* ```
|
|
11
11
|
*
|
|
12
|
+
* `reason` is optional: the model's own explanation of its answer (#3345).
|
|
13
|
+
* Core keeps it in the answer record beside a proposal, or as `model_reason`
|
|
14
|
+
* in the escalation entry of an answer below the threshold.
|
|
15
|
+
*
|
|
12
16
|
* {@link backendAsk} turns a set of backends into core's `ModelAsk`, the
|
|
13
17
|
* model call `askPoint` takes (`../workspace/points.ts`). This file
|
|
14
18
|
* only speaks the wire format: whether an answer is observed, proposed or
|
|
@@ -10,10 +10,12 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Read by id or name here:
|
|
12
12
|
*
|
|
13
|
-
* record, decision, work-item a record, by id, from the declared record kinds (`records --json`)
|
|
13
|
+
* record, decision, work-item a record, by id, from the declared record kinds (`records --json`);
|
|
14
|
+
* a work item also has its size, `criteria`, `files`, `words` and
|
|
15
|
+
* `fits_<tier>`, for the slice-tier point (`../workspace/work-size.ts`, #3150)
|
|
14
16
|
* member a member, by name (`ls --json`)
|
|
15
17
|
*
|
|
16
|
-
* The other outputs a point may name (finding, region, commit, gate, release,
|
|
18
|
+
* The other outputs a point may name (finding, region, commit, node, gate, release,
|
|
17
19
|
* environment, component) are passed in `inputs`, as the output printed them.
|
|
18
20
|
* These reads never call a model, and never write. The module loads code
|
|
19
21
|
* under `workspace/`, so the `decide` activity imports it on first call.
|
|
@@ -22,6 +24,11 @@
|
|
|
22
24
|
import { declaredKindFiles, queryDeclaredRecords } from "../workspace/records-cli";
|
|
23
25
|
import { listWorkspace } from "../workspace/ls";
|
|
24
26
|
import { inputOutput } from "../workspace/points";
|
|
27
|
+
import { readFileSync } from "node:fs";
|
|
28
|
+
import { join } from "node:path";
|
|
29
|
+
import { bodyText, loadRecordKind } from "../workspace/records";
|
|
30
|
+
import { locateWorkspace } from "../workspace/which-chant";
|
|
31
|
+
import { DEFAULT_TIER_LIMITS, measureWorkItem, sizeFields } from "../workspace/work-size";
|
|
25
32
|
|
|
26
33
|
/** The outputs {@link readInputs} reads by id or name. */
|
|
27
34
|
export const READABLE_OUTPUTS = ["record", "decision", "work-item", "member"] as const;
|
|
@@ -45,19 +52,40 @@ export function fieldOf(value: unknown, path: string): unknown {
|
|
|
45
52
|
}
|
|
46
53
|
|
|
47
54
|
async function readRecord(id: string, cwd: string, output: string): Promise<Record<string, unknown>> {
|
|
48
|
-
const
|
|
55
|
+
const files = declaredKindFiles(cwd);
|
|
56
|
+
const set = await queryDeclaredRecords(files, { cwd });
|
|
49
57
|
const unread: string[] = [];
|
|
50
|
-
for (const doc of set.kinds) {
|
|
58
|
+
for (const [i, doc] of set.kinds.entries()) {
|
|
51
59
|
if ("error" in doc) {
|
|
52
60
|
unread.push(`${doc.declared.path}: ${doc.error.code}`);
|
|
53
61
|
continue;
|
|
54
62
|
}
|
|
55
63
|
const found = doc.records.find((r) => r.id === id);
|
|
56
|
-
if (found)
|
|
64
|
+
if (found) {
|
|
65
|
+
const record = found as unknown as Record<string, unknown>;
|
|
66
|
+
// A work item's size, for the slice-tier point (#3150): criteria, files, words and fits_<tier>.
|
|
67
|
+
return output === "work-item" ? { ...record, ...(await workItemSizeFields(files[i].file, found.path, found.data, cwd)) } : record;
|
|
68
|
+
}
|
|
57
69
|
}
|
|
58
70
|
throw new InputReadError(`no declared record kind holds a record with id ${id} (read for ${output})${unread.length ? `; not read: ${unread.join(", ")}` : ""}`);
|
|
59
71
|
}
|
|
60
72
|
|
|
73
|
+
/** The size fields of a work item of the kind at `kindFile`, measured from its record file. Empty for a kind with no work block. */
|
|
74
|
+
async function workItemSizeFields(kindFile: string, path: string, data: Record<string, unknown> | null, cwd: string): Promise<Record<string, unknown>> {
|
|
75
|
+
const loaded = await loadRecordKind(kindFile, cwd);
|
|
76
|
+
const work = loaded.kind.work;
|
|
77
|
+
if (!work) return {};
|
|
78
|
+
const located = locateWorkspace(cwd);
|
|
79
|
+
let body = "";
|
|
80
|
+
try {
|
|
81
|
+
body = bodyText(readFileSync(join(located.top ?? located.rootOnDisk, ...path.split("/")), "utf-8"));
|
|
82
|
+
} catch {
|
|
83
|
+
// A record that can't be read again is measured from its front matter alone.
|
|
84
|
+
}
|
|
85
|
+
const size = measureWorkItem(data, body, work.acceptance?.field ?? "acceptance");
|
|
86
|
+
return sizeFields(size, work.tier?.limits ?? DEFAULT_TIER_LIMITS);
|
|
87
|
+
}
|
|
88
|
+
|
|
61
89
|
function readMember(name: string, cwd: string): Record<string, unknown> {
|
|
62
90
|
const doc = listWorkspace({ cwd });
|
|
63
91
|
if ("error" in doc) throw new InputReadError(`the workspace can't be listed: ${doc.error.code}: ${doc.error.message}`);
|
|
@@ -39,3 +39,26 @@ describe("emulatorLifecycle command builders", () => {
|
|
|
39
39
|
expect(emu.endpoint(4599)).toBe("http://localhost:4599");
|
|
40
40
|
});
|
|
41
41
|
});
|
|
42
|
+
|
|
43
|
+
describe("an emulator reached by its own client, not over HTTP", () => {
|
|
44
|
+
const pg = emulatorLifecycle({
|
|
45
|
+
name: "chant-postgres",
|
|
46
|
+
image: "postgres:18",
|
|
47
|
+
containerPort: 5432,
|
|
48
|
+
readyCommand: ["pg_isready", "-h", "127.0.0.1"],
|
|
49
|
+
endpoint: (port) => `postgres://postgres@localhost:${port}/postgres`,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("readiness is a command run in the container", () => {
|
|
53
|
+
expect(pg.readyExecCommand("chant-postgres")).toBe("docker exec chant-postgres pg_isready -h 127.0.0.1");
|
|
54
|
+
expect(emulatorLifecycle({ name: "x", image: "x:1", containerPort: 1, healthPath: "/h" }).readyExecCommand("x")).toBeUndefined();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("the endpoint is the declared one, not an http URL", () => {
|
|
58
|
+
expect(pg.endpoint(55432)).toBe("postgres://postgres@localhost:55432/postgres");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("a spec with neither a health path nor a ready command is refused", () => {
|
|
62
|
+
expect(() => emulatorLifecycle({ name: "x", image: "x:1", containerPort: 1 })).toThrow(/neither a healthPath nor a readyCommand/);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -16,8 +16,25 @@ export interface EmulatorSpec {
|
|
|
16
16
|
image: string;
|
|
17
17
|
/** Port the emulator listens on inside the container (e.g. 4566, 4280). */
|
|
18
18
|
containerPort: number;
|
|
19
|
-
/**
|
|
20
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Health path on the host port (e.g. `/_localstack/health`, `/_mudflaps/health`).
|
|
21
|
+
* Required unless {@link readyCommand} is set: an emulator is reached over
|
|
22
|
+
* HTTP or checks itself inside its container, one or the other.
|
|
23
|
+
*/
|
|
24
|
+
healthPath?: string;
|
|
25
|
+
/**
|
|
26
|
+
* A command run inside the container (`docker exec <name> ...`) whose exit
|
|
27
|
+
* status 0 means ready, for an emulator with no HTTP health endpoint: a
|
|
28
|
+
* database server answers its own client (`pg_isready`), not a URL. When
|
|
29
|
+
* set, it replaces the HTTP poll of {@link healthPath}.
|
|
30
|
+
*/
|
|
31
|
+
readyCommand?: readonly string[];
|
|
32
|
+
/**
|
|
33
|
+
* The endpoint a tool connects to, for an emulator that is not reached over
|
|
34
|
+
* HTTP, e.g. a `postgres://` URL for a database server.
|
|
35
|
+
* Default: `http://localhost:<port>`.
|
|
36
|
+
*/
|
|
37
|
+
endpoint?: (port: number) => string;
|
|
21
38
|
/** Readiness predicate over the health body. Default: any 200 response is ready. */
|
|
22
39
|
ready?: (healthBody: string) => boolean;
|
|
23
40
|
/** Extra `docker run` args inserted before the image (e.g. a socket mount). */
|
|
@@ -102,6 +119,8 @@ export interface EmulatorLifecycle {
|
|
|
102
119
|
existsCommand(name: string): string;
|
|
103
120
|
rmCommand(name: string): string;
|
|
104
121
|
healthUrl(port: number): string;
|
|
122
|
+
/** `docker exec <name> <readyCommand...>`, or undefined for an emulator polled over HTTP. */
|
|
123
|
+
readyExecCommand(name: string): string | undefined;
|
|
105
124
|
endpoint(port: number): string;
|
|
106
125
|
up(args?: EmulatorUpArgs, signal?: AbortSignal): Promise<{ endpoint: string }>;
|
|
107
126
|
down(args?: { name?: string }, signal?: AbortSignal): Promise<void>;
|
|
@@ -116,6 +135,9 @@ export interface EmulatorLifecycle {
|
|
|
116
135
|
*/
|
|
117
136
|
export function emulatorLifecycle(spec: EmulatorSpec): EmulatorLifecycle {
|
|
118
137
|
const ready = spec.ready ?? (() => true);
|
|
138
|
+
if (spec.healthPath === undefined && !spec.readyCommand?.length) {
|
|
139
|
+
throw new Error(`emulator "${spec.name}" declares neither a healthPath nor a readyCommand, so nothing can tell when it is ready`);
|
|
140
|
+
}
|
|
119
141
|
|
|
120
142
|
const runCommand = (args: EmulatorUpArgs = {}): string => {
|
|
121
143
|
const name = args.name ?? spec.name;
|
|
@@ -128,8 +150,30 @@ export function emulatorLifecycle(spec: EmulatorSpec): EmulatorLifecycle {
|
|
|
128
150
|
};
|
|
129
151
|
const existsCommand = (name: string): string => `docker ps -q -f name=${name}`;
|
|
130
152
|
const rmCommand = (name: string): string => `docker rm -f ${name}`;
|
|
131
|
-
const healthUrl = (port: number): string => `http://localhost:${port}${spec.healthPath}`;
|
|
132
|
-
const endpoint = (port: number): string => `http://localhost:${port}
|
|
153
|
+
const healthUrl = (port: number): string => `http://localhost:${port}${spec.healthPath ?? ""}`;
|
|
154
|
+
const endpoint = (port: number): string => (spec.endpoint ? spec.endpoint(port) : `http://localhost:${port}`);
|
|
155
|
+
const readyExecCommand = (name: string): string | undefined =>
|
|
156
|
+
spec.readyCommand?.length ? ["docker", "exec", name, ...spec.readyCommand].join(" ") : undefined;
|
|
157
|
+
|
|
158
|
+
/** One readiness probe: the in-container command when declared, else the HTTP health path. */
|
|
159
|
+
async function probe(name: string, port: number, signal?: AbortSignal): Promise<boolean> {
|
|
160
|
+
const command = readyExecCommand(name);
|
|
161
|
+
if (command) {
|
|
162
|
+
try {
|
|
163
|
+
await execAsync(command, { signal });
|
|
164
|
+
return true;
|
|
165
|
+
} catch {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
const res = await fetch(healthUrl(port), { signal });
|
|
171
|
+
return res.ok && ready(await res.text());
|
|
172
|
+
} catch {
|
|
173
|
+
// Not up yet (connection refused / non-2xx) — retry.
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
133
177
|
|
|
134
178
|
async function up(args: EmulatorUpArgs = {}, signal?: AbortSignal): Promise<{ endpoint: string }> {
|
|
135
179
|
const name = args.name ?? spec.name;
|
|
@@ -153,19 +197,13 @@ export function emulatorLifecycle(spec: EmulatorSpec): EmulatorLifecycle {
|
|
|
153
197
|
await execAsync(runCommand({ ...args, name, port }), { signal });
|
|
154
198
|
}
|
|
155
199
|
|
|
156
|
-
const url = healthUrl(port);
|
|
157
200
|
const deadline = Date.now() + timeoutMs;
|
|
158
201
|
let ok = false;
|
|
159
202
|
while (Date.now() < deadline) {
|
|
160
203
|
if (signal?.aborted) throw new Error(`emulator "${name}" wait aborted`);
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
ok = true;
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
} catch {
|
|
168
|
-
// Not up yet (connection refused / non-2xx) — retry.
|
|
204
|
+
if (await probe(name, port, signal)) {
|
|
205
|
+
ok = true;
|
|
206
|
+
break;
|
|
169
207
|
}
|
|
170
208
|
await sleep(intervalMs, signal);
|
|
171
209
|
}
|
|
@@ -187,5 +225,5 @@ export function emulatorLifecycle(spec: EmulatorSpec): EmulatorLifecycle {
|
|
|
187
225
|
}
|
|
188
226
|
}
|
|
189
227
|
|
|
190
|
-
return { runCommand, existsCommand, rmCommand, healthUrl, endpoint, up, down };
|
|
228
|
+
return { runCommand, existsCommand, rmCommand, healthUrl, readyExecCommand, endpoint, up, down };
|
|
191
229
|
}
|