@intentius/chant 0.124.13 → 0.124.15
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/bin/chant +11 -0
- package/dist/agents/checks.js +326 -0
- package/dist/agents/discover.js +885 -0
- package/dist/agents/importer.js +17 -0
- package/dist/agents/index.js +12 -0
- package/dist/agents/types.js +19 -0
- package/dist/apply.js +151 -0
- package/dist/attrref.js +70 -0
- package/dist/audit/catalog.js +350 -0
- package/dist/audit/core.js +252 -0
- package/dist/audit/discover.js +633 -0
- package/dist/audit/fetch.js +666 -0
- package/dist/audit/lineage.js +91 -0
- package/dist/audit/nginx.js +366 -0
- package/dist/audit/prior-art.js +132 -0
- package/dist/audit/proof.js +321 -0
- package/dist/audit/report-html.js +194 -0
- package/dist/audit/report-model.js +198 -0
- package/dist/audit/report.js +102 -0
- package/dist/audit/rules-doc.js +144 -0
- package/dist/audit/secrets.js +405 -0
- package/dist/audit/terraform-state.js +140 -0
- package/dist/audit/wrangler.js +262 -0
- package/dist/behaviour-delta.js +401 -0
- package/dist/behaviour-engine.js +357 -0
- package/dist/behaviour-graph.js +83 -0
- package/dist/behaviour-http.js +188 -0
- package/dist/behaviour-kinds.js +172 -0
- package/dist/behaviour-overlay.js +50 -0
- package/dist/behaviour-predict.js +188 -0
- package/dist/behaviour-request.js +194 -0
- package/dist/behaviour.js +1325 -0
- package/dist/build-params.js +108 -0
- package/dist/build.d.ts +6 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +669 -0
- package/dist/builder.js +44 -0
- package/dist/cdk/advise.js +30 -0
- package/dist/cdk/assembly.js +122 -0
- package/dist/cdk/graph.js +444 -0
- package/dist/cdk/tier-map.js +64 -0
- package/dist/cdk/types.js +24 -0
- package/dist/change-set.d.ts +24 -2
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +361 -0
- package/dist/child-project.js +21 -0
- package/dist/ci-jobs.d.ts +227 -0
- package/dist/ci-jobs.d.ts.map +1 -0
- package/dist/ci-jobs.js +448 -0
- package/dist/claimed-fields.js +135 -0
- package/dist/cli/build-options.js +70 -0
- package/dist/cli/build-params-cli.js +139 -0
- package/dist/cli/command-group.js +123 -0
- package/dist/cli/commands/audit-agents.js +326 -0
- package/dist/cli/commands/audit.js +571 -0
- package/dist/cli/commands/build.js +920 -0
- package/dist/cli/commands/carve-apply.js +153 -0
- package/dist/cli/commands/carve-bridge.js +201 -0
- package/dist/cli/commands/carve-emit.js +332 -0
- package/dist/cli/commands/carve-status.js +119 -0
- package/dist/cli/commands/carve.js +204 -0
- package/dist/cli/commands/check-lexicon-docs.js +79 -0
- package/dist/cli/commands/check-lexicon-examples.js +177 -0
- package/dist/cli/commands/check-lexicon-intrinsics.js +291 -0
- package/dist/cli/commands/check-lexicon-mcp.js +82 -0
- package/dist/cli/commands/check-lexicon-plugin.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-plugin.js +104 -0
- package/dist/cli/commands/check-lexicon.js +766 -0
- package/dist/cli/commands/describe.js +85 -0
- package/dist/cli/commands/diff.js +175 -0
- package/dist/cli/commands/doctor.js +350 -0
- package/dist/cli/commands/import-agents.js +155 -0
- package/dist/cli/commands/import.js +670 -0
- package/dist/cli/commands/init-lexicon/templates/codegen.js +194 -0
- package/dist/cli/commands/init-lexicon/templates/docs.js +100 -0
- package/dist/cli/commands/init-lexicon/templates/examples.js +29 -0
- package/dist/cli/commands/init-lexicon/templates/lint.js +34 -0
- package/dist/cli/commands/init-lexicon/templates/lsp.js +37 -0
- package/dist/cli/commands/init-lexicon/templates/plugin.js +108 -0
- package/dist/cli/commands/init-lexicon/templates/project.js +240 -0
- package/dist/cli/commands/init-lexicon/templates/spec.js +56 -0
- package/dist/cli/commands/init-lexicon/templates/tests.js +66 -0
- package/dist/cli/commands/init-lexicon.js +172 -0
- package/dist/cli/commands/init.js +381 -0
- package/dist/cli/commands/lexicon-rolling-upgrade.js +145 -0
- package/dist/cli/commands/lexicon-surface-diff.js +145 -0
- package/dist/cli/commands/licenses.js +125 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +948 -0
- package/dist/cli/commands/list.js +63 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -1
- package/dist/cli/commands/migrate.js +423 -0
- package/dist/cli/commands/onboard.js +403 -0
- package/dist/cli/commands/pinned-upgrade.js +191 -0
- package/dist/cli/commands/update.js +194 -0
- package/dist/cli/commands/vendor.js +217 -0
- package/dist/cli/conflict-check.js +104 -0
- package/dist/cli/debug.js +8 -0
- package/dist/cli/format.js +104 -0
- package/dist/cli/handlers/build.js +267 -0
- package/dist/cli/handlers/carve-apply.js +30 -0
- package/dist/cli/handlers/carve-bridge.js +28 -0
- package/dist/cli/handlers/carve-emit.js +50 -0
- package/dist/cli/handlers/carve-status.js +26 -0
- package/dist/cli/handlers/carve.js +40 -0
- package/dist/cli/handlers/change-set.js +46 -0
- package/dist/cli/handlers/components.js +730 -0
- package/dist/cli/handlers/dev.js +113 -0
- package/dist/cli/handlers/emulator.js +233 -0
- package/dist/cli/handlers/explain.js +54 -0
- package/dist/cli/handlers/fan-out.js +422 -0
- package/dist/cli/handlers/gate-resume.js +275 -0
- package/dist/cli/handlers/generate.js +84 -0
- package/dist/cli/handlers/graph.js +969 -0
- package/dist/cli/handlers/init.js +102 -0
- package/dist/cli/handlers/lifecycle.js +1727 -0
- package/dist/cli/handlers/lint.js +62 -0
- package/dist/cli/handlers/migrate.js +48 -0
- package/dist/cli/handlers/misc.js +391 -0
- package/dist/cli/handlers/operator.js +1162 -0
- package/dist/cli/handlers/override-approve.js +102 -0
- package/dist/cli/handlers/pr.js +503 -0
- package/dist/cli/handlers/promote.js +342 -0
- package/dist/cli/handlers/run-generate.js +206 -0
- package/dist/cli/handlers/run-wave.js +66 -0
- package/dist/cli/handlers/run.js +1191 -0
- package/dist/cli/handlers/scenario.js +325 -0
- package/dist/cli/handlers/search.js +924 -0
- package/dist/cli/handlers/serve.js +32 -0
- package/dist/cli/handlers/vendor.js +154 -0
- package/dist/cli/index.js +3 -0
- package/dist/cli/is-entry-point.js +23 -0
- package/dist/cli/lsp/capabilities.js +28 -0
- package/dist/cli/lsp/diagnostics.js +34 -0
- package/dist/cli/lsp/server.js +329 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +2540 -0
- package/dist/cli/mcp/lifecycle-tools.js +80 -0
- package/dist/cli/mcp/op-tools.js +306 -0
- package/dist/cli/mcp/resource-handlers.js +258 -0
- package/dist/cli/mcp/resources/context.js +85 -0
- package/dist/cli/mcp/server.js +353 -0
- package/dist/cli/mcp/tools/build.js +111 -0
- package/dist/cli/mcp/tools/composites.js +95 -0
- package/dist/cli/mcp/tools/explain.js +166 -0
- package/dist/cli/mcp/tools/import.js +49 -0
- package/dist/cli/mcp/tools/lint.js +41 -0
- package/dist/cli/mcp/tools/scaffold.js +111 -0
- package/dist/cli/mcp/tools/search.js +112 -0
- package/dist/cli/mcp/types.js +1 -0
- package/dist/cli/mcp/workspace-plugins.js +91 -0
- package/dist/cli/mcp/workspace-tools.d.ts +1 -1
- package/dist/cli/mcp/workspace-tools.js +564 -0
- package/dist/cli/mcp-config.js +70 -0
- package/dist/cli/plugins.js +313 -0
- package/dist/cli/registry.js +23 -0
- package/dist/cli/reporters/stylish.js +329 -0
- package/dist/cli/version.js +15 -0
- package/dist/cli/watch.js +79 -0
- package/dist/codegen/bound-property-types.js +82 -0
- package/dist/codegen/coverage.js +119 -0
- package/dist/codegen/docs-file-markers.js +60 -0
- package/dist/codegen/docs-pages.js +115 -0
- package/dist/codegen/docs-rule-scanning.js +164 -0
- package/dist/codegen/docs-rules.js +76 -0
- package/dist/codegen/docs-sections.js +117 -0
- package/dist/codegen/docs-sidebar.js +65 -0
- package/dist/codegen/docs-types.js +4 -0
- package/dist/codegen/docs.js +356 -0
- package/dist/codegen/fetch.js +340 -0
- package/dist/codegen/generate-post-synth-barrel.js +63 -0
- package/dist/codegen/generate-registry.js +71 -0
- package/dist/codegen/generate-runtime-index.js +56 -0
- package/dist/codegen/generate-typescript.js +119 -0
- package/dist/codegen/generate.js +115 -0
- package/dist/codegen/json-patch.js +141 -0
- package/dist/codegen/json-schema-to-ts.js +344 -0
- package/dist/codegen/json-schema.js +246 -0
- package/dist/codegen/lexicon-regen.js +412 -0
- package/dist/codegen/naming.js +217 -0
- package/dist/codegen/okf-lexicon.js +245 -0
- package/dist/codegen/package.js +150 -0
- package/dist/codegen/pinned-upgrade.d.ts.map +1 -1
- package/dist/codegen/pinned-upgrade.js +494 -0
- package/dist/codegen/registry.js +60 -0
- package/dist/codegen/rehype-base-url.mjs +68 -0
- package/dist/codegen/rolling-upgrade.js +217 -0
- package/dist/codegen/surface-snapshot.js +537 -0
- package/dist/codegen/testdata/postgres-tags.json +242 -0
- package/dist/codegen/topo-sort.js +36 -0
- package/dist/codegen/typecheck.js +115 -0
- package/dist/codegen/validate.js +200 -0
- package/dist/codegen/version-bump.js +35 -0
- package/dist/components/auto-release.js +143 -0
- package/dist/components/builders.js +47 -0
- package/dist/components/capability-plugin-loader.js +175 -0
- package/dist/components/capability-plugin-schema.js +46 -0
- package/dist/components/capability-plugin.js +99 -0
- package/dist/components/capability.js +60 -0
- package/dist/components/changed-files.js +72 -0
- package/dist/components/cli-support.js +427 -0
- package/dist/components/component.js +120 -0
- package/dist/components/component.schema.json +271 -0
- package/dist/components/config-defaults.js +130 -0
- package/dist/components/deploy-units.js +60 -0
- package/dist/components/discover.d.ts.map +1 -1
- package/dist/components/discover.js +189 -0
- package/dist/components/driver-output.js +86 -0
- package/dist/components/driver.js +728 -0
- package/dist/components/fan-out-output.js +165 -0
- package/dist/components/fan-out-record.js +94 -0
- package/dist/components/fan-out-run.js +373 -0
- package/dist/components/fan-out-support.js +60 -0
- package/dist/components/fan-out.js +273 -0
- package/dist/components/gate-plan.js +41 -0
- package/dist/components/gated-wave-pipeline.js +46 -0
- package/dist/components/index.js +24 -0
- package/dist/components/layers.js +28 -0
- package/dist/components/manifest-persistence.js +108 -0
- package/dist/components/pilots/alb-ecs.pilot.js +59 -0
- package/dist/components/pilots/dynamodb.pilot.js +51 -0
- package/dist/components/pilots/jar-emr.pilot.js +65 -0
- package/dist/components/pilots/lambda.pilot.js +52 -0
- package/dist/components/pilots/neo4j-fanout.pilot.js +68 -0
- package/dist/components/pilots/project.js +12 -0
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +135 -0
- package/dist/components/pr-run.js +363 -0
- package/dist/components/presets/ecs-fargate.js +72 -0
- package/dist/components/presets/index.js +28 -0
- package/dist/components/presets/lambda.js +34 -0
- package/dist/components/presets/single-host-compose.js +41 -0
- package/dist/components/promote.js +549 -0
- package/dist/components/registry.js +34 -0
- package/dist/components/run-progress.js +33 -0
- package/dist/components/sandbox/driver.d.ts.map +1 -1
- package/dist/components/sandbox/driver.js +93 -0
- package/dist/components/sandbox/run.js +115 -0
- package/dist/components/starter-plugin.js +104 -0
- package/dist/components/verbs/__tests__/mock-cloud-executor.js +68 -0
- package/dist/components/verbs/__tests__/mock-process-runner.js +45 -0
- package/dist/components/verbs/__tests__/mock-sbom-generator.js +56 -0
- package/dist/components/verbs/bom-writer.js +287 -0
- package/dist/components/verbs/build-archive.js +188 -0
- package/dist/components/verbs/build.js +142 -0
- package/dist/components/verbs/cloud-executor.js +110 -0
- package/dist/components/verbs/component-bom.js +125 -0
- package/dist/components/verbs/ensure-secret.js +50 -0
- package/dist/components/verbs/index.js +61 -0
- package/dist/components/verbs/license-policy.js +75 -0
- package/dist/components/verbs/lockfile-sbom-generator.js +191 -0
- package/dist/components/verbs/process-runner.js +78 -0
- package/dist/components/verbs/r2-sync.js +93 -0
- package/dist/components/verbs/reproducibility.js +62 -0
- package/dist/components/verbs/run-agent.js +577 -0
- package/dist/components/verbs/sbom-generator.js +119 -0
- package/dist/components/verbs/sbom.js +97 -0
- package/dist/components/verbs/shell.js +32 -0
- package/dist/components/verbs/sign.js +221 -0
- package/dist/components/verbs/stub.js +28 -0
- package/dist/components/verbs/tool-sbom-generator.js +154 -0
- package/dist/components/verbs/verify.js +112 -0
- package/dist/components/verbs/vex.js +131 -0
- package/dist/components/verbs/vuln-gate.js +152 -0
- package/dist/components/verbs/vuln-scan.js +288 -0
- package/dist/components/verbs/wait-verify.js +106 -0
- package/dist/components/verbs/wrangler.js +179 -0
- package/dist/components/wave-plan.js +102 -0
- package/dist/composite.d.ts +10 -2
- package/dist/composite.d.ts.map +1 -1
- package/dist/composite.js +313 -0
- package/dist/config-import.d.ts.map +1 -1
- package/dist/config-import.js +22 -0
- package/dist/config-sandbox.js +122 -0
- package/dist/config-static.js +206 -0
- package/dist/config.js +605 -0
- package/dist/content-digest.js +23 -0
- package/dist/declarable.js +114 -0
- package/dist/deep-observation.js +437 -0
- package/dist/detectLexicon.js +54 -0
- package/dist/discovery/cache.js +70 -0
- package/dist/discovery/collect.d.ts +2 -1
- package/dist/discovery/collect.d.ts.map +1 -1
- package/dist/discovery/collect.js +223 -0
- package/dist/discovery/cycles.js +95 -0
- package/dist/discovery/entity-wire-codec.js +391 -0
- package/dist/discovery/entity-wire.js +42 -0
- package/dist/discovery/files.js +121 -0
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/fold-import.js +4073 -0
- package/dist/discovery/fold-rank.js +292 -0
- package/dist/discovery/graph.js +115 -0
- package/dist/discovery/host-composite.d.ts +35 -0
- package/dist/discovery/host-composite.d.ts.map +1 -0
- package/dist/discovery/host-composite.js +93 -0
- package/dist/discovery/import.d.ts.map +1 -1
- package/dist/discovery/import.js +65 -0
- package/dist/discovery/index.d.ts +9 -0
- package/dist/discovery/index.d.ts.map +1 -1
- package/dist/discovery/index.js +333 -0
- package/dist/discovery/param-deps.js +487 -0
- package/dist/discovery/resolve.js +39 -0
- package/dist/discovery/sandbox/bundle.js +214 -0
- package/dist/discovery/sandbox/child-errors.js +26 -0
- package/dist/discovery/sandbox/config-run.js +100 -0
- package/dist/discovery/sandbox/config-wire.js +183 -0
- package/dist/discovery/sandbox/driver.d.ts.map +1 -1
- package/dist/discovery/sandbox/driver.js +333 -0
- package/dist/discovery/sandbox/fork.js +229 -0
- package/dist/discovery/sandbox/policy-run.js +142 -0
- package/dist/discovery/sandbox/policy-wire.js +152 -0
- package/dist/discovery/sandbox/run.js +77 -0
- package/dist/discovery/specifier-resolve.js +320 -0
- package/dist/discovery/walk.js +284 -0
- package/dist/effect-receipt.js +340 -0
- package/dist/env.js +55 -0
- package/dist/errors.js +62 -0
- package/dist/fold/fold.js +1434 -0
- package/dist/fold/foldable-helpers.js +229 -0
- package/dist/fold/subset.js +696 -0
- package/dist/fold-provenance.js +414 -0
- package/dist/gate-decision.d.ts +20 -9
- package/dist/gate-decision.d.ts.map +1 -1
- package/dist/gate-decision.js +313 -0
- package/dist/gate-resume-run.js +154 -0
- package/dist/gated-waves.js +165 -0
- package/dist/governance.js +43 -0
- package/dist/graph-declared.js +45 -0
- package/dist/graph-detail.js +207 -0
- package/dist/graph-dot.js +54 -0
- package/dist/graph-effective.js +107 -0
- package/dist/graph-ir.js +623 -0
- package/dist/graph-layout.js +184 -0
- package/dist/graph-lens.js +105 -0
- package/dist/graph-mermaid.js +83 -0
- package/dist/graph-ops.js +39 -0
- package/dist/graph-refs.js +156 -0
- package/dist/held-elsewhere.js +87 -0
- package/dist/identity.js +251 -0
- package/dist/import/base-parser.js +34 -0
- package/dist/import/embedded.js +255 -0
- package/dist/import/generator.js +1 -0
- package/dist/import/ir-utils.js +85 -0
- package/dist/import/parser-options.js +45 -0
- package/dist/import/parser.js +1 -0
- package/dist/index.js +118 -0
- package/dist/intrinsic-interpolation.js +73 -0
- package/dist/intrinsic.js +31 -0
- package/dist/join-key.js +35 -0
- package/dist/kubectl-context.js +150 -0
- package/dist/lexicon-config.js +58 -0
- package/dist/lexicon-integrity.js +47 -0
- package/dist/lexicon-manifest.js +70 -0
- package/dist/lexicon-module.d.ts.map +1 -1
- package/dist/lexicon-module.js +241 -0
- package/dist/lexicon-output.js +218 -0
- package/dist/lexicon-plugin-helpers.js +104 -0
- package/dist/lexicon-schema.js +136 -0
- package/dist/lexicon.js +130 -0
- package/dist/lifecycle/affected.js +224 -0
- package/dist/lifecycle/assert-live.js +110 -0
- package/dist/lifecycle/build-ledger-store.js +160 -0
- package/dist/lifecycle/build-ledger.js +155 -0
- package/dist/lifecycle/change-set.js +356 -0
- package/dist/lifecycle/converge-ledger.js +161 -0
- package/dist/lifecycle/deep-diff.js +233 -0
- package/dist/lifecycle/deep-observe.js +147 -0
- package/dist/lifecycle/digest.js +143 -0
- package/dist/lifecycle/disruption.js +135 -0
- package/dist/lifecycle/gate-applied.js +113 -0
- package/dist/lifecycle/gate-audit.d.ts +69 -2
- package/dist/lifecycle/gate-audit.d.ts.map +1 -1
- package/dist/lifecycle/gate-audit.js +415 -0
- package/dist/lifecycle/gate-ledger-select.js +89 -0
- package/dist/lifecycle/gate-ledger.d.ts +24 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.js +201 -0
- package/dist/lifecycle/gate-origin.js +117 -0
- package/dist/lifecycle/gate-pending.js +58 -0
- package/dist/lifecycle/git.js +1182 -0
- package/dist/lifecycle/identity.js +58 -0
- package/dist/lifecycle/index.js +26 -0
- package/dist/lifecycle/lease.js +283 -0
- package/dist/lifecycle/ledger-port.js +1 -0
- package/dist/lifecycle/legacy-digest.js +91 -0
- package/dist/lifecycle/live-diff.js +274 -0
- package/dist/lifecycle/local-note.js +15 -0
- package/dist/lifecycle/member-ledger.js +122 -0
- package/dist/lifecycle/observation-baseline.js +155 -0
- package/dist/lifecycle/observe.js +375 -0
- package/dist/lifecycle/oras-referrer-lookup.js +82 -0
- package/dist/lifecycle/override-ledger.js +54 -0
- package/dist/lifecycle/plan-digest.js +110 -0
- package/dist/lifecycle/plan-ledger.js +129 -0
- package/dist/lifecycle/receipt-plan.js +192 -0
- package/dist/lifecycle/release-ledger.js +155 -0
- package/dist/lifecycle/release-read.js +64 -0
- package/dist/lifecycle/replay.js +193 -0
- package/dist/lifecycle/rollback.js +102 -0
- package/dist/lifecycle/run-ledger.js +183 -0
- package/dist/lifecycle/scenario-eval.js +204 -0
- package/dist/lifecycle/scenario.js +214 -0
- package/dist/lifecycle/snapshot.js +239 -0
- package/dist/lifecycle/status.js +447 -0
- package/dist/lifecycle/symptoms.js +117 -0
- package/dist/lifecycle/teardown.js +255 -0
- package/dist/lifecycle/types.js +1 -0
- package/dist/lifecycle/unobserved-gate.js +33 -0
- package/dist/lifecycle/wave-plans.js +68 -0
- package/dist/lifecycle/work-item-id.js +36 -0
- package/dist/lifecycle/work-lease.js +393 -0
- package/dist/lint/component-checks.js +87 -0
- package/dist/lint/config.js +483 -0
- package/dist/lint/declarative.js +122 -0
- package/dist/lint/discover.d.ts.map +1 -1
- package/dist/lint/discover.js +138 -0
- package/dist/lint/engine.js +246 -0
- package/dist/lint/knowledge-checks.js +64 -0
- package/dist/lint/named-checks.js +22 -0
- package/dist/lint/output-checks.js +87 -0
- package/dist/lint/output-docs.js +163 -0
- package/dist/lint/parser.js +33 -0
- package/dist/lint/pipeline-change-gate.js +70 -0
- package/dist/lint/policy-import.d.ts +1 -1
- package/dist/lint/policy-import.d.ts.map +1 -1
- package/dist/lint/policy-import.js +62 -0
- package/dist/lint/policy-sandbox.js +86 -0
- package/dist/lint/policy.js +122 -0
- package/dist/lint/post-synth.js +87 -0
- package/dist/lint/presets/relaxed.json +26 -0
- package/dist/lint/presets/strict.json +24 -24
- package/dist/lint/receipt-checks.js +83 -0
- package/dist/lint/rule-loader.d.ts.map +1 -1
- package/dist/lint/rule-loader.js +89 -0
- package/dist/lint/rule-registry.js +86 -0
- package/dist/lint/rule.js +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.js +7 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.js +7 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.js +9 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.js +11 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.js +9 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.js +25 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.js +8 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.js +21 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.js +8 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/agent-turn.component.js +24 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.js +17 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.js +8 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.js +18 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.js +20 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.js +8 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.js +12 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.js +16 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.js +8 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.js +12 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.js +11 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.js +11 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.js +10 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.js +16 -0
- package/dist/lint/rules/comp/comp001-publishes-never-applies.js +69 -0
- package/dist/lint/rules/comp/comp002-dangling-wiring-ref.js +84 -0
- package/dist/lint/rules/comp/comp003-mutating-no-rollback.js +103 -0
- package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.js +70 -0
- package/dist/lint/rules/comp/comp005-capability-kind-is-noun.js +109 -0
- package/dist/lint/rules/comp/comp006-shell-needs-reason.js +49 -0
- package/dist/lint/rules/comp/comp007-composition-sprawl.js +64 -0
- package/dist/lint/rules/comp/index.js +33 -0
- package/dist/lint/rules/comp/support.js +129 -0
- package/dist/lint/rules/composite-scope.js +51 -0
- package/dist/lint/rules/cor017-composite-name-match.js +93 -0
- package/dist/lint/rules/cor018-composite-prefer-lexicon-type.js +136 -0
- package/dist/lint/rules/cor021-env-literal-name.js +100 -0
- package/dist/lint/rules/cor022-receipt-leaf.js +118 -0
- package/dist/lint/rules/cor024-receipt-secret-pointer.js +199 -0
- package/dist/lint/rules/declarable-naming-convention.js +62 -0
- package/dist/lint/rules/evl001-non-literal-expression.js +66 -0
- package/dist/lint/rules/evl002-control-flow-resource.js +69 -0
- package/dist/lint/rules/evl003-dynamic-property-access.js +44 -0
- package/dist/lint/rules/evl004-spread-non-const.js +94 -0
- package/dist/lint/rules/evl005-resource-block-body.js +41 -0
- package/dist/lint/rules/evl007-invalid-siblings.js +105 -0
- package/dist/lint/rules/evl009-composite-no-constant.js +158 -0
- package/dist/lint/rules/evl010-composite-no-transform.js +59 -0
- package/dist/lint/rules/evl011-symbolic-in-template.js +106 -0
- package/dist/lint/rules/export-required.js +115 -0
- package/dist/lint/rules/file-declarable-limit.js +88 -0
- package/dist/lint/rules/flat-declarations.js +62 -0
- package/dist/lint/rules/index.js +90 -0
- package/dist/lint/rules/no-cyclic-declarable-ref.js +138 -0
- package/dist/lint/rules/no-redundant-type-import.js +76 -0
- package/dist/lint/rules/no-redundant-value-cast.js +41 -0
- package/dist/lint/rules/no-string-ref.js +59 -0
- package/dist/lint/rules/no-unused-declarable-import.js +75 -0
- package/dist/lint/rules/no-unused-declarable.js +142 -0
- package/dist/lint/rules/op/index.js +28 -0
- package/dist/lint/rules/op/ops012-activity-contract.js +54 -0
- package/dist/lint/rules/op/ops013-step-output-ref.js +88 -0
- package/dist/lint/rules/op/ops014-converge-rule-refusals.js +114 -0
- package/dist/lint/rules/op/ops015-gate-approval.js +45 -0
- package/dist/lint/rules/op/support.js +11 -0
- package/dist/lint/rules/op/sys010-key-over-plain-http.js +100 -0
- package/dist/lint/rules/property-kind.js +56 -0
- package/dist/lint/rules/single-concern-file.js +71 -0
- package/dist/lint/rules/sys001-no-literal-key.js +60 -0
- package/dist/lint/selectors.js +168 -0
- package/dist/lint/suppressions.js +129 -0
- package/dist/lint/typescript.js +17 -0
- package/dist/live-endpoint.js +113 -0
- package/dist/live-read-session.js +76 -0
- package/dist/lsp/lexicon-providers.js +163 -0
- package/dist/lsp/types.js +5 -0
- package/dist/managed-fields.js +293 -0
- package/dist/mcp/types.js +4 -0
- package/dist/notify-verify.js +0 -1
- package/dist/notify.js +0 -1
- package/dist/notify.schema.json +72 -0
- package/dist/observation.js +266 -0
- package/dist/okf-read.js +134 -0
- package/dist/okf.js +275 -0
- package/dist/op/__fixtures__/decide-stub-backend.js +125 -0
- package/dist/op/activities/activity-contracts.d.ts +1 -1
- package/dist/op/activities/activity-contracts.js +313 -0
- package/dist/op/activities/apply.js +582 -0
- package/dist/op/activities/build.js +18 -0
- package/dist/op/activities/change-coverage.js +40 -0
- package/dist/op/activities/change-set.d.ts +8 -3
- package/dist/op/activities/change-set.d.ts.map +1 -1
- package/dist/op/activities/change-set.js +67 -0
- package/dist/op/activities/converge.js +492 -0
- package/dist/op/activities/decide.js +211 -0
- package/dist/op/activities/env-teardown.js +110 -0
- package/dist/op/activities/factory.js +591 -0
- package/dist/op/activities/forge-pull-request.js +82 -0
- package/dist/op/activities/gh-host.js +78 -0
- package/dist/op/activities/guard-validate.js +165 -0
- package/dist/op/activities/http-check.js +40 -0
- package/dist/op/activities/index.js +59 -0
- package/dist/op/activities/lexicon-upgrade.js +629 -0
- package/dist/op/activities/lifecycle.js +109 -0
- package/dist/op/activities/pipeline-audit.js +147 -0
- package/dist/op/activities/policy.js +26 -0
- package/dist/op/activities/predict-behaviour.js +341 -0
- package/dist/op/activities/propose-upgrade.js +165 -0
- package/dist/op/activities/reconcile.d.ts +28 -16
- package/dist/op/activities/reconcile.d.ts.map +1 -1
- package/dist/op/activities/reconcile.js +1011 -0
- package/dist/op/activities/shell.js +118 -0
- package/dist/op/activities/source-release.js +97 -0
- package/dist/op/activities/source-rollback.js +165 -0
- package/dist/op/activities/teardown.js +17 -0
- package/dist/op/activities/util.js +6 -0
- package/dist/op/activities/wait.js +51 -0
- package/dist/op/activities/work-evidence.js +35 -0
- package/dist/op/activities/workflow-audit.js +133 -0
- package/dist/op/activity-contract-registry.js +106 -0
- package/dist/op/activity-contract.js +232 -0
- package/dist/op/activity-failure.js +31 -0
- package/dist/op/activity-profiles.js +129 -0
- package/dist/op/activity-registry.js +105 -0
- package/dist/op/activity-runtime.js +28 -0
- package/dist/op/builders.d.ts +1 -1
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/builders.js +801 -0
- package/dist/op/change-signal.js +118 -0
- package/dist/op/composites/apply-op.js +151 -0
- package/dist/op/composites/behaviour-op.js +65 -0
- package/dist/op/composites/converge-op.js +141 -0
- package/dist/op/composites/index.js +19 -0
- package/dist/op/composites/lexicon-upgrade-op.js +107 -0
- package/dist/op/composites/pipeline-audit-op.js +50 -0
- package/dist/op/composites/reconcile-op.js +84 -0
- package/dist/op/composites/watch-op.js +69 -0
- package/dist/op/composites/workflow-audit-op.js +57 -0
- package/dist/op/converge-rule.js +205 -0
- package/dist/op/cron.js +146 -0
- package/dist/op/decide-backend.js +181 -0
- package/dist/op/decide-config.js +68 -0
- package/dist/op/decide-read-inputs.js +141 -0
- package/dist/op/discover.d.ts.map +1 -1
- package/dist/op/discover.js +213 -0
- package/dist/op/duration.js +21 -0
- package/dist/op/emulator-freshness.js +80 -0
- package/dist/op/emulator-lifecycle.js +269 -0
- package/dist/op/factory.js +83 -0
- package/dist/op/gate-approval.js +172 -0
- package/dist/op/gate-name.js +86 -0
- package/dist/op/gate-plan-context.js +167 -0
- package/dist/op/gate-point-run.js +67 -0
- package/dist/op/gate-point.js +111 -0
- package/dist/op/gate-resume-plan.js +155 -0
- package/dist/op/gate-resume.js +31 -0
- package/dist/op/gate-review.js +290 -0
- package/dist/op/gate-run-locator.js +85 -0
- package/dist/op/gate-summary.js +100 -0
- package/dist/op/gate-wait.js +56 -0
- package/dist/op/gate.js +449 -0
- package/dist/op/generate-pipeline.js +124 -0
- package/dist/op/index.js +51 -0
- package/dist/op/lifecycle-receipt-store.js +45 -0
- package/dist/op/local-executor.js +1164 -0
- package/dist/op/local-output.js +140 -0
- package/dist/op/op-ir.js +317 -0
- package/dist/op/op-verb-class.js +131 -0
- package/dist/op/op-waves-notify.js +136 -0
- package/dist/op/op-waves-run.d.ts +1 -1
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves-run.js +1657 -0
- package/dist/op/op-waves.js +409 -0
- package/dist/op/operator.js +743 -0
- package/dist/op/receipt-store.js +94 -0
- package/dist/op/resource.js +23 -0
- package/dist/op/run-context.js +28 -0
- package/dist/op/run-live.js +256 -0
- package/dist/op/runtime.js +21 -0
- package/dist/op/runtimes/local.js +195 -0
- package/dist/op/source-archive.js +131 -0
- package/dist/op/step-output-ref.js +397 -0
- package/dist/op/steward-beside.js +169 -0
- package/dist/op/steward-points.js +138 -0
- package/dist/op/steward-turn.js +59 -0
- package/dist/op/steward.js +317 -0
- package/dist/op/types.js +25 -0
- package/dist/op/work-lease-decl.js +81 -0
- package/dist/op/work-lease-run.js +393 -0
- package/dist/override-gate.js +284 -0
- package/dist/owner-chain.js +74 -0
- package/dist/ownership.js +92 -0
- package/dist/params.js +61 -0
- package/dist/plan-summary.js +711 -0
- package/dist/point-decision.js +211 -0
- package/dist/pr-forge.js +810 -0
- package/dist/pr-loop.js +203 -0
- package/dist/project-codegen.js +191 -0
- package/dist/project-root.js +74 -0
- package/dist/project-validation.js +50 -0
- package/dist/provenance.js +157 -0
- package/dist/pseudo-parameter.js +40 -0
- package/dist/reconcile.js +450 -0
- package/dist/resource-attributes.js +33 -0
- package/dist/runtime-adapter.js +77 -0
- package/dist/runtime.js +66 -0
- package/dist/secret-materialization.js +153 -0
- package/dist/secret-provenance.js +250 -0
- package/dist/serializer-walker.js +112 -0
- package/dist/serializer.js +1 -0
- package/dist/sort.js +45 -0
- package/dist/stack-output.js +115 -0
- package/dist/telemetry-attribution.js +149 -0
- package/dist/terraform/__fixtures__/build-graph.js +63 -0
- package/dist/terraform/adopt-state.js +40 -0
- package/dist/terraform/aws-resources.js +384 -0
- package/dist/terraform/bridge.js +204 -0
- package/dist/terraform/carve-provider.js +155 -0
- package/dist/terraform/carve.js +138 -0
- package/dist/terraform/data-source-shape.js +57 -0
- package/dist/terraform/emit-source.js +36 -0
- package/dist/terraform/excise.js +123 -0
- package/dist/terraform/graduate.js +128 -0
- package/dist/terraform/graph.js +435 -0
- package/dist/terraform/hcl2json.js +60 -0
- package/dist/terraform/manifest.js +149 -0
- package/dist/terraform/parse.js +81 -0
- package/dist/terraform/providers/aws.js +146 -0
- package/dist/terraform/providers/gcp.js +294 -0
- package/dist/terraform/providers/index.js +17 -0
- package/dist/terraform/providers/kubernetes.js +253 -0
- package/dist/terraform/score.js +151 -0
- package/dist/terraform/state.js +67 -0
- package/dist/terraform/tier-map.js +74 -0
- package/dist/terraform/types.js +13 -0
- package/dist/terraform/unified-diff.js +132 -0
- package/dist/testing.js +295 -0
- package/dist/toml-emit.js +153 -0
- package/dist/toml-parse.js +355 -0
- package/dist/toml-utils.js +60 -0
- package/dist/toml.js +428 -0
- package/dist/ts-loader.d.ts +46 -0
- package/dist/ts-loader.d.ts.map +1 -0
- package/dist/ts-loader.js +103 -0
- package/dist/types.js +1 -0
- package/dist/utils.js +61 -0
- package/dist/validation.js +20 -0
- package/dist/vendor/js-yaml-load.js +1662 -0
- package/dist/workspace/__fixtures__/contract-repo.d.ts +7 -0
- package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/contract-repo.js +119 -0
- package/dist/workspace/__fixtures__/decide-workspace.js +112 -0
- package/dist/workspace/__fixtures__/sessions.d.ts +1 -1
- package/dist/workspace/__fixtures__/sessions.d.ts.map +1 -1
- package/dist/workspace/__fixtures__/sessions.js +91 -0
- package/dist/workspace/__fixtures__/two-member-workspace.js +34 -0
- package/dist/workspace/agent-cli.js +99 -0
- package/dist/workspace/agent.schema.json +390 -0
- package/dist/workspace/answers-ledger.js +89 -0
- package/dist/workspace/box-cli.js +142 -0
- package/dist/workspace/box-factory-write.js +196 -0
- package/dist/workspace/box-factory-write.schema.json +342 -0
- package/dist/workspace/box-factory.js +88 -0
- package/dist/workspace/box-intent.js +126 -0
- package/dist/workspace/box-isolation.js +169 -0
- package/dist/workspace/box-listing-write.schema.json +204 -0
- package/dist/workspace/box-listing.js +298 -0
- package/dist/workspace/box-publish.js +352 -0
- package/dist/workspace/box-publish.schema.json +498 -0
- package/dist/workspace/box-services.js +39 -0
- package/dist/workspace/broker-protocol.js +359 -0
- package/dist/workspace/broker-protocol.schema.json +228 -0
- package/dist/workspace/change-set.schema.json +462 -0
- package/dist/workspace/changes-cli.js +56 -0
- package/dist/workspace/changes.js +446 -0
- package/dist/workspace/changes.schema.json +642 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-fly-site.js +198 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-live-names.js +155 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-rollback.js +214 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-inputs.js +180 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit-ship-policy.js +99 -0
- package/dist/workspace/chant-migrations/chud-lexicon-exit.js +847 -0
- package/dist/workspace/chant-migrations.js +113 -0
- package/dist/workspace/check.schema.json +433 -0
- package/dist/workspace/checks/box-isolation.js +62 -0
- package/dist/workspace/checks/boxes.js +491 -0
- package/dist/workspace/checks/diagrams.js +104 -0
- package/dist/workspace/checks/generated.js +419 -0
- package/dist/workspace/checks/ledgers.js +212 -0
- package/dist/workspace/checks/links.js +191 -0
- package/dist/workspace/checks/live.js +100 -0
- package/dist/workspace/checks/pipelines.js +188 -0
- package/dist/workspace/checks/records.js +169 -0
- package/dist/workspace/checks.js +426 -0
- package/dist/workspace/ci-green-cli.js +125 -0
- package/dist/workspace/ci-green-forge.js +83 -0
- package/dist/workspace/ci-green-workflow.d.ts +3 -1
- package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
- package/dist/workspace/ci-green-workflow.js +202 -0
- package/dist/workspace/ci-green.js +325 -0
- package/dist/workspace/ci-last-green.schema.json +158 -0
- package/dist/workspace/class-data.d.ts +84 -0
- package/dist/workspace/class-data.d.ts.map +1 -0
- package/dist/workspace/class-data.js +238 -0
- package/dist/workspace/compose-graph.js +235 -0
- package/dist/workspace/compose-reports.js +146 -0
- package/dist/workspace/composites.js +264 -0
- package/dist/workspace/composites.schema.json +617 -0
- package/dist/workspace/conformance/__fixture__/app/package.json +7 -0
- package/dist/workspace/conformance/__fixture__/app/src/server.mjs +29 -0
- package/dist/workspace/conformance/__fixture__/decisions/decision.kind.mjs +54 -0
- package/dist/workspace/conformance/__fixture__/decisions/decision.schema.json +512 -0
- package/dist/workspace/conformance/__fixture__/decisions/fix-001-how-the-app-is-deployed.md +40 -0
- package/dist/workspace/conformance/__fixture__/delivery/chant.config.ts +7 -0
- package/dist/workspace/conformance/__fixture__/delivery/lexicon/index.ts +26 -0
- package/dist/workspace/conformance/__fixture__/delivery/package.json +7 -0
- package/dist/workspace/conformance/__fixture__/delivery/src/app.component.ts +14 -0
- package/dist/workspace/conformance/__fixture__/delivery/src/app.ts +4 -0
- package/dist/workspace/conformance/__fixtures__/reference-broker.js +205 -0
- package/dist/workspace/conformance/__writer_fixture__/answers/answer.kind.mjs +32 -0
- package/dist/workspace/conformance/__writer_fixture__/answers/answer.schema.json +135 -0
- package/dist/workspace/conformance/__writer_fixture__/contracts/contract.kind.mjs +37 -0
- package/dist/workspace/conformance/__writer_fixture__/contracts/contract.schema.json +213 -0
- package/dist/workspace/conformance/__writer_fixture__/decisions/points.json +228 -0
- package/dist/workspace/conformance/__writer_fixture__/drivers/driver.kind.mjs +15 -0
- package/dist/workspace/conformance/__writer_fixture__/drivers/driver.schema.json +38 -0
- package/dist/workspace/conformance/__writer_fixture__/sessions/session.kind.mjs +54 -0
- package/dist/workspace/conformance/__writer_fixture__/sessions/session.schema.json +289 -0
- package/dist/workspace/conformance/__writer_fixture__/work/W-001-the-writer-suite-works-this-item.md +25 -0
- package/dist/workspace/conformance/__writer_fixture__/work/work.kind.mjs +60 -0
- package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +603 -0
- package/dist/workspace/conformance/broker.js +736 -0
- package/dist/workspace/conformance/index.js +673 -0
- package/dist/workspace/conformance/vitest.js +108 -0
- package/dist/workspace/conformance/writer.js +1080 -0
- package/dist/workspace/decide.js +879 -0
- package/dist/workspace/decision-points.schema.json +135 -135
- package/dist/workspace/declaration-write-cli.js +74 -0
- package/dist/workspace/declaration-write.js +238 -0
- package/dist/workspace/declaration.js +938 -0
- package/dist/workspace/declaration.schema.json +1413 -1413
- package/dist/workspace/declared-kinds.js +106 -0
- package/dist/workspace/environments.js +164 -0
- package/dist/workspace/evidence.schema.json +279 -0
- package/dist/workspace/export-cli.js +185 -0
- package/dist/workspace/export.js +499 -0
- package/dist/workspace/factory-rules.js +175 -0
- package/dist/workspace/generated-files.js +92 -0
- package/dist/workspace/glob.js +45 -0
- package/dist/workspace/graph-cache.js +352 -0
- package/dist/workspace/graph-cli.js +348 -0
- package/dist/workspace/graph.schema.json +1338 -0
- package/dist/workspace/identity-gate-rule.js +75 -0
- package/dist/workspace/identity.js +126 -0
- package/dist/workspace/import.js +283 -0
- package/dist/workspace/init.js +620 -0
- package/dist/workspace/intent-cli.js +263 -0
- package/dist/workspace/intent-joins.js +201 -0
- package/dist/workspace/intent-record.js +352 -0
- package/dist/workspace/intent-record.schema.json +864 -0
- package/dist/workspace/intent.js +1582 -0
- package/dist/workspace/intent.schema.json +2420 -0
- package/dist/workspace/json-edit.js +221 -0
- package/dist/workspace/jsonc.js +235 -0
- package/dist/workspace/kind-readers.js +103 -0
- package/dist/workspace/kinds.d.ts +3 -7
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/kinds.js +553 -0
- package/dist/workspace/lexicon-symbols.js +112 -0
- package/dist/workspace/lineage-adopt-cli.js +102 -0
- package/dist/workspace/lineage-adopt.js +360 -0
- package/dist/workspace/lineage-check.js +282 -0
- package/dist/workspace/lineage-cli.js +121 -0
- package/dist/workspace/lineage-hash-index.js +284 -0
- package/dist/workspace/lineage-init.js +507 -0
- package/dist/workspace/lineage-lock.js +387 -0
- package/dist/workspace/lineage-merge.js +45 -0
- package/dist/workspace/lineage-migrations.d.ts.map +1 -1
- package/dist/workspace/lineage-migrations.js +329 -0
- package/dist/workspace/lineage-provenance.js +36 -0
- package/dist/workspace/lineage-update.js +138 -0
- package/dist/workspace/lineage-upgrade-cli.js +131 -0
- package/dist/workspace/lineage-upgrade.js +889 -0
- package/dist/workspace/lineage-vendor.js +171 -0
- package/dist/workspace/lineage-version.js +128 -0
- package/dist/workspace/lineage-versions.js +275 -0
- package/dist/workspace/links.js +330 -0
- package/dist/workspace/ls-generated.js +95 -0
- package/dist/workspace/ls.js +277 -0
- package/dist/workspace/ls.schema.json +333 -0
- package/dist/workspace/member-commands.js +508 -0
- package/dist/workspace/member-handles.js +216 -0
- package/dist/workspace/member-pipeline.js +258 -0
- package/dist/workspace/member-run.js +117 -0
- package/dist/workspace/member-write.schema.json +193 -0
- package/dist/workspace/nested-graph.js +156 -0
- package/dist/workspace/nesting.js +38 -0
- package/dist/workspace/patch.js +301 -0
- package/dist/workspace/patch.schema.json +321 -0
- package/dist/workspace/pin-cli.js +55 -0
- package/dist/workspace/pin-integrity.js +100 -0
- package/dist/workspace/plan-summary.schema.json +155 -0
- package/dist/workspace/point-answer.schema.json +129 -129
- package/dist/workspace/points-cli.js +291 -0
- package/dist/workspace/points-write.schema.json +660 -0
- package/dist/workspace/points.js +521 -0
- package/dist/workspace/points.schema.json +916 -0
- package/dist/workspace/pr-report.schema.json +108 -0
- package/dist/workspace/principal-classes.d.ts +4 -11
- package/dist/workspace/principal-classes.d.ts.map +1 -1
- package/dist/workspace/principal-classes.js +162 -0
- package/dist/workspace/reason-codes.js +326 -0
- package/dist/workspace/record-assets.js +151 -0
- package/dist/workspace/record-decided.js +105 -0
- package/dist/workspace/record-sessions.js +96 -0
- package/dist/workspace/record-source.js +114 -0
- package/dist/workspace/records-amend.schema.json +284 -0
- package/dist/workspace/records-checkout.js +76 -0
- package/dist/workspace/records-cli.js +707 -0
- package/dist/workspace/records-close.js +116 -0
- package/dist/workspace/records-close.schema.json +278 -0
- package/dist/workspace/records-new.schema.json +202 -0
- package/dist/workspace/records-review.schema.json +367 -0
- package/dist/workspace/records-since.js +317 -0
- package/dist/workspace/records-since.schema.json +218 -0
- package/dist/workspace/records-write.js +1229 -0
- package/dist/workspace/records.js +1345 -0
- package/dist/workspace/records.schema.json +604 -0
- package/dist/workspace/reference-kinds/app/package.json +10 -0
- package/dist/workspace/reference-kinds/app/workspace-kinds.json +45 -0
- package/dist/workspace/returns.js +303 -0
- package/dist/workspace/root-refusal.js +75 -0
- package/dist/workspace/run-statement.schema.json +622 -0
- package/dist/workspace/runs-cli.js +584 -0
- package/dist/workspace/runs-write.schema.json +994 -0
- package/dist/workspace/runs.js +708 -0
- package/dist/workspace/runs.schema.json +1257 -0
- package/dist/workspace/runtimes.js +76 -0
- package/dist/workspace/session-kinds.js +83 -0
- package/dist/workspace/signers.schema.json +206 -0
- package/dist/workspace/source-block.js +125 -0
- package/dist/workspace/squash.js +177 -0
- package/dist/workspace/status-gates.js +162 -0
- package/dist/workspace/status-stewards.js +330 -0
- package/dist/workspace/status.js +514 -0
- package/dist/workspace/status.schema.json +998 -0
- package/dist/workspace/steward-index.js +191 -0
- package/dist/workspace/symbols.js +188 -0
- package/dist/workspace/template-manifest.js +227 -0
- package/dist/workspace/template-pins.js +115 -0
- package/dist/workspace/trailer-joins.js +65 -0
- package/dist/workspace/trailers.js +111 -0
- package/dist/workspace/tree.js +136 -0
- package/dist/workspace/trust/attestor.js +63 -0
- package/dist/workspace/trust/dsse.js +108 -0
- package/dist/workspace/trust/evidence-cli.js +175 -0
- package/dist/workspace/trust/evidence.js +161 -0
- package/dist/workspace/trust/gate-seal.js +226 -0
- package/dist/workspace/trust/policy.js +190 -0
- package/dist/workspace/trust/provenance.js +180 -0
- package/dist/workspace/trust/rotation.js +298 -0
- package/dist/workspace/trust/run-commits.js +101 -0
- package/dist/workspace/trust/run-statement.js +182 -0
- package/dist/workspace/trust/seal.js +272 -0
- package/dist/workspace/trust/signers-cli.js +152 -0
- package/dist/workspace/trust/ssh-commit.js +178 -0
- package/dist/workspace/trust/test-repo.js +118 -0
- package/dist/workspace/trust/trust-files.js +193 -0
- package/dist/workspace/trust/verify-cli.js +63 -0
- package/dist/workspace/trust/verify.js +192 -0
- package/dist/workspace/which-chant.js +141 -0
- package/dist/workspace/wip-cli.js +95 -0
- package/dist/workspace/wip-write.schema.json +504 -0
- package/dist/workspace/wip.js +631 -0
- package/dist/workspace/wip.schema.json +334 -0
- package/dist/workspace/work-cli.js +448 -0
- package/dist/workspace/work-evidence.js +122 -0
- package/dist/workspace/work-evidence.schema.json +222 -0
- package/dist/workspace/work-history.schema.json +421 -0
- package/dist/workspace/work-lease.schema.json +246 -0
- package/dist/workspace/work-size.js +77 -0
- package/dist/workspace/work.js +283 -0
- package/dist/workspace/workspace-kinds.schema.json +259 -259
- package/dist/workspace/workspace-principals.schema.json +53 -53
- package/dist/workspace/write-lock-cli.js +105 -0
- package/dist/workspace/write-lock.js +424 -0
- package/dist/workspace/write-lock.schema.json +172 -0
- package/dist/workspace/write-scope.js +484 -0
- package/dist/yaml.js +459 -0
- package/package.json +2 -2
- package/src/build.ts +8 -0
- package/src/change-set.test.ts +48 -0
- package/src/change-set.ts +52 -2
- package/src/ci-jobs.test.ts +49 -0
- package/src/ci-jobs.ts +515 -0
- package/src/cli/commands/check-lexicon-plugin.ts +2 -0
- package/src/cli/commands/lint.ts +3 -0
- package/src/cli/commands/migrate.ts +2 -0
- package/src/cli/compiled-cli.e2e.test.ts +165 -0
- package/src/cli/main.ts +121 -27
- package/src/cli/mcp/workspace-tools.ts +1 -1
- package/src/codegen/pinned-upgrade.ts +2 -0
- package/src/components/discover.ts +2 -0
- package/src/components/pr-pipeline.ts +3 -2
- package/src/components/sandbox/driver.ts +3 -1
- package/src/composite.ts +15 -3
- package/src/config-import.ts +3 -0
- package/src/discovery/collect.ts +15 -1
- package/src/discovery/fold-build-parity.test.ts +71 -0
- package/src/discovery/fold-import.ts +25 -127
- package/src/discovery/fold-project-provenance.test.ts +21 -4
- package/src/discovery/host-composite.ts +101 -0
- package/src/discovery/import.ts +2 -0
- package/src/discovery/index.ts +11 -1
- package/src/discovery/sandbox/driver.ts +3 -1
- package/src/gate-decision-bundle.test.ts +5 -4
- package/src/gate-decision-identity.test.ts +59 -6
- package/src/gate-decision.ts +81 -21
- package/src/lexicon-module.ts +3 -0
- package/src/lifecycle/gate-audit.test.ts +55 -1
- package/src/lifecycle/gate-audit.ts +116 -3
- package/src/lifecycle/gate-ledger.test.ts +20 -1
- package/src/lifecycle/gate-ledger.ts +33 -1
- package/src/lint/config.ts +1 -1
- package/src/lint/discover.ts +28 -8
- package/src/lint/policy-import.ts +4 -1
- package/src/lint/rule-loader.ts +2 -0
- package/src/op/activities/activity-contracts.ts +1 -1
- package/src/op/activities/change-set.ts +11 -3
- package/src/op/activities/lexicon-upgrade.test.ts +2 -0
- package/src/op/activities/reconcile.test.ts +62 -2
- package/src/op/activities/reconcile.ts +46 -22
- package/src/op/builders.ts +1 -1
- package/src/op/discover.ts +3 -0
- package/src/op/op-waves-run.ts +4 -3
- package/src/op/op-waves.test.ts +2 -0
- package/src/op/work-lease-run.test.ts +12 -4
- package/src/ts-loader.test.ts +23 -0
- package/src/ts-loader.ts +122 -0
- package/src/workspace/__fixtures__/contract-repo.ts +17 -1
- package/src/workspace/__fixtures__/sessions.ts +3 -3
- package/src/workspace/change-set.schema.json +5 -3
- package/src/workspace/chant-migrations/chud-lexicon-exit.ts +1 -1
- package/src/workspace/ci-green-workflow.test.ts +4 -4
- package/src/workspace/ci-green-workflow.ts +5 -2
- package/src/workspace/class-data.test.ts +64 -0
- package/src/workspace/class-data.ts +236 -0
- package/src/workspace/declaration.ts +1 -1
- package/src/workspace/kinds.ts +7 -36
- package/src/workspace/lineage-migrations.ts +2 -0
- package/src/workspace/points.ts +1 -1
- package/src/workspace/principal-classes.ts +12 -95
- package/src/workspace/records-formats.test.ts +7 -2
- package/src/workspace/records-sessions-write.test.ts +3 -3
- package/src/workspace/status-contract.e2e.test.ts +37 -0
- package/src/workspace/status-contract.test.ts +23 -21
|
@@ -0,0 +1,743 @@
|
|
|
1
|
+
import { discoverOps } from "./discover.js";
|
|
2
|
+
import { runOpLocally, OpRunFailure } from "./local-executor.js";
|
|
3
|
+
import { acquireLease, releaseLease, stillHoldsLease, currentHolderId, readLease, DEFAULT_LEASE_TTL_MS } from "../lifecycle/lease.js";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { readRunLedger, runEnvOf } from "../lifecycle/run-ledger.js";
|
|
6
|
+
import { readGateLedger, latestResolutionSince } from "../lifecycle/gate-ledger.js";
|
|
7
|
+
import { enterStewardTurn } from "./steward-turn.js";
|
|
8
|
+
import { stewardBesideOf, stewardLeaseName, stewardTurnLeaseName, stewardTurnOps } from "./steward.js";
|
|
9
|
+
import { askReady, spawnBesideRun } from "./steward-beside.js";
|
|
10
|
+
import { stewardWorkHolder } from "./work-lease-run.js";
|
|
11
|
+
import { StaleLockError } from "../lifecycle/git.js";
|
|
12
|
+
import { cronMatches, cronDueBetween } from "./cron.js";
|
|
13
|
+
import { createChangeSignalGate, DEFAULT_SIGNAL_FLOOR_MS } from "./change-signal.js";
|
|
14
|
+
/**
|
|
15
|
+
* Poll interval between rounds — the operator's own cadence, and the fallback
|
|
16
|
+
* for an Op that declares none. Since #2120 an Op can carry its own
|
|
17
|
+
* `schedule.cron` (`./composites/converge-op.ts`), which this loop honours per
|
|
18
|
+
* Op: the round still wakes every `intervalMs`, but an Op with a cron is
|
|
19
|
+
* ticked only on the minutes that cron fires. Chosen short enough to converge
|
|
20
|
+
* promptly, long enough not to hammer `chant lifecycle plan --live` every few
|
|
21
|
+
* seconds — and short enough that a per-minute cron is not missed.
|
|
22
|
+
*/
|
|
23
|
+
export const DEFAULT_OPERATOR_INTERVAL_MS = 60000;
|
|
24
|
+
/** One ConvergeOp's own `labels.Env` (`./composites/converge-op.ts` always sets it). `undefined` for a non-ConvergeOp or a hand-built one missing it — filtered out by `isConvergeOp` before this is trusted. */
|
|
25
|
+
function envOf(config) {
|
|
26
|
+
return config.labels?.Env;
|
|
27
|
+
}
|
|
28
|
+
function isConvergeOp(config) {
|
|
29
|
+
return config.labels?.Converge === "true";
|
|
30
|
+
}
|
|
31
|
+
/** Discover every `ConvergeOp` in the project (`labels.Converge === "true"`), optionally filtered to one environment. Ops that don't declare an `Env` label are excluded from an `--env`-filtered discovery (there's nothing to match), but included when no `env` filter is given. */
|
|
32
|
+
export async function discoverConvergeOps(opts) {
|
|
33
|
+
const { ops, errors } = await discoverOps({ cwd: opts?.cwd });
|
|
34
|
+
const converge = [...ops.values()].filter((d) => isConvergeOp(d.config));
|
|
35
|
+
const filtered = opts?.env ? converge.filter((d) => envOf(d.config) === opts.env) : converge;
|
|
36
|
+
return { ops: filtered.sort((a, b) => a.config.name.localeCompare(b.config.name)), errors };
|
|
37
|
+
}
|
|
38
|
+
/** A fresh {@link BesideState}. */
|
|
39
|
+
export function createBesideState() {
|
|
40
|
+
return { running: new Map(), started: new Map(), ended: [] };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Release the per-Op leases a stopped operator still holds (#2879), best
|
|
44
|
+
* effort: a lease that is gone or taken over since is left alone, and one that
|
|
45
|
+
* can't be released expires on its TTL as before.
|
|
46
|
+
*/
|
|
47
|
+
export async function releaseHeldLeases(held, holder, opts = {}) {
|
|
48
|
+
const entries = [...held];
|
|
49
|
+
held.clear();
|
|
50
|
+
await Promise.allSettled(entries.map(([op, token]) => releaseLease(op, holder, token, opts)));
|
|
51
|
+
}
|
|
52
|
+
/** Wait for every run in flight beside the turns to end. `chant operator --steward --once` does before it exits. */
|
|
53
|
+
export async function waitForBesideRuns(state) {
|
|
54
|
+
await Promise.all([...state.running.values()].map((r) => r.handle.done));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Ask every run in flight beside the turns to stop, and wait up to `graceMs`
|
|
58
|
+
* for them to end. The operator does when it stops, so no run it started
|
|
59
|
+
* outlives it holding the Op's lease past its renewals.
|
|
60
|
+
*/
|
|
61
|
+
export async function stopBesideRuns(state, graceMs = 10000) {
|
|
62
|
+
const runs = [...state.running.values()];
|
|
63
|
+
for (const r of runs)
|
|
64
|
+
r.handle.stop();
|
|
65
|
+
let timer;
|
|
66
|
+
await Promise.race([
|
|
67
|
+
Promise.all(runs.map((r) => r.handle.done)),
|
|
68
|
+
new Promise((resolve) => {
|
|
69
|
+
timer = setTimeout(resolve, graceMs);
|
|
70
|
+
timer.unref?.();
|
|
71
|
+
}),
|
|
72
|
+
]);
|
|
73
|
+
if (timer)
|
|
74
|
+
clearTimeout(timer);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The steward's Ops whose newest run is the steward's own and stopped on a
|
|
78
|
+
* decision point, with that question's state now. The questions are read
|
|
79
|
+
* from the workspace the way `points` reads them; a workspace that can't be
|
|
80
|
+
* read leaves every run waiting.
|
|
81
|
+
*/
|
|
82
|
+
async function stewardWaits(steward, opts) {
|
|
83
|
+
const out = new Map();
|
|
84
|
+
const runs = [];
|
|
85
|
+
for (const op of steward.ops) {
|
|
86
|
+
try {
|
|
87
|
+
const newest = (await readRunLedger(runEnvOf(op), op.name, { cwd: opts.cwd })).records.at(-1);
|
|
88
|
+
if (newest?.status === "waiting" && newest.point && newest.steward === steward.name) {
|
|
89
|
+
runs.push({ op: op.name, question: newest.point.id, point: newest.point.point, state: newest.point.state });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// A ledger that can't be read has no waiting run to resume.
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (runs.length === 0)
|
|
97
|
+
return out;
|
|
98
|
+
const states = await (opts.readQuestions ?? readQuestionStates)(opts.cwd ?? process.cwd());
|
|
99
|
+
for (const r of runs) {
|
|
100
|
+
const now = states?.get(r.question);
|
|
101
|
+
const answered = states !== null && (now === undefined || now === "answered");
|
|
102
|
+
out.set(r.op, { question: r.question, point: r.point, state: now ?? r.state, answered });
|
|
103
|
+
}
|
|
104
|
+
return out;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The steward's Ops whose newest run is the steward's own and stopped at a
|
|
108
|
+
* gate, and whether the gate has been approved since. A gate ledger that
|
|
109
|
+
* can't be read leaves the run where it stopped.
|
|
110
|
+
*/
|
|
111
|
+
async function stewardGates(steward, opts) {
|
|
112
|
+
const out = new Map();
|
|
113
|
+
for (const op of steward.ops) {
|
|
114
|
+
try {
|
|
115
|
+
const newest = (await readRunLedger(runEnvOf(op), op.name, { cwd: opts.cwd })).records.at(-1);
|
|
116
|
+
if (newest?.status !== "gated" || !newest.gate || newest.steward !== steward.name)
|
|
117
|
+
continue;
|
|
118
|
+
const gateOp = newest.gate.op ?? op.name;
|
|
119
|
+
const { resolutions } = await readGateLedger(gateOp, { cwd: opts.cwd });
|
|
120
|
+
const approved = latestResolutionSince(resolutions, newest.gate.name, newest.gate.since) !== undefined;
|
|
121
|
+
out.set(op.name, { gateOp, gate: newest.gate.name, approved });
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// A ledger that can't be read has no gated run to resume.
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
/** Every question's state in the workspace, by id, or null when the workspace's points can't be read. */
|
|
130
|
+
async function readQuestionStates(cwd) {
|
|
131
|
+
const { readQuestionStates: read } = await import("../workspace/points-cli.js");
|
|
132
|
+
return read(cwd);
|
|
133
|
+
}
|
|
134
|
+
/** Take or renew a local steward's own lease (#2731). */
|
|
135
|
+
export async function acquireStewardLease(steward, holder, opts = {}) {
|
|
136
|
+
return acquireLease(stewardLeaseName(steward), holder, { ...opts, ttlMs: opts.ttlMs ?? DEFAULT_LEASE_TTL_MS });
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* How long a caller contending for a steward's turn lease
|
|
140
|
+
* (`acquireStewardTurn`) retries before giving up (#2750). Long enough to
|
|
141
|
+
* ride out a race with a turn that is just ending; short enough that a
|
|
142
|
+
* genuinely busy steward is reported back promptly. A round never waits
|
|
143
|
+
* (`waitMs` omitted there): it already runs on its own timer and simply
|
|
144
|
+
* tries the turn again next round, exactly as it already does for a busy
|
|
145
|
+
* per-op lease. `chant run <op>` (`../cli/handlers/run.ts`) is the caller
|
|
146
|
+
* that waits, since a human is standing at the terminal for the answer.
|
|
147
|
+
*/
|
|
148
|
+
export const STEWARD_TURN_WAIT_MS = 2000;
|
|
149
|
+
/** How often {@link acquireStewardTurn} retries while it waits. */
|
|
150
|
+
const STEWARD_TURN_POLL_MS = 150;
|
|
151
|
+
/**
|
|
152
|
+
* Take the steward's turn lease (#2750): the lease every run of one of its
|
|
153
|
+
* Ops — a round's scheduled tick, or `chant run <op>` typed by hand — holds
|
|
154
|
+
* for exactly as long as that one run takes, so the two are never beside each
|
|
155
|
+
* other. Distinct from {@link acquireStewardLease}, which one `chant operator
|
|
156
|
+
* --steward` process holds for its whole life: this one is held per-run, so a
|
|
157
|
+
* hand run succeeds the moment a round's tick ends, not only once the daemon
|
|
158
|
+
* itself stops.
|
|
159
|
+
*
|
|
160
|
+
* Contention never queues past `waitMs` (0 by default): consistent with a
|
|
161
|
+
* round's own leases, which skip and report rather than wait (see this
|
|
162
|
+
* module's doc), and with the fountain form, whose busy teammate is likewise
|
|
163
|
+
* refused rather than retried. A caller that wants to ride out a race with a
|
|
164
|
+
* turn about to end passes `waitMs`, and this polls every
|
|
165
|
+
* {@link STEWARD_TURN_POLL_MS} until it acquires or the wait runs out.
|
|
166
|
+
*/
|
|
167
|
+
export async function acquireStewardTurn(steward, holder, opts = {}) {
|
|
168
|
+
const deadline = Date.now() + (opts.waitMs ?? 0);
|
|
169
|
+
for (;;) {
|
|
170
|
+
const result = await acquireLease(stewardTurnLeaseName(steward), holder, {
|
|
171
|
+
cwd: opts.cwd,
|
|
172
|
+
ttlMs: opts.ttlMs ?? DEFAULT_LEASE_TTL_MS,
|
|
173
|
+
now: opts.now,
|
|
174
|
+
});
|
|
175
|
+
if (result.acquired || result.reason !== "held" || Date.now() >= deadline)
|
|
176
|
+
return result;
|
|
177
|
+
await new Promise((r) => setTimeout(r, STEWARD_TURN_POLL_MS));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/** Release a steward's turn lease, best-effort — a run whose turn was never actually acquired (or already lost) has nothing to release. */
|
|
181
|
+
async function releaseStewardTurn(steward, holder, token, opts = {}) {
|
|
182
|
+
await releaseLease(stewardTurnLeaseName(steward), holder, token, opts).catch(() => false);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* The Ops one round runs as turns: a steward's Ops but those beside its turns
|
|
186
|
+
* (#2861), or every ConvergeOp. A steward's Op with no schedule is considered
|
|
187
|
+
* only to resume a run of the steward's that waits on a decision point.
|
|
188
|
+
*/
|
|
189
|
+
async function roundOps(opts) {
|
|
190
|
+
if (opts.steward)
|
|
191
|
+
return stewardTurnOps(opts.steward);
|
|
192
|
+
const { ops } = await discoverConvergeOps({ cwd: opts.cwd, env: opts.env });
|
|
193
|
+
return ops.map((d) => d.config);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Run exactly one round: for every discovered ConvergeOp (filtered per
|
|
197
|
+
* `opts.env`), try its lease; tick the ones this holder wins. Returns one
|
|
198
|
+
* event per discovered op, in discovery order — deterministic, so tests can
|
|
199
|
+
* assert on it directly without depending on log output.
|
|
200
|
+
*/
|
|
201
|
+
export async function runOperatorRound(opts) {
|
|
202
|
+
const holder = opts.holder ?? currentHolderId();
|
|
203
|
+
const events = [];
|
|
204
|
+
const steward = opts.steward;
|
|
205
|
+
const leaseOpts = { cwd: opts.cwd, ttlMs: opts.leaseTtlMs, now: opts.now };
|
|
206
|
+
// A local steward is one writer (#2731): its round runs only while it holds
|
|
207
|
+
// its own lease, renewed here and again after every tick, so a turn longer
|
|
208
|
+
// than the lease's TTL still keeps it.
|
|
209
|
+
const holdSteward = async () => {
|
|
210
|
+
if (!steward)
|
|
211
|
+
return true;
|
|
212
|
+
let acquired;
|
|
213
|
+
try {
|
|
214
|
+
acquired = await acquireStewardLease(steward.name, holder, leaseOpts);
|
|
215
|
+
}
|
|
216
|
+
catch (err) {
|
|
217
|
+
events.push({
|
|
218
|
+
kind: "lease-error",
|
|
219
|
+
op: stewardLeaseName(steward.name),
|
|
220
|
+
env: "-",
|
|
221
|
+
error: err instanceof Error ? err.message : String(err),
|
|
222
|
+
});
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
if (acquired.acquired)
|
|
226
|
+
return true;
|
|
227
|
+
events.push({
|
|
228
|
+
kind: "steward-busy",
|
|
229
|
+
op: stewardLeaseName(steward.name),
|
|
230
|
+
env: "-",
|
|
231
|
+
steward: steward.name,
|
|
232
|
+
...(acquired.heldBy?.holder ? { heldBy: acquired.heldBy.holder } : {}),
|
|
233
|
+
});
|
|
234
|
+
return false;
|
|
235
|
+
};
|
|
236
|
+
if (!(await holdSteward()))
|
|
237
|
+
return events;
|
|
238
|
+
// The runs started beside the turns that ended since the last round (#2861).
|
|
239
|
+
const besideState = opts.besideState ?? createBesideState();
|
|
240
|
+
events.push(...besideState.ended.splice(0));
|
|
241
|
+
// A steward's Ops whose last run waits on a decision point (#2749), read
|
|
242
|
+
// once per round, and the state of those questions now.
|
|
243
|
+
const waiting = steward ? await stewardWaits(steward, opts) : new Map();
|
|
244
|
+
// And those whose last run stopped at a gate (#2779), with whether it has
|
|
245
|
+
// been approved since.
|
|
246
|
+
const gated = steward ? await stewardGates(steward, opts) : new Map();
|
|
247
|
+
let stewardLost = false;
|
|
248
|
+
for (const config of await roundOps(opts)) {
|
|
249
|
+
const env = steward ? runEnvOf(config) : (envOf(config) ?? "unknown");
|
|
250
|
+
const wait = waiting.get(config.name);
|
|
251
|
+
const stopped = gated.get(config.name);
|
|
252
|
+
let resumed;
|
|
253
|
+
let approved;
|
|
254
|
+
// A run waiting on a question that is now answered is resumed on this
|
|
255
|
+
// round, whatever its cron says. One whose question is still open is left
|
|
256
|
+
// until a person answers it, unless its cron fires, which asks again.
|
|
257
|
+
if (wait?.answered)
|
|
258
|
+
resumed = wait.question;
|
|
259
|
+
// The same for a run stopped at a gate that is now approved (#2779).
|
|
260
|
+
if (stopped?.approved)
|
|
261
|
+
approved = { op: stopped.gateOp, gate: stopped.gate };
|
|
262
|
+
const standing = wait
|
|
263
|
+
? { kind: "waiting-on-point", op: config.name, env, point: wait.point, question: wait.question, state: wait.state }
|
|
264
|
+
: stopped
|
|
265
|
+
? { kind: "waiting-on-gate", op: config.name, env, gateOp: stopped.gateOp, gate: stopped.gate }
|
|
266
|
+
: undefined;
|
|
267
|
+
const resuming = resumed !== undefined || approved !== undefined;
|
|
268
|
+
// An Op that declares its own cadence (#2120) is ticked on that cron
|
|
269
|
+
// rather than on every round. Level-triggered: the question is whether a
|
|
270
|
+
// firing minute has passed since this Op was last looked at, so a round
|
|
271
|
+
// that arrives late still owes exactly one tick — a converge tick
|
|
272
|
+
// re-observes everything anyway, and several missed fires are one tick's
|
|
273
|
+
// worth of work.
|
|
274
|
+
const cron = config.schedule?.cron;
|
|
275
|
+
if (cron) {
|
|
276
|
+
const now = (opts.now ?? (() => new Date()))();
|
|
277
|
+
const lastSeen = opts.scheduleState?.get(config.name);
|
|
278
|
+
const due = lastSeen === undefined ? cronMatches(cron, now) : cronDueBetween(cron, lastSeen, now);
|
|
279
|
+
opts.scheduleState?.set(config.name, now);
|
|
280
|
+
if (!due && !resuming) {
|
|
281
|
+
events.push(standing ?? { kind: "skipped-not-due", op: config.name, env, cron });
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
else if (steward && !resuming) {
|
|
286
|
+
// An unscheduled Op runs when someone asks for it; the steward runs it
|
|
287
|
+
// only to resume its own waiting or gated run.
|
|
288
|
+
if (standing)
|
|
289
|
+
events.push(standing);
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
let acquired;
|
|
293
|
+
try {
|
|
294
|
+
acquired = await acquireLease(config.name, holder, {
|
|
295
|
+
cwd: opts.cwd,
|
|
296
|
+
ttlMs: opts.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS,
|
|
297
|
+
now: opts.now,
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
catch (err) {
|
|
301
|
+
// Not lease contention — the acquire attempt itself failed (most
|
|
302
|
+
// likely a StaleLockError, ./lifecycle/git.ts's diagnosable
|
|
303
|
+
// stand-in for "a previous operator was killed mid-write"). Report it
|
|
304
|
+
// for this op and move on to the next; never abort the whole round.
|
|
305
|
+
const message = err instanceof StaleLockError ? err.message : err instanceof Error ? err.message : String(err);
|
|
306
|
+
events.push({ kind: "lease-error", op: config.name, env, error: message });
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
if (!acquired.acquired) {
|
|
310
|
+
events.push({ kind: "skipped-lease-held", op: config.name, env, heldBy: acquired.heldBy?.holder });
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
const lease = acquired.lease;
|
|
314
|
+
opts.heldLeases?.set(config.name, lease.token);
|
|
315
|
+
// A local steward is one turn at a time (#2750): a hand run (`chant run
|
|
316
|
+
// <op>`) holds this same lease for as long as it runs, so a round never
|
|
317
|
+
// ticks beside one. It is one lease for the whole steward, not one per
|
|
318
|
+
// op, so finding it held stops the round outright — every op still ahead
|
|
319
|
+
// of it in `roundOps` would fail the identical check.
|
|
320
|
+
let turn;
|
|
321
|
+
if (steward) {
|
|
322
|
+
try {
|
|
323
|
+
turn = await acquireStewardTurn(steward.name, holder, { cwd: opts.cwd, ttlMs: opts.leaseTtlMs, now: opts.now });
|
|
324
|
+
}
|
|
325
|
+
catch (err) {
|
|
326
|
+
// Not turn contention — the acquire attempt itself failed (most
|
|
327
|
+
// likely a StaleLockError). Same shape as the per-op acquire's own
|
|
328
|
+
// catch above: report it and stop, rather than let it propagate and
|
|
329
|
+
// leak the per-op lease this round just took.
|
|
330
|
+
await releaseLease(config.name, holder, lease.token, { cwd: opts.cwd }).catch(() => false);
|
|
331
|
+
opts.heldLeases?.delete(config.name);
|
|
332
|
+
const message = err instanceof StaleLockError ? err.message : err instanceof Error ? err.message : String(err);
|
|
333
|
+
events.push({ kind: "lease-error", op: stewardTurnLeaseName(steward.name), env, error: message });
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
if (!turn.acquired) {
|
|
337
|
+
await releaseLease(config.name, holder, lease.token, { cwd: opts.cwd }).catch(() => false);
|
|
338
|
+
opts.heldLeases?.delete(config.name);
|
|
339
|
+
events.push({ kind: "turn-busy", op: config.name, env, steward: steward.name, heldBy: turn.heldBy?.holder });
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// The run is the steward's turn (#2749): a decision point it asks names the
|
|
344
|
+
// steward and makes its model call through the steward's broker, and an
|
|
345
|
+
// answer from inside the turn is refused.
|
|
346
|
+
const runId = randomUUID();
|
|
347
|
+
const restoreTurn = steward
|
|
348
|
+
? enterStewardTurn({ steward: steward.name, capabilities: steward.capabilities, vault: steward.vault, run: runId })
|
|
349
|
+
: undefined;
|
|
350
|
+
try {
|
|
351
|
+
const result = await runOpLocally(config, opts.activities, opts.profiles, opts.signal, {
|
|
352
|
+
runId,
|
|
353
|
+
// #2522: the environment the operator was started for (`--env`, or a
|
|
354
|
+
// steward's environment) reaches the activities through the run
|
|
355
|
+
// context, as `chant run --env` does.
|
|
356
|
+
...(opts.env ?? opts.stewardEnv ? { env: opts.env ?? opts.stewardEnv } : {}),
|
|
357
|
+
...(steward ? { steward: steward.name } : {}),
|
|
358
|
+
ledger: { cwd: opts.cwd },
|
|
359
|
+
// A steward's turn claims work leases as `<steward>/<op>@<holder>`
|
|
360
|
+
// (#2748), which is how `workspace status` finds the lease it holds.
|
|
361
|
+
...(steward ? { work: { holder: stewardWorkHolder(steward.name, config.name, holder) } } : {}),
|
|
362
|
+
// #2301: without a sink, `settle` catches a failed ledger append and
|
|
363
|
+
// drops it. That is the failure this tick can least afford to lose —
|
|
364
|
+
// the message below points the reader at the ledger record, which is
|
|
365
|
+
// exactly the artifact a failed append means is not there.
|
|
366
|
+
onLedgerError: (err) => events.push({
|
|
367
|
+
kind: "tick-failed",
|
|
368
|
+
op: config.name,
|
|
369
|
+
env,
|
|
370
|
+
error: `Op "${config.name}" ran, but its record could not be appended to the run ledger: ` +
|
|
371
|
+
`${err instanceof Error ? err.message : String(err)}`,
|
|
372
|
+
}),
|
|
373
|
+
});
|
|
374
|
+
const held = await stillHoldsLease(config.name, holder, lease.token, { cwd: opts.cwd });
|
|
375
|
+
events.push(held
|
|
376
|
+
? {
|
|
377
|
+
kind: "ticked",
|
|
378
|
+
op: config.name,
|
|
379
|
+
env,
|
|
380
|
+
result,
|
|
381
|
+
...(resumed !== undefined ? { resumed } : {}),
|
|
382
|
+
...(approved !== undefined ? { approved } : {}),
|
|
383
|
+
}
|
|
384
|
+
: { kind: "fenced", op: config.name, env });
|
|
385
|
+
}
|
|
386
|
+
catch (err) {
|
|
387
|
+
// #2301: "see its ledger record" was the whole message, and it sent the
|
|
388
|
+
// reader to an artifact that a failed ledger append means is missing —
|
|
389
|
+
// while `err.result` was carrying the failing steps all along. Name the
|
|
390
|
+
// failing steps here, and fall back to `cause` for a failure that
|
|
391
|
+
// produced no step record at all.
|
|
392
|
+
const message = err instanceof OpRunFailure
|
|
393
|
+
? failureDetail(config.name, err)
|
|
394
|
+
: err instanceof Error
|
|
395
|
+
? err.message
|
|
396
|
+
: String(err);
|
|
397
|
+
events.push({ kind: "tick-failed", op: config.name, env, error: message });
|
|
398
|
+
}
|
|
399
|
+
finally {
|
|
400
|
+
restoreTurn?.();
|
|
401
|
+
if (steward && turn?.acquired)
|
|
402
|
+
await releaseStewardTurn(steward.name, holder, turn.lease.token, { cwd: opts.cwd });
|
|
403
|
+
}
|
|
404
|
+
if (!(await holdSteward())) {
|
|
405
|
+
stewardLost = true;
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
// The Ops beside the turns (#2861) are considered whatever became of the
|
|
410
|
+
// turns: a turn in progress holds none of them. Only a steward that lost its
|
|
411
|
+
// own lease starts nothing.
|
|
412
|
+
if (steward && !stewardLost) {
|
|
413
|
+
await besideRound(steward, opts, holder, besideState, waiting, gated, events);
|
|
414
|
+
}
|
|
415
|
+
return events;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* One round for a steward's Ops beside its turns (#2861). For each one not
|
|
419
|
+
* already running: start it when a run of the steward's waits on a question
|
|
420
|
+
* now answered or a gate now approved, when its cron fires, or when its ready
|
|
421
|
+
* step names work it has not started a run for. The run is started and not
|
|
422
|
+
* waited for.
|
|
423
|
+
*/
|
|
424
|
+
async function besideRound(steward, opts, holder, state, waiting, gated, events) {
|
|
425
|
+
for (const beside of stewardBesideOf(steward)) {
|
|
426
|
+
const config = steward.ops.find((op) => op.name === beside.op);
|
|
427
|
+
if (!config)
|
|
428
|
+
continue;
|
|
429
|
+
const env = runEnvOf(config);
|
|
430
|
+
// The cron is read whether or not a run is in flight, so a fire during a
|
|
431
|
+
// run is dropped (overlap "skip") rather than owed afterwards.
|
|
432
|
+
const cron = config.schedule?.cron;
|
|
433
|
+
let due = false;
|
|
434
|
+
if (cron) {
|
|
435
|
+
const now = (opts.now ?? (() => new Date()))();
|
|
436
|
+
const lastSeen = opts.scheduleState?.get(config.name);
|
|
437
|
+
due = lastSeen === undefined ? cronMatches(cron, now) : cronDueBetween(cron, lastSeen, now);
|
|
438
|
+
opts.scheduleState?.set(config.name, now);
|
|
439
|
+
}
|
|
440
|
+
const mine = state.running.get(config.name);
|
|
441
|
+
if (mine) {
|
|
442
|
+
events.push({ kind: "beside-running", op: config.name, env, heldBy: mine.holder });
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
// A run another process holds the lease for: a hand `chant run`, or one
|
|
446
|
+
// this steward started before its operator restarted.
|
|
447
|
+
let current;
|
|
448
|
+
try {
|
|
449
|
+
current = (await readLease(config.name, { cwd: opts.cwd })).record;
|
|
450
|
+
}
|
|
451
|
+
catch (err) {
|
|
452
|
+
events.push({ kind: "lease-error", op: config.name, env, error: err instanceof Error ? err.message : String(err) });
|
|
453
|
+
continue;
|
|
454
|
+
}
|
|
455
|
+
const now = (opts.now ?? (() => new Date()))();
|
|
456
|
+
if (current && new Date(current.expiresAt).getTime() > now.getTime()) {
|
|
457
|
+
events.push({ kind: "beside-running", op: config.name, env, heldBy: current.holder });
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
const wait = waiting.get(config.name);
|
|
461
|
+
const stopped = gated.get(config.name);
|
|
462
|
+
const standing = wait
|
|
463
|
+
? { kind: "waiting-on-point", op: config.name, env, point: wait.point, question: wait.question, state: wait.state }
|
|
464
|
+
: stopped
|
|
465
|
+
? { kind: "waiting-on-gate", op: config.name, env, gateOp: stopped.gateOp, gate: stopped.gate }
|
|
466
|
+
: undefined;
|
|
467
|
+
let why;
|
|
468
|
+
if (wait?.answered)
|
|
469
|
+
why = "resumed";
|
|
470
|
+
else if (stopped?.approved)
|
|
471
|
+
why = "approved";
|
|
472
|
+
else if (due)
|
|
473
|
+
why = "cron";
|
|
474
|
+
let keys;
|
|
475
|
+
if (!why && beside.ready) {
|
|
476
|
+
const answer = await askReady(beside.ready, opts.activities, opts.signal);
|
|
477
|
+
if ("error" in answer) {
|
|
478
|
+
events.push({ kind: "ready-failed", op: config.name, env, error: answer.error });
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
if (answer.ready) {
|
|
482
|
+
const seen = state.started.get(config.name) ?? new Set();
|
|
483
|
+
if (answer.keys.length === 0 || answer.keys.some((k) => !seen.has(k))) {
|
|
484
|
+
why = "ready";
|
|
485
|
+
keys = answer.keys;
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
events.push(standing ?? { kind: "skipped-not-ready", op: config.name, env, already: answer.keys });
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
events.push(standing ?? { kind: "skipped-not-ready", op: config.name, env });
|
|
494
|
+
continue;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
if (!why) {
|
|
498
|
+
const idle = standing ?? (cron ? { kind: "skipped-not-due", op: config.name, env, cron } : undefined);
|
|
499
|
+
if (idle)
|
|
500
|
+
events.push(idle);
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
const runHolder = stewardWorkHolder(steward.name, config.name, holder);
|
|
504
|
+
let handle;
|
|
505
|
+
try {
|
|
506
|
+
handle = (opts.launchBeside ?? spawnBesideRun)({
|
|
507
|
+
op: config,
|
|
508
|
+
steward: steward.name,
|
|
509
|
+
...(opts.stewardEnv !== undefined ? { env: opts.stewardEnv } : {}),
|
|
510
|
+
holder: runHolder,
|
|
511
|
+
cwd: opts.cwd ?? process.cwd(),
|
|
512
|
+
...(opts.leaseTtlMs !== undefined ? { leaseTtlMs: opts.leaseTtlMs } : {}),
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
catch (err) {
|
|
516
|
+
events.push({ kind: "tick-failed", op: config.name, env, error: err instanceof Error ? err.message : String(err) });
|
|
517
|
+
continue;
|
|
518
|
+
}
|
|
519
|
+
if (keys) {
|
|
520
|
+
const seen = state.started.get(config.name) ?? new Set();
|
|
521
|
+
for (const k of keys)
|
|
522
|
+
seen.add(k);
|
|
523
|
+
state.started.set(config.name, seen);
|
|
524
|
+
}
|
|
525
|
+
state.running.set(config.name, { handle, holder: runHolder, why });
|
|
526
|
+
void handle.done.then((exit) => {
|
|
527
|
+
state.running.delete(config.name);
|
|
528
|
+
state.ended.push({ kind: "beside-ended", op: config.name, env, code: exit.code, ...(exit.error ? { error: exit.error } : {}) });
|
|
529
|
+
});
|
|
530
|
+
events.push({
|
|
531
|
+
kind: "beside-started",
|
|
532
|
+
op: config.name,
|
|
533
|
+
env,
|
|
534
|
+
why,
|
|
535
|
+
holder: runHolder,
|
|
536
|
+
...(keys && keys.length > 0 ? { keys } : {}),
|
|
537
|
+
...(why === "resumed" && wait ? { resumed: wait.question } : {}),
|
|
538
|
+
...(why === "approved" && stopped ? { approved: { op: stopped.gateOp, gate: stopped.gate } } : {}),
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* What a failed tick says about itself (#2301).
|
|
544
|
+
*
|
|
545
|
+
* `chant operator` renders its own events rather than going through
|
|
546
|
+
* `renderHuman`, so the executor's step records reached nobody here even after
|
|
547
|
+
* the executor stopped dropping them. Every failing step's message, in order,
|
|
548
|
+
* or the underlying error when the run failed without producing one.
|
|
549
|
+
*/
|
|
550
|
+
function failureDetail(op, err) {
|
|
551
|
+
const failed = err.result.records.filter((r) => r.status === "fail" && r.error);
|
|
552
|
+
if (failed.length > 0) {
|
|
553
|
+
return `Op "${op}" failed: ${failed.map((r) => `${r.fn}: ${r.error}`).join("; ")}`;
|
|
554
|
+
}
|
|
555
|
+
const cause = err.cause;
|
|
556
|
+
if (cause !== undefined) {
|
|
557
|
+
return `Op "${op}" failed: ${cause instanceof Error ? cause.message : String(cause)}`;
|
|
558
|
+
}
|
|
559
|
+
return `Op "${op}" failed — see its ledger record for step-level detail`;
|
|
560
|
+
}
|
|
561
|
+
/** Abortable sleep — resolves early (without throwing) if `signal` fires mid-wait, so the operator loop can stop promptly on Ctrl-C rather than finishing out a long interval. */
|
|
562
|
+
function sleepAbortable(ms, signal) {
|
|
563
|
+
return new Promise((resolve) => {
|
|
564
|
+
if (signal?.aborted)
|
|
565
|
+
return resolve();
|
|
566
|
+
const timer = setTimeout(() => {
|
|
567
|
+
signal?.removeEventListener("abort", onAbort);
|
|
568
|
+
resolve();
|
|
569
|
+
}, ms);
|
|
570
|
+
const onAbort = () => {
|
|
571
|
+
clearTimeout(timer);
|
|
572
|
+
resolve();
|
|
573
|
+
};
|
|
574
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
/** Render one signal event as `chant operator`'s log line shape. */
|
|
578
|
+
export function formatSignalLine(event) {
|
|
579
|
+
switch (event.kind) {
|
|
580
|
+
case "subscribed":
|
|
581
|
+
return `operator: ${event.lexicon} change signal subscribed (the timer still runs)`;
|
|
582
|
+
case "subscribe-failed":
|
|
583
|
+
return `operator: ${event.lexicon} change signal unavailable, polling on the timer (${event.error})`;
|
|
584
|
+
case "subscription-lost":
|
|
585
|
+
return `operator: ${event.lexicon} change signal lost, polling on the timer until the next round re-subscribes (${event.error})`;
|
|
586
|
+
case "woken":
|
|
587
|
+
return `operator: woken by a change signal after ${event.afterMs}ms, running an ordinary round`;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Run rounds forever, sleeping `intervalMs` between them, until
|
|
592
|
+
* `opts.signal` aborts. The daemon is a convenience, never a requirement
|
|
593
|
+
* (issue: "if it dies, nothing breaks and nothing is lost") — this function
|
|
594
|
+
* is exactly `while (!aborted) { round(); sleep(); }`, nothing durable lives
|
|
595
|
+
* in its own memory that a restart would need to recover.
|
|
596
|
+
*
|
|
597
|
+
* With `subscribers` (#1981) the sleep gains a second wake source, and only a
|
|
598
|
+
* wake source. A signal aborts the current sleep; the round that follows is
|
|
599
|
+
* the same round the timer would have run, deriving everything from a fresh
|
|
600
|
+
* observation. Nothing a subscription reports reaches a tick, because the
|
|
601
|
+
* seam has nowhere to put it: `onChange` takes no arguments.
|
|
602
|
+
*/
|
|
603
|
+
export async function runOperatorForever(opts) {
|
|
604
|
+
const holder = opts.holder ?? currentHolderId();
|
|
605
|
+
// Per-op cron state (#2120) lives for the life of the loop. A restart starts
|
|
606
|
+
// it empty, which means the first round ticks a scheduled Op only if it
|
|
607
|
+
// lands on a firing minute — a fresh operator owes no catch-up for the ticks
|
|
608
|
+
// it was not running for.
|
|
609
|
+
const scheduleState = opts.scheduleState ?? new Map();
|
|
610
|
+
// The runs a steward starts beside its turns (#2861), for the life of the
|
|
611
|
+
// loop. When the loop stops, so do they.
|
|
612
|
+
const besideState = opts.besideState ?? createBesideState();
|
|
613
|
+
// The per-Op leases the rounds leave held (#2879), released when the loop stops.
|
|
614
|
+
const heldLeases = opts.heldLeases ?? new Map();
|
|
615
|
+
const intervalMs = opts.intervalMs ?? DEFAULT_OPERATOR_INTERVAL_MS;
|
|
616
|
+
const subscribers = opts.subscribers ?? [];
|
|
617
|
+
// Nothing to subscribe to: the loop below is the loop that shipped before
|
|
618
|
+
// #1981, and takes none of the machinery's cost.
|
|
619
|
+
if (subscribers.length === 0) {
|
|
620
|
+
try {
|
|
621
|
+
while (!opts.signal?.aborted) {
|
|
622
|
+
const events = await runOperatorRound({ ...opts, holder, scheduleState, besideState, heldLeases });
|
|
623
|
+
opts.onRound?.(events);
|
|
624
|
+
if (opts.signal?.aborted)
|
|
625
|
+
break;
|
|
626
|
+
await sleepAbortable(intervalMs, opts.signal);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
finally {
|
|
630
|
+
await stopBesideRuns(besideState);
|
|
631
|
+
await releaseHeldLeases(heldLeases, holder, { cwd: opts.cwd });
|
|
632
|
+
}
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
const gate = createChangeSignalGate({ floorMs: opts.signalFloorMs ?? DEFAULT_SIGNAL_FLOOR_MS });
|
|
636
|
+
// The subscriptions the loop currently holds, by lexicon. A lexicon absent
|
|
637
|
+
// from this map is one to (re-)subscribe on the next round, which is how a
|
|
638
|
+
// killed watch comes back without a special retry path.
|
|
639
|
+
const live = new Map();
|
|
640
|
+
// Stops every subscription at once when the loop ends, whatever ends it.
|
|
641
|
+
const subscriptionsAbort = new AbortController();
|
|
642
|
+
const closeAll = async () => {
|
|
643
|
+
subscriptionsAbort.abort();
|
|
644
|
+
const open = [...live.values()];
|
|
645
|
+
live.clear();
|
|
646
|
+
// A close that throws must not mask why the loop is unwinding.
|
|
647
|
+
await Promise.allSettled(open.map((s) => s.close()));
|
|
648
|
+
};
|
|
649
|
+
const ensureSubscribed = async () => {
|
|
650
|
+
for (const subscriber of subscribers) {
|
|
651
|
+
if (live.has(subscriber.lexicon) || subscriptionsAbort.signal.aborted)
|
|
652
|
+
continue;
|
|
653
|
+
try {
|
|
654
|
+
const subscription = await subscriber.subscribe({
|
|
655
|
+
onChange: () => gate.signal(),
|
|
656
|
+
onError: (error) => {
|
|
657
|
+
// Reported once, then forgotten: dropping it from `live` is what
|
|
658
|
+
// makes the next round re-subscribe. The loop itself is untouched.
|
|
659
|
+
if (!live.delete(subscriber.lexicon))
|
|
660
|
+
return;
|
|
661
|
+
opts.onSignalEvent?.({ kind: "subscription-lost", lexicon: subscriber.lexicon, error });
|
|
662
|
+
},
|
|
663
|
+
signal: subscriptionsAbort.signal,
|
|
664
|
+
});
|
|
665
|
+
live.set(subscriber.lexicon, subscription);
|
|
666
|
+
opts.onSignalEvent?.({ kind: "subscribed", lexicon: subscriber.lexicon });
|
|
667
|
+
}
|
|
668
|
+
catch (err) {
|
|
669
|
+
// A subscription that cannot be established is a slower loop, never a
|
|
670
|
+
// stopped one: report it and fall through to the timer.
|
|
671
|
+
opts.onSignalEvent?.({
|
|
672
|
+
kind: "subscribe-failed",
|
|
673
|
+
lexicon: subscriber.lexicon,
|
|
674
|
+
error: err instanceof Error ? err.message : String(err),
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
};
|
|
679
|
+
try {
|
|
680
|
+
while (!opts.signal?.aborted) {
|
|
681
|
+
gate.roundStarted();
|
|
682
|
+
const startedAt = Date.now();
|
|
683
|
+
const events = await runOperatorRound({ ...opts, holder, scheduleState, besideState, heldLeases });
|
|
684
|
+
opts.onRound?.(events);
|
|
685
|
+
if (opts.signal?.aborted)
|
|
686
|
+
break;
|
|
687
|
+
await ensureSubscribed();
|
|
688
|
+
if (opts.signal?.aborted)
|
|
689
|
+
break;
|
|
690
|
+
const reason = await gate.wait(intervalMs, opts.signal);
|
|
691
|
+
if (reason === "signal") {
|
|
692
|
+
opts.onSignalEvent?.({ kind: "woken", afterMs: Date.now() - startedAt });
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
finally {
|
|
697
|
+
await closeAll();
|
|
698
|
+
await stopBesideRuns(besideState);
|
|
699
|
+
await releaseHeldLeases(heldLeases, holder, { cwd: opts.cwd });
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
/** Render one round's events as `chant operator`'s log line shape — one line per ticked/skipped/failed op, reusing each ticked op's own `convergeTick` log line (`OpRunResult`'s outcome attribute doesn't carry it, so this reads the tick's step record's `Remediated`... actually the human-readable summary comes from the ledger, not the run result — see `../cli/handlers/operator.ts` for where `chant operator status` reads it back). This formats what's available from the round itself: which op, which env, and whether it ticked, skipped, or failed. */
|
|
703
|
+
export function formatRoundLine(event) {
|
|
704
|
+
switch (event.kind) {
|
|
705
|
+
case "ticked":
|
|
706
|
+
return `operator: ${event.op}@${event.env} ticked=1 status=${event.result.status}` +
|
|
707
|
+
(event.result.gate ? ` gate="${event.result.gate.gate}"` : "") +
|
|
708
|
+
(event.result.point ? ` point="${event.result.point.id}"` : "") +
|
|
709
|
+
(event.resumed ? ` resumed="${event.resumed}"` : "") +
|
|
710
|
+
(event.approved ? ` approved="${event.approved.op}/${event.approved.gate}"` : "");
|
|
711
|
+
case "waiting-on-point":
|
|
712
|
+
return `operator: ${event.op}@${event.env} waiting=1(point:${event.question}:${event.state})`;
|
|
713
|
+
case "waiting-on-gate":
|
|
714
|
+
return `operator: ${event.op}@${event.env} gated=1(gate:${event.gateOp}/${event.gate})`;
|
|
715
|
+
case "skipped-lease-held":
|
|
716
|
+
return `operator: ${event.op}@${event.env} skipped=1(lease-held${event.heldBy ? `:${event.heldBy}` : ""})`;
|
|
717
|
+
case "skipped-not-due":
|
|
718
|
+
return `operator: ${event.op}@${event.env} skipped=1(not-due:${event.cron})`;
|
|
719
|
+
case "tick-failed":
|
|
720
|
+
return `operator: ${event.op}@${event.env} failed=1 error="${event.error}"`;
|
|
721
|
+
case "fenced":
|
|
722
|
+
return `operator: ${event.op}@${event.env} fenced=1(lease lost mid-tick — ledger record still written)`;
|
|
723
|
+
case "lease-error":
|
|
724
|
+
return `operator: ${event.op}@${event.env} error=1(lease acquire failed — ${event.error})`;
|
|
725
|
+
case "steward-busy":
|
|
726
|
+
return `operator: steward ${event.steward} skipped=1(steward-lease-held${event.heldBy ? `:${event.heldBy}` : ""})`;
|
|
727
|
+
case "turn-busy":
|
|
728
|
+
return `operator: ${event.op}@${event.env} skipped=1(turn-held${event.heldBy ? `:${event.heldBy}` : ""}, steward "${event.steward}" is already mid-turn)`;
|
|
729
|
+
case "beside-started":
|
|
730
|
+
return `operator: ${event.op}@${event.env} started=1(beside:${event.why}) holder="${event.holder}"` +
|
|
731
|
+
(event.keys ? ` keys="${event.keys.join(",")}"` : "") +
|
|
732
|
+
(event.resumed ? ` resumed="${event.resumed}"` : "") +
|
|
733
|
+
(event.approved ? ` approved="${event.approved.op}/${event.approved.gate}"` : "");
|
|
734
|
+
case "beside-running":
|
|
735
|
+
return `operator: ${event.op}@${event.env} skipped=1(beside-running${event.heldBy ? `:${event.heldBy}` : ""})`;
|
|
736
|
+
case "beside-ended":
|
|
737
|
+
return `operator: ${event.op}@${event.env} ended=1(beside) exit=${event.code ?? "none"}` + (event.error ? ` error="${event.error}"` : "");
|
|
738
|
+
case "skipped-not-ready":
|
|
739
|
+
return `operator: ${event.op}@${event.env} skipped=1(not-ready${event.already ? `:already-started:${event.already.join(",")}` : ""})`;
|
|
740
|
+
case "ready-failed":
|
|
741
|
+
return `operator: ${event.op}@${event.env} failed=1(ready) error="${event.error}"`;
|
|
742
|
+
}
|
|
743
|
+
}
|