@intentius/chant 0.57.0 → 0.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit/catalog.d.ts +51 -1
- package/dist/audit/catalog.d.ts.map +1 -1
- package/dist/audit/core.d.ts +20 -1
- package/dist/audit/core.d.ts.map +1 -1
- package/dist/audit/discover.d.ts +14 -8
- package/dist/audit/discover.d.ts.map +1 -1
- package/dist/audit/lineage.d.ts +10 -0
- package/dist/audit/lineage.d.ts.map +1 -0
- package/dist/audit/prior-art.d.ts +385 -0
- package/dist/audit/prior-art.d.ts.map +1 -0
- package/dist/audit/proof.d.ts +16 -0
- package/dist/audit/proof.d.ts.map +1 -1
- package/dist/audit/report-html.d.ts.map +1 -1
- package/dist/audit/report-model.d.ts +8 -1
- package/dist/audit/report-model.d.ts.map +1 -1
- package/dist/audit/report.d.ts.map +1 -1
- package/dist/audit/rules-doc.d.ts +3 -0
- package/dist/audit/rules-doc.d.ts.map +1 -1
- package/dist/audit/secrets.d.ts +15 -0
- package/dist/audit/secrets.d.ts.map +1 -1
- package/dist/audit/terraform-state.d.ts +46 -0
- package/dist/audit/terraform-state.d.ts.map +1 -0
- package/dist/build.d.ts +17 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/claimed-fields.d.ts +161 -0
- package/dist/claimed-fields.d.ts.map +1 -0
- package/dist/cli/build-params-cli.d.ts +2 -2
- package/dist/cli/command-group.d.ts +14 -0
- package/dist/cli/command-group.d.ts.map +1 -1
- package/dist/cli/commands/audit.d.ts +17 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-docs.d.ts +1 -1
- package/dist/cli/commands/check-lexicon-examples.d.ts +16 -6
- package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/codegen.d.ts +1 -0
- package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/project.d.ts +7 -0
- package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/onboard.d.ts +2 -0
- package/dist/cli/commands/onboard.d.ts.map +1 -1
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/operator.d.ts +82 -16
- package/dist/cli/handlers/operator.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts +49 -42
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/main.d.ts +28 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/mcp/op-tools.d.ts +16 -1
- package/dist/cli/mcp/op-tools.d.ts.map +1 -1
- package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
- package/dist/cli/mcp/resources/context.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +26 -9
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/generate-post-synth-barrel.d.ts +1 -1
- package/dist/components/auto-release.d.ts +10 -20
- package/dist/components/auto-release.d.ts.map +1 -1
- package/dist/components/capability.d.ts +4 -4
- package/dist/components/cli-support.d.ts +20 -21
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/component.d.ts +3 -3
- package/dist/components/component.d.ts.map +1 -1
- package/dist/components/driver-output.d.ts.map +1 -1
- package/dist/components/driver.d.ts +66 -36
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/manifest-persistence.d.ts +1 -9
- package/dist/components/manifest-persistence.d.ts.map +1 -1
- package/dist/components/run-progress.d.ts +6 -6
- package/dist/components/run-progress.d.ts.map +1 -1
- package/dist/components/verbs/run-agent.d.ts +9 -15
- package/dist/components/verbs/run-agent.d.ts.map +1 -1
- package/dist/components/verbs/verify.d.ts +2 -2
- package/dist/deep-observation.d.ts +17 -0
- package/dist/deep-observation.d.ts.map +1 -1
- package/dist/discovery/files.d.ts +4 -4
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/param-deps.d.ts +33 -0
- package/dist/discovery/param-deps.d.ts.map +1 -1
- package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
- package/dist/discovery/sandbox/config-wire.d.ts +2 -2
- package/dist/fold/foldable-helpers.d.ts +5 -1
- package/dist/fold/foldable-helpers.d.ts.map +1 -1
- package/dist/fold-provenance.d.ts +236 -0
- package/dist/fold-provenance.d.ts.map +1 -0
- package/dist/graph-ops.d.ts +1 -1
- package/dist/held-elsewhere.d.ts +85 -0
- package/dist/held-elsewhere.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/kubectl-context.d.ts +3 -3
- package/dist/lexicon-config.d.ts +4 -4
- package/dist/lexicon-plugin-helpers.d.ts +1 -1
- package/dist/lexicon.d.ts +104 -14
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/change-set.d.ts +13 -0
- package/dist/lifecycle/change-set.d.ts.map +1 -1
- package/dist/lifecycle/deep-diff.d.ts +133 -6
- package/dist/lifecycle/deep-diff.d.ts.map +1 -1
- package/dist/lifecycle/deep-observe.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +71 -3
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/index.d.ts +1 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/release-ledger.d.ts +2 -2
- package/dist/lifecycle/run-ledger.d.ts +53 -0
- package/dist/lifecycle/run-ledger.d.ts.map +1 -0
- package/dist/lifecycle/symptoms.d.ts +3 -3
- package/dist/lifecycle/symptoms.d.ts.map +1 -1
- package/dist/lint/config.d.ts +81 -2
- package/dist/lint/config.d.ts.map +1 -1
- package/dist/lint/post-synth.d.ts +55 -2
- package/dist/lint/post-synth.d.ts.map +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +1 -1
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -1
- package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts +44 -0
- package/dist/lint/rules/comp/comp004-gate-needs-durable-runtime.d.ts.map +1 -0
- package/dist/lint/rules/comp/index.d.ts +1 -1
- package/dist/lint/rules/comp/index.d.ts.map +1 -1
- package/dist/lint/rules/op/index.d.ts +16 -0
- package/dist/lint/rules/op/index.d.ts.map +1 -0
- package/dist/lint/rules/op/ops012-activity-contract.d.ts +27 -0
- package/dist/lint/rules/op/ops012-activity-contract.d.ts.map +1 -0
- package/dist/lint/rules/op/ops013-step-output-ref.d.ts +61 -0
- package/dist/lint/rules/op/ops013-step-output-ref.d.ts.map +1 -0
- package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts +55 -0
- package/dist/lint/rules/op/ops014-converge-rule-refusals.d.ts.map +1 -0
- package/dist/lint/rules/op/support.d.ts +12 -0
- package/dist/lint/rules/op/support.d.ts.map +1 -0
- package/dist/lint/suppressions.d.ts +108 -0
- package/dist/lint/suppressions.d.ts.map +1 -0
- package/dist/live-endpoint.d.ts +1 -1
- package/dist/op/activities/activity-contracts.d.ts +54 -0
- package/dist/op/activities/activity-contracts.d.ts.map +1 -0
- package/dist/op/activities/apply.d.ts +262 -0
- package/dist/op/activities/apply.d.ts.map +1 -0
- package/dist/op/activities/build.d.ts +13 -0
- package/dist/op/activities/build.d.ts.map +1 -0
- package/dist/op/activities/converge.d.ts +110 -0
- package/dist/op/activities/converge.d.ts.map +1 -0
- package/dist/op/activities/env-teardown.d.ts +76 -0
- package/dist/op/activities/env-teardown.d.ts.map +1 -0
- package/dist/op/activities/guard-validate.d.ts +64 -0
- package/dist/op/activities/guard-validate.d.ts.map +1 -0
- package/dist/op/activities/http-check.d.ts +34 -0
- package/dist/op/activities/http-check.d.ts.map +1 -0
- package/dist/op/activities/index.d.ts +31 -0
- package/dist/op/activities/index.d.ts.map +1 -0
- package/dist/op/activities/lexicon-upgrade.d.ts +182 -0
- package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -0
- package/dist/op/activities/lifecycle.d.ts +42 -0
- package/dist/op/activities/lifecycle.d.ts.map +1 -0
- package/dist/op/activities/pipeline-audit.d.ts +84 -0
- package/dist/op/activities/pipeline-audit.d.ts.map +1 -0
- package/dist/op/activities/policy.d.ts +17 -0
- package/dist/op/activities/policy.d.ts.map +1 -0
- package/dist/op/activities/reconcile.d.ts +89 -0
- package/dist/op/activities/reconcile.d.ts.map +1 -0
- package/dist/op/activities/shell.d.ts +13 -0
- package/dist/op/activities/shell.d.ts.map +1 -0
- package/dist/op/activities/teardown.d.ts +10 -0
- package/dist/op/activities/teardown.d.ts.map +1 -0
- package/dist/op/activities/util.d.ts +7 -0
- package/dist/op/activities/util.d.ts.map +1 -0
- package/dist/op/activities/wait.d.ts +28 -0
- package/dist/op/activities/wait.d.ts.map +1 -0
- package/dist/op/activities/workflow-audit.d.ts +92 -0
- package/dist/op/activities/workflow-audit.d.ts.map +1 -0
- package/dist/op/activity-contract-registry.d.ts +76 -0
- package/dist/op/activity-contract-registry.d.ts.map +1 -0
- package/dist/op/activity-contract.d.ts +25 -18
- package/dist/op/activity-contract.d.ts.map +1 -1
- package/dist/op/activity-failure.d.ts +28 -0
- package/dist/op/activity-failure.d.ts.map +1 -0
- package/dist/op/activity-profiles.d.ts +118 -0
- package/dist/op/activity-profiles.d.ts.map +1 -0
- package/dist/op/activity-registry.d.ts +22 -38
- package/dist/op/activity-registry.d.ts.map +1 -1
- package/dist/op/activity-runtime.d.ts +3 -14
- package/dist/op/activity-runtime.d.ts.map +1 -1
- package/dist/op/builders.d.ts +84 -29
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/composites/apply-op.d.ts +113 -0
- package/dist/op/composites/apply-op.d.ts.map +1 -0
- package/dist/op/composites/converge-op.d.ts +120 -0
- package/dist/op/composites/converge-op.d.ts.map +1 -0
- package/dist/op/composites/index.d.ts +26 -0
- package/dist/op/composites/index.d.ts.map +1 -0
- package/dist/op/composites/lexicon-upgrade-op.d.ts +78 -0
- package/dist/op/composites/lexicon-upgrade-op.d.ts.map +1 -0
- package/dist/op/composites/pipeline-audit-op.d.ts +50 -0
- package/dist/op/composites/pipeline-audit-op.d.ts.map +1 -0
- package/dist/op/composites/reconcile-op.d.ts +57 -0
- package/dist/op/composites/reconcile-op.d.ts.map +1 -0
- package/dist/op/composites/watch-op.d.ts +60 -0
- package/dist/op/composites/watch-op.d.ts.map +1 -0
- package/dist/op/composites/workflow-audit-op.d.ts +57 -0
- package/dist/op/composites/workflow-audit-op.d.ts.map +1 -0
- package/dist/op/converge-rule.d.ts +12 -10
- package/dist/op/converge-rule.d.ts.map +1 -1
- package/dist/op/cron.d.ts +51 -0
- package/dist/op/cron.d.ts.map +1 -0
- package/dist/op/discover.d.ts +9 -0
- package/dist/op/discover.d.ts.map +1 -1
- package/dist/op/duration.d.ts +11 -0
- package/dist/op/duration.d.ts.map +1 -0
- package/dist/op/emulator-lifecycle.d.ts.map +1 -1
- package/dist/op/gate.d.ts +90 -0
- package/dist/op/gate.d.ts.map +1 -0
- package/dist/op/generate-pipeline.d.ts +9 -0
- package/dist/op/generate-pipeline.d.ts.map +1 -1
- package/dist/op/index.d.ts +23 -7
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/local-executor.d.ts +114 -28
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-output.d.ts +11 -1
- package/dist/op/local-output.d.ts.map +1 -1
- package/dist/op/op-ir.d.ts +184 -0
- package/dist/op/op-ir.d.ts.map +1 -0
- package/dist/op/op-verb-class.d.ts +10 -2
- package/dist/op/op-verb-class.d.ts.map +1 -1
- package/dist/op/operator.d.ts +30 -5
- package/dist/op/operator.d.ts.map +1 -1
- package/dist/op/receipt-store.d.ts +1 -1
- package/dist/op/receipt-store.d.ts.map +1 -1
- package/dist/op/resource.d.ts +15 -1
- package/dist/op/resource.d.ts.map +1 -1
- package/dist/op/runtime.d.ts +200 -0
- package/dist/op/runtime.d.ts.map +1 -0
- package/dist/op/runtimes/local.d.ts +29 -0
- package/dist/op/runtimes/local.d.ts.map +1 -0
- package/dist/op/step-output-ref.d.ts +15 -13
- package/dist/op/step-output-ref.d.ts.map +1 -1
- package/dist/op/types.d.ts +79 -27
- package/dist/op/types.d.ts.map +1 -1
- package/dist/ownership.d.ts +1 -1
- package/dist/provenance.d.ts +21 -0
- package/dist/provenance.d.ts.map +1 -1
- package/dist/serializer-walker.d.ts.map +1 -1
- package/package.json +6 -1
- package/src/audit/catalog.test.ts +79 -3
- package/src/audit/catalog.ts +111 -13
- package/src/audit/core.test.ts +26 -0
- package/src/audit/core.ts +61 -17
- package/src/audit/discover.test.ts +39 -0
- package/src/audit/discover.ts +91 -15
- package/src/audit/lineage.ts +100 -0
- package/src/audit/prior-art.ts +153 -0
- package/src/audit/proof.test.ts +67 -0
- package/src/audit/proof.ts +70 -0
- package/src/audit/report-html.ts +9 -4
- package/src/audit/report-model.ts +16 -2
- package/src/audit/report.test.ts +33 -0
- package/src/audit/report.ts +5 -3
- package/src/audit/rules-doc.test.ts +34 -2
- package/src/audit/rules-doc.ts +82 -9
- package/src/audit/secrets.ts +15 -3
- package/src/audit/terraform-state.test.ts +144 -0
- package/src/audit/terraform-state.ts +131 -0
- package/src/build.ts +31 -1
- package/src/claimed-fields.test.ts +145 -0
- package/src/claimed-fields.ts +208 -0
- package/src/cli/build-params-cli.ts +2 -2
- package/src/cli/command-group.ts +14 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/.terraform/providers/lock.txt +1 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/main.tf +1 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/modules/foo/main.tf +1 -0
- package/src/cli/commands/__fixtures__/audit-terraform/infra/variables.tf +3 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +13 -4
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/docs-cli.ts +4 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/package.ts +1 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/package-cli.ts +21 -0
- package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +1 -0
- package/src/cli/commands/audit.test.ts +189 -11
- package/src/cli/commands/audit.ts +73 -27
- package/src/cli/commands/build.test.ts +292 -9
- package/src/cli/commands/build.ts +156 -24
- package/src/cli/commands/check-lexicon-docs.ts +1 -1
- package/src/cli/commands/check-lexicon-examples.test.ts +29 -1
- package/src/cli/commands/check-lexicon-examples.ts +42 -10
- package/src/cli/commands/init-lexicon/templates/codegen.ts +9 -0
- package/src/cli/commands/init-lexicon/templates/project.ts +44 -4
- package/src/cli/commands/init-lexicon.test.ts +97 -2
- package/src/cli/commands/init-lexicon.ts +4 -2
- package/src/cli/commands/init.test.ts +35 -1
- package/src/cli/commands/init.ts +14 -3
- package/src/cli/commands/lint.test.ts +48 -0
- package/src/cli/commands/lint.ts +123 -0
- package/src/cli/commands/onboard.test.ts +75 -0
- package/src/cli/commands/onboard.ts +54 -23
- package/src/cli/handlers/build.test.ts +81 -1
- package/src/cli/handlers/build.ts +15 -1
- package/src/cli/handlers/graph.test.ts +3 -3
- package/src/cli/handlers/lifecycle.test.ts +195 -12
- package/src/cli/handlers/lifecycle.ts +123 -6
- package/src/cli/handlers/misc.ts +1 -1
- package/src/cli/handlers/operator.test.ts +183 -11
- package/src/cli/handlers/operator.ts +260 -55
- package/src/cli/handlers/run.test.ts +431 -1287
- package/src/cli/handlers/run.ts +365 -915
- package/src/cli/main.test.ts +23 -15
- package/src/cli/main.ts +88 -33
- package/src/cli/mcp/op-tools.ts +147 -88
- package/src/cli/mcp/resource-handlers.ts +10 -37
- package/src/cli/mcp/resources/context.ts +11 -12
- package/src/cli/mcp/server.test.ts +25 -27
- package/src/cli/mcp/server.ts +2 -2
- package/src/cli/registry.ts +26 -9
- package/src/codegen/docs.ts +1 -1
- package/src/codegen/generate-post-synth-barrel.test.ts +1 -1
- package/src/codegen/generate-post-synth-barrel.ts +1 -1
- package/src/components/README.md +3 -2
- package/src/components/auto-release.test.ts +4 -20
- package/src/components/auto-release.ts +17 -42
- package/src/components/capability.ts +4 -4
- package/src/components/cli-support.test.ts +10 -5
- package/src/components/cli-support.ts +52 -44
- package/src/components/component.schema.json +2 -2
- package/src/components/component.ts +3 -3
- package/src/components/driver-output.ts +14 -2
- package/src/components/driver.test.ts +92 -22
- package/src/components/driver.ts +193 -83
- package/src/components/index.ts +1 -6
- package/src/components/manifest-persistence.test.ts +2 -20
- package/src/components/manifest-persistence.ts +4 -24
- package/src/components/pilots/pilots-lint-clean.test.ts +11 -10
- package/src/components/run-progress.ts +6 -6
- package/src/components/verbs/run-agent.ts +11 -17
- package/src/components/verbs/verify.ts +2 -2
- package/src/deep-observation.test.ts +75 -0
- package/src/deep-observation.ts +48 -0
- package/src/discovery/collect.test.ts +3 -3
- package/src/discovery/files.ts +4 -4
- package/src/discovery/fold-import.ts +105 -2
- package/src/discovery/param-deps.test.ts +112 -1
- package/src/discovery/param-deps.ts +193 -0
- package/src/discovery/sandbox/bundle.ts +15 -1
- package/src/discovery/sandbox/config-wire.test.ts +2 -2
- package/src/discovery/sandbox/config-wire.ts +2 -2
- package/src/fold/fold.test.ts +56 -0
- package/src/fold/foldable-helpers.ts +81 -1
- package/src/fold-provenance-exclusion.test.ts +186 -0
- package/src/fold-provenance.test.ts +495 -0
- package/src/fold-provenance.ts +441 -0
- package/src/graph-ops.test.ts +2 -2
- package/src/graph-ops.ts +1 -1
- package/src/held-elsewhere.test.ts +102 -0
- package/src/held-elsewhere.ts +114 -0
- package/src/index.ts +3 -0
- package/src/kubectl-context.ts +3 -3
- package/src/lexicon-config.test.ts +5 -5
- package/src/lexicon-config.ts +4 -4
- package/src/lexicon-plugin-helpers.ts +1 -1
- package/src/lexicon.ts +120 -14
- package/src/lifecycle/change-set.test.ts +49 -0
- package/src/lifecycle/change-set.ts +67 -0
- package/src/lifecycle/converge-ledger.ts +1 -1
- package/src/lifecycle/deep-diff.test.ts +267 -14
- package/src/lifecycle/deep-diff.ts +217 -14
- package/src/lifecycle/deep-observe.test.ts +3 -1
- package/src/lifecycle/deep-observe.ts +16 -6
- package/src/lifecycle/gate-ledger.test.ts +74 -2
- package/src/lifecycle/gate-ledger.ts +143 -36
- package/src/lifecycle/index.ts +1 -0
- package/src/lifecycle/release-ledger.ts +2 -2
- package/src/lifecycle/run-ledger.test.ts +268 -0
- package/src/lifecycle/run-ledger.ts +201 -0
- package/src/lifecycle/symptoms.ts +3 -3
- package/src/lint/config.test.ts +82 -1
- package/src/lint/config.ts +112 -3
- package/src/lint/policy.test.ts +1 -1
- package/src/lint/post-synth.test.ts +31 -0
- package/src/lint/post-synth.ts +54 -1
- package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +2 -2
- package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +1 -1
- package/src/lint/rules/comp/comp.test.ts +1 -1
- package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +74 -0
- package/src/lint/rules/comp/index.ts +3 -3
- package/src/lint/rules/op/index.ts +23 -0
- package/src/lint/rules/op/ops012-activity-contract.test.ts +161 -0
- package/src/lint/rules/op/ops012-activity-contract.ts +64 -0
- package/src/lint/rules/op/ops013-step-output-ref.test.ts +237 -0
- package/src/lint/rules/op/ops013-step-output-ref.ts +98 -0
- package/src/lint/rules/op/ops014-converge-rule-refusals.test.ts +263 -0
- package/src/lint/rules/op/ops014-converge-rule-refusals.ts +179 -0
- package/src/lint/rules/op/support.ts +11 -0
- package/src/lint/suppressions.test.ts +163 -0
- package/src/lint/suppressions.ts +204 -0
- package/src/live-endpoint.ts +1 -1
- package/src/op/activities/activity-contracts.ts +66 -0
- package/src/op/activities/apply.test.ts +567 -0
- package/src/op/activities/apply.ts +662 -0
- package/src/op/activities/build.ts +26 -0
- package/src/op/activities/converge.test.ts +330 -0
- package/src/op/activities/converge.ts +449 -0
- package/src/op/activities/env-teardown.test.ts +187 -0
- package/src/op/activities/env-teardown.ts +171 -0
- package/src/op/activities/guard-validate.test.ts +139 -0
- package/src/op/activities/guard-validate.ts +223 -0
- package/src/op/activities/http-check.test.ts +48 -0
- package/src/op/activities/http-check.ts +55 -0
- package/src/op/activities/index.ts +119 -0
- package/src/op/activities/lexicon-upgrade.test.ts +492 -0
- package/src/op/activities/lexicon-upgrade.ts +673 -0
- package/src/op/activities/lifecycle.ts +85 -0
- package/src/op/activities/pipeline-audit.test.ts +67 -0
- package/src/op/activities/pipeline-audit.ts +201 -0
- package/src/op/activities/policy.test.ts +19 -0
- package/src/op/activities/policy.ts +37 -0
- package/src/op/activities/reconcile.test.ts +81 -0
- package/src/op/activities/reconcile.ts +187 -0
- package/src/op/activities/shell.ts +26 -0
- package/src/op/activities/teardown.ts +22 -0
- package/src/op/activities/util.ts +6 -0
- package/src/op/activities/wait.ts +69 -0
- package/src/op/activities/workflow-audit.test.ts +90 -0
- package/src/op/activities/workflow-audit.ts +203 -0
- package/src/op/activity-contract-registry.test.ts +98 -0
- package/src/op/activity-contract-registry.ts +114 -0
- package/src/op/activity-contract.test.ts +1 -1
- package/src/op/activity-contract.ts +37 -33
- package/src/op/activity-failure.ts +34 -0
- package/src/op/activity-profiles.test.ts +56 -0
- package/src/op/activity-profiles.ts +116 -0
- package/src/op/activity-registry.test.ts +37 -28
- package/src/op/activity-registry.ts +27 -56
- package/src/op/activity-runtime.ts +3 -47
- package/src/op/builders-exports.test.ts +0 -49
- package/src/op/builders-typed.test.ts +164 -0
- package/src/op/builders.ts +123 -39
- package/src/op/composites/apply-op.ts +208 -0
- package/src/op/composites/composites.test.ts +366 -0
- package/src/op/composites/converge-op.test.ts +168 -0
- package/src/op/composites/converge-op.ts +214 -0
- package/src/op/composites/index.ts +26 -0
- package/src/op/composites/lexicon-upgrade-op.test.ts +68 -0
- package/src/op/composites/lexicon-upgrade-op.ts +134 -0
- package/src/op/composites/pipeline-audit-op.test.ts +25 -0
- package/src/op/composites/pipeline-audit-op.ts +78 -0
- package/src/op/composites/reconcile-op.test.ts +51 -0
- package/src/op/composites/reconcile-op.ts +107 -0
- package/src/op/composites/watch-op.ts +108 -0
- package/src/op/composites/workflow-audit-op.test.ts +25 -0
- package/src/op/composites/workflow-audit-op.ts +88 -0
- package/src/op/converge-rule.ts +12 -10
- package/src/op/cron.test.ts +128 -0
- package/src/op/cron.ts +149 -0
- package/src/op/discover-root.test.ts +105 -1
- package/src/op/discover.test.ts +6 -2
- package/src/op/discover.ts +84 -16
- package/src/op/duration.ts +21 -0
- package/src/op/effect-step.test.ts +26 -11
- package/src/op/emulator-lifecycle.ts +1 -2
- package/src/op/gate.ts +155 -0
- package/src/op/generate-pipeline.test.ts +65 -3
- package/src/op/generate-pipeline.ts +19 -2
- package/src/op/index.ts +39 -6
- package/src/op/local-executor.test.ts +163 -34
- package/src/op/local-executor.ts +370 -102
- package/src/op/local-output.test.ts +95 -11
- package/src/op/local-output.ts +33 -4
- package/src/op/op-ir.test.ts +281 -0
- package/src/op/op-ir.ts +417 -0
- package/src/op/op-verb-class.ts +19 -5
- package/src/op/op.test.ts +26 -5
- package/src/op/operator.test.ts +175 -6
- package/src/op/operator.ts +63 -16
- package/src/op/receipt-store.ts +1 -1
- package/src/op/resource.ts +20 -2
- package/src/op/runtime.ts +203 -0
- package/src/op/runtimes/local.test.ts +181 -0
- package/src/op/runtimes/local.ts +212 -0
- package/src/op/step-output-ref.ts +15 -13
- package/src/op/types.ts +84 -24
- package/src/ownership.ts +1 -1
- package/src/provenance.test.ts +6 -0
- package/src/provenance.ts +21 -1
- package/src/serializer-walker.test.ts +42 -0
- package/src/serializer-walker.ts +21 -2
- package/dist/cli/handlers/op-progress.d.ts +0 -90
- package/dist/cli/handlers/op-progress.d.ts.map +0 -1
- package/dist/cli/handlers/run-client.d.ts +0 -127
- package/dist/cli/handlers/run-client.d.ts.map +0 -1
- package/dist/cli/handlers/run-report.d.ts +0 -5
- package/dist/cli/handlers/run-report.d.ts.map +0 -1
- package/dist/components/temporal-codegen-loader.d.ts +0 -27
- package/dist/components/temporal-codegen-loader.d.ts.map +0 -1
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +0 -37
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +0 -1
- package/src/cli/handlers/op-progress.test.ts +0 -268
- package/src/cli/handlers/op-progress.ts +0 -248
- package/src/cli/handlers/run-client.test.ts +0 -82
- package/src/cli/handlers/run-client.ts +0 -219
- package/src/cli/handlers/run-report.test.ts +0 -62
- package/src/cli/handlers/run-report.ts +0 -122
- package/src/components/temporal-codegen-loader.ts +0 -41
- package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +0 -66
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Op run ledger (#2118, epic #2114) — one immutable record per Op run, on the
|
|
3
|
+
* `chant/lifecycle` orphan branch, modelled on `./converge-ledger.ts` down to
|
|
4
|
+
* the CAS-retry loop and the "skip a malformed line, count it" reader.
|
|
5
|
+
*
|
|
6
|
+
* ## Why an Op run leaves a record at all
|
|
7
|
+
*
|
|
8
|
+
* `OpConfig` used to carry `searchAttributes`, and the generated orchestrator
|
|
9
|
+
* code upserted `Phase`, `Drift`, `Approver` and `RollbackFailed` into them as
|
|
10
|
+
* it ran. Those are not properties of the declaration — they are facts about
|
|
11
|
+
* one run, and they only existed while a cluster held the run's history. Ops
|
|
12
|
+
* now run on whatever runtime `chant run --on`
|
|
13
|
+
* selects (#2121), including the plain in-process one, so the outcome has to
|
|
14
|
+
* be durable somewhere chant owns. Here. What stayed on the declaration is
|
|
15
|
+
* `OpConfig.labels`, the discovery half of the same field, and it is copied
|
|
16
|
+
* onto every record so a reader can filter runs the way it filters
|
|
17
|
+
* declarations.
|
|
18
|
+
*
|
|
19
|
+
* The record shape itself lives in `../op/runtime.ts`, beside the provider
|
|
20
|
+
* contract that reads it back: this is the ledger, not the vocabulary.
|
|
21
|
+
*
|
|
22
|
+
* ## Storage
|
|
23
|
+
*
|
|
24
|
+
* `<env>/runs__<op>.jsonl`, beside `<env>/converge.jsonl`. The `runs__`
|
|
25
|
+
* prefix folds what would read as a `runs/` subdirectory into one path
|
|
26
|
+
* segment: `writeBlobToPath` (./git.ts) builds the orphan branch's tree with
|
|
27
|
+
* `git mktree` over a flat `<env>/<file>` layout, and mktree rejects a slash
|
|
28
|
+
* in an entry name outright, so a genuine third level would mean rewriting
|
|
29
|
+
* that function's tree assembly. `__` is the same separator `./git.ts`'s
|
|
30
|
+
* `snapshotKey` already uses to fold a stack name into a flat blob name.
|
|
31
|
+
*
|
|
32
|
+
* Per-op rather than one file per env because a run ledger's reader almost
|
|
33
|
+
* always wants one op's history (`chant run <op>`'s own record, the local
|
|
34
|
+
* runtime's `status`/`log`), and an env with a busy op should not make every
|
|
35
|
+
* other op's read proportional to it.
|
|
36
|
+
*/
|
|
37
|
+
import { randomUUID } from "node:crypto";
|
|
38
|
+
import { sortedJsonReplacer } from "../utils";
|
|
39
|
+
import type { OpConfig } from "../op/types";
|
|
40
|
+
import type { StepRecord } from "../op/local-executor";
|
|
41
|
+
import type { OpRunRecord, OpRunRecordInput, OpRunPhaseRecord, OpRunStepRecord } from "../op/runtime";
|
|
42
|
+
import { readBlobFromPath, readPathSha, readBlobBySha, writeBlobToPath, RefCASConflictError } from "./git";
|
|
43
|
+
|
|
44
|
+
/** Prefix folding the per-op run ledgers into one flat name under `<env>/`. See the module doc. */
|
|
45
|
+
const PREFIX = "runs__";
|
|
46
|
+
|
|
47
|
+
/** Read-modify-append retry budget, same shape and reasoning as `appendConvergeRecord`'s. */
|
|
48
|
+
const APPEND_RETRY_ATTEMPTS = 5;
|
|
49
|
+
|
|
50
|
+
/** The env a run records against when its Op declares no `labels.Env`. */
|
|
51
|
+
export const DEFAULT_RUN_ENV = "local";
|
|
52
|
+
|
|
53
|
+
function fileFor(op: string): string {
|
|
54
|
+
return `${PREFIX}${op}.jsonl`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** The env a run records against: the Op's own `labels.Env`, else {@link DEFAULT_RUN_ENV}. */
|
|
58
|
+
export function runEnvOf(config: Pick<OpConfig, "labels">): string {
|
|
59
|
+
return config.labels?.Env ?? DEFAULT_RUN_ENV;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function phaseStatus(steps: OpRunStepRecord[]): OpRunPhaseRecord["status"] {
|
|
63
|
+
if (steps.some((s) => s.status === "fail")) return "fail";
|
|
64
|
+
if (steps.length > 0 && steps.every((s) => s.status === "skipped")) return "skipped";
|
|
65
|
+
return "ok";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Fold a run's step records into the ledger shape, pure — no clock, no git.
|
|
70
|
+
* `started`/`ended` are supplied by the caller for the same reason
|
|
71
|
+
* `ConvergeTickRecord.timestamp` is: library code here never calls
|
|
72
|
+
* `Date.now()` itself.
|
|
73
|
+
*
|
|
74
|
+
* Phases are grouped by `StepRecord.phase` in first-seen order, which is
|
|
75
|
+
* execution order for the sequential path and the authored order for a
|
|
76
|
+
* parallel one. A compensation (`onFailure`) phase appears after the phase
|
|
77
|
+
* that failed, exactly where the executor emitted its records.
|
|
78
|
+
*/
|
|
79
|
+
export function buildRunRecord(
|
|
80
|
+
config: Pick<OpConfig, "name" | "labels">,
|
|
81
|
+
records: readonly StepRecord[],
|
|
82
|
+
times: {
|
|
83
|
+
started: string;
|
|
84
|
+
ended: string;
|
|
85
|
+
status: OpRunRecord["status"];
|
|
86
|
+
id?: string;
|
|
87
|
+
gate?: OpRunRecord["gate"];
|
|
88
|
+
},
|
|
89
|
+
): OpRunRecordInput {
|
|
90
|
+
const phases: OpRunPhaseRecord[] = [];
|
|
91
|
+
const byName = new Map<string, OpRunPhaseRecord>();
|
|
92
|
+
const outcomes: Record<string, unknown> = {};
|
|
93
|
+
|
|
94
|
+
for (const record of records) {
|
|
95
|
+
let phase = byName.get(record.phase);
|
|
96
|
+
if (!phase) {
|
|
97
|
+
phase = { name: record.phase, status: "ok", steps: [] };
|
|
98
|
+
byName.set(record.phase, phase);
|
|
99
|
+
phases.push(phase);
|
|
100
|
+
}
|
|
101
|
+
phase.steps.push({
|
|
102
|
+
fn: record.fn,
|
|
103
|
+
status: record.status,
|
|
104
|
+
durationMs: record.durationMs,
|
|
105
|
+
...(record.outcome ? { outcome: record.outcome } : {}),
|
|
106
|
+
...(record.approval ? { approval: record.approval } : {}),
|
|
107
|
+
...(record.error !== undefined ? { error: record.error } : {}),
|
|
108
|
+
});
|
|
109
|
+
if (record.outcome) outcomes[record.outcome.name] = record.outcome.value;
|
|
110
|
+
}
|
|
111
|
+
for (const phase of phases) phase.status = phaseStatus(phase.steps);
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
...(times.id !== undefined ? { id: times.id } : {}),
|
|
115
|
+
op: config.name,
|
|
116
|
+
env: runEnvOf(config),
|
|
117
|
+
started: times.started,
|
|
118
|
+
ended: times.ended,
|
|
119
|
+
status: times.status,
|
|
120
|
+
labels: { ...(config.labels ?? {}) },
|
|
121
|
+
outcomes,
|
|
122
|
+
phases,
|
|
123
|
+
...(times.gate ? { gate: times.gate } : {}),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Append one immutable run record. Does not push to the remote — call
|
|
129
|
+
* `pushLifecycle` (./git.ts) afterward, the two-step shape every ledger here
|
|
130
|
+
* uses.
|
|
131
|
+
*
|
|
132
|
+
* Mints `record.id` when the input carries none, and retries the whole
|
|
133
|
+
* read-modify-write on `RefCASConflictError` re-reading fresh each attempt —
|
|
134
|
+
* see `appendConvergeRecord`'s doc for why both of those live in the append
|
|
135
|
+
* function rather than in its callers.
|
|
136
|
+
*/
|
|
137
|
+
export async function appendRunRecord(
|
|
138
|
+
input: OpRunRecordInput,
|
|
139
|
+
opts?: { cwd?: string },
|
|
140
|
+
): Promise<{ commit: string; record: OpRunRecord }> {
|
|
141
|
+
const record: OpRunRecord = { version: 1, ...input, id: input.id ?? randomUUID() };
|
|
142
|
+
const json = JSON.stringify(record, sortedJsonReplacer);
|
|
143
|
+
const filename = fileFor(record.op);
|
|
144
|
+
|
|
145
|
+
let lastErr: unknown;
|
|
146
|
+
for (let attempt = 1; attempt <= APPEND_RETRY_ATTEMPTS; attempt++) {
|
|
147
|
+
try {
|
|
148
|
+
const priorSha = await readPathSha(record.env, filename, opts);
|
|
149
|
+
const existing = priorSha ? await readBlobBySha(priorSha, opts) : null;
|
|
150
|
+
const content = existing ? `${existing.replace(/\n$/, "")}\n${json}` : json;
|
|
151
|
+
const commit = await writeBlobToPath(record.env, filename, content, `Op run record: ${record.op}`, {
|
|
152
|
+
...opts,
|
|
153
|
+
expectPriorPathSha: priorSha,
|
|
154
|
+
});
|
|
155
|
+
return { commit, record };
|
|
156
|
+
} catch (err) {
|
|
157
|
+
if (!(err instanceof RefCASConflictError)) throw err;
|
|
158
|
+
lastErr = err;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
throw lastErr;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Read every run record for `op` in `environment`, oldest first. Malformed
|
|
166
|
+
* lines are skipped and counted, never thrown on — a hand-edited or truncated
|
|
167
|
+
* ledger degrades to a shorter history, the stance every ledger here takes.
|
|
168
|
+
*/
|
|
169
|
+
export async function readRunLedger(
|
|
170
|
+
environment: string,
|
|
171
|
+
op: string,
|
|
172
|
+
opts?: { cwd?: string },
|
|
173
|
+
): Promise<{ records: OpRunRecord[]; malformed: number }> {
|
|
174
|
+
const content = await readBlobFromPath(environment, fileFor(op), opts);
|
|
175
|
+
if (!content) return { records: [], malformed: 0 };
|
|
176
|
+
|
|
177
|
+
const lines = content.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
178
|
+
const records: OpRunRecord[] = [];
|
|
179
|
+
let malformed = 0;
|
|
180
|
+
for (const line of lines) {
|
|
181
|
+
try {
|
|
182
|
+
const parsed = JSON.parse(line) as Partial<OpRunRecord>;
|
|
183
|
+
if (
|
|
184
|
+
parsed.version !== 1 ||
|
|
185
|
+
typeof parsed.op !== "string" ||
|
|
186
|
+
typeof parsed.env !== "string" ||
|
|
187
|
+
typeof parsed.started !== "string" ||
|
|
188
|
+
typeof parsed.ended !== "string" ||
|
|
189
|
+
typeof parsed.status !== "string" ||
|
|
190
|
+
!Array.isArray(parsed.phases)
|
|
191
|
+
) {
|
|
192
|
+
malformed++;
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
records.push(parsed as OpRunRecord);
|
|
196
|
+
} catch {
|
|
197
|
+
malformed++;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return { records, malformed };
|
|
201
|
+
}
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* `LexiconPlugin.symptoms?()` interface in v1 — everything here is a pure
|
|
9
9
|
* projection of structures chant already computes (`ChangeSet`,
|
|
10
10
|
* `ComponentStatusRow[]`). No I/O in this module; a caller (the `convergeTick`
|
|
11
|
-
* activity,
|
|
12
|
-
*
|
|
11
|
+
* activity, ../op/activities/converge.ts) gathers those inputs and hands them
|
|
12
|
+
* here.
|
|
13
13
|
*
|
|
14
14
|
* One record per tick, not per component: the issue's own rule sketch reads
|
|
15
15
|
* `s.status`/`s.backupVerifiedAge` as a single symptom `s` a rule closes
|
|
@@ -109,7 +109,7 @@ export function deriveSymptoms(env: string, cs: ChangeSet, statusRows: Component
|
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
/** Every field name a `ConvergeSymptom` produces — the runtime whitelist `
|
|
112
|
+
/** Every field name a `ConvergeSymptom` produces — the runtime whitelist `OPS014` (packages/core/src/lint/rules/op/ops014-converge-rule-refusals.ts) re-validates a serialized rule table's predicates against. Kept in sync with {@link ConvergeSymptom} by hand (deliberately small, changes rarely). */
|
|
113
113
|
export const CONVERGE_SYMPTOM_FIELDS: ReadonlySet<string> = new Set([
|
|
114
114
|
"env",
|
|
115
115
|
"status",
|
package/src/lint/config.test.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
-
import { loadConfig, DEFAULT_CONFIG, findProjectRoot, resolveConfiguredSeverity, applyConfiguredSeverity } from "./config";
|
|
2
|
+
import { loadConfig, DEFAULT_CONFIG, findProjectRoot, resolveConfiguredSeverity, applyConfiguredSeverity, resolvePresetIds, applyConfiguredPreset } from "./config";
|
|
3
3
|
import type { PostSynthDiagnostic } from "./post-synth";
|
|
4
|
+
import { auditRule, type RuleMeta } from "../audit/catalog";
|
|
4
5
|
import { writeFileSync, mkdirSync, rmSync } from "fs";
|
|
5
6
|
import { join, resolve } from "path";
|
|
6
7
|
|
|
@@ -755,6 +756,26 @@ describe("resolveConfiguredSeverity", () => {
|
|
|
755
756
|
resolveConfiguredSeverity({ COR009: ["fatal" as never, { max: 12 }] }, "COR009", "error"),
|
|
756
757
|
).toThrow(/severity "fatal"/);
|
|
757
758
|
});
|
|
759
|
+
|
|
760
|
+
describe("alias resolution (chant #2113, opt-in via `catalog`)", () => {
|
|
761
|
+
const catalog: Record<string, RuleMeta> = {
|
|
762
|
+
NEW001: { ...auditRule("NEW001", "report-only", "guidance", "T", "r"), aliases: ["OLD001"] },
|
|
763
|
+
};
|
|
764
|
+
|
|
765
|
+
test("with no catalog, a `rules` key naming an alias does not match, today's behavior, unchanged", () => {
|
|
766
|
+
expect(resolveConfiguredSeverity({ OLD001: "off" }, "NEW001", "error")).toEqual({ severity: "error" });
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
test("with a catalog, a `rules` key naming an alias resolves to the canonical id", () => {
|
|
770
|
+
expect(resolveConfiguredSeverity({ OLD001: "off" }, "NEW001", "error", catalog)).toEqual({ severity: "off" });
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
test("a `rules` key already at the canonical id still wins over an alias entry", () => {
|
|
774
|
+
expect(
|
|
775
|
+
resolveConfiguredSeverity({ OLD001: "off", NEW001: "warning" }, "NEW001", "error", catalog),
|
|
776
|
+
).toEqual({ severity: "warning" });
|
|
777
|
+
});
|
|
778
|
+
});
|
|
758
779
|
});
|
|
759
780
|
|
|
760
781
|
/**
|
|
@@ -808,4 +829,64 @@ describe("applyConfiguredSeverity", () => {
|
|
|
808
829
|
test("an empty diagnostics list is a no-op", () => {
|
|
809
830
|
expect(applyConfiguredSeverity([], { WAW019: "off" })).toEqual({ diagnostics: [], suppressed: [] });
|
|
810
831
|
});
|
|
832
|
+
|
|
833
|
+
test("a `rules` key naming a retired rule's alias suppresses the renamed rule's finding, given a catalog (#2113)", () => {
|
|
834
|
+
const catalog: Record<string, RuleMeta> = {
|
|
835
|
+
WAW019: { ...auditRule("WAW019", "merge-worthy", "guidance", "T", "r"), aliases: ["WAW019-OLD"] },
|
|
836
|
+
};
|
|
837
|
+
const result = applyConfiguredSeverity([diag()], { "WAW019-OLD": "off" }, catalog);
|
|
838
|
+
expect(result.diagnostics).toEqual([]);
|
|
839
|
+
expect(result.suppressed).toEqual([diag()]);
|
|
840
|
+
});
|
|
841
|
+
});
|
|
842
|
+
|
|
843
|
+
describe("resolvePresetIds (chant #2113)", () => {
|
|
844
|
+
const presets = { recommended: ["A001", "A002"], all: ["A001", "A002", "A003"] };
|
|
845
|
+
|
|
846
|
+
test("a lexicon with no presets at all returns undefined (no filtering)", () => {
|
|
847
|
+
expect(resolvePresetIds(undefined, "recommended")).toBeUndefined();
|
|
848
|
+
});
|
|
849
|
+
|
|
850
|
+
test("a known preset name resolves to its id set", () => {
|
|
851
|
+
expect(resolvePresetIds(presets, "recommended")).toEqual(new Set(["A001", "A002"]));
|
|
852
|
+
expect(resolvePresetIds(presets, "all")).toEqual(new Set(["A001", "A002", "A003"]));
|
|
853
|
+
});
|
|
854
|
+
|
|
855
|
+
test("an unrecognized preset name falls back to unfiltered (undefined), not an empty set", () => {
|
|
856
|
+
expect(resolvePresetIds(presets, "typo-of-recommended")).toBeUndefined();
|
|
857
|
+
});
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
describe("applyConfiguredPreset (chant #2113)", () => {
|
|
861
|
+
function diag(checkId: string, overrides: Partial<PostSynthDiagnostic> = {}): PostSynthDiagnostic {
|
|
862
|
+
return { checkId, severity: "warning", message: `finding for ${checkId}`, ...overrides };
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
test("no presetIds (undefined) is a no-op: every diagnostic passes through", () => {
|
|
866
|
+
const diags = [diag("A001"), diag("Z999")];
|
|
867
|
+
const result = applyConfiguredPreset(diags, undefined, undefined);
|
|
868
|
+
expect(result.diagnostics).toEqual(diags);
|
|
869
|
+
expect(result.suppressed).toEqual([]);
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
test("a report-only rule outside the active preset is not reported, moved to suppressed, not dropped", () => {
|
|
873
|
+
const recommended = new Set(["A001"]);
|
|
874
|
+
const result = applyConfiguredPreset([diag("A001"), diag("Z999")], recommended, undefined);
|
|
875
|
+
expect(result.diagnostics.map((d) => d.checkId)).toEqual(["A001"]);
|
|
876
|
+
expect(result.suppressed.map((d) => d.checkId)).toEqual(["Z999"]);
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
test("the same rule under a wider preset (e.g. `all`) IS reported", () => {
|
|
880
|
+
const all = new Set(["A001", "Z999"]);
|
|
881
|
+
const result = applyConfiguredPreset([diag("A001"), diag("Z999")], all, undefined);
|
|
882
|
+
expect(result.diagnostics.map((d) => d.checkId).sort()).toEqual(["A001", "Z999"]);
|
|
883
|
+
expect(result.suppressed).toEqual([]);
|
|
884
|
+
});
|
|
885
|
+
|
|
886
|
+
test("an explicit `lint.rules` entry re-enables a rule the active preset excludes", () => {
|
|
887
|
+
const recommended = new Set(["A001"]);
|
|
888
|
+
const result = applyConfiguredPreset([diag("Z999")], recommended, { Z999: "warning" });
|
|
889
|
+
expect(result.diagnostics.map((d) => d.checkId)).toEqual(["Z999"]);
|
|
890
|
+
expect(result.suppressed).toEqual([]);
|
|
891
|
+
});
|
|
811
892
|
});
|
package/src/lint/config.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { evaluateProjectConfigSync } from "../config-sandbox";
|
|
|
5
5
|
import type { Severity, RuleConfig } from "./rule";
|
|
6
6
|
import type { PostSynthDiagnostic } from "./post-synth";
|
|
7
7
|
import { moduleDir, getRuntime } from "../runtime-adapter";
|
|
8
|
+
import { canonicalRuleId, type RuleMeta } from "../audit/catalog";
|
|
8
9
|
import strictPreset from "./presets/strict.json";
|
|
9
10
|
|
|
10
11
|
// chant #1117 — the upward config-discovery walk moved to a shared module
|
|
@@ -38,6 +39,7 @@ export const LintConfigSchema = z.object({
|
|
|
38
39
|
})).optional(),
|
|
39
40
|
plugins: z.array(z.string()).optional(),
|
|
40
41
|
policies: z.array(z.string()).optional(),
|
|
42
|
+
presets: z.record(z.string(), z.string()).optional(),
|
|
41
43
|
});
|
|
42
44
|
|
|
43
45
|
/**
|
|
@@ -166,6 +168,23 @@ export interface LintConfig {
|
|
|
166
168
|
* phase; same engine.
|
|
167
169
|
*/
|
|
168
170
|
policies?: string[];
|
|
171
|
+
/**
|
|
172
|
+
* Lexicon name mapped to a preset name (chant #2113), e.g.
|
|
173
|
+
* `{ terraform: "recommended" }`. A preset is a lexicon's own bundle of
|
|
174
|
+
* post-synth check ids. tflint ships `recommended` (a subset) and `all`
|
|
175
|
+
* for its Terraform-language rules the same way, and a lexicon that ships
|
|
176
|
+
* one exposes it through its plugin's `lintPresets()` (`../lexicon.ts`).
|
|
177
|
+
* Naming a preset here changes which of that lexicon's post-synth findings
|
|
178
|
+
* are reported at all, distinct from `rules`, which changes an
|
|
179
|
+
* already-reported finding's severity. A rule a preset excludes is not
|
|
180
|
+
* suppressed (it never runs the severity-override gauntlet in the first
|
|
181
|
+
* place), but an explicit `rules` entry for it always wins and re-enables
|
|
182
|
+
* it regardless of the active preset, see `resolvePresetIds`/
|
|
183
|
+
* `applyConfiguredPreset` below. Unset, or naming a preset the lexicon
|
|
184
|
+
* does not export, falls back to `"recommended"`. A lexicon that ships no
|
|
185
|
+
* presets at all is unaffected by this field, same as today.
|
|
186
|
+
*/
|
|
187
|
+
presets?: Record<string, string>;
|
|
169
188
|
}
|
|
170
189
|
|
|
171
190
|
/**
|
|
@@ -226,15 +245,30 @@ export function parseRuleConfig(value: RuleConfig): ParsedRuleConfig {
|
|
|
226
245
|
* checks have no per-file scope to begin with (see {@link
|
|
227
246
|
* ./post-synth.ts!PostSynthDiagnostic}'s doc for why), so they always pass
|
|
228
247
|
* `config.rules` directly.
|
|
248
|
+
*
|
|
249
|
+
* `catalog` (chant #2113) is optional and off by default: pass a resolved
|
|
250
|
+
* audit catalog to also honor a `rules` key that names one of `id`'s
|
|
251
|
+
* `RuleMeta.aliases` rather than `id` itself. A project's
|
|
252
|
+
* `lint.rules: { OLD_ID: "off" }` then keeps suppressing the rule after it
|
|
253
|
+
* is renamed/renumbered, instead of silently starting to match nothing. Every
|
|
254
|
+
* existing call site omits `catalog` and is unaffected; a caller that has one
|
|
255
|
+
* handy (an audit-shaped consumer, not `chant build`'s post-synth loop, which
|
|
256
|
+
* has no catalog readily resolved at that point) opts in by passing it.
|
|
229
257
|
*/
|
|
230
258
|
export function resolveConfiguredSeverity(
|
|
231
259
|
rules: Record<string, RuleConfig> | undefined,
|
|
232
260
|
id: string,
|
|
233
261
|
defaultSeverity: Severity,
|
|
262
|
+
catalog?: Record<string, RuleMeta>,
|
|
234
263
|
): ParsedRuleConfig {
|
|
235
264
|
const configValue = rules?.[id];
|
|
236
|
-
if (configValue
|
|
237
|
-
|
|
265
|
+
if (configValue !== undefined) return parseRuleConfig(configValue);
|
|
266
|
+
if (catalog && rules) {
|
|
267
|
+
for (const [key, value] of Object.entries(rules)) {
|
|
268
|
+
if (canonicalRuleId(key, catalog) === id) return parseRuleConfig(value);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return { severity: defaultSeverity };
|
|
238
272
|
}
|
|
239
273
|
|
|
240
274
|
/**
|
|
@@ -500,16 +534,30 @@ export interface PostSynthSeverityResult {
|
|
|
500
534
|
* remove. Config severity (`"off"`) is the one suppression surface this can
|
|
501
535
|
* offer uniformly; a check that wants a per-instance escape hatch can read
|
|
502
536
|
* `ctx.env`/its own options to decide not to emit a diagnostic at all.
|
|
537
|
+
*
|
|
538
|
+
* chant #2111 adds a second, narrower surface next to this one:
|
|
539
|
+
* `./suppressions.ts`'s `applyInlineSuppressions` matches `diag.entity`
|
|
540
|
+
* against `ctx.entities` (a source-level map key every `PostSynthContext`
|
|
541
|
+
* carries) instead of a name in the synthesized output, so it sidesteps the
|
|
542
|
+
* exact mismatch this comment describes. It is opt-in per lexicon (an entity
|
|
543
|
+
* has to carry a `suppressions` field) and runs as its own pass, right after
|
|
544
|
+
* this one, in both `chant build` and `chant audit`. See that module's doc
|
|
545
|
+
* for the full reasoning.
|
|
546
|
+
*
|
|
547
|
+
* `catalog` (chant #2113, optional) passes straight through to
|
|
548
|
+
* `resolveConfiguredSeverity` above for alias resolution; see its doc for
|
|
549
|
+
* what that buys and why it's opt-in.
|
|
503
550
|
*/
|
|
504
551
|
export function applyConfiguredSeverity(
|
|
505
552
|
diagnostics: readonly PostSynthDiagnostic[],
|
|
506
553
|
rules: Record<string, RuleConfig> | undefined,
|
|
554
|
+
catalog?: Record<string, RuleMeta>,
|
|
507
555
|
): PostSynthSeverityResult {
|
|
508
556
|
const kept: PostSynthDiagnostic[] = [];
|
|
509
557
|
const suppressed: PostSynthDiagnostic[] = [];
|
|
510
558
|
|
|
511
559
|
for (const diag of diagnostics) {
|
|
512
|
-
const resolved = resolveConfiguredSeverity(rules, diag.checkId, diag.severity);
|
|
560
|
+
const resolved = resolveConfiguredSeverity(rules, diag.checkId, diag.severity, catalog);
|
|
513
561
|
if (resolved.severity === "off") {
|
|
514
562
|
suppressed.push(diag);
|
|
515
563
|
continue;
|
|
@@ -519,3 +567,64 @@ export function applyConfiguredSeverity(
|
|
|
519
567
|
|
|
520
568
|
return { diagnostics: kept, suppressed };
|
|
521
569
|
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Result of applying a lexicon preset to a set of post-synth diagnostics.
|
|
573
|
+
* Shaped like {@link PostSynthSeverityResult} so a caller threading both
|
|
574
|
+
* through (a preset filter, then a severity override) handles them the same
|
|
575
|
+
* way. See `applyConfiguredPreset` below.
|
|
576
|
+
*/
|
|
577
|
+
export interface PostSynthPresetResult {
|
|
578
|
+
/** Diagnostics whose check id the active preset enables (or that `rules` explicitly configures, see below). */
|
|
579
|
+
diagnostics: PostSynthDiagnostic[];
|
|
580
|
+
/** Diagnostics the active preset excluded, unaltered. Countable rather than silently dropped, mirroring `PostSynthSeverityResult.suppressed`. */
|
|
581
|
+
suppressed: PostSynthDiagnostic[];
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Resolve `lint.presets`' name for one lexicon into the set of check ids that
|
|
586
|
+
* preset enables (chant #2113). `presets` is what a lexicon plugin's
|
|
587
|
+
* `lintPresets()` returns (`../lexicon.ts`). A lexicon that ships none
|
|
588
|
+
* passes `undefined` here, in which case this returns `undefined` and
|
|
589
|
+
* `applyConfiguredPreset` below becomes a no-op (every rule reports, exactly
|
|
590
|
+
* today's behavior for a lexicon this feature doesn't touch).
|
|
591
|
+
*
|
|
592
|
+
* An unrecognized preset name (a typo, or a name the lexicon doesn't define)
|
|
593
|
+
* also returns `undefined` rather than an empty set. Falling back to
|
|
594
|
+
* unfiltered is the safe failure direction; silently reporting nothing would
|
|
595
|
+
* not be.
|
|
596
|
+
*/
|
|
597
|
+
export function resolvePresetIds(
|
|
598
|
+
presets: Record<string, string[]> | undefined,
|
|
599
|
+
presetName: string,
|
|
600
|
+
): Set<string> | undefined {
|
|
601
|
+
const ids = presets?.[presetName];
|
|
602
|
+
return ids ? new Set(ids) : undefined;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Filter post-synth diagnostics down to an active preset's ids (chant
|
|
607
|
+
* #2113). `presetIds` is `resolvePresetIds`'s output. `undefined` disables
|
|
608
|
+
* filtering entirely (a lexicon with no presets, or an unresolved preset
|
|
609
|
+
* name), matching tflint's own precedence chain (`--only` / rule config,
|
|
610
|
+
* then preset, then `disabled_by_default`, `tflint-ruleset-terraform`'s
|
|
611
|
+
* config docs): an explicit `lint.rules` entry for a check id always keeps
|
|
612
|
+
* that id's findings, whether or not the active preset includes it, so a
|
|
613
|
+
* project can opt a single report-only rule back in under `recommended`
|
|
614
|
+
* without switching its whole lexicon to `all`.
|
|
615
|
+
*/
|
|
616
|
+
export function applyConfiguredPreset(
|
|
617
|
+
diagnostics: readonly PostSynthDiagnostic[],
|
|
618
|
+
presetIds: Set<string> | undefined,
|
|
619
|
+
rules: Record<string, RuleConfig> | undefined,
|
|
620
|
+
): PostSynthPresetResult {
|
|
621
|
+
if (!presetIds) return { diagnostics: [...diagnostics], suppressed: [] };
|
|
622
|
+
|
|
623
|
+
const kept: PostSynthDiagnostic[] = [];
|
|
624
|
+
const suppressed: PostSynthDiagnostic[] = [];
|
|
625
|
+
for (const diag of diagnostics) {
|
|
626
|
+
if (presetIds.has(diag.checkId) || rules?.[diag.checkId] !== undefined) kept.push(diag);
|
|
627
|
+
else suppressed.push(diag);
|
|
628
|
+
}
|
|
629
|
+
return { diagnostics: kept, suppressed };
|
|
630
|
+
}
|
package/src/lint/policy.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* chant #1138 — `evaluateProjectPolicies` (the `policyGate` Op step's entry
|
|
3
|
-
* point,
|
|
3
|
+
* point, ./op/activities/policy.ts) applies
|
|
4
4
|
* `lint.rules` severity overrides to policy diagnostics the same way `chant
|
|
5
5
|
* build` does (`../cli/commands/build.ts`), so a check `lint.rules` turns
|
|
6
6
|
* "off" no longer gates an apply either — before this fix, only `chant
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
2
|
import { runPostSynthChecks } from "./post-synth";
|
|
3
|
+
import { activityContract, type ActivityContract } from "../op/activity-contract";
|
|
4
|
+
import { z } from "zod";
|
|
3
5
|
import type { PostSynthCheck, PostSynthContext } from "./post-synth";
|
|
4
6
|
|
|
5
7
|
function createBuildResult(overrides: Partial<PostSynthContext["buildResult"]> = {}) {
|
|
@@ -131,6 +133,35 @@ describe("environment-aware checks (#201)", () => {
|
|
|
131
133
|
});
|
|
132
134
|
});
|
|
133
135
|
|
|
136
|
+
describe("cross-lexicon activity contracts (#2101)", () => {
|
|
137
|
+
// A check shaped like temporal's TMP012/TMP013: it reads the merged
|
|
138
|
+
// contract map the runner hands it, and behaves as it did before the field
|
|
139
|
+
// existed when the context carries none.
|
|
140
|
+
const readsContracts: PostSynthCheck = {
|
|
141
|
+
id: "CONTRACTS",
|
|
142
|
+
description: "reports the activity names the context carries contracts for",
|
|
143
|
+
check(ctx) {
|
|
144
|
+
const names = [...(ctx.activityContracts?.keys() ?? [])].sort();
|
|
145
|
+
return [{ checkId: "CONTRACTS", severity: "warning", message: names.join(",") }];
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
test("the contract map is threaded into the context", () => {
|
|
150
|
+
const contracts = new Map<string, ActivityContract>([
|
|
151
|
+
["terraformPlan", activityContract("terraformPlan", z.strictObject({ root: z.string() }))],
|
|
152
|
+
]);
|
|
153
|
+
const diags = runPostSynthChecks([readsContracts], createBuildResult(), undefined, {
|
|
154
|
+
activityContracts: contracts,
|
|
155
|
+
});
|
|
156
|
+
expect(diags[0].message).toBe("terraformPlan");
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test("a run with no contracts leaves the field undefined, not an empty map", () => {
|
|
160
|
+
const diags = runPostSynthChecks([readsContracts], createBuildResult());
|
|
161
|
+
expect(diags[0].message).toBe("");
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
134
165
|
describe("isPostSynthCheck", () => {
|
|
135
166
|
test("accepts a well-formed check and rejects others", async () => {
|
|
136
167
|
const { isPostSynthCheck } = await import("./post-synth");
|
package/src/lint/post-synth.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Declarable } from "../declarable";
|
|
2
|
+
import type { ActivityContract } from "../op/activity-contract";
|
|
2
3
|
import type { SerializerResult } from "../serializer";
|
|
3
4
|
import type { Severity } from "./rule";
|
|
4
5
|
import { parseOutputDocs, type OutputDoc } from "./output-docs";
|
|
@@ -38,6 +39,22 @@ export interface PostSynthContext {
|
|
|
38
39
|
* with `ctx.docs ?? []` only when a context's provenance is unknown.
|
|
39
40
|
*/
|
|
40
41
|
readonly docs?: OutputDoc[];
|
|
42
|
+
/**
|
|
43
|
+
* Activity contracts resolved across every lexicon this build configured
|
|
44
|
+
* (chant #2101), keyed by activity name — core's own plus whatever each
|
|
45
|
+
* lexicon contributes at `@intentius/chant-lexicon-<name>/op/activity-contracts`
|
|
46
|
+
* or through its plugin. Filled in by `chant build`, `chant lint` and
|
|
47
|
+
* `check-lexicon`'s example harness via `loadActivityContracts`.
|
|
48
|
+
*
|
|
49
|
+
* The checks that validate Op steps against contracts (OPS012 and OPS013,
|
|
50
|
+
* `./rules/op/`) merge this over their own statically imported table with
|
|
51
|
+
* `mergeActivityContracts`, so an Op calling `terraformPlan` or
|
|
52
|
+
* `k3sInstall` validates against the contract the owning lexicon declared
|
|
53
|
+
* instead of failing for the absence of one. Optional, and absent from a
|
|
54
|
+
* hand-built context: a check must behave as it did before this existed
|
|
55
|
+
* when it is `undefined`.
|
|
56
|
+
*/
|
|
57
|
+
readonly activityContracts?: ReadonlyMap<string, ActivityContract>;
|
|
41
58
|
/** Raw build result object */
|
|
42
59
|
buildResult: {
|
|
43
60
|
outputs: Map<string, string | SerializerResult>;
|
|
@@ -104,6 +121,14 @@ export function getAdditionalFiles(output: string | SerializerResult): Record<st
|
|
|
104
121
|
* comment (`chant-disable`) suppression is out of scope for post-synth
|
|
105
122
|
* findings — see `./config.ts`'s `applyConfiguredSeverity` doc for the full
|
|
106
123
|
* reasoning and what suppression surface post-synth findings get instead.
|
|
124
|
+
*
|
|
125
|
+
* chant #2111 finds a narrower anchor that does generalize: `./suppressions.ts`'s
|
|
126
|
+
* `applyInlineSuppressions` matches `entity` against `ctx.entities` (a map key
|
|
127
|
+
* every context already carries, source-level, before serialization), not
|
|
128
|
+
* against a name in the synthesized OUTPUT. A lexicon whose entities carry a
|
|
129
|
+
* `suppressions` field (see that file's module doc) gets inline `# chant-
|
|
130
|
+
* ignore`-style comments this way; one that doesn't is unaffected, and this
|
|
131
|
+
* interface's own contract (no `file`/`line`) is unchanged either way.
|
|
107
132
|
*/
|
|
108
133
|
export interface PostSynthDiagnostic {
|
|
109
134
|
/** ID of the check that produced this diagnostic */
|
|
@@ -120,6 +145,30 @@ export interface PostSynthDiagnostic {
|
|
|
120
145
|
entity?: string;
|
|
121
146
|
/** Optional lexicon related to this diagnostic */
|
|
122
147
|
lexicon?: string;
|
|
148
|
+
/**
|
|
149
|
+
* Set when the finding is that something does not exist, rather than that
|
|
150
|
+
* something present is wrong (chant #2113). TF001 (no remote backend) is
|
|
151
|
+
* the motivating case: there is no resource to set `entity` to, only the
|
|
152
|
+
* scope that is missing one. Snyk's policy-engine spec names this the
|
|
153
|
+
* "missing-resource" archetype (a `deny` whose `info` carries a
|
|
154
|
+
* `resource_type` instead of a `resource`, because there is nothing to
|
|
155
|
+
* attach to) and is the only tool in chant's TF-family survey with a
|
|
156
|
+
* first-class shape for it; trivy's own inline-ignore comments admit they
|
|
157
|
+
* cannot suppress an absence finding for exactly this reason. `kind` names
|
|
158
|
+
* what is missing (a `backend`/`cloud` block, a required resource type);
|
|
159
|
+
* `scope` names where it is missing (a root module name, a file). Renders
|
|
160
|
+
* distinctly in all three reporters (stylish/JSON/SARIF, `../cli/commands/
|
|
161
|
+
* audit.ts` and `../audit/report-model.ts`) instead of falling back to
|
|
162
|
+
* `entity`, and gives #2111's HCL suppression a block-anchored key to
|
|
163
|
+
* suppress an absence finding by (the block that *should* declare `kind`
|
|
164
|
+
* inside `scope`), independent of whatever `entity` this diagnostic sets.
|
|
165
|
+
*/
|
|
166
|
+
missing?: {
|
|
167
|
+
/** What kind of thing is absent (e.g. `"backend"`, `"cloud"`). */
|
|
168
|
+
kind: string;
|
|
169
|
+
/** Where it is missing from (e.g. a root module name). */
|
|
170
|
+
scope: string;
|
|
171
|
+
};
|
|
123
172
|
}
|
|
124
173
|
|
|
125
174
|
/**
|
|
@@ -149,12 +198,15 @@ export function isPostSynthCheck(value: unknown): value is PostSynthCheck {
|
|
|
149
198
|
|
|
150
199
|
/**
|
|
151
200
|
* Run a set of post-synthesis checks against a build result. `env` is threaded
|
|
152
|
-
* into the context so a check can branch on the current environment/stack
|
|
201
|
+
* into the context so a check can branch on the current environment/stack, and
|
|
202
|
+
* `opts.activityContracts` (chant #2101) carries the build's cross-lexicon
|
|
203
|
+
* activity-contract map to the checks that validate Op steps against it.
|
|
153
204
|
*/
|
|
154
205
|
export function runPostSynthChecks(
|
|
155
206
|
checks: PostSynthCheck[],
|
|
156
207
|
buildResult: PostSynthContext["buildResult"],
|
|
157
208
|
env?: string,
|
|
209
|
+
opts?: { activityContracts?: ReadonlyMap<string, ActivityContract> },
|
|
158
210
|
): PostSynthDiagnostic[] {
|
|
159
211
|
const getDocs = createDocsAccessor(buildResult.outputs);
|
|
160
212
|
const ctx: PostSynthContext = {
|
|
@@ -162,6 +214,7 @@ export function runPostSynthChecks(
|
|
|
162
214
|
entities: buildResult.entities,
|
|
163
215
|
env,
|
|
164
216
|
buildResult,
|
|
217
|
+
...(opts?.activityContracts ? { activityContracts: opts.activityContracts } : {}),
|
|
165
218
|
get docs(): OutputDoc[] {
|
|
166
219
|
return getDocs();
|
|
167
220
|
},
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// chant-disable COMP004 --
|
|
1
|
+
// chant-disable COMP004 -- the Node 1 gate is a deliberate human-approval wait, cleared with `chant approve neo4j-cluster approve-neo4j-node-1`
|
|
2
2
|
import type { Component } from "../../../../../../components/component";
|
|
3
3
|
import { gate, phase } from "../../../../../../components/component";
|
|
4
4
|
|
|
5
|
-
/** COMP004 pass case: a genuine gate, opted out via a file-level disable directive with a documented reason — the intended path for a component
|
|
5
|
+
/** COMP004 pass case: a genuine gate, opted out via a file-level disable directive with a documented reason — the intended path for a component whose rollout genuinely waits on a person. */
|
|
6
6
|
export const neo4jCluster: Component = {
|
|
7
7
|
name: "neo4j-cluster",
|
|
8
8
|
archetype: "infra",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Component } from "../../../../../../components/component";
|
|
2
2
|
import { phase } from "../../../../../../components/component";
|
|
3
3
|
|
|
4
|
-
/** COMP004 pass case: no gate step anywhere — nothing
|
|
4
|
+
/** COMP004 pass case: no gate step anywhere — nothing here stops the run for a person. */
|
|
5
5
|
export const ordersTable: Component = {
|
|
6
6
|
name: "orders-table",
|
|
7
7
|
archetype: "infra",
|