@intentius/chant 0.124.12 → 0.124.14
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.js +668 -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.js +312 -0
- package/dist/child-project.js +21 -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.js +134 -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.js +305 -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.js +208 -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 +4178 -0
- package/dist/discovery/fold-rank.js +292 -0
- package/dist/discovery/graph.js +115 -0
- package/dist/discovery/import.d.ts.map +1 -1
- package/dist/discovery/import.js +65 -0
- 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 +36 -4
- package/dist/gate-decision.d.ts.map +1 -1
- package/dist/gate-decision.js +260 -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.js +341 -0
- package/dist/lifecycle/gate-ledger-select.js +89 -0
- package/dist/lifecycle/gate-ledger.d.ts +8 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.js +193 -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.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.js +64 -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.js +997 -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.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.js +103 -0
- package/dist/workspace/__fixtures__/decide-workspace.js +112 -0
- 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 +460 -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.js +199 -0
- package/dist/workspace/ci-green.js +325 -0
- package/dist/workspace/ci-last-green.schema.json +158 -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.d.ts +65 -0
- package/dist/workspace/identity-gate-rule.d.ts.map +1 -0
- package/dist/workspace/identity-gate-rule.js +75 -0
- package/dist/workspace/identity.d.ts +4 -2
- package/dist/workspace/identity.d.ts.map +1 -1
- 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.js +587 -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 +3 -14
- package/dist/workspace/principal-classes.d.ts.map +1 -1
- package/dist/workspace/principal-classes.js +245 -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/cli/commands/check-lexicon-plugin.ts +2 -0
- package/src/cli/commands/lint.ts +36 -6
- 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/sandbox/driver.ts +3 -1
- package/src/config-import.ts +3 -0
- package/src/discovery/fold-import.ts +23 -14
- package/src/discovery/import.ts +2 -0
- package/src/discovery/sandbox/driver.ts +3 -1
- package/src/gate-decision-bundle.test.ts +3 -2
- package/src/gate-decision-identity.test.ts +176 -0
- package/src/gate-decision.ts +100 -22
- package/src/lexicon-module.ts +3 -0
- package/src/lifecycle/gate-ledger.ts +8 -0
- 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/discover.ts +3 -0
- package/src/op/op-waves-point.test.ts +1 -0
- package/src/op/op-waves-run.ts +5 -4
- package/src/op/op-waves.test.ts +14 -0
- package/src/ts-loader.test.ts +23 -0
- package/src/ts-loader.ts +122 -0
- package/src/workspace/chant-migrations/chud-lexicon-exit.ts +1 -1
- package/src/workspace/declaration.ts +1 -1
- package/src/workspace/identity-gate-rule.ts +109 -0
- package/src/workspace/identity.ts +8 -18
- package/src/workspace/kinds.ts +1 -1
- package/src/workspace/lineage-migrations.ts +2 -0
- package/src/workspace/points.ts +1 -1
- package/src/workspace/principal-classes.ts +5 -30
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A gate's decision for a plan digest, and the seal check it needs, for a
|
|
3
|
+
* tool that runs from one bundled file (#3763, decision #3756).
|
|
4
|
+
*
|
|
5
|
+
* `@intentius/chant/gate-decision` holds what a tool needs to decide a
|
|
6
|
+
* plan-bound gate the way chant's own wave gate does (`chant run wave`,
|
|
7
|
+
* `./op/op-waves-run.ts`) under each approval mode:
|
|
8
|
+
*
|
|
9
|
+
* - `ledger`: an approval of this digest on `chant/lifecycle`, newer than the
|
|
10
|
+
* gate's newest pending fact ({@link decideGateApproval}).
|
|
11
|
+
* - `sealed`: the same, counting only an approval whose seal verifies for its
|
|
12
|
+
* approver against the signers file at base ({@link gateSignersAt},
|
|
13
|
+
* {@link gateSealRefusal}). The seal is checked with node:crypto, so the job
|
|
14
|
+
* needs no ssh-keygen.
|
|
15
|
+
* - `pr-review`: the same as `ledger`, or else the merged pull request's
|
|
16
|
+
* approving review, when its head planned this digest
|
|
17
|
+
* ({@link reviewApproval}).
|
|
18
|
+
*
|
|
19
|
+
* A gate the declaration at base names under `identity.gates` counts only a
|
|
20
|
+
* sealed approval from its class: {@link identityGateAdmissionAt} reads that
|
|
21
|
+
* rule from a bare clone at base and judges by `admitApprover`, the function
|
|
22
|
+
* chant's `gateAdmission` judges by (#3862); pass its `refuses` to
|
|
23
|
+
* {@link decideGateApproval}.
|
|
24
|
+
*
|
|
25
|
+
* With `spend` (#3784), an approval a wave already applied under is spent and
|
|
26
|
+
* counts for nothing, as terragucci's wave gate has it: the caller hands in
|
|
27
|
+
* the lines of `_gates/<op>/applied.jsonl` ({@link parseAppliedGateLines}).
|
|
28
|
+
*
|
|
29
|
+
* The module reads the ledger lines and the review it is handed; reading
|
|
30
|
+
* them is the caller's. It imports no TypeScript, esbuild, zod, lint, fold or
|
|
31
|
+
* codegen module, and none of chant's git ledger code, which
|
|
32
|
+
* `gate-decision-bundle.test.ts` holds it to. Its rules are chant's own:
|
|
33
|
+
* `./lifecycle/gate-ledger-select.ts` is what `evaluateGate` decides by, and
|
|
34
|
+
* `gate-decision.test.ts` decides the same ledgers both ways.
|
|
35
|
+
*/
|
|
36
|
+
import { spawnSync } from "node:child_process";
|
|
37
|
+
import { isPendingGateExpired, latestPendingGate, latestResolutionForPlan, } from "./lifecycle/gate-ledger-select.js";
|
|
38
|
+
import { samePlanDigest } from "./lifecycle/plan-digest.js";
|
|
39
|
+
import { isApprovalSpent } from "./lifecycle/gate-applied.js";
|
|
40
|
+
import { gateSealRefusal } from "./workspace/trust/gate-seal.js";
|
|
41
|
+
import { DEFAULT_SIGNERS_PATH, TRUST_CONFIG_PATH, parseAllowedSigners, trustConfigProblems, } from "./workspace/trust/trust-files.js";
|
|
42
|
+
import { parseJsonText } from "./workspace/jsonc.js";
|
|
43
|
+
import { CORE_CLASSES, admitApprover } from "./workspace/identity-gate-rule.js";
|
|
44
|
+
export { GATE_APPROVAL_SOURCES } from "./op/op-waves.js";
|
|
45
|
+
export { isPendingGateExpired, latestPendingGate, latestResolutionForPlan, latestResolutionSince, } from "./lifecycle/gate-ledger-select.js";
|
|
46
|
+
export { GATE_SEAL_NAMESPACE, gateSealPayload, gateSealRefusal, sshKeyFingerprint, verifySshSignatureWith, } from "./workspace/trust/gate-seal.js";
|
|
47
|
+
export { DEFAULT_SIGNERS_PATH, TRUST_CONFIG_PATH, parseAllowedSigners, trustConfigProblems, } from "./workspace/trust/trust-files.js";
|
|
48
|
+
export { CORE_CLASSES, admitApprover, grantedClasses, } from "./workspace/identity-gate-rule.js";
|
|
49
|
+
export { appliedGateApplies, appliedGatePath, isApprovalSpent, parseAppliedGateLines, } from "./lifecycle/gate-applied.js";
|
|
50
|
+
// ── reading at base ──────────────────────────────────────────────────────
|
|
51
|
+
function git(repo, args) {
|
|
52
|
+
return spawnSync("git", args, { cwd: repo, encoding: "utf-8" });
|
|
53
|
+
}
|
|
54
|
+
/** A file's text at `base`, or undefined when `base` holds no file at `path`. */
|
|
55
|
+
function showAt(repo, base, path) {
|
|
56
|
+
const r = git(repo, ["cat-file", "blob", `${base}:${path}`]);
|
|
57
|
+
return r.status === 0 ? r.stdout : undefined;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The commit a gate's rule is read at when the default branch applies its
|
|
61
|
+
* own commit: the first parent of HEAD, the branch as it stood before the
|
|
62
|
+
* merge, so a merge that adds a signer or drops a gate does not judge its own
|
|
63
|
+
* apply. A shallow checkout fetches that one commit from `origin`. A root
|
|
64
|
+
* commit has no parent and is its own base. Throws when it cannot be read.
|
|
65
|
+
*/
|
|
66
|
+
export function baseCommit(repo) {
|
|
67
|
+
const head = git(repo, ["rev-parse", "--verify", "-q", "HEAD^{commit}"]);
|
|
68
|
+
const sha = head.stdout.trim();
|
|
69
|
+
if (head.status !== 0 || !sha)
|
|
70
|
+
throw new Error(`${repo} has no commit checked out, so the gate cannot be decided`);
|
|
71
|
+
// The commit object's first `parent` line: a shallow clone keeps it even when it lacks the parent itself.
|
|
72
|
+
const header = git(repo, ["cat-file", "commit", sha]).stdout.split("\n\n")[0] ?? "";
|
|
73
|
+
const parent = /^parent ([0-9a-f]{40,64})$/m.exec(header)?.[1];
|
|
74
|
+
if (!parent)
|
|
75
|
+
return sha;
|
|
76
|
+
const has = () => git(repo, ["cat-file", "-e", `${parent}^{commit}`]).status === 0;
|
|
77
|
+
if (!has())
|
|
78
|
+
git(repo, ["fetch", "-q", "--depth=1", "origin", parent]);
|
|
79
|
+
if (!has())
|
|
80
|
+
throw new Error(`cannot fetch ${parent.slice(0, 12)}, the commit before this one, so the gate cannot be decided`);
|
|
81
|
+
return parent;
|
|
82
|
+
}
|
|
83
|
+
/** The signers and role grants at `base`, as chant's trust policy reads them. */
|
|
84
|
+
function trustAt(repo, base) {
|
|
85
|
+
const off = (problems) => ({ signers: { base, signersPath: DEFAULT_SIGNERS_PATH, active: false, signers: [], problems }, roles: {} });
|
|
86
|
+
const configText = showAt(repo, base, TRUST_CONFIG_PATH);
|
|
87
|
+
let signersPath = DEFAULT_SIGNERS_PATH;
|
|
88
|
+
let roles = {};
|
|
89
|
+
if (configText !== undefined) {
|
|
90
|
+
let raw;
|
|
91
|
+
try {
|
|
92
|
+
raw = JSON.parse(configText);
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
return off([`${TRUST_CONFIG_PATH} is not JSON: ${err instanceof Error ? err.message : String(err)}`]);
|
|
96
|
+
}
|
|
97
|
+
const problems = trustConfigProblems(raw);
|
|
98
|
+
if (problems.length > 0)
|
|
99
|
+
return off([`${TRUST_CONFIG_PATH} is invalid: ${problems.join("; ")}`]);
|
|
100
|
+
signersPath = raw.signers ?? DEFAULT_SIGNERS_PATH;
|
|
101
|
+
roles = raw.roles ?? {};
|
|
102
|
+
}
|
|
103
|
+
const text = showAt(repo, base, signersPath);
|
|
104
|
+
return { signers: { base, signersPath, active: text !== undefined, signers: text === undefined ? [] : parseAllowedSigners(text).signers, problems: [] }, roles };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The signers at `base`: the file `.chant/trust.json` names there, else
|
|
108
|
+
* `.chant/allowed_signers`, read as chant's trust policy reads it. A
|
|
109
|
+
* trust.json that is not valid (`trustConfigProblems`) turns attestation
|
|
110
|
+
* off, as it does in chant, so a sealed gate passes nothing. `base` is a
|
|
111
|
+
* commit the repository holds, such as {@link baseCommit}'s answer.
|
|
112
|
+
*/
|
|
113
|
+
export function gateSignersAt(repo, base) {
|
|
114
|
+
return trustAt(repo, base).signers;
|
|
115
|
+
}
|
|
116
|
+
/** The declaration at `base`, parsed, or null when there is none. Throws when it cannot be parsed. */
|
|
117
|
+
function declarationAt(repo, base) {
|
|
118
|
+
for (const file of ["chant.workspace.json", "chant.workspace.jsonc"]) {
|
|
119
|
+
const text = showAt(repo, base, file);
|
|
120
|
+
if (text === undefined)
|
|
121
|
+
continue;
|
|
122
|
+
const parsed = parseJsonText(text, { jsonc: file.endsWith(".jsonc") });
|
|
123
|
+
if (!parsed.ok)
|
|
124
|
+
throw new Error(`${file} at base is not valid JSON (${parsed.message}), so the gate cannot be decided`);
|
|
125
|
+
return { file, value: parsed.value };
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
function identityGatesOf(declaration) {
|
|
130
|
+
const gates = declaration?.identity?.gates ?? {};
|
|
131
|
+
return Object.entries(gates).map(([gate, entry]) => ({ gate, class: typeof entry?.class === "string" ? entry.class : null }));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The gates `chant.workspace.json` (or `.jsonc`) at `base` names under
|
|
135
|
+
* `identity.gates`: each counts only a sealed approval, from its class when
|
|
136
|
+
* it names one. {@link identityGateAdmissionAt} judges an approval by one.
|
|
137
|
+
* Empty when there is no declaration at base. Throws when the declaration
|
|
138
|
+
* there cannot be parsed, since the gate cannot be decided.
|
|
139
|
+
*/
|
|
140
|
+
export function identityGatesAt(repo, base) {
|
|
141
|
+
const declaration = declarationAt(repo, base);
|
|
142
|
+
return declaration === null ? [] : identityGatesOf(declaration.value);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* The `identity.gates` rule for `gate` at `base`, or null when the
|
|
146
|
+
* declaration there names none: what chant's `gateAdmission(cwd, gate, base)`
|
|
147
|
+
* answers, read from a bare clone. An approval counts when its seal verifies
|
|
148
|
+
* for its approver against the signers at base and, when the gate names a
|
|
149
|
+
* class, the role grants in `.chant/trust.json` at base put the approver in
|
|
150
|
+
* it. Both judge with the same function ({@link admitApprover}).
|
|
151
|
+
*
|
|
152
|
+
* The classes are the four core ones, then `classes`, the domain classes the
|
|
153
|
+
* caller read from the pinned packages (`./workspace-principals`), in pin
|
|
154
|
+
* order. This reader loads no package. A gate whose class is in neither
|
|
155
|
+
* refuses every approval, and when the declaration at base pins anything the
|
|
156
|
+
* reason says the pins were not read, since one of them may supply it.
|
|
157
|
+
* Throws when the declaration at base cannot be parsed.
|
|
158
|
+
*/
|
|
159
|
+
export function identityGateAdmissionAt(repo, base, gate, opts = {}) {
|
|
160
|
+
const declaration = declarationAt(repo, base);
|
|
161
|
+
const requirement = declaration === null ? undefined : identityGatesOf(declaration.value).find((g) => g.gate === gate);
|
|
162
|
+
if (!requirement)
|
|
163
|
+
return null;
|
|
164
|
+
const { signers, roles } = trustAt(repo, base);
|
|
165
|
+
const pins = declaration.value.pins;
|
|
166
|
+
const rule = {
|
|
167
|
+
gate,
|
|
168
|
+
class: requirement.class,
|
|
169
|
+
signers,
|
|
170
|
+
roles,
|
|
171
|
+
classes: [...CORE_CLASSES, ...(opts.classes ?? [])],
|
|
172
|
+
...(Array.isArray(pins) && pins.length > 0
|
|
173
|
+
? { unknownClass: `is not a core class, and this reader does not load the classes the pinned packages in ${declaration.file} at base supply` }
|
|
174
|
+
: {}),
|
|
175
|
+
};
|
|
176
|
+
return { requirement, refuses: (a) => admitApprover(rule, a) };
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Whether the merged pull request's review approves `digest` (#3684): a
|
|
180
|
+
* writer other than its author approved its head, and the head planned this
|
|
181
|
+
* digest (`headDigest`, from the plans `chant run wave --record-plans`
|
|
182
|
+
* recorded for the head; undefined when none were). Reading the review and
|
|
183
|
+
* the plans is the caller's; under `pr-review` the caller records the
|
|
184
|
+
* approval on the ledger when this approves.
|
|
185
|
+
*/
|
|
186
|
+
export function reviewApproval(merged, headDigest, digest) {
|
|
187
|
+
const seen = { pr: merged.pr, head: merged.head, ...(merged.url ? { url: merged.url } : {}) };
|
|
188
|
+
if (merged.approvers.length === 0) {
|
|
189
|
+
const why = merged.refused.length > 0 ? merged.refused.join("; ") : "nobody approved it";
|
|
190
|
+
return { approved: false, review: { ...seen, reason: `no writer other than its author approved the head of #${merged.pr}: ${why}` } };
|
|
191
|
+
}
|
|
192
|
+
if (headDigest === undefined) {
|
|
193
|
+
return {
|
|
194
|
+
approved: false,
|
|
195
|
+
review: { ...seen, approvers: merged.approvers, reason: `no plans are recorded for the head ${merged.head.slice(0, 12)} of #${merged.pr} (its pipeline runs \`chant run wave --record-plans\`)` },
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
if (headDigest !== digest) {
|
|
199
|
+
return {
|
|
200
|
+
approved: false,
|
|
201
|
+
review: { ...seen, approvers: merged.approvers, reason: `the plan moved after the review: the head planned ${headDigest}, and the merge plans ${digest}` },
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
return { approved: true, review: { ...seen, approvers: merged.approvers } };
|
|
205
|
+
}
|
|
206
|
+
const EPOCH = new Date(0).toISOString();
|
|
207
|
+
/**
|
|
208
|
+
* Decide a plan-bound gate against its ledger lines, as chant's wave gate
|
|
209
|
+
* does: an approval counts when it names this gate and digest (and
|
|
210
|
+
* environment, when set), is newer than the gate's newest pending fact, and
|
|
211
|
+
* passes the mode's rule: any under `ledger` and `pr-review`, a verified seal
|
|
212
|
+
* under `sealed`. With none, `pr-review` takes the review's answer. Writes
|
|
213
|
+
* nothing: recording a pending fact, or the review's approval, is the
|
|
214
|
+
* caller's.
|
|
215
|
+
*/
|
|
216
|
+
export function decideGateApproval(input) {
|
|
217
|
+
const { gate, planDigest, environment: env } = input;
|
|
218
|
+
const mode = input.mode ?? "ledger";
|
|
219
|
+
const pending = env === undefined ? input.ledger.pending : input.ledger.pending.filter((p) => p.environment === env);
|
|
220
|
+
const mine = (env === undefined ? input.ledger.resolutions : input.ledger.resolutions.filter((r) => r.environment === undefined || r.environment === env)).filter((r) => r.gate === gate);
|
|
221
|
+
const sealed = mode === "sealed";
|
|
222
|
+
const noSigners = { base: null, signersPath: DEFAULT_SIGNERS_PATH, active: false, signers: [], problems: ["no signers were read for this sealed gate"] };
|
|
223
|
+
const why = (r) => input.refuses?.(r) ?? (sealed ? gateSealRefusal(input.signers ?? noSigners, r) : null);
|
|
224
|
+
const standingFact = latestPendingGate(pending, gate);
|
|
225
|
+
const since = standingFact?.timestamp ?? EPOCH;
|
|
226
|
+
const counted = [];
|
|
227
|
+
const uncounted = [];
|
|
228
|
+
let spent;
|
|
229
|
+
for (const r of mine) {
|
|
230
|
+
if (input.spend && isApprovalSpent(input.ledger.applied ?? [], r)) {
|
|
231
|
+
if (new Date(r.timestamp).getTime() >= new Date(since).getTime() && (!spent || new Date(r.timestamp).getTime() >= new Date(spent.timestamp).getTime()))
|
|
232
|
+
spent = r;
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
const reason = why(r);
|
|
236
|
+
if (reason === null)
|
|
237
|
+
counted.push(r);
|
|
238
|
+
else if (samePlanDigest(r.planDigest, planDigest) && new Date(r.timestamp).getTime() >= new Date(since).getTime())
|
|
239
|
+
uncounted.push({ resolution: r, reason });
|
|
240
|
+
}
|
|
241
|
+
const found = latestResolutionForPlan(counted, gate, since, planDigest);
|
|
242
|
+
if (found.resolution)
|
|
243
|
+
return { status: "approved", via: "ledger", resolution: found.resolution };
|
|
244
|
+
const reviewSpent = input.spend === true && input.review?.approved === true &&
|
|
245
|
+
isApprovalSpent(input.ledger.applied ?? [], { gate, planDigest, review: { ...(input.review.review.head ? { head: input.review.review.head } : {}) } });
|
|
246
|
+
if (mode === "pr-review" && input.review?.approved && !reviewSpent)
|
|
247
|
+
return { status: "approved", via: "pr-review", review: input.review.review };
|
|
248
|
+
const now = input.now ?? new Date().toISOString();
|
|
249
|
+
const standing = standingFact && !isPendingGateExpired(standingFact, now) && samePlanDigest(standingFact.planDigest, planDigest) ? standingFact : undefined;
|
|
250
|
+
return {
|
|
251
|
+
status: "waiting",
|
|
252
|
+
...(standing ? { standing } : {}),
|
|
253
|
+
...(found.mismatched ? { mismatched: found.mismatched } : {}),
|
|
254
|
+
uncounted: uncounted.sort((a, b) => new Date(a.resolution.timestamp).getTime() - new Date(b.resolution.timestamp).getTime()),
|
|
255
|
+
...(mode === "pr-review" && input.review
|
|
256
|
+
? { review: reviewSpent ? { ...input.review.review, reason: `a wave already applied this digest under the review of ${input.review.review.head?.slice(0, 12) ?? "its head"}, so the review is spent` } : input.review.review }
|
|
257
|
+
: {}),
|
|
258
|
+
...(spent ? { spent } : {}),
|
|
259
|
+
};
|
|
260
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resume the job that waits at a gate (#3683), bundle-safe (#3854).
|
|
3
|
+
*
|
|
4
|
+
* A CI job that reaches a gate nobody approved records a pending fact on
|
|
5
|
+
* `chant/lifecycle` and exits 3. Nothing re-runs it when the approval lands,
|
|
6
|
+
* because a push to the ledger branch starts no pipeline. This module closes
|
|
7
|
+
* that loop through the forge's API.
|
|
8
|
+
*
|
|
9
|
+
* When the job runs in CI, the pending fact it records carries a
|
|
10
|
+
* {@link GateRunLocator}, read from the job's environment by
|
|
11
|
+
* {@link resolveGateRunLocator}: which forge, the API base, the repository,
|
|
12
|
+
* the run, and what the forge needs to start it again. After an approval,
|
|
13
|
+
* {@link resumeGateRun} starts it again:
|
|
14
|
+
*
|
|
15
|
+
* | Forge | Call | Token |
|
|
16
|
+
* |---|---|---|
|
|
17
|
+
* | GitHub | `POST /repos/{repo}/actions/runs/{run}/rerun-failed-jobs` | `actions: write` (the job's `GITHUB_TOKEN` with that permission, or a fine-grained token with Actions read and write) |
|
|
18
|
+
* | GitLab | `POST /projects/{id}/jobs/{job}/retry` | a project or personal access token with the `api` scope and the Developer role; `CI_JOB_TOKEN` cannot retry jobs |
|
|
19
|
+
* | Forgejo | `POST /repos/{repo}/actions/workflows/{file}/dispatches` on the run's branch | a token with the `write:repository` scope; Forgejo has no API to re-run a run, so it starts a new run of the workflow |
|
|
20
|
+
*
|
|
21
|
+
* GitHub re-runs the failed job and the jobs that need it, at the same
|
|
22
|
+
* commit. GitLab retries the job, and the jobs it skipped run after it. A
|
|
23
|
+
* Forgejo dispatch runs the whole workflow again at the branch's head, so the
|
|
24
|
+
* jobs before the gate run again too; they must be safe to repeat (a wave
|
|
25
|
+
* whose runs already applied plans nothing and applies nothing new).
|
|
26
|
+
*
|
|
27
|
+
* Resuming approves nothing. The resumed job decides the gate again from the
|
|
28
|
+
* ledger, so resuming a run whose approval does not count only makes it wait
|
|
29
|
+
* again. {@link resumeGateRun} skips a run that is still going, that ended
|
|
30
|
+
* well, or that was already resumed (a later GitHub attempt, a newer GitLab
|
|
31
|
+
* job of the same name, a newer Forgejo run of the workflow), so a scheduled
|
|
32
|
+
* resume job can call it every few minutes without starting a run twice.
|
|
33
|
+
*
|
|
34
|
+
* This module imports no workspace, ledger, schema or git code, so a product
|
|
35
|
+
* that ships one bundled file (terragucci) can import it as
|
|
36
|
+
* `@intentius/chant/gate-resume-run` and resume a job in process. Which
|
|
37
|
+
* approval answers a pending fact is `./op/gate-resume.ts`'s
|
|
38
|
+
* `resolutionAnswering`, which reads the gate's quorum rules and does pull the
|
|
39
|
+
* workspace in; that module re-exports everything here.
|
|
40
|
+
*/
|
|
41
|
+
import { ForgeApiError } from "./pr-forge.js";
|
|
42
|
+
export { isGateRunLocator, resolveGateRunLocator } from "./op/gate-run-locator.js";
|
|
43
|
+
const trimSlash = (s) => s.replace(/\/+$/, "");
|
|
44
|
+
const isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
45
|
+
function client(base, headers, fetchImpl) {
|
|
46
|
+
return async (method, path, body) => {
|
|
47
|
+
const url = `${trimSlash(base)}${path}`;
|
|
48
|
+
const res = await fetchImpl(url, {
|
|
49
|
+
method,
|
|
50
|
+
headers: { ...headers, ...(body !== undefined ? { "Content-Type": "application/json" } : {}) },
|
|
51
|
+
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
52
|
+
});
|
|
53
|
+
const text = await res.text();
|
|
54
|
+
if (!res.ok)
|
|
55
|
+
throw new ForgeApiError(method, url, res.status, text);
|
|
56
|
+
if (!text)
|
|
57
|
+
return null;
|
|
58
|
+
try {
|
|
59
|
+
return JSON.parse(text);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return text;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Start the job a pending fact's locator names again, or say why not. Throws
|
|
68
|
+
* {@link ForgeApiError} when the forge refuses a call, such as a token
|
|
69
|
+
* without the access the table in the module doc lists.
|
|
70
|
+
*/
|
|
71
|
+
export async function resumeGateRun(loc, opts) {
|
|
72
|
+
const fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
73
|
+
const url = loc.url ? { url: loc.url } : {};
|
|
74
|
+
const skip = (reason) => ({ status: "skipped", forge: loc.forge, reason, ...url });
|
|
75
|
+
const wouldResume = (how) => ({ status: "would-resume", forge: loc.forge, how: `would ${how}`, ...url });
|
|
76
|
+
if (loc.forge === "github") {
|
|
77
|
+
const call = client(loc.api, { Authorization: `Bearer ${opts.token}`, Accept: "application/vnd.github+json" }, fetchImpl);
|
|
78
|
+
const path = `/repos/${loc.repo}/actions/runs/${loc.run}`;
|
|
79
|
+
const run = await call("GET", path);
|
|
80
|
+
if (!isObject(run))
|
|
81
|
+
throw new Error(`GET ${path} returned no run`);
|
|
82
|
+
if (run.status !== "completed")
|
|
83
|
+
return skip(`run ${loc.run} is ${String(run.status)}, not finished`);
|
|
84
|
+
const attempt = typeof run.run_attempt === "number" ? run.run_attempt : undefined;
|
|
85
|
+
if (loc.attempt !== undefined && attempt !== undefined && attempt > loc.attempt) {
|
|
86
|
+
return skip(`run ${loc.run} was already re-run (attempt ${attempt}; attempt ${loc.attempt} waited)`);
|
|
87
|
+
}
|
|
88
|
+
if (run.conclusion === "success")
|
|
89
|
+
return skip(`run ${loc.run} succeeded`);
|
|
90
|
+
if (opts.dryRun)
|
|
91
|
+
return wouldResume(`re-run the failed jobs of run ${loc.run}`);
|
|
92
|
+
await call("POST", `${path}/rerun-failed-jobs`, {});
|
|
93
|
+
return { status: "resumed", forge: "github", how: `re-ran the failed jobs of run ${loc.run}`, ...url };
|
|
94
|
+
}
|
|
95
|
+
if (loc.forge === "gitlab") {
|
|
96
|
+
const call = client(loc.api, { "PRIVATE-TOKEN": opts.token }, fetchImpl);
|
|
97
|
+
const project = `/projects/${encodeURIComponent(decodeURIComponent(loc.repo))}`;
|
|
98
|
+
const job = await call("GET", `${project}/jobs/${loc.job}`);
|
|
99
|
+
if (!isObject(job))
|
|
100
|
+
throw new Error(`GET ${project}/jobs/${loc.job} returned no job`);
|
|
101
|
+
const status = String(job.status);
|
|
102
|
+
if (status === "success")
|
|
103
|
+
return skip(`job ${loc.job} succeeded`);
|
|
104
|
+
if (!["failed", "canceled", "skipped"].includes(status))
|
|
105
|
+
return skip(`job ${loc.job} is ${status}, not finished`);
|
|
106
|
+
const name = loc.jobName ?? (typeof job.name === "string" ? job.name : undefined);
|
|
107
|
+
if (name) {
|
|
108
|
+
// The pipeline's jobs list leaves retried jobs out, so the job of this name is its newest try.
|
|
109
|
+
const jobs = await call("GET", `${project}/pipelines/${loc.run}/jobs?per_page=100`);
|
|
110
|
+
const newest = Array.isArray(jobs) ? jobs.find((j) => isObject(j) && j.name === name) : undefined;
|
|
111
|
+
if (isObject(newest) && String(newest.id) !== String(loc.job)) {
|
|
112
|
+
return skip(`job ${loc.job} (${name}) was already retried as job ${String(newest.id)}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (opts.dryRun)
|
|
116
|
+
return wouldResume(`retry job ${loc.job}`);
|
|
117
|
+
const retried = await call("POST", `${project}/jobs/${loc.job}/retry`);
|
|
118
|
+
const id = isObject(retried) && retried.id !== undefined ? ` as job ${String(retried.id)}` : "";
|
|
119
|
+
return { status: "resumed", forge: "gitlab", how: `retried job ${loc.job}${id}`, ...url };
|
|
120
|
+
}
|
|
121
|
+
const call = client(loc.api, { Authorization: `token ${opts.token}`, Accept: "application/json" }, fetchImpl);
|
|
122
|
+
const repo = `/repos/${loc.repo}`;
|
|
123
|
+
const run = await call("GET", `${repo}/actions/runs/${loc.run}`);
|
|
124
|
+
if (!isObject(run))
|
|
125
|
+
throw new Error(`GET ${repo}/actions/runs/${loc.run} returned no run`);
|
|
126
|
+
const status = String(run.status);
|
|
127
|
+
if (status === "success")
|
|
128
|
+
return skip(`run ${loc.run} succeeded`);
|
|
129
|
+
if (["waiting", "running", "blocked", "unknown"].includes(status))
|
|
130
|
+
return skip(`run ${loc.run} is ${status}, not finished`);
|
|
131
|
+
const listed = await call("GET", `${repo}/actions/runs?workflow_id=${encodeURIComponent(loc.workflow)}&limit=50`);
|
|
132
|
+
const runs = isObject(listed) && Array.isArray(listed.workflow_runs) ? listed.workflow_runs : Array.isArray(listed) ? listed : [];
|
|
133
|
+
// Forgejo reports `created` in whole seconds.
|
|
134
|
+
const since = opts.since ? Math.floor(new Date(opts.since).getTime() / 1000) * 1000 : undefined;
|
|
135
|
+
const later = runs.find((r) => isObject(r) && Number(r.id) > Number(loc.run) &&
|
|
136
|
+
(r.prettyref === undefined || r.prettyref === loc.ref) &&
|
|
137
|
+
(since === undefined || (typeof r.created === "string" && new Date(r.created).getTime() >= since)));
|
|
138
|
+
if (isObject(later))
|
|
139
|
+
return skip(`run ${String(later.id)} of ${loc.workflow} started after the approval`);
|
|
140
|
+
if (opts.dryRun)
|
|
141
|
+
return wouldResume(`dispatch ${loc.workflow} on ${loc.ref}`);
|
|
142
|
+
await call("POST", `${repo}/actions/workflows/${encodeURIComponent(loc.workflow)}/dispatches`, { ref: loc.ref });
|
|
143
|
+
return { status: "resumed", forge: "forgejo", how: `dispatched ${loc.workflow} on ${loc.ref}`, ...url };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The token a resume uses: `CHANT_FORGE_TOKEN`, else the forge's own
|
|
147
|
+
* (`GITHUB_TOKEN` or `GH_TOKEN` on GitHub and Forgejo, `GITLAB_TOKEN` on
|
|
148
|
+
* GitLab), the same order the pull-request loop reads (`../pr-forge.ts`).
|
|
149
|
+
*/
|
|
150
|
+
export function resumeTokenFromEnv(forge, env = process.env) {
|
|
151
|
+
if (env.CHANT_FORGE_TOKEN)
|
|
152
|
+
return env.CHANT_FORGE_TOKEN;
|
|
153
|
+
return forge === "gitlab" ? env.GITLAB_TOKEN : env.GITHUB_TOKEN ?? env.GH_TOKEN;
|
|
154
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gated waves (#3049): one change rolled out across many roots, a wave at a
|
|
3
|
+
* time, each wave behind its own gate bound to that wave's set digest.
|
|
4
|
+
*
|
|
5
|
+
* `chant components fan-out --wave-gate` is the runner. This module holds the
|
|
6
|
+
* parts that need no runner: how a set of roots is cut into waves, what a
|
|
7
|
+
* wave's digest is, what its gate is called, and what the attempt record says
|
|
8
|
+
* about each wave. They are kept apart from the runner because terragucci
|
|
9
|
+
* calls them from its CI stages as one bundled file with no TypeScript
|
|
10
|
+
* toolchain (#3421). Everything here imports `./change-set` and nothing else,
|
|
11
|
+
* and `gated-waves-bundle.test.ts` holds that.
|
|
12
|
+
*
|
|
13
|
+
* ## The set digest
|
|
14
|
+
*
|
|
15
|
+
* A wave's digest is {@link changeSetDigest} over its members' `{ member,
|
|
16
|
+
* planDigest }` pairs, the function #3181's change-set document uses. A
|
|
17
|
+
* terraform-family member is named after its root, so this is the issue's
|
|
18
|
+
* `jcs1-sha256` over sorted `{ root, planDigest }`, and a wave's digest equals
|
|
19
|
+
* the change-set digest of the wave's members. Each member's plan digest is
|
|
20
|
+
* the one a gate on that root alone binds (`terraformPlanDigest`, #2300), so a
|
|
21
|
+
* one-root wave and a one-root `TerraformApplyOp` approve the same value.
|
|
22
|
+
*
|
|
23
|
+
* ## Why a wave is planned when it is reached
|
|
24
|
+
*
|
|
25
|
+
* A later wave planned up front reads outputs that do not exist yet. Planned
|
|
26
|
+
* after the wave before it applied, its digest describes the real upstream
|
|
27
|
+
* values, which is what an approver of that wave is shown.
|
|
28
|
+
*/
|
|
29
|
+
import { changeSetDigest } from "./change-set.js";
|
|
30
|
+
/** Thrown when a canary names something that is not in the set being planned. */
|
|
31
|
+
export class UnknownCanaryError extends Error {
|
|
32
|
+
constructor(canary, known) {
|
|
33
|
+
super(`canary names "${canary}", which is not in this set (known: ${known.join(", ") || "none"})`);
|
|
34
|
+
this.canary = canary;
|
|
35
|
+
this.name = "UnknownCanaryError";
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Thrown when the nodes being layered depend on each other in a cycle. */
|
|
39
|
+
export class WaveCycleError extends Error {
|
|
40
|
+
constructor(members) {
|
|
41
|
+
super(`dependency cycle among: ${members.join(", ")}`);
|
|
42
|
+
this.members = members;
|
|
43
|
+
this.name = "WaveCycleError";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Cut `nodes` into ordered waves: each node lands after every node it reads
|
|
48
|
+
* from, and each wave is sorted by name so the same graph always produces the
|
|
49
|
+
* same waves. With a canary list, those nodes are wave 1.
|
|
50
|
+
*
|
|
51
|
+
* A dependency on a name outside `nodes` does not hold a node back. That is
|
|
52
|
+
* the subset case: the dependency already applied, or is not changing.
|
|
53
|
+
*/
|
|
54
|
+
export function layerWaves(nodes, options = {}) {
|
|
55
|
+
const names = new Set(nodes.map((n) => n.name));
|
|
56
|
+
const known = new Set([...names, ...(options.known ?? [])]);
|
|
57
|
+
for (const canary of options.canary ?? []) {
|
|
58
|
+
if (!known.has(canary))
|
|
59
|
+
throw new UnknownCanaryError(canary, [...known].sort());
|
|
60
|
+
}
|
|
61
|
+
const canaries = [...new Set((options.canary ?? []).filter((c) => names.has(c)))].sort();
|
|
62
|
+
const waves = canaries.length > 0 ? [canaries] : [];
|
|
63
|
+
const remaining = new Set([...names].filter((n) => !canaries.includes(n)));
|
|
64
|
+
const deps = new Map(nodes.map((n) => [n.name, (n.dependsOn ?? []).filter((d) => remaining.has(d))]));
|
|
65
|
+
while (remaining.size > 0) {
|
|
66
|
+
const wave = [...remaining].filter((n) => deps.get(n).every((d) => !remaining.has(d))).sort();
|
|
67
|
+
if (wave.length === 0)
|
|
68
|
+
throw new WaveCycleError([...remaining].sort());
|
|
69
|
+
for (const n of wave)
|
|
70
|
+
remaining.delete(n);
|
|
71
|
+
waves.push(wave);
|
|
72
|
+
}
|
|
73
|
+
return waves;
|
|
74
|
+
}
|
|
75
|
+
/** Thrown when a wave's members include a provisional plan, which no gate may bind. */
|
|
76
|
+
export class ProvisionalWaveMemberError extends Error {
|
|
77
|
+
constructor(members) {
|
|
78
|
+
super(`a wave cannot be gated on a provisional plan: ${members.join(", ")} planned before what it reads applied. ` +
|
|
79
|
+
`Plan it again in its own wave, after its upstream applied`);
|
|
80
|
+
this.members = members;
|
|
81
|
+
this.name = "ProvisionalWaveMemberError";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A wave's set digest: {@link changeSetDigest} over its members. Order does
|
|
86
|
+
* not matter, and it moves whenever one member's plan digest does. A wave
|
|
87
|
+
* naming one member twice has no digest and is refused, and so is a wave
|
|
88
|
+
* holding a provisional plan (#3416): a gate bound to it would approve
|
|
89
|
+
* values nobody has yet.
|
|
90
|
+
*/
|
|
91
|
+
export function waveSetDigest(members) {
|
|
92
|
+
const provisional = members.filter((m) => m.provisional === true).map((m) => m.member);
|
|
93
|
+
if (provisional.length > 0)
|
|
94
|
+
throw new ProvisionalWaveMemberError([...new Set(provisional)].sort());
|
|
95
|
+
return changeSetDigest(members);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The gate a wave waits on: `<gate>-wave-<n>`, under the fan-out's op.
|
|
99
|
+
*
|
|
100
|
+
* One gate name per wave keeps each wave's approvals apart. With one name
|
|
101
|
+
* shared by every wave, wave 2 would find wave 1's approval and report it as
|
|
102
|
+
* an approval of another plan, which is true and useless. Wave numbers come
|
|
103
|
+
* from the derivation, not from what is left to run, so wave 3 stays wave 3
|
|
104
|
+
* on a resumed attempt and its approval still applies.
|
|
105
|
+
*/
|
|
106
|
+
export function waveGateName(gate, wave) {
|
|
107
|
+
return `${gate}-wave-${wave}`;
|
|
108
|
+
}
|
|
109
|
+
const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
110
|
+
const strings = (value) => Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
|
|
111
|
+
/**
|
|
112
|
+
* Read the `waves` array of an attempt record, dropping anything malformed.
|
|
113
|
+
* A record written before #3049 has none, which reads as no waves.
|
|
114
|
+
*/
|
|
115
|
+
export function readWaveRecords(value) {
|
|
116
|
+
if (!Array.isArray(value))
|
|
117
|
+
return [];
|
|
118
|
+
const out = [];
|
|
119
|
+
for (const raw of value) {
|
|
120
|
+
if (!isObject(raw))
|
|
121
|
+
continue;
|
|
122
|
+
const { wave, op, gate, digest, status } = raw;
|
|
123
|
+
if (typeof wave !== "number" || typeof op !== "string" || typeof gate !== "string" || typeof digest !== "string")
|
|
124
|
+
continue;
|
|
125
|
+
if (status !== "gated" && status !== "applied" && status !== "failed")
|
|
126
|
+
continue;
|
|
127
|
+
const members = Array.isArray(raw.members)
|
|
128
|
+
? raw.members.filter((m) => isObject(m) && typeof m.member === "string" && typeof m.planDigest === "string")
|
|
129
|
+
: [];
|
|
130
|
+
const failed = Array.isArray(raw.failed)
|
|
131
|
+
? raw.failed
|
|
132
|
+
.filter((f) => isObject(f) && typeof f.component === "string")
|
|
133
|
+
.map((f) => ({ component: f.component, ...(typeof f.error === "string" ? { error: f.error } : {}) }))
|
|
134
|
+
: [];
|
|
135
|
+
out.push({
|
|
136
|
+
wave,
|
|
137
|
+
op,
|
|
138
|
+
gate,
|
|
139
|
+
components: strings(raw.components),
|
|
140
|
+
digest,
|
|
141
|
+
members: members.map((m) => ({ member: m.member, planDigest: m.planDigest })),
|
|
142
|
+
status,
|
|
143
|
+
...(typeof raw.approvedBy === "string" ? { approvedBy: raw.approvedBy } : {}),
|
|
144
|
+
...(typeof raw.approved === "string" ? { approved: raw.approved } : {}),
|
|
145
|
+
...(failed.length > 0 ? { failed } : {}),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return out;
|
|
149
|
+
}
|
|
150
|
+
/** Put `record` in `records` in place of any earlier record for the same wave, sorted by wave. */
|
|
151
|
+
export function withWaveRecord(records, record) {
|
|
152
|
+
return [...records.filter((r) => r.wave !== record.wave), record].sort((a, b) => a.wave - b.wave);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* The refusal for a wave whose set changed after it was approved: the digest
|
|
156
|
+
* that was approved, the one planned now, and that nothing in the wave ran.
|
|
157
|
+
* On a sealed gate the approve hint ends in `--sign`.
|
|
158
|
+
*/
|
|
159
|
+
export function describeChangedWave(record,
|
|
160
|
+
/** True when the gate is sealed (`identity.gates`): an approval without `--sign` doesn't count, so the hint says to sign. */
|
|
161
|
+
sealed = false) {
|
|
162
|
+
return (`wave ${record.wave} changed after it was approved, so nothing in it was applied. ` +
|
|
163
|
+
`approved: ${record.approved ?? "(none)"}; planned now: ${record.digest}. ` +
|
|
164
|
+
`Read the new plan, then approve it: chant approve ${record.op} ${record.gate} --plan ${record.digest}${sealed ? " --sign" : ""}`);
|
|
165
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Governance verb vocabulary .
|
|
3
|
+
*
|
|
4
|
+
* `resourceType` on a change-set entry is a free provider-specific string
|
|
5
|
+
* ("team", "branch-protection", "protected-tag", …) chosen per cycle. That is
|
|
6
|
+
* right for display but useless for reading two providers' plans as one
|
|
7
|
+
* grammar. The verb is the cross-provider category a cycle reconciles;
|
|
8
|
+
* provider-specific cycle names stay for display.
|
|
9
|
+
*
|
|
10
|
+
* SCM and cloud cycles stamp the same verbs, so a GitHub plan and an AWS plan
|
|
11
|
+
* group the same way:
|
|
12
|
+
*
|
|
13
|
+
* - `org-unit` — the containers and their settings: GitHub org/repo settings,
|
|
14
|
+
* GitLab group/project/instance settings, cloud OUs/folders/accounts.
|
|
15
|
+
* - `policy-guardrail` — rules constraining what may happen: branch
|
|
16
|
+
* protections, rulesets, push rules, MR approvals, security features,
|
|
17
|
+
* dependency hygiene, SCPs, Org Policies.
|
|
18
|
+
* - `membership` — who belongs, directly or via teams: org members, team
|
|
19
|
+
* membership, group members.
|
|
20
|
+
* - `identity-assignment` — non-person and delegated access: tokens, deploy
|
|
21
|
+
* keys, service credentials, SSO/IAM assignments. `membership` is people
|
|
22
|
+
* in containers; this is everything else that can act.
|
|
23
|
+
* - `audit-sink` — where events and evidence flow: webhooks, integrations,
|
|
24
|
+
* CloudTrail/audit-log sinks.
|
|
25
|
+
* - `secret-material` — secrets and CI variables the platform stores.
|
|
26
|
+
*
|
|
27
|
+
* A cycle has exactly one verb. When a cycle plausibly spans two (GitHub
|
|
28
|
+
* `environments` carries both reviewer gates and secrets), stamp the verb of
|
|
29
|
+
* the cycle's primary object — the thing whose create/delete the cycle owns —
|
|
30
|
+
* not of fields it also happens to write.
|
|
31
|
+
*/
|
|
32
|
+
/** Every verb, for exhaustiveness checks ("does each cycle stamp one?"). */
|
|
33
|
+
export const GOVERNANCE_VERBS = [
|
|
34
|
+
"org-unit",
|
|
35
|
+
"policy-guardrail",
|
|
36
|
+
"membership",
|
|
37
|
+
"identity-assignment",
|
|
38
|
+
"audit-sink",
|
|
39
|
+
"secret-material",
|
|
40
|
+
];
|
|
41
|
+
export function isGovernanceVerb(v) {
|
|
42
|
+
return typeof v === "string" && GOVERNANCE_VERBS.includes(v);
|
|
43
|
+
}
|