@intentius/chant 0.57.0 → 0.59.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 +36 -1
- package/dist/audit/core.d.ts.map +1 -1
- package/dist/audit/discover.d.ts +26 -9
- 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/carve-bridge.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 +13 -0
- 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 +12 -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/plugins.d.ts +22 -0
- package/dist/cli/plugins.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +40 -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 +24 -22
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/component.d.ts +21 -6
- 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 +73 -37
- 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 +10 -22
- 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/detectLexicon.d.ts +13 -0
- package/dist/detectLexicon.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 +273 -16
- 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 +79 -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 +149 -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 +85 -30
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/change-signal.d.ts +91 -0
- package/dist/op/change-signal.d.ts.map +1 -0
- package/dist/op/composites/apply-op.d.ts +118 -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-name.d.ts +40 -0
- package/dist/op/gate-name.d.ts.map +1 -0
- package/dist/op/gate-summary.d.ts +43 -0
- package/dist/op/gate-summary.d.ts.map +1 -0
- 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 +29 -9
- 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 +185 -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 +93 -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 +96 -29
- 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/dist/terraform/bridge.d.ts +26 -7
- package/dist/terraform/bridge.d.ts.map +1 -1
- package/dist/terraform/carve-provider.d.ts +28 -2
- package/dist/terraform/carve-provider.d.ts.map +1 -1
- package/dist/terraform/data-source-shape.d.ts +77 -0
- package/dist/terraform/data-source-shape.d.ts.map +1 -0
- package/dist/terraform/graph.d.ts.map +1 -1
- package/dist/terraform/providers/kubernetes.d.ts +5 -0
- package/dist/terraform/providers/kubernetes.d.ts.map +1 -1
- package/dist/terraform/tier-map.d.ts +16 -4
- package/dist/terraform/tier-map.d.ts.map +1 -1
- package/dist/terraform/types.d.ts +8 -0
- package/dist/terraform/types.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 +84 -18
- package/src/audit/discover.test.ts +39 -0
- package/src/audit/discover.ts +202 -18
- 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 +191 -11
- package/src/cli/commands/audit.ts +78 -28
- package/src/cli/commands/build.test.ts +330 -9
- package/src/cli/commands/build.ts +170 -24
- package/src/cli/commands/carve-bridge.test.ts +237 -14
- package/src/cli/commands/carve-bridge.ts +21 -17
- package/src/cli/commands/carve-emit-k8s.test.ts +17 -10
- 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 +194 -1
- package/src/cli/commands/lint.ts +205 -7
- 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 +341 -55
- package/src/cli/handlers/run.test.ts +568 -1295
- package/src/cli/handlers/run.ts +446 -912
- package/src/cli/main.test.ts +22 -16
- package/src/cli/main.ts +66 -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/plugins.test.ts +68 -2
- package/src/cli/plugins.ts +39 -0
- package/src/cli/registry.ts +40 -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 +4 -3
- package/src/components/__fixtures__/neo4j-fanout.json +1 -1
- 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 +28 -12
- package/src/components/cli-support.ts +60 -47
- package/src/components/component-schema.test.ts +18 -2
- package/src/components/component.schema.json +18 -5
- package/src/components/component.test.ts +2 -2
- package/src/components/component.ts +27 -7
- package/src/components/config-defaults.test.ts +2 -2
- package/src/components/driver-output.ts +14 -2
- package/src/components/driver.test.ts +109 -20
- package/src/components/driver.ts +201 -84
- 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/neo4j-fanout.pilot.ts +3 -3
- 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.test.ts +19 -0
- package/src/components/verbs/run-agent.ts +12 -24
- 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/detectLexicon.ts +18 -1
- package/src/discovery/collect.test.ts +3 -3
- package/src/discovery/files.ts +4 -4
- package/src/discovery/fold-import.test.ts +1 -1
- 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 +82 -2
- 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 +3 -3
- 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 +296 -16
- 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 +154 -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/pipeline-change-gate.test.ts +2 -2
- 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 +27 -1
- package/src/lint/rules/comp/comp004-gate-needs-durable-runtime.ts +76 -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 +161 -0
- package/src/op/activities/reconcile.ts +354 -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 +125 -41
- package/src/op/change-signal.test.ts +117 -0
- package/src/op/change-signal.ts +169 -0
- package/src/op/composites/apply-op.ts +218 -0
- package/src/op/composites/composites.test.ts +379 -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 +110 -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 +29 -14
- package/src/op/emulator-lifecycle.ts +1 -2
- package/src/op/gate-name.test.ts +65 -0
- package/src/op/gate-name.ts +60 -0
- package/src/op/gate-summary.ts +84 -0
- 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 +48 -8
- package/src/op/local-executor.test.ts +178 -34
- package/src/op/local-executor.ts +371 -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 +292 -0
- package/src/op/op-ir.ts +419 -0
- package/src/op/op-verb-class.test.ts +2 -2
- package/src/op/op-verb-class.ts +19 -5
- package/src/op/op.test.ts +28 -7
- package/src/op/operator.test.ts +543 -6
- package/src/op/operator.ts +203 -20
- 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 +106 -26
- 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/src/terraform/aws-resources.test.ts +13 -4
- package/src/terraform/bridge.test.ts +22 -9
- package/src/terraform/bridge.ts +89 -28
- package/src/terraform/carve-provider.ts +38 -2
- package/src/terraform/data-source-shape.ts +95 -0
- package/src/terraform/graph.ts +35 -7
- package/src/terraform/providers/kubernetes.ts +48 -2
- package/src/terraform/tier-map.ts +21 -6
- package/src/terraform/types.ts +8 -0
- 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
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
export * from "./declarable";
|
|
8
|
+
export * from "./held-elsewhere";
|
|
8
9
|
export * from "./composite";
|
|
9
10
|
export * from "./provenance";
|
|
10
11
|
export * from "./secret-provenance";
|
|
@@ -56,6 +57,8 @@ export * from "./observation";
|
|
|
56
57
|
export * from "./identity";
|
|
57
58
|
export * from "./apply";
|
|
58
59
|
export * from "./deep-observation";
|
|
60
|
+
export * from "./claimed-fields";
|
|
61
|
+
export * from "./fold-provenance";
|
|
59
62
|
export * from "./owner-chain";
|
|
60
63
|
export * from "./lexicon-integrity";
|
|
61
64
|
export * from "./lexicon-manifest";
|
package/src/kubectl-context.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Every cloud lexicon binds an environment to a scope: AWS resolves `<env>`
|
|
5
5
|
* to a CloudFormation stack, Azure treats `<env>` as the resource group,
|
|
6
|
-
*
|
|
6
|
+
* Fly resolves it to an app. K8s (and
|
|
7
7
|
* GCP-via-Config-Connector, which observes through the same kubectl path)
|
|
8
8
|
* bound nothing — `describeResources` shelled out to `kubectl get` with no
|
|
9
9
|
* `--context`, so it read whatever cluster `kubectl config current-context`
|
|
@@ -111,8 +111,8 @@ export interface ResolveClusterTargetOptions {
|
|
|
111
111
|
* Resolve the kubectl context an environment should be observed/applied
|
|
112
112
|
* against, reading `k8s.profiles.<environment>.context` from `chant.config.ts`
|
|
113
113
|
* (the `config` passed in is the passthrough `ChantConfig`, cast loosely since
|
|
114
|
-
* the `k8s` key isn't declared on the core schema — same pattern
|
|
115
|
-
*
|
|
114
|
+
* the `k8s` key isn't declared on the core schema — the same pattern every
|
|
115
|
+
* lexicon namespace follows).
|
|
116
116
|
*
|
|
117
117
|
* - No binding declared: returns `{ source: "ambient" }` — unchanged
|
|
118
118
|
* behavior — but logs a visible warning identifying the caller and
|
|
@@ -67,15 +67,15 @@ describe("validateLexiconConfig (#1344)", () => {
|
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
test("validates each declaring lexicon independently", () => {
|
|
70
|
-
const
|
|
71
|
-
name: "
|
|
70
|
+
const k8s = {
|
|
71
|
+
name: "k8s",
|
|
72
72
|
configSchema: z.strictObject({ defaultProfile: z.string().optional() }),
|
|
73
73
|
};
|
|
74
74
|
const problems = validateLexiconConfig(
|
|
75
|
-
[forgejo,
|
|
76
|
-
cfg({ forgejo: { actionsRoot: "https://x" },
|
|
75
|
+
[forgejo, k8s],
|
|
76
|
+
cfg({ forgejo: { actionsRoot: "https://x" }, k8s: { defaultProfil: "local" } }),
|
|
77
77
|
);
|
|
78
|
-
expect(problems.map((p) => p.lexicon)).toEqual(["
|
|
78
|
+
expect(problems.map((p) => p.lexicon)).toEqual(["k8s"]);
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
test("no config at all is not a problem", () => {
|
package/src/lexicon-config.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The config namespace a lexicon owns (#1344).
|
|
3
3
|
*
|
|
4
4
|
* Three lexicons read a top-level `chant.config.ts` key named after themselves —
|
|
5
|
-
* `k8s.profiles.<env>.context`, `
|
|
5
|
+
* `k8s.profiles.<env>.context`, `forgejo.runnerLabels` and
|
|
6
6
|
* `forgejo.actionsRoot` — all documented for users, none declared anywhere.
|
|
7
7
|
* `ChantConfigSchema` is `.passthrough()`, so at runtime any key is accepted and
|
|
8
8
|
* a typo is silently ignored: write `runnerLabel` and the Forgejo dialect just
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
* error TS2353: Object literal may only specify known properties,
|
|
13
13
|
* and 'forgejo' does not exist in type 'ChantConfig'.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* The lexicons had arrived at different workarounds: one exported its own
|
|
16
|
+
* widened config type, k8s's docs dropped `satisfies`, and forgejo's kept it
|
|
17
|
+
* and were wrong.
|
|
18
18
|
*
|
|
19
19
|
* A lexicon now declares the shape of its namespace. The declaration is both
|
|
20
20
|
* halves of the fix at once: core validates against it at load, and the lexicon
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Shared helpers for lexicon plugin implementations.
|
|
3
3
|
*
|
|
4
|
-
* Eliminates boilerplate across the
|
|
4
|
+
* Eliminates boilerplate across the 15 lexicon plugins that use it by providing
|
|
5
5
|
* factory functions for common plugin methods: skills loading,
|
|
6
6
|
* MCP diff tool, and MCP catalog resource.
|
|
7
7
|
*/
|
package/src/lexicon.ts
CHANGED
|
@@ -12,6 +12,9 @@ import type { CompletionContext, CompletionItem, HoverContext, HoverInfo, CodeAc
|
|
|
12
12
|
import type { McpToolContribution, McpResourceContribution } from "./mcp/types";
|
|
13
13
|
import type { DriverComponent } from "./components/driver";
|
|
14
14
|
import type { EmulatorDeclaration } from "./op/emulator-lifecycle";
|
|
15
|
+
import type { OpRuntimeProvider } from "./op/runtime";
|
|
16
|
+
import type { OpSchedule } from "./op/types";
|
|
17
|
+
import type { ActivityContract } from "./op/activity-contract";
|
|
15
18
|
import type { OwnershipChannel, OwnershipMarker } from "./ownership";
|
|
16
19
|
import type { LexiconConfigSchema } from "./lexicon-config";
|
|
17
20
|
import type { RuleMeta } from "./audit/catalog";
|
|
@@ -24,6 +27,17 @@ import type { DisruptionQuery, DisruptionVerdict } from "./lifecycle/disruption"
|
|
|
24
27
|
import type { OwnerChainVerdict } from "./owner-chain";
|
|
25
28
|
import type { CommandGroup } from "./cli/command-group";
|
|
26
29
|
|
|
30
|
+
// Re-exported so a lexicon that hosts Op runs (#2121) can type its
|
|
31
|
+
// `opRuntime` from the same entry it imports the plugin contract from.
|
|
32
|
+
export type {
|
|
33
|
+
OpRuntimeProvider,
|
|
34
|
+
OpRunHandle,
|
|
35
|
+
OpRunRecord,
|
|
36
|
+
OpRunStartOptions,
|
|
37
|
+
OpRunState,
|
|
38
|
+
OpRunStatus,
|
|
39
|
+
} from "./op/runtime";
|
|
40
|
+
|
|
27
41
|
// Re-exported so a lexicon can author its command group (#1078) from the
|
|
28
42
|
// same `@intentius/chant/lexicon` entry it imports the plugin contract from.
|
|
29
43
|
export type { CommandGroup, CommandGroupCommand, CommandGroupContext } from "./cli/command-group";
|
|
@@ -472,24 +486,133 @@ export interface ComponentPipelineResult {
|
|
|
472
486
|
}
|
|
473
487
|
|
|
474
488
|
/**
|
|
475
|
-
* Finding-mode a scheduled Op surfaces on drift — the vocabulary the
|
|
476
|
-
*
|
|
477
|
-
*
|
|
489
|
+
* Finding-mode a scheduled Op surfaces on drift — the vocabulary the core
|
|
490
|
+
* composites (`WorkflowAuditOp`/`PipelineAuditOp`/`ReconcileOp`) already
|
|
491
|
+
* declare on the Op itself (#927). The mode is baked
|
|
478
492
|
* into the Op's own activity args at build time and is never re-passed on the
|
|
479
493
|
* generated CI invocation; here it decides only what token/permission wiring
|
|
480
494
|
* the generated job needs to act on a finding — elevated write access for
|
|
481
|
-
* `issue`/`pull-request`/`merge-request`, none for `report`.
|
|
495
|
+
* `issue`/`comment`/`pull-request`/`merge-request`, none for `report`.
|
|
496
|
+
*
|
|
497
|
+
* `comment` posts the finding on the pull request that triggered the run
|
|
498
|
+
* (#2231), so unlike every other mode it constrains the trigger: the github
|
|
499
|
+
* generator refuses it by name on anything but `pull_request`, and the gitlab
|
|
500
|
+
* and forgejo generators refuse it outright.
|
|
501
|
+
*/
|
|
502
|
+
export type OpFindingMode = "report" | "issue" | "comment" | "pull-request" | "merge-request";
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* The CI-native trigger driving a scheduled Op's generated workflow. `cron`
|
|
506
|
+
* is the historical shape — the CI-only way to give an Op a cadence.
|
|
507
|
+
* `pull_request` and `push` are generic beyond cron: a
|
|
508
|
+
* Terraform CI shape needs `plan` on `pull_request` (posted as a PR comment)
|
|
509
|
+
* and `apply` on `push` to the default branch, each its own Op with its own
|
|
510
|
+
* trigger (#2081, #2084).
|
|
511
|
+
*/
|
|
512
|
+
export type OpTrigger =
|
|
513
|
+
| { kind: "cron"; schedule: string }
|
|
514
|
+
| { kind: "pull_request"; branches?: string[] }
|
|
515
|
+
| { kind: "push"; branches?: string[] };
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* One step a generated Op job runs between the checkout and the
|
|
519
|
+
* `beforeScript` lines (#2242). Two shapes, matching what a GitHub Actions
|
|
520
|
+
* step can be: a marketplace action (`uses`, with its `with:` inputs and
|
|
521
|
+
* `env:`), or a shell line (`run`). The `uses` shape is the reason this
|
|
522
|
+
* exists at all: `beforeScript` covers everything a shell line can install,
|
|
523
|
+
* but an action like `aws-actions/configure-aws-credentials` is not a shell
|
|
524
|
+
* line, and OIDC has no shell equivalent.
|
|
525
|
+
*
|
|
526
|
+
* A CI provider with no action concept degrades by name rather than
|
|
527
|
+
* silently: the gitlab generator refuses a `uses` entry at build time and
|
|
528
|
+
* emits a `run` entry as an ordinary script line.
|
|
482
529
|
*/
|
|
483
|
-
export type
|
|
530
|
+
export type OpSetupStep = OpSetupUsesStep | OpSetupRunStep;
|
|
531
|
+
|
|
532
|
+
/** A marketplace-action setup step (`uses:` with its inputs). */
|
|
533
|
+
export interface OpSetupUsesStep {
|
|
534
|
+
/**
|
|
535
|
+
* `owner/repo[/subpath]@ref`. The ref is required and must not be the
|
|
536
|
+
* action repository's own default branch — see the github generator's
|
|
537
|
+
* `assertSetupSteps`, which refuses both at build time.
|
|
538
|
+
*/
|
|
539
|
+
uses: string;
|
|
540
|
+
/** The action's inputs, emitted as the step's `with:` mapping. */
|
|
541
|
+
with?: Record<string, string | number | boolean>;
|
|
542
|
+
/** Environment for this step alone, emitted as the step's `env:` mapping. */
|
|
543
|
+
env?: Record<string, string>;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/** A shell setup step, the same shape a `beforeScript` line emits as. */
|
|
547
|
+
export interface OpSetupRunStep {
|
|
548
|
+
/** The shell line, emitted as the step's `run:`. */
|
|
549
|
+
run: string;
|
|
550
|
+
/** Environment for this step alone, emitted as the step's `env:` mapping. */
|
|
551
|
+
env?: Record<string, string>;
|
|
552
|
+
}
|
|
484
553
|
|
|
485
554
|
/** One scheduled Op to generate CI for — the cron-triggered counterpart to a component (generate mode). */
|
|
486
555
|
export interface ScheduledOpSpec {
|
|
487
556
|
/** Op name (`*.op.ts`'s `Op({ name })`) — what `chant run <name>` targets. */
|
|
488
557
|
name: string;
|
|
489
|
-
/**
|
|
490
|
-
|
|
558
|
+
/**
|
|
559
|
+
* Cron expression driving the CI-native trigger. Superseded by `trigger`; kept for
|
|
560
|
+
* backward compatibility, so an omitted `trigger` with `schedule` present
|
|
561
|
+
* still means `{ kind: "cron", schedule }` (see {@link resolveOpTrigger}).
|
|
562
|
+
*/
|
|
563
|
+
schedule?: string;
|
|
564
|
+
/**
|
|
565
|
+
* The CI-native trigger driving this Op's generated workflow (#2084).
|
|
566
|
+
* Omit this and set only `schedule` for the pre-existing cron behavior;
|
|
567
|
+
* set explicitly for `pull_request`/`push`, or to spell cron the same way.
|
|
568
|
+
*/
|
|
569
|
+
trigger?: OpTrigger;
|
|
570
|
+
/**
|
|
571
|
+
* The declaring Op's own cadence (#2120) — `OpConfig.schedule`, filled in
|
|
572
|
+
* by `generateOpsPipeline` from the discovered Op so a scheduled Op needs
|
|
573
|
+
* no second cron declaration on the CI side. The lowest-precedence source
|
|
574
|
+
* of a trigger: an explicit `trigger` first, then an explicit `schedule` on
|
|
575
|
+
* this spec, then this (see {@link resolveOpTrigger}).
|
|
576
|
+
*/
|
|
577
|
+
opSchedule?: OpSchedule;
|
|
491
578
|
/** This Op's finding-mode, for permission/token wiring only (see {@link OpFindingMode}). Default: "report" — no elevated permissions. */
|
|
492
579
|
findingMode?: OpFindingMode;
|
|
580
|
+
/**
|
|
581
|
+
* Steps this Op's generated job runs between the checkout and the
|
|
582
|
+
* `beforeScript` lines (#2242), in the order given. Per-Op rather than a
|
|
583
|
+
* `ComponentPipelineOptions` knob because the setup an Op needs is a
|
|
584
|
+
* property of that Op: a plan job assumes a read-only role, an apply job
|
|
585
|
+
* assumes the one that can write.
|
|
586
|
+
*/
|
|
587
|
+
setup?: OpSetupStep[];
|
|
588
|
+
/**
|
|
589
|
+
* Scopes added to the ones this Op's finding-mode already grants (#2242).
|
|
590
|
+
* Strictly additive: the generator refuses a scope the mode's own set
|
|
591
|
+
* already names, at any value, so this can neither downgrade nor restate
|
|
592
|
+
* least privilege, and it refuses `write-all`/`read-all` outright. The
|
|
593
|
+
* motivating value is `{ "id-token": "write" }`, which no finding-mode
|
|
594
|
+
* grants and OIDC cannot work without.
|
|
595
|
+
*/
|
|
596
|
+
permissions?: Record<string, "read" | "write">;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Resolve a `ScheduledOpSpec`'s effective trigger, most specific first:
|
|
601
|
+
* `trigger` when given; else the backward-compatible `{ kind: "cron",
|
|
602
|
+
* schedule }` built from this spec's own `schedule` — every pre-#2084 caller
|
|
603
|
+
* (`WorkflowAuditOp`, `PipelineAuditOp`, `ReconcileOp`, …, and their tests)
|
|
604
|
+
* sets only that and keeps meaning cron unchanged; else the declaring Op's
|
|
605
|
+
* own `schedule.cron` (#2120), so an Op that already carries its cadence
|
|
606
|
+
* needs no second cron declaration on the CI side. Throws when none of the
|
|
607
|
+
* three is present — a `ScheduledOpSpec` needs exactly one trigger.
|
|
608
|
+
*/
|
|
609
|
+
export function resolveOpTrigger(spec: ScheduledOpSpec): OpTrigger {
|
|
610
|
+
if (spec.trigger) return spec.trigger;
|
|
611
|
+
if (spec.schedule) return { kind: "cron", schedule: spec.schedule };
|
|
612
|
+
if (spec.opSchedule) return { kind: "cron", schedule: spec.opSchedule.cron };
|
|
613
|
+
throw new Error(
|
|
614
|
+
`Scheduled Op "${spec.name}" has neither \`trigger\` nor \`schedule\`, and the Op itself declares no \`schedule\` — one is required.`,
|
|
615
|
+
);
|
|
493
616
|
}
|
|
494
617
|
|
|
495
618
|
/** One CI job generated for a scheduled Op. */
|
|
@@ -498,8 +621,8 @@ export interface OpPipelineJob {
|
|
|
498
621
|
jobName: string;
|
|
499
622
|
/** The Op this job runs. */
|
|
500
623
|
op: string;
|
|
501
|
-
/**
|
|
502
|
-
|
|
624
|
+
/** The trigger driving this job's generated workflow (#2084) — lets a consumer tell cron/`pull_request`/`push` jobs apart. */
|
|
625
|
+
trigger: OpTrigger;
|
|
503
626
|
/** The finding-mode wired for this job. */
|
|
504
627
|
findingMode: OpFindingMode;
|
|
505
628
|
}
|
|
@@ -599,6 +722,29 @@ export type BuildRootContributor = (
|
|
|
599
722
|
ctx: Pick<BuildRootContext, "entities">,
|
|
600
723
|
) => Promise<BuildRootContribution>;
|
|
601
724
|
|
|
725
|
+
/**
|
|
726
|
+
* Where the content handed to `auditEntities` came from (#2217).
|
|
727
|
+
*
|
|
728
|
+
* The hook's first argument is the text audit discovery classified for a
|
|
729
|
+
* lexicon. For most lexicons that is the whole unit of parsing. For terraform
|
|
730
|
+
* it is not: a root module's `module` blocks name sibling directories, and a
|
|
731
|
+
* rule about what a CHILD module may contain cannot be answered from one
|
|
732
|
+
* directory's text. So the discovery facts a lexicon may need to read further
|
|
733
|
+
* travel with the content.
|
|
734
|
+
*
|
|
735
|
+
* `dir` and `baseDir` are set only when discovery walked a local filesystem.
|
|
736
|
+
* A remote tree fetch leaves both undefined, and a lexicon that finds them
|
|
737
|
+
* undefined parses the content it was given and nothing else.
|
|
738
|
+
*/
|
|
739
|
+
export interface AuditEntitiesInput {
|
|
740
|
+
/** The input's path as discovery recorded it, relative to the audited root. `"."` for the root itself. */
|
|
741
|
+
path: string;
|
|
742
|
+
/** Absolute path of the directory this input's files were read from. */
|
|
743
|
+
dir?: string;
|
|
744
|
+
/** Absolute path of the audited root: the boundary a lexicon may read within. */
|
|
745
|
+
baseDir?: string;
|
|
746
|
+
}
|
|
747
|
+
|
|
602
748
|
export interface LexiconPlugin {
|
|
603
749
|
// ── Required ──────────────────────────────────────────────
|
|
604
750
|
/** Human-readable name (e.g. "aws", "gcp") */
|
|
@@ -623,8 +769,8 @@ export interface LexiconPlugin {
|
|
|
623
769
|
* The shape of this lexicon's own `chant.config.ts` namespace — the top-level
|
|
624
770
|
* key named after the lexicon (#1344).
|
|
625
771
|
*
|
|
626
|
-
* k8s reads `k8s.profiles.<env>.context`,
|
|
627
|
-
*
|
|
772
|
+
* k8s reads `k8s.profiles.<env>.context`, forgejo `forgejo.runnerLabels`
|
|
773
|
+
* and `forgejo.actionsRoot`. All were
|
|
628
774
|
* documented for users and declared nowhere: the config schema is
|
|
629
775
|
* `.passthrough()`, so a typo was accepted and silently ignored, and the
|
|
630
776
|
* `ChantConfig` interface is closed, so the documented examples did not
|
|
@@ -680,6 +826,22 @@ export interface LexiconPlugin {
|
|
|
680
826
|
/** Return post-synthesis checks for build validation */
|
|
681
827
|
postSynthChecks?(): PostSynthCheck[];
|
|
682
828
|
|
|
829
|
+
/**
|
|
830
|
+
* Activity contracts (`ActivityContract`, `./op/activity-contract.ts`) for
|
|
831
|
+
* the activities this lexicon implements, so another lexicon's post-synth
|
|
832
|
+
* check can validate an Op step calling one of them (chant #2101).
|
|
833
|
+
*
|
|
834
|
+
* The ordinary way to contribute these is the same convention activities
|
|
835
|
+
* themselves use: export them from
|
|
836
|
+
* `@intentius/chant-lexicon-<name>/op/activity-contracts`, and
|
|
837
|
+
* `loadActivityContracts` (`./op/activity-contract-registry.ts`) finds them
|
|
838
|
+
* with no plugin member at all. This member is the escape hatch for a
|
|
839
|
+
* lexicon whose contracts are not reachable at that subpath — a bundled
|
|
840
|
+
* single-file plugin, a project-local one — and both sources are merged
|
|
841
|
+
* when both are present. Omit it in the common case.
|
|
842
|
+
*/
|
|
843
|
+
activityContracts?(): ActivityContract[];
|
|
844
|
+
|
|
683
845
|
/**
|
|
684
846
|
* Audit catalog metadata (title/tier/fix/authority/category) for this
|
|
685
847
|
* lexicon's `postSynthChecks`, keyed by check id — the per-provider half of
|
|
@@ -689,6 +851,17 @@ export interface LexiconPlugin {
|
|
|
689
851
|
*/
|
|
690
852
|
auditCatalog?(): Record<string, RuleMeta>;
|
|
691
853
|
|
|
854
|
+
/**
|
|
855
|
+
* Preset name mapped to the post-synth check ids that preset enables
|
|
856
|
+
* (chant #2113), e.g. `{ recommended: ["TF001", ...], all: ["TF001", ..., "TF011"] }`.
|
|
857
|
+
* A project selects one via `lint.presets: { "<this lexicon's name>": "<preset>" }`
|
|
858
|
+
* (`./lint/config.ts`'s `LintConfig.presets`). `resolvePresetIds` and
|
|
859
|
+
* `applyConfiguredPreset` (same file) do the filtering. Omit for a lexicon
|
|
860
|
+
* that ships no presets. Its post-synth findings are unaffected by
|
|
861
|
+
* `lint.presets`, exactly as before this existed.
|
|
862
|
+
*/
|
|
863
|
+
lintPresets?(): Record<string, string[]>;
|
|
864
|
+
|
|
692
865
|
/**
|
|
693
866
|
* Parse standalone template content (a file audit discovery classified for
|
|
694
867
|
* this lexicon) into the lexicon's entity graph, keyed the way `ctx.entities`
|
|
@@ -696,9 +869,21 @@ export interface LexiconPlugin {
|
|
|
696
869
|
* `chant audit` of hand-written manifests — parse-to-graph rather than
|
|
697
870
|
* output-reading rule variants (#1567). Implementations must tolerate
|
|
698
871
|
* arbitrary external content: a malformed document yields no entities, never
|
|
699
|
-
* a throw. Omit for lexicons whose audit checks read `ctx.outputs`.
|
|
872
|
+
* a throw. Omit for lexicons whose audit checks read `ctx.outputs`. May
|
|
873
|
+
* return a `Promise` for a lexicon whose parser is inherently async (e.g.
|
|
874
|
+
* terraform's HCL parser, a lazy-loaded wasm module). `auditLexicon` awaits
|
|
875
|
+
* it before reading `ctx.entities`.
|
|
876
|
+
*
|
|
877
|
+
* `input` says where the content came from (#2217). It is optional so a
|
|
878
|
+
* caller can still parse a bare string, and a lexicon that only needs the
|
|
879
|
+
* text ignores it. A lexicon whose unit of parsing is a directory rather
|
|
880
|
+
* than a file (terraform: a root module and the local modules it calls)
|
|
881
|
+
* reads `dir` to descend, and stays inside `baseDir` while doing it.
|
|
700
882
|
*/
|
|
701
|
-
auditEntities?(
|
|
883
|
+
auditEntities?(
|
|
884
|
+
content: string,
|
|
885
|
+
input?: AuditEntitiesInput,
|
|
886
|
+
): Map<string, Declarable> | Promise<Map<string, Declarable>>;
|
|
702
887
|
|
|
703
888
|
/**
|
|
704
889
|
* Machine-readable spec-coverage accounting for `check-lexicon` (#1330).
|
|
@@ -785,6 +970,18 @@ export interface LexiconPlugin {
|
|
|
785
970
|
options?: ComponentPipelineOptions,
|
|
786
971
|
): OpPipelineResult;
|
|
787
972
|
|
|
973
|
+
/**
|
|
974
|
+
* Host Op runs — the seam `chant run <op> --on <this lexicon>` dispatches to
|
|
975
|
+
* (#2121, epic #2114). Core ships one provider of its own, `local`, and
|
|
976
|
+
* selects it when no `--on` is passed; a lexicon that can start, watch,
|
|
977
|
+
* cancel and wake runs somewhere else implements the same contract and
|
|
978
|
+
* every `chant run` subcommand goes through it unchanged.
|
|
979
|
+
*
|
|
980
|
+
* Core never imports a hosting lexicon, so this is the only direction the
|
|
981
|
+
* dependency runs. Omit for lexicons that host nothing.
|
|
982
|
+
*/
|
|
983
|
+
readonly opRuntime?: OpRuntimeProvider;
|
|
984
|
+
|
|
788
985
|
/**
|
|
789
986
|
* Render this lexicon's config-declared build roots into entities (#1548
|
|
790
987
|
* piece 3) — the seam for a build root that is NOT typed chant source. The
|
|
@@ -842,7 +1039,7 @@ export interface LexiconPlugin {
|
|
|
842
1039
|
* Query deployed resources and return API metadata. Opt-in.
|
|
843
1040
|
*
|
|
844
1041
|
* Use this when each chant entity has a 1:1 cloud equivalent — e.g. an
|
|
845
|
-
* AWS CFN resource, a K8s object, an ARM resource, a
|
|
1042
|
+
* AWS CFN resource, a K8s object, an ARM resource, a Fly app.
|
|
846
1043
|
*
|
|
847
1044
|
* **The observation contract (#1089).** Returning nothing for a declared
|
|
848
1045
|
* entity is a claim, and there are two different claims to make. Either the
|
|
@@ -875,8 +1072,8 @@ export interface LexiconPlugin {
|
|
|
875
1072
|
* `entities` carries the chant-side entity declarations for this lexicon,
|
|
876
1073
|
* keyed by chant entity name (e.g. the export name from a `*.ts` file).
|
|
877
1074
|
* Implementations that need to map cloud-side names back to chant entity
|
|
878
|
-
* names (
|
|
879
|
-
*
|
|
1075
|
+
* names (server-side name `prod` ↔ chant entity `ns` declared with
|
|
1076
|
+
* `name: "prod"`) read this; implementations that already
|
|
880
1077
|
* have name parity (e.g. AWS CloudFormation logical IDs == chant entity
|
|
881
1078
|
* names) can ignore it.
|
|
882
1079
|
*
|
|
@@ -1040,6 +1237,39 @@ export interface LexiconPlugin {
|
|
|
1040
1237
|
region?: string;
|
|
1041
1238
|
}): Promise<Record<string, ResourceMetadata>>;
|
|
1042
1239
|
|
|
1240
|
+
/**
|
|
1241
|
+
* Subscribe to this substrate's own change notifications (#1981), so an
|
|
1242
|
+
* operator tick can run when something moved instead of only when the timer
|
|
1243
|
+
* came round. Optional, and consumed by exactly one caller: `chant
|
|
1244
|
+
* operator`'s loop (`./op/operator.ts`). A lexicon that does not implement
|
|
1245
|
+
* it behaves exactly as it did: the loop keeps its timer and never asks.
|
|
1246
|
+
*
|
|
1247
|
+
* Three rules make the seam honest, and the types are shaped to enforce the
|
|
1248
|
+
* first one rather than describe it.
|
|
1249
|
+
*
|
|
1250
|
+
* - **The signal is a trigger, never a fact.** {@link
|
|
1251
|
+
* SubscribeChangesOptions.onChange} takes no arguments and returns
|
|
1252
|
+
* nothing, so there is no channel through which a watch event could reach
|
|
1253
|
+
* a change set, a snapshot row or a diff line. The tick that follows an
|
|
1254
|
+
* early wake re-observes and re-derives from scratch, exactly as a
|
|
1255
|
+
* timer-driven tick does; waking early changes *when* a tick runs and
|
|
1256
|
+
* nothing about what it concludes.
|
|
1257
|
+
* - **A dropped subscription degrades to the timer and says so.** Report it
|
|
1258
|
+
* through {@link SubscribeChangesOptions.onError} and stop; the operator
|
|
1259
|
+
* logs one line and re-subscribes on its next round. Losing the stream
|
|
1260
|
+
* slows detection back to the interval. It must never stop the loop, and
|
|
1261
|
+
* must never read as a clean estate.
|
|
1262
|
+
* - **The timer stays.** A signal shortens the sleep, it does not replace
|
|
1263
|
+
* it, so a substrate that silently stops sending still converges on the
|
|
1264
|
+
* interval.
|
|
1265
|
+
*
|
|
1266
|
+
* Only implement it where the substrate has a change stream that needs
|
|
1267
|
+
* nothing deployed into the account being observed. See the per-lexicon
|
|
1268
|
+
* verdict table in the operator guide for where that holds and where it does
|
|
1269
|
+
* not.
|
|
1270
|
+
*/
|
|
1271
|
+
subscribeChanges?(options: SubscribeChangesOptions): Promise<ChangeSubscription>;
|
|
1272
|
+
|
|
1043
1273
|
/**
|
|
1044
1274
|
* Read the full live *property tree* for each declared entity (#1014). Opt-in,
|
|
1045
1275
|
* and strictly deeper than {@link describeResources}, which reports existence
|
|
@@ -1462,6 +1692,56 @@ export interface DependencyObservation {
|
|
|
1462
1692
|
edges?: IREdge[];
|
|
1463
1693
|
}
|
|
1464
1694
|
|
|
1695
|
+
/**
|
|
1696
|
+
* What {@link LexiconPlugin.subscribeChanges} is handed (#1981).
|
|
1697
|
+
*
|
|
1698
|
+
* `onChange` is the whole payload channel, and it has no payload. That is the
|
|
1699
|
+
* point: a substrate's change notification is a reason to look again, never
|
|
1700
|
+
* evidence of what is there. An implementation that wanted to pass the watch
|
|
1701
|
+
* event through would have nowhere to put it.
|
|
1702
|
+
*/
|
|
1703
|
+
export interface SubscribeChangesOptions {
|
|
1704
|
+
/** chant environment being watched. Resolves the same binding a read does. */
|
|
1705
|
+
environment: string;
|
|
1706
|
+
/** Directory whose `chant.config.ts` carries the binding. Defaults to cwd. */
|
|
1707
|
+
cwd?: string;
|
|
1708
|
+
/**
|
|
1709
|
+
* Declared entities for this lexicon, keyed by chant entity name. The same
|
|
1710
|
+
* map {@link LexiconPlugin.describeResources} receives, and the bound on
|
|
1711
|
+
* what a subscription may watch. An implementation scopes its streams to the
|
|
1712
|
+
* kinds and namespaces these entities name; it must never subscribe to the
|
|
1713
|
+
* whole substrate. Absent, or empty, means there is nothing in scope to
|
|
1714
|
+
* watch and the implementation should say so through {@link onError} rather
|
|
1715
|
+
* than widening.
|
|
1716
|
+
*/
|
|
1717
|
+
entities?: Map<string, { entityType: string; props: Record<string, unknown> }>;
|
|
1718
|
+
/**
|
|
1719
|
+
* Something moved. No arguments, deliberately (see {@link
|
|
1720
|
+
* LexiconPlugin.subscribeChanges}). The caller re-observes from scratch and
|
|
1721
|
+
* nothing about the notification reaches what it reports.
|
|
1722
|
+
*/
|
|
1723
|
+
onChange(): void;
|
|
1724
|
+
/**
|
|
1725
|
+
* The subscription died, or could not be established for part of its scope.
|
|
1726
|
+
* Reported once per occurrence; the caller logs it and falls back to its
|
|
1727
|
+
* timer. Never a throw once the subscription is live: a stream that ends is
|
|
1728
|
+
* a degradation, not a crash.
|
|
1729
|
+
*/
|
|
1730
|
+
onError?(message: string): void;
|
|
1731
|
+
/** Aborts the subscription. Closing on abort is the implementation's job. */
|
|
1732
|
+
signal: AbortSignal;
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
/**
|
|
1736
|
+
* A live subscription handed back by {@link LexiconPlugin.subscribeChanges}
|
|
1737
|
+
* (#1981). `close()` releases every stream the subscription holds and resolves
|
|
1738
|
+
* once they are gone; it must be safe to call twice, and safe to call after
|
|
1739
|
+
* the subscription has already died on its own.
|
|
1740
|
+
*/
|
|
1741
|
+
export interface ChangeSubscription {
|
|
1742
|
+
close(): Promise<void>;
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1465
1745
|
export interface ResourceMetadata {
|
|
1466
1746
|
/** Entity type (e.g. AWS::S3::Bucket, K8s::Apps::Deployment) */
|
|
1467
1747
|
type: string;
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
unobservedPlanNotice,
|
|
9
9
|
type ChangeSet,
|
|
10
10
|
type ChangeSetEntry,
|
|
11
|
+
type HeldEntitySet,
|
|
11
12
|
} from "./change-set";
|
|
12
13
|
import type { ResourceMetadata } from "../lexicon";
|
|
13
14
|
|
|
@@ -589,3 +590,51 @@ describe("renderChangeSetMarkdown (#1983)", () => {
|
|
|
589
590
|
expect(few).not.toContain("<details>");
|
|
590
591
|
});
|
|
591
592
|
});
|
|
593
|
+
|
|
594
|
+
// #2162 — a held property is never a `ChangeAction`: it rides beside
|
|
595
|
+
// `entries` on the change set, in its own section, in both renders.
|
|
596
|
+
describe("ChangeSet.held (#2162)", () => {
|
|
597
|
+
const heldEntities: HeldEntitySet[] = [
|
|
598
|
+
{
|
|
599
|
+
name: "web",
|
|
600
|
+
type: "K8s::Apps::Deployment",
|
|
601
|
+
lexicon: "k8s",
|
|
602
|
+
held: [
|
|
603
|
+
{ path: "spec.replicas", by: "hpa", reason: "the autoscaler owns replicas after the first apply", live: 5, suspicious: false },
|
|
604
|
+
],
|
|
605
|
+
},
|
|
606
|
+
];
|
|
607
|
+
|
|
608
|
+
test("renderChangeSet: a HELD section, separate from every action group", () => {
|
|
609
|
+
const cs: ChangeSet = { ...set([entry({ action: "noop" })]), held: heldEntities };
|
|
610
|
+
const out = renderChangeSet(cs);
|
|
611
|
+
expect(out).toContain("HELD (declared heldElsewhere(); not drift, never proposed for update)");
|
|
612
|
+
expect(out).toContain("web (K8s::Apps::Deployment) k8s");
|
|
613
|
+
expect(out).toContain("spec.replicas: held by hpa — 5 (the autoscaler owns replicas after the first apply)");
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
test("renderChangeSetMarkdown: its own section, held entries never counted in the header", () => {
|
|
617
|
+
const cs: ChangeSet = { ...set([entry({ action: "noop" })]), held: heldEntities };
|
|
618
|
+
const out = renderChangeSetMarkdown(cs);
|
|
619
|
+
expect(out).toContain("### HELD (declared heldElsewhere(); not drift, never proposed for update)");
|
|
620
|
+
expect(out).toContain("`web` (K8s::Apps::Deployment) `k8s`");
|
|
621
|
+
expect(out).toContain("spec.replicas: held by hpa — 5");
|
|
622
|
+
// The counts header only ever tallies `ChangeAction`s.
|
|
623
|
+
expect(out).toContain("0 create, 0 update, 0 effect, 0 delete, 0 adopt, 0 runtime, 1 noop, 0 unobserved");
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
test("a suspicious held property is marked in both renders", () => {
|
|
627
|
+
const suspicious: HeldEntitySet[] = [
|
|
628
|
+
{ name: "cfg", type: "T", held: [{ path: "A", by: "controller", reason: "x", suspicious: true }] },
|
|
629
|
+
];
|
|
630
|
+
const cs: ChangeSet = { ...set([]), held: suspicious };
|
|
631
|
+
expect(renderChangeSet(cs)).toContain("[SUSPICIOUS: no live value ever showed up here]");
|
|
632
|
+
expect(renderChangeSetMarkdown(cs)).toContain("SUSPICIOUS: no live value ever showed up here");
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
test("omitted entirely when nothing is held — no empty section in either render", () => {
|
|
636
|
+
const cs = set([entry({ action: "noop" })]);
|
|
637
|
+
expect(renderChangeSet(cs)).not.toContain("HELD");
|
|
638
|
+
expect(renderChangeSetMarkdown(cs)).not.toContain("HELD");
|
|
639
|
+
});
|
|
640
|
+
});
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { diffLive, type AttributeChange, type DiffLiveInput } from "./live-diff";
|
|
16
16
|
import { unobservedReasonText, type UnobservedReason } from "../observation";
|
|
17
17
|
import { renderDisruption, summarizeDisruption, type Disruption } from "./disruption";
|
|
18
|
+
import type { DeepEntityHeld } from "./deep-diff";
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* What the projection proposes for a single resource.
|
|
@@ -148,9 +149,22 @@ export interface ChangeSetEntry {
|
|
|
148
149
|
disruptionDetail?: string;
|
|
149
150
|
}
|
|
150
151
|
|
|
152
|
+
/** One entity's held properties (#2162), attributed to the lexicon that observed it — a plan merges every lexicon's, so the attribution has to survive the merge the same way {@link ChangeSetEntry.lexicon} does. */
|
|
153
|
+
export interface HeldEntitySet extends DeepEntityHeld {
|
|
154
|
+
lexicon?: string;
|
|
155
|
+
}
|
|
156
|
+
|
|
151
157
|
export interface ChangeSet {
|
|
152
158
|
env: string;
|
|
153
159
|
entries: ChangeSetEntry[];
|
|
160
|
+
/**
|
|
161
|
+
* Properties declared `heldElsewhere()` (#2162), across every lexicon this
|
|
162
|
+
* plan checked. Not part of `entries`: a held property is never a proposal
|
|
163
|
+
* — it carries no `ChangeAction` — so it rides beside the actionable set
|
|
164
|
+
* rather than inside it, the same way `unobservedPlanNotice` rides beside
|
|
165
|
+
* rather than inside. Omitted when nothing declared one.
|
|
166
|
+
*/
|
|
167
|
+
held?: HeldEntitySet[];
|
|
154
168
|
}
|
|
155
169
|
|
|
156
170
|
/**
|
|
@@ -407,9 +421,58 @@ export function renderChangeSet(cs: ChangeSet): string {
|
|
|
407
421
|
}
|
|
408
422
|
}
|
|
409
423
|
|
|
424
|
+
if (cs.held && cs.held.length > 0) {
|
|
425
|
+
lines.push(`\n${heldSectionLabel()}:`);
|
|
426
|
+
for (const line of heldLines(cs.held)) lines.push(line);
|
|
427
|
+
}
|
|
428
|
+
|
|
410
429
|
return lines.join("\n");
|
|
411
430
|
}
|
|
412
431
|
|
|
432
|
+
/**
|
|
433
|
+
* Section heading for the held set (#2162) — shared between {@link renderChangeSet}
|
|
434
|
+
* and {@link renderChangeSetMarkdown}.
|
|
435
|
+
*/
|
|
436
|
+
function heldSectionLabel(): string {
|
|
437
|
+
return "HELD (declared heldElsewhere(); not drift, never proposed for update)";
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/** One held property's plain-text line, indented under its entity. */
|
|
441
|
+
function heldLines(held: readonly HeldEntitySet[]): string[] {
|
|
442
|
+
const lines: string[] = [];
|
|
443
|
+
for (const entity of held) {
|
|
444
|
+
const lexicon = entity.lexicon ? ` ${entity.lexicon}` : "";
|
|
445
|
+
lines.push(` ${entity.name} (${entity.type})${lexicon}`);
|
|
446
|
+
for (const h of entity.held) {
|
|
447
|
+
const live = "live" in h ? fmt(h.live) : "<absent>";
|
|
448
|
+
const suspicious = h.suspicious
|
|
449
|
+
? " [SUSPICIOUS: no live value ever showed up here]"
|
|
450
|
+
: "";
|
|
451
|
+
lines.push(` ${h.path}: held by ${h.by} — ${live} (${h.reason})${suspicious}`);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return lines;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/** One held property's markdown line, mirroring {@link renderMarkdownEntry}'s formatting. */
|
|
458
|
+
function heldLinesMarkdown(held: readonly HeldEntitySet[]): string[] {
|
|
459
|
+
const lines: string[] = [];
|
|
460
|
+
for (const entity of held) {
|
|
461
|
+
const lexicon = entity.lexicon ? ` \`${entity.lexicon}\`` : "";
|
|
462
|
+
lines.push(`- \`${entity.name}\` (${entity.type})${lexicon}`);
|
|
463
|
+
if (entity.held.length > 0) {
|
|
464
|
+
lines.push(" ```");
|
|
465
|
+
for (const h of entity.held) {
|
|
466
|
+
const live = "live" in h ? fmt(h.live) : "<absent>";
|
|
467
|
+
const suspicious = h.suspicious ? " SUSPICIOUS: no live value ever showed up here" : "";
|
|
468
|
+
lines.push(` ${h.path}: held by ${h.by} — ${live} (${h.reason})${suspicious}`);
|
|
469
|
+
}
|
|
470
|
+
lines.push(" ```");
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
return lines;
|
|
474
|
+
}
|
|
475
|
+
|
|
413
476
|
/**
|
|
414
477
|
* Entries beyond this in one action group are collapsed into a `<details>`
|
|
415
478
|
* block in {@link renderChangeSetMarkdown} — a group's worth of rows is fine
|
|
@@ -500,6 +563,10 @@ export function renderChangeSetMarkdown(cs: ChangeSet): string {
|
|
|
500
563
|
}
|
|
501
564
|
}
|
|
502
565
|
|
|
566
|
+
if (cs.held && cs.held.length > 0) {
|
|
567
|
+
lines.push("", `### ${heldSectionLabel()}`, "", ...heldLinesMarkdown(cs.held));
|
|
568
|
+
}
|
|
569
|
+
|
|
503
570
|
return lines.join("\n").trimEnd() + "\n";
|
|
504
571
|
}
|
|
505
572
|
|