@intentius/chant 0.13.0 → 0.15.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 +45 -5
- package/dist/audit/catalog.d.ts.map +1 -1
- package/dist/audit/fetch.d.ts.map +1 -1
- package/dist/audit/proof.d.ts +3 -0
- package/dist/audit/proof.d.ts.map +1 -1
- package/dist/audit/report-model.d.ts +4 -1
- package/dist/audit/report-model.d.ts.map +1 -1
- package/dist/audit/report.d.ts +3 -0
- package/dist/audit/report.d.ts.map +1 -1
- package/dist/audit/rules-doc.d.ts +8 -2
- package/dist/audit/rules-doc.d.ts.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/lexicon-rolling-upgrade.d.ts +37 -0
- package/dist/cli/commands/lexicon-rolling-upgrade.d.ts.map +1 -0
- package/dist/cli/commands/lexicon-surface-diff.d.ts +48 -0
- package/dist/cli/commands/lexicon-surface-diff.d.ts.map +1 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/pinned-upgrade.d.ts +41 -0
- package/dist/cli/commands/pinned-upgrade.d.ts.map +1 -0
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/components.d.ts +39 -0
- package/dist/cli/handlers/components.d.ts.map +1 -0
- package/dist/cli/handlers/dev.d.ts +3 -0
- package/dist/cli/handlers/dev.d.ts.map +1 -1
- package/dist/cli/handlers/graph.d.ts +4 -2
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts +49 -0
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +35 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/fetch.d.ts +22 -0
- package/dist/codegen/fetch.d.ts.map +1 -1
- package/dist/codegen/lexicon-regen.d.ts +110 -0
- package/dist/codegen/lexicon-regen.d.ts.map +1 -0
- package/dist/codegen/pinned-upgrade.d.ts +153 -0
- package/dist/codegen/pinned-upgrade.d.ts.map +1 -0
- package/dist/codegen/rolling-upgrade.d.ts +138 -0
- package/dist/codegen/rolling-upgrade.d.ts.map +1 -0
- package/dist/codegen/surface-snapshot.d.ts +173 -0
- package/dist/codegen/surface-snapshot.d.ts.map +1 -0
- package/dist/codegen/version-bump.d.ts +21 -0
- package/dist/codegen/version-bump.d.ts.map +1 -0
- package/dist/components/auto-release.d.ts +93 -0
- package/dist/components/auto-release.d.ts.map +1 -0
- package/dist/components/builders.d.ts +37 -0
- package/dist/components/builders.d.ts.map +1 -0
- package/dist/components/capability-plugin-loader.d.ts +111 -0
- package/dist/components/capability-plugin-loader.d.ts.map +1 -0
- package/dist/components/capability-plugin-schema.d.ts +24 -0
- package/dist/components/capability-plugin-schema.d.ts.map +1 -0
- package/dist/components/capability-plugin.d.ts +85 -0
- package/dist/components/capability-plugin.d.ts.map +1 -0
- package/dist/components/capability.d.ts +89 -0
- package/dist/components/capability.d.ts.map +1 -0
- package/dist/components/cli-support.d.ts +204 -0
- package/dist/components/cli-support.d.ts.map +1 -0
- package/dist/components/component.d.ts +179 -0
- package/dist/components/component.d.ts.map +1 -0
- package/dist/components/config-defaults.d.ts +41 -0
- package/dist/components/config-defaults.d.ts.map +1 -0
- package/dist/components/discover.d.ts +60 -0
- package/dist/components/discover.d.ts.map +1 -0
- package/dist/components/driver-output.d.ts +20 -0
- package/dist/components/driver-output.d.ts.map +1 -0
- package/dist/components/driver.d.ts +209 -0
- package/dist/components/driver.d.ts.map +1 -0
- package/dist/components/index.d.ts +22 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/manifest-persistence.d.ts +79 -0
- package/dist/components/manifest-persistence.d.ts.map +1 -0
- package/dist/components/pilots/alb-ecs.pilot.d.ts +27 -0
- package/dist/components/pilots/alb-ecs.pilot.d.ts.map +1 -0
- package/dist/components/pilots/dynamodb.pilot.d.ts +22 -0
- package/dist/components/pilots/dynamodb.pilot.d.ts.map +1 -0
- package/dist/components/pilots/jar-emr.pilot.d.ts +37 -0
- package/dist/components/pilots/jar-emr.pilot.d.ts.map +1 -0
- package/dist/components/pilots/lambda.pilot.d.ts +35 -0
- package/dist/components/pilots/lambda.pilot.d.ts.map +1 -0
- package/dist/components/pilots/neo4j-fanout.pilot.d.ts +17 -0
- package/dist/components/pilots/neo4j-fanout.pilot.d.ts.map +1 -0
- package/dist/components/pilots/project.d.ts +13 -0
- package/dist/components/pilots/project.d.ts.map +1 -0
- package/dist/components/presets/ecs-fargate.d.ts +59 -0
- package/dist/components/presets/ecs-fargate.d.ts.map +1 -0
- package/dist/components/presets/index.d.ts +29 -0
- package/dist/components/presets/index.d.ts.map +1 -0
- package/dist/components/presets/lambda.d.ts +35 -0
- package/dist/components/presets/lambda.d.ts.map +1 -0
- package/dist/components/presets/single-host-compose.d.ts +43 -0
- package/dist/components/presets/single-host-compose.d.ts.map +1 -0
- package/dist/components/registry.d.ts +29 -0
- package/dist/components/registry.d.ts.map +1 -0
- package/dist/components/starter-plugin.d.ts +51 -0
- package/dist/components/starter-plugin.d.ts.map +1 -0
- package/dist/components/temporal-codegen-loader.d.ts +27 -0
- package/dist/components/temporal-codegen-loader.d.ts.map +1 -0
- package/dist/components/verbs/__tests__/mock-cloud-executor.d.ts +35 -0
- package/dist/components/verbs/__tests__/mock-cloud-executor.d.ts.map +1 -0
- package/dist/components/verbs/__tests__/mock-process-runner.d.ts +45 -0
- package/dist/components/verbs/__tests__/mock-process-runner.d.ts.map +1 -0
- package/dist/components/verbs/__tests__/mock-sbom-generator.d.ts +33 -0
- package/dist/components/verbs/__tests__/mock-sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/bom-writer.d.ts +155 -0
- package/dist/components/verbs/bom-writer.d.ts.map +1 -0
- package/dist/components/verbs/build-archive.d.ts +205 -0
- package/dist/components/verbs/build-archive.d.ts.map +1 -0
- package/dist/components/verbs/build.d.ts +150 -0
- package/dist/components/verbs/build.d.ts.map +1 -0
- package/dist/components/verbs/cloud-executor.d.ts +88 -0
- package/dist/components/verbs/cloud-executor.d.ts.map +1 -0
- package/dist/components/verbs/component-bom.d.ts +103 -0
- package/dist/components/verbs/component-bom.d.ts.map +1 -0
- package/dist/components/verbs/index.d.ts +49 -0
- package/dist/components/verbs/index.d.ts.map +1 -0
- package/dist/components/verbs/license-policy.d.ts +56 -0
- package/dist/components/verbs/license-policy.d.ts.map +1 -0
- package/dist/components/verbs/lockfile-sbom-generator.d.ts +81 -0
- package/dist/components/verbs/lockfile-sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/process-runner.d.ts +64 -0
- package/dist/components/verbs/process-runner.d.ts.map +1 -0
- package/dist/components/verbs/reproducibility.d.ts +80 -0
- package/dist/components/verbs/reproducibility.d.ts.map +1 -0
- package/dist/components/verbs/sbom-generator.d.ts +157 -0
- package/dist/components/verbs/sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/sbom.d.ts +79 -0
- package/dist/components/verbs/sbom.d.ts.map +1 -0
- package/dist/components/verbs/shell.d.ts +35 -0
- package/dist/components/verbs/shell.d.ts.map +1 -0
- package/dist/components/verbs/sign.d.ts +222 -0
- package/dist/components/verbs/sign.d.ts.map +1 -0
- package/dist/components/verbs/stub.d.ts +18 -0
- package/dist/components/verbs/stub.d.ts.map +1 -0
- package/dist/components/verbs/tool-sbom-generator.d.ts +51 -0
- package/dist/components/verbs/tool-sbom-generator.d.ts.map +1 -0
- package/dist/components/verbs/verify.d.ts +106 -0
- package/dist/components/verbs/verify.d.ts.map +1 -0
- package/dist/components/verbs/vex.d.ts +65 -0
- package/dist/components/verbs/vex.d.ts.map +1 -0
- package/dist/components/verbs/vuln-gate.d.ts +91 -0
- package/dist/components/verbs/vuln-gate.d.ts.map +1 -0
- package/dist/components/verbs/vuln-scan.d.ts +116 -0
- package/dist/components/verbs/vuln-scan.d.ts.map +1 -0
- package/dist/components/verbs/wait-verify.d.ts +85 -0
- package/dist/components/verbs/wait-verify.d.ts.map +1 -0
- package/dist/config.d.ts +205 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/lexicon.d.ts +78 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/build-ledger-store.d.ts +121 -0
- package/dist/lifecycle/build-ledger-store.d.ts.map +1 -0
- package/dist/lifecycle/build-ledger.d.ts +225 -0
- package/dist/lifecycle/build-ledger.d.ts.map +1 -0
- package/dist/lifecycle/git.d.ts +84 -0
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/index.d.ts +5 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/oras-referrer-lookup.d.ts +41 -0
- package/dist/lifecycle/oras-referrer-lookup.d.ts.map +1 -0
- package/dist/lifecycle/release-ledger.d.ts +122 -0
- package/dist/lifecycle/release-ledger.d.ts.map +1 -0
- package/dist/lifecycle/status.d.ts +150 -0
- package/dist/lifecycle/status.d.ts.map +1 -0
- package/dist/lint/component-checks.d.ts +95 -0
- package/dist/lint/component-checks.d.ts.map +1 -0
- package/dist/lint/engine.d.ts +23 -0
- package/dist/lint/engine.d.ts.map +1 -1
- package/dist/lint/presets/strict.json +8 -1
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.d.ts +10 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.d.ts +3 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.d.ts +3 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp001-publishes-never-applies.d.ts +20 -0
- package/dist/lint/rules/comp/comp001-publishes-never-applies.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp002-dangling-wiring-ref.d.ts +28 -0
- package/dist/lint/rules/comp/comp002-dangling-wiring-ref.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp003-mutating-no-rollback.d.ts +39 -0
- package/dist/lint/rules/comp/comp003-mutating-no-rollback.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts +37 -0
- package/dist/lint/rules/comp/comp004-gate-needs-temporal.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp005-capability-kind-is-noun.d.ts +43 -0
- package/dist/lint/rules/comp/comp005-capability-kind-is-noun.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp006-shell-needs-reason.d.ts +22 -0
- package/dist/lint/rules/comp/comp006-shell-needs-reason.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp007-composition-sprawl.d.ts +33 -0
- package/dist/lint/rules/comp/comp007-composition-sprawl.d.ts.map +1 -0
- package/dist/lint/rules/comp/index.d.ts +18 -0
- package/dist/lint/rules/comp/index.d.ts.map +1 -0
- package/dist/lint/rules/comp/support.d.ts +71 -0
- package/dist/lint/rules/comp/support.d.ts.map +1 -0
- package/dist/lsp/lexicon-providers.d.ts.map +1 -1
- package/dist/op/activity-registry.d.ts +11 -6
- package/dist/op/activity-registry.d.ts.map +1 -1
- package/dist/op/activity-runtime.d.ts +24 -0
- package/dist/op/activity-runtime.d.ts.map +1 -0
- package/dist/op/builders.d.ts +56 -0
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/index.d.ts +2 -1
- package/dist/op/index.d.ts.map +1 -1
- package/dist/ownership.d.ts +20 -14
- package/dist/ownership.d.ts.map +1 -1
- package/package.json +14 -1
- package/src/audit/catalog.test.ts +74 -22
- package/src/audit/catalog.ts +74 -471
- package/src/audit/fetch.test.ts +112 -8
- package/src/audit/fetch.ts +53 -8
- package/src/audit/proof.ts +4 -2
- package/src/audit/report-html.test.ts +14 -7
- package/src/audit/report-model.ts +20 -9
- package/src/audit/report.test.ts +36 -13
- package/src/audit/report.ts +2 -0
- package/src/audit/rules-doc.test.ts +8 -6
- package/src/audit/rules-doc.ts +13 -5
- package/src/cli/commands/audit.ts +23 -18
- package/src/cli/commands/component-lint.test.ts +158 -0
- package/src/cli/commands/doctor.test.ts +116 -2
- package/src/cli/commands/doctor.ts +46 -0
- package/src/cli/commands/lexicon-rolling-upgrade.ts +198 -0
- package/src/cli/commands/lexicon-surface-diff.test.ts +104 -0
- package/src/cli/commands/lexicon-surface-diff.ts +185 -0
- package/src/cli/commands/lint.ts +142 -1
- package/src/cli/commands/pinned-upgrade.ts +204 -0
- package/src/cli/handlers/build.ts +58 -1
- package/src/cli/handlers/components.test.ts +504 -0
- package/src/cli/handlers/components.ts +404 -0
- package/src/cli/handlers/dev.ts +60 -1
- package/src/cli/handlers/graph.ts +47 -2
- package/src/cli/handlers/misc.ts +45 -1
- package/src/cli/handlers/run.test.ts +967 -3
- package/src/cli/handlers/run.ts +618 -11
- package/src/cli/main.test.ts +66 -0
- package/src/cli/main.ts +105 -2
- package/src/cli/registry.ts +35 -0
- package/src/codegen/fetch.test.ts +84 -3
- package/src/codegen/fetch.ts +76 -2
- package/src/codegen/lexicon-regen.test.ts +298 -0
- package/src/codegen/lexicon-regen.ts +545 -0
- package/src/codegen/pinned-upgrade.test.ts +399 -0
- package/src/codegen/pinned-upgrade.ts +423 -0
- package/src/codegen/rolling-upgrade.test.ts +333 -0
- package/src/codegen/rolling-upgrade.ts +320 -0
- package/src/codegen/surface-snapshot.test.ts +461 -0
- package/src/codegen/surface-snapshot.ts +546 -0
- package/src/codegen/version-bump.test.ts +47 -0
- package/src/codegen/version-bump.ts +39 -0
- package/src/components/README.md +130 -0
- package/src/components/SPRAWL-VALIDATION.md +181 -0
- package/src/components/__fixtures__/alb-ecs-service.json +51 -0
- package/src/components/__fixtures__/dynamodb-infra.json +32 -0
- package/src/components/__fixtures__/emr-job-consumer.json +26 -0
- package/src/components/__fixtures__/jar-lib-producer.json +16 -0
- package/src/components/__fixtures__/lambda-image-processor.json +28 -0
- package/src/components/__fixtures__/neo4j-fanout.json +34 -0
- package/src/components/__fixtures__/single-host-compose.json +29 -0
- package/src/components/auto-release.test.ts +217 -0
- package/src/components/auto-release.ts +216 -0
- package/src/components/builders.test.ts +45 -0
- package/src/components/builders.ts +71 -0
- package/src/components/capability-plugin-loader.ts +218 -0
- package/src/components/capability-plugin-schema.ts +56 -0
- package/src/components/capability-plugin.test.ts +235 -0
- package/src/components/capability-plugin.ts +108 -0
- package/src/components/capability.ts +117 -0
- package/src/components/cli-support.test.ts +579 -0
- package/src/components/cli-support.ts +481 -0
- package/src/components/component-schema.test.ts +265 -0
- package/src/components/component.schema.json +235 -0
- package/src/components/component.test.ts +251 -0
- package/src/components/component.ts +255 -0
- package/src/components/config-defaults.test.ts +263 -0
- package/src/components/config-defaults.ts +145 -0
- package/src/components/discover.test.ts +352 -0
- package/src/components/discover.ts +167 -0
- package/src/components/driver-output.ts +71 -0
- package/src/components/driver.test.ts +638 -0
- package/src/components/driver.ts +690 -0
- package/src/components/index.ts +113 -0
- package/src/components/manifest-persistence.test.ts +152 -0
- package/src/components/manifest-persistence.ts +164 -0
- package/src/components/pilots/README.md +33 -0
- package/src/components/pilots/alb-ecs.pilot.ts +63 -0
- package/src/components/pilots/dynamodb.pilot.ts +59 -0
- package/src/components/pilots/jar-emr.pilot.ts +69 -0
- package/src/components/pilots/lambda.pilot.ts +55 -0
- package/src/components/pilots/neo4j-fanout.pilot.ts +92 -0
- package/src/components/pilots/pilots-lint-clean.test.ts +78 -0
- package/src/components/pilots/pilots.test.ts +126 -0
- package/src/components/pilots/project.ts +13 -0
- package/src/components/presets/comp007-reduction.test.ts +122 -0
- package/src/components/presets/ecs-fargate.test.ts +84 -0
- package/src/components/presets/ecs-fargate.ts +103 -0
- package/src/components/presets/index.ts +32 -0
- package/src/components/presets/lambda.test.ts +35 -0
- package/src/components/presets/lambda.ts +53 -0
- package/src/components/presets/single-host-compose.test.ts +65 -0
- package/src/components/presets/single-host-compose.ts +64 -0
- package/src/components/registry.test.ts +112 -0
- package/src/components/registry.ts +37 -0
- package/src/components/starter-plugin.ts +105 -0
- package/src/components/temporal-codegen-loader.ts +41 -0
- package/src/components/verbs/__fixtures__/package-lock.json +45 -0
- package/src/components/verbs/__fixtures__/pom.xml +37 -0
- package/src/components/verbs/__fixtures__/schemas/cyclonedx-1.5.schema.json +3800 -0
- package/src/components/verbs/__fixtures__/schemas/cyclonedx-spdx-license.schema.json +621 -0
- package/src/components/verbs/__fixtures__/schemas/jsf-0.82.schema.json +240 -0
- package/src/components/verbs/__fixtures__/schemas/spdx-2.3.schema.json +740 -0
- package/src/components/verbs/__tests__/mock-cloud-executor.ts +102 -0
- package/src/components/verbs/__tests__/mock-process-runner.ts +79 -0
- package/src/components/verbs/__tests__/mock-sbom-generator.ts +85 -0
- package/src/components/verbs/bom-writer.test.ts +331 -0
- package/src/components/verbs/bom-writer.ts +386 -0
- package/src/components/verbs/build-archive.test.ts +251 -0
- package/src/components/verbs/build-archive.ts +296 -0
- package/src/components/verbs/build.test.ts +222 -0
- package/src/components/verbs/build.ts +252 -0
- package/src/components/verbs/cloud-executor.ts +181 -0
- package/src/components/verbs/component-bom.test.ts +219 -0
- package/src/components/verbs/component-bom.ts +189 -0
- package/src/components/verbs/index.ts +49 -0
- package/src/components/verbs/license-policy.ts +115 -0
- package/src/components/verbs/lockfile-sbom-generator.test.ts +195 -0
- package/src/components/verbs/lockfile-sbom-generator.ts +236 -0
- package/src/components/verbs/process-runner.test.ts +79 -0
- package/src/components/verbs/process-runner.ts +113 -0
- package/src/components/verbs/reproducibility.test.ts +24 -0
- package/src/components/verbs/reproducibility.ts +100 -0
- package/src/components/verbs/sbom-generator.test.ts +96 -0
- package/src/components/verbs/sbom-generator.ts +209 -0
- package/src/components/verbs/sbom.test.ts +184 -0
- package/src/components/verbs/sbom.ts +152 -0
- package/src/components/verbs/shell.test.ts +36 -0
- package/src/components/verbs/shell.ts +51 -0
- package/src/components/verbs/sign.test.ts +210 -0
- package/src/components/verbs/sign.ts +350 -0
- package/src/components/verbs/stub.ts +34 -0
- package/src/components/verbs/tool-sbom-generator.test.ts +194 -0
- package/src/components/verbs/tool-sbom-generator.ts +192 -0
- package/src/components/verbs/verify.test.ts +159 -0
- package/src/components/verbs/verify.ts +179 -0
- package/src/components/verbs/vex.ts +182 -0
- package/src/components/verbs/vuln-gate.test.ts +201 -0
- package/src/components/verbs/vuln-gate.ts +170 -0
- package/src/components/verbs/vuln-scan.test.ts +145 -0
- package/src/components/verbs/vuln-scan.ts +266 -0
- package/src/components/verbs/wait-verify.test.ts +111 -0
- package/src/components/verbs/wait-verify.ts +171 -0
- package/src/config.test.ts +74 -1
- package/src/config.ts +219 -0
- package/src/index.ts +32 -0
- package/src/lexicon.ts +88 -0
- package/src/lifecycle/build-ledger-store.test.ts +217 -0
- package/src/lifecycle/build-ledger-store.ts +165 -0
- package/src/lifecycle/build-ledger.test.ts +349 -0
- package/src/lifecycle/build-ledger.ts +305 -0
- package/src/lifecycle/git.test.ts +118 -0
- package/src/lifecycle/git.ts +149 -14
- package/src/lifecycle/index.ts +5 -0
- package/src/lifecycle/oras-referrer-lookup.test.ts +116 -0
- package/src/lifecycle/oras-referrer-lookup.ts +110 -0
- package/src/lifecycle/release-ledger.test.ts +209 -0
- package/src/lifecycle/release-ledger.ts +185 -0
- package/src/lifecycle/status.test.ts +330 -0
- package/src/lifecycle/status.ts +278 -0
- package/src/lint/component-checks.ts +148 -0
- package/src/lint/config.test.ts +21 -0
- package/src/lint/engine.ts +11 -2
- package/src/lint/presets/relaxed.json +8 -1
- package/src/lint/presets/strict.json +8 -1
- package/src/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-a.component.ts +9 -0
- package/src/lint/rules/__fixtures__/comp/comp000-discovery-error/broken-b.component.ts +9 -0
- package/src/lint/rules/__fixtures__/comp/comp001/fail/orphan-lib.component.ts +11 -0
- package/src/lint/rules/__fixtures__/comp/comp001/pass/emr-job.component.ts +13 -0
- package/src/lint/rules/__fixtures__/comp/comp001/pass/jar-lib.component.ts +11 -0
- package/src/lint/rules/__fixtures__/comp/comp002/fail/search-service.component.ts +27 -0
- package/src/lint/rules/__fixtures__/comp/comp002/pass/jar-lib.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp002/pass/search-service.component.ts +23 -0
- package/src/lint/rules/__fixtures__/comp/comp003/fail/migrator.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp003/pass/migrator.component.ts +19 -0
- package/src/lint/rules/__fixtures__/comp/comp003/pass/orders-table.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp004/fail/neo4j-cluster.component.ts +20 -0
- package/src/lint/rules/__fixtures__/comp/comp004/pass/neo4j-cluster.component.ts +23 -0
- package/src/lint/rules/__fixtures__/comp/comp004/pass/orders-table.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp005/fail/search-service.component.ts +14 -0
- package/src/lint/rules/__fixtures__/comp/comp005/pass/search-service.component.ts +18 -0
- package/src/lint/rules/__fixtures__/comp/comp006/fail/legacy-tool.component.ts +10 -0
- package/src/lint/rules/__fixtures__/comp/comp006/pass/legacy-tool.component.ts +14 -0
- package/src/lint/rules/__fixtures__/comp/comp007/fail/inventory-table.component.ts +13 -0
- package/src/lint/rules/__fixtures__/comp/comp007/fail/orders-table.component.ts +13 -0
- package/src/lint/rules/__fixtures__/comp/comp007/pass/orders-table.component.ts +12 -0
- package/src/lint/rules/__fixtures__/comp/comp007/pass/search-service.component.ts +18 -0
- package/src/lint/rules/comp/comp.test.ts +378 -0
- package/src/lint/rules/comp/comp001-publishes-never-applies.ts +78 -0
- package/src/lint/rules/comp/comp002-dangling-wiring-ref.ts +94 -0
- package/src/lint/rules/comp/comp003-mutating-no-rollback.ts +115 -0
- package/src/lint/rules/comp/comp004-gate-needs-temporal.ts +66 -0
- package/src/lint/rules/comp/comp005-capability-kind-is-noun.ts +113 -0
- package/src/lint/rules/comp/comp006-shell-needs-reason.ts +55 -0
- package/src/lint/rules/comp/comp007-composition-sprawl.ts +71 -0
- package/src/lint/rules/comp/index.ts +37 -0
- package/src/lint/rules/comp/support.ts +173 -0
- package/src/lsp/lexicon-providers.test.ts +55 -0
- package/src/lsp/lexicon-providers.ts +13 -3
- package/src/op/activity-registry.test.ts +38 -0
- package/src/op/activity-registry.ts +31 -12
- package/src/op/activity-runtime.ts +73 -0
- package/src/op/builders.ts +92 -0
- package/src/op/index.ts +3 -1
- package/src/ownership.test.ts +24 -26
- package/src/ownership.ts +26 -38
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { existsSync, statSync, writeFileSync } from "fs";
|
|
9
9
|
import { auditFiles, type AuditInput, type AuditFinding, type ChecksProvider } from "../../audit/core";
|
|
10
10
|
import { discoverByDetection, classifyFiles, loadAuditPlugins, AUDIT_LEXICONS } from "../../audit/discover";
|
|
11
|
-
import { RULE_CATALOG } from "../../audit/catalog";
|
|
11
|
+
import { RULE_CATALOG, resolveAuditCatalog, type RuleMeta } from "../../audit/catalog";
|
|
12
12
|
import { renderMarkdown } from "../../audit/report";
|
|
13
13
|
import { renderHtml, type ReportTheme } from "../../audit/report-html";
|
|
14
14
|
import { buildReportJson, type AuditSnapshot } from "../../audit/report-model";
|
|
@@ -88,12 +88,12 @@ function githubToken(env: NodeJS.ProcessEnv = process.env): string | undefined {
|
|
|
88
88
|
return env.GITHUB_TOKEN ?? env.CHANT_AUDIT_GITHUB_TOKEN;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
function isMergeWorthy(f: AuditFinding): boolean {
|
|
92
|
-
return
|
|
91
|
+
function isMergeWorthy(f: AuditFinding, catalog: Record<string, RuleMeta> = RULE_CATALOG): boolean {
|
|
92
|
+
return catalog[f.checkId]?.tier === "merge-worthy";
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
function exitCodeFor(findings: AuditFinding[], failOn: AuditFailOn): number {
|
|
96
|
-
if (failOn === "merge-worthy") return findings.some(isMergeWorthy) ? 1 : 0;
|
|
95
|
+
function exitCodeFor(findings: AuditFinding[], failOn: AuditFailOn, catalog: Record<string, RuleMeta> = RULE_CATALOG): number {
|
|
96
|
+
if (failOn === "merge-worthy") return findings.some((f) => isMergeWorthy(f, catalog)) ? 1 : 0;
|
|
97
97
|
if (failOn === "warning") {
|
|
98
98
|
return findings.some((f) => f.severity === "error" || f.severity === "warning") ? 1 : 0;
|
|
99
99
|
}
|
|
@@ -116,12 +116,12 @@ export function coverageNotes(inputs: AuditInput[]): string[] {
|
|
|
116
116
|
return notes;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
function renderStylish(findings: AuditFinding[], scanned: string[], notes: string[]): string {
|
|
119
|
+
function renderStylish(findings: AuditFinding[], scanned: string[], notes: string[], catalog: Record<string, RuleMeta> = RULE_CATALOG): string {
|
|
120
120
|
const lines: string[] = [];
|
|
121
121
|
for (const note of notes) lines.push(`Note: ${note}`);
|
|
122
122
|
if (notes.length > 0) lines.push("");
|
|
123
|
-
const mw = findings.filter(isMergeWorthy);
|
|
124
|
-
const ro = findings.filter((f) => !isMergeWorthy(f));
|
|
123
|
+
const mw = findings.filter((f) => isMergeWorthy(f, catalog));
|
|
124
|
+
const ro = findings.filter((f) => !isMergeWorthy(f, catalog));
|
|
125
125
|
lines.push(
|
|
126
126
|
`Audited ${scanned.length} file${scanned.length === 1 ? "" : "s"} — ` +
|
|
127
127
|
`${findings.length} finding${findings.length === 1 ? "" : "s"} ` +
|
|
@@ -132,7 +132,7 @@ function renderStylish(findings: AuditFinding[], scanned: string[], notes: strin
|
|
|
132
132
|
lines.push("", title);
|
|
133
133
|
for (const f of list) {
|
|
134
134
|
const where = f.entity ? `${f.file} (${f.entity})` : f.file;
|
|
135
|
-
const title =
|
|
135
|
+
const title = catalog[f.checkId]?.title ?? f.checkId;
|
|
136
136
|
lines.push(` [${f.checkId}] ${f.severity} ${where} — ${title}`);
|
|
137
137
|
}
|
|
138
138
|
};
|
|
@@ -141,10 +141,10 @@ function renderStylish(findings: AuditFinding[], scanned: string[], notes: strin
|
|
|
141
141
|
return lines.join("\n");
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
function renderSarif(findings: AuditFinding[]): string {
|
|
144
|
+
function renderSarif(findings: AuditFinding[], catalog: Record<string, RuleMeta> = RULE_CATALOG): string {
|
|
145
145
|
const ruleIds = [...new Set(findings.map((f) => f.checkId))].sort();
|
|
146
146
|
const rules = ruleIds.map((id) => {
|
|
147
|
-
const m =
|
|
147
|
+
const m = catalog[id];
|
|
148
148
|
return {
|
|
149
149
|
id,
|
|
150
150
|
name: m?.title ?? id,
|
|
@@ -255,7 +255,12 @@ export async function auditCommand(options: AuditCommandOptions): Promise<AuditC
|
|
|
255
255
|
const msg = err instanceof Error ? err.message : String(err);
|
|
256
256
|
return { success: false, output: "", findings: [], scanned, exitCode: 1, error: msg };
|
|
257
257
|
}
|
|
258
|
-
|
|
258
|
+
// Resolve the audit catalog once, aggregating the audited lexicons' own
|
|
259
|
+
// metadata over core's static catalog (#687). The lexicons are already loaded
|
|
260
|
+
// by `auditFiles` above, so this is cheap.
|
|
261
|
+
const catalog = await resolveAuditCatalog([...new Set(inputs.map((i) => i.lexicon))]);
|
|
262
|
+
|
|
263
|
+
if (tier === "merge-worthy") findings = findings.filter((f) => isMergeWorthy(f, catalog));
|
|
259
264
|
const notes = coverageNotes(inputs);
|
|
260
265
|
|
|
261
266
|
// Diff-bearing renderers (markdown, html) need action SHAs / image digests
|
|
@@ -299,25 +304,25 @@ export async function auditCommand(options: AuditCommandOptions): Promise<AuditC
|
|
|
299
304
|
switch (format) {
|
|
300
305
|
case "json": {
|
|
301
306
|
const snapshot = await buildSnapshot(options, scanned, isUrl);
|
|
302
|
-
output = JSON.stringify(buildReportJson(findings, { snapshot, toolVersion: options.toolVersion }), null, 2);
|
|
307
|
+
output = JSON.stringify(buildReportJson(findings, { snapshot, toolVersion: options.toolVersion, catalog }), null, 2);
|
|
303
308
|
break;
|
|
304
309
|
}
|
|
305
310
|
case "sarif":
|
|
306
|
-
output = renderSarif(findings);
|
|
311
|
+
output = renderSarif(findings, catalog);
|
|
307
312
|
break;
|
|
308
313
|
case "markdown":
|
|
309
|
-
output = renderMarkdown(findings, { target: options.path, files, resolveSha, resolveDigest, notes });
|
|
314
|
+
output = renderMarkdown(findings, { target: options.path, files, resolveSha, resolveDigest, notes, catalog });
|
|
310
315
|
break;
|
|
311
316
|
case "html": {
|
|
312
317
|
const snapshot = await buildSnapshot(options, scanned, isUrl);
|
|
313
|
-
output = renderHtml(findings, { files, resolveSha, resolveDigest, notes, snapshot, theme: options.theme, template: options.template });
|
|
318
|
+
output = renderHtml(findings, { files, resolveSha, resolveDigest, notes, snapshot, theme: options.theme, template: options.template, catalog });
|
|
314
319
|
break;
|
|
315
320
|
}
|
|
316
321
|
default:
|
|
317
|
-
output = renderStylish(findings, scanned, notes);
|
|
322
|
+
output = renderStylish(findings, scanned, notes, catalog);
|
|
318
323
|
}
|
|
319
324
|
|
|
320
|
-
const exitCode = exitCodeFor(findings, failOn);
|
|
325
|
+
const exitCode = exitCodeFor(findings, failOn, catalog);
|
|
321
326
|
if (options.output) {
|
|
322
327
|
try {
|
|
323
328
|
writeFileSync(options.output, output);
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant lint` end-to-end integration for the COMP* composition checks
|
|
3
|
+
* (#562, epic #551) — confirms `lintCommand` itself (not just
|
|
4
|
+
* `runComponentChecks` in isolation, see
|
|
5
|
+
* ../../lint/rules/comp/comp.test.ts) merges COMP* diagnostics into its
|
|
6
|
+
* output, gates the build at error severity the same way COR/EVL rules do,
|
|
7
|
+
* honors config severity overrides (including "off"), and honors the
|
|
8
|
+
* file-level `chant-disable` directive form.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
|
12
|
+
import { lintCommand, type LintOptions } from "./lint";
|
|
13
|
+
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { tmpdir } from "node:os";
|
|
16
|
+
|
|
17
|
+
const COMPONENT_MODULE_SPECIFIER = JSON.stringify(
|
|
18
|
+
new URL("../../components/component.ts", import.meta.url).pathname,
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
function componentSource(body: string): string {
|
|
22
|
+
return `import type { Component } from ${COMPONENT_MODULE_SPECIFIER};\nimport { phase } from ${COMPONENT_MODULE_SPECIFIER};\n\n${body}\n`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe("chant lint: COMP* composition checks (#562)", () => {
|
|
26
|
+
let testDir: string;
|
|
27
|
+
|
|
28
|
+
beforeEach(async () => {
|
|
29
|
+
testDir = join(tmpdir(), `chant-comp-lint-test-${Date.now()}-${Math.random()}`);
|
|
30
|
+
await mkdir(testDir, { recursive: true });
|
|
31
|
+
process.env.NO_COLOR = "1";
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
afterEach(async () => {
|
|
35
|
+
await rm(testDir, { recursive: true, force: true });
|
|
36
|
+
delete process.env.NO_COLOR;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("a clean component (no *.component.ts issues) lints with no COMP diagnostics", async () => {
|
|
40
|
+
await writeFile(
|
|
41
|
+
join(testDir, "orders-table.component.ts"),
|
|
42
|
+
componentSource(
|
|
43
|
+
`export const ordersTable: Component = {\n` +
|
|
44
|
+
` name: "orders-table",\n` +
|
|
45
|
+
` archetype: "infra",\n` +
|
|
46
|
+
` dependsOn: [],\n` +
|
|
47
|
+
` deploy: [phase("Apply", [{ kind: "cfn-deploy", template: "archive:orders-table.template.json" }])],\n` +
|
|
48
|
+
`};\n`,
|
|
49
|
+
),
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const result = await lintCommand({ path: testDir, format: "stylish" } satisfies LintOptions);
|
|
53
|
+
expect(result.diagnostics.filter((d) => d.ruleId.startsWith("COMP"))).toHaveLength(0);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("a raw shell step with no reason fails the lint at error severity (COMP006), gating the build like a COR* error", async () => {
|
|
57
|
+
await writeFile(
|
|
58
|
+
join(testDir, "legacy.component.ts"),
|
|
59
|
+
componentSource(
|
|
60
|
+
`export const legacyTool: Component = {\n` +
|
|
61
|
+
` name: "legacy-tool",\n` +
|
|
62
|
+
` archetype: "infra",\n` +
|
|
63
|
+
` dependsOn: [],\n` +
|
|
64
|
+
` deploy: [phase("Apply", [{ kind: "shell", cmd: "./deploy.sh" }])],\n` +
|
|
65
|
+
`};\n`,
|
|
66
|
+
),
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const result = await lintCommand({ path: testDir, format: "stylish" } satisfies LintOptions);
|
|
70
|
+
expect(result.success).toBe(false);
|
|
71
|
+
const hit = result.diagnostics.find((d) => d.ruleId === "COMP006");
|
|
72
|
+
expect(hit).toBeDefined();
|
|
73
|
+
expect(hit!.severity).toBe("error");
|
|
74
|
+
expect(result.errorCount).toBeGreaterThan(0);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("a chant-disable COMP006 file-level directive suppresses the diagnostic", async () => {
|
|
78
|
+
await writeFile(
|
|
79
|
+
join(testDir, "legacy.component.ts"),
|
|
80
|
+
`// chant-disable COMP006 -- vendor CLI, tracked in TICKET-123\n` +
|
|
81
|
+
componentSource(
|
|
82
|
+
`export const legacyTool: Component = {\n` +
|
|
83
|
+
` name: "legacy-tool",\n` +
|
|
84
|
+
` archetype: "infra",\n` +
|
|
85
|
+
` dependsOn: [],\n` +
|
|
86
|
+
` deploy: [phase("Apply", [{ kind: "shell", cmd: "./deploy.sh" }])],\n` +
|
|
87
|
+
`};\n`,
|
|
88
|
+
),
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const result = await lintCommand({ path: testDir, format: "stylish" } satisfies LintOptions);
|
|
92
|
+
expect(result.diagnostics.some((d) => d.ruleId === "COMP006")).toBe(false);
|
|
93
|
+
expect(result.success).toBe(true);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("a bare chant-disable (no rule ids) suppresses every COMP diagnostic for that file", async () => {
|
|
97
|
+
await writeFile(
|
|
98
|
+
join(testDir, "legacy.component.ts"),
|
|
99
|
+
`// chant-disable\n` +
|
|
100
|
+
componentSource(
|
|
101
|
+
`export const legacyTool: Component = {\n` +
|
|
102
|
+
` name: "legacy-tool",\n` +
|
|
103
|
+
` archetype: "infra",\n` +
|
|
104
|
+
` dependsOn: [],\n` +
|
|
105
|
+
` deploy: [phase("Apply", [{ kind: "shell", cmd: "./deploy.sh" }])],\n` +
|
|
106
|
+
`};\n`,
|
|
107
|
+
),
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const result = await lintCommand({ path: testDir, format: "stylish" } satisfies LintOptions);
|
|
111
|
+
expect(result.diagnostics.filter((d) => d.ruleId.startsWith("COMP"))).toHaveLength(0);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("chant.config.ts can turn a COMP rule off entirely", async () => {
|
|
115
|
+
await writeFile(
|
|
116
|
+
join(testDir, "legacy.component.ts"),
|
|
117
|
+
componentSource(
|
|
118
|
+
`export const legacyTool: Component = {\n` +
|
|
119
|
+
` name: "legacy-tool",\n` +
|
|
120
|
+
` archetype: "infra",\n` +
|
|
121
|
+
` dependsOn: [],\n` +
|
|
122
|
+
` deploy: [phase("Apply", [{ kind: "shell", cmd: "./deploy.sh" }])],\n` +
|
|
123
|
+
`};\n`,
|
|
124
|
+
),
|
|
125
|
+
);
|
|
126
|
+
await writeFile(
|
|
127
|
+
join(testDir, "chant.config.json"),
|
|
128
|
+
JSON.stringify({ rules: { COMP006: "off" } }),
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
const result = await lintCommand({ path: testDir, format: "stylish" } satisfies LintOptions);
|
|
132
|
+
expect(result.diagnostics.some((d) => d.ruleId === "COMP006")).toBe(false);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test("chant.config.ts can downgrade a COMP rule to warning, so it no longer fails the build", async () => {
|
|
136
|
+
await writeFile(
|
|
137
|
+
join(testDir, "legacy.component.ts"),
|
|
138
|
+
componentSource(
|
|
139
|
+
`export const legacyTool: Component = {\n` +
|
|
140
|
+
` name: "legacy-tool",\n` +
|
|
141
|
+
` archetype: "infra",\n` +
|
|
142
|
+
` dependsOn: [],\n` +
|
|
143
|
+
` deploy: [phase("Apply", [{ kind: "shell", cmd: "./deploy.sh" }])],\n` +
|
|
144
|
+
`};\n`,
|
|
145
|
+
),
|
|
146
|
+
);
|
|
147
|
+
await writeFile(
|
|
148
|
+
join(testDir, "chant.config.json"),
|
|
149
|
+
JSON.stringify({ rules: { COMP006: "warning" } }),
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
const result = await lintCommand({ path: testDir, format: "stylish" } satisfies LintOptions);
|
|
153
|
+
const hit = result.diagnostics.find((d) => d.ruleId === "COMP006");
|
|
154
|
+
expect(hit).toBeDefined();
|
|
155
|
+
expect(hit!.severity).toBe("warning");
|
|
156
|
+
expect(result.success).toBe(true);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
@@ -1,8 +1,33 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
2
|
import { doctorCommand } from "./doctor";
|
|
3
3
|
import { withTestDir } from "@intentius/chant-test-utils";
|
|
4
|
-
import { writeFileSync, mkdirSync } from "fs";
|
|
5
|
-
import { join } from "path";
|
|
4
|
+
import { writeFileSync, mkdirSync, rmSync, existsSync } from "fs";
|
|
5
|
+
import { join, dirname } from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Root `node_modules/` — where a bare `@intentius/chant-capability-<name>`
|
|
10
|
+
* specifier actually resolves from from within this package (dynamic
|
|
11
|
+
* `import()` in ../../components/capability-plugin-loader.ts resolves
|
|
12
|
+
* relative to the importing module, not to whatever `testDir` a doctor test
|
|
13
|
+
* points `doctorCommand` at). Used below to install a throwaway, genuinely
|
|
14
|
+
* malformed capability package for the duration of one test, then remove it.
|
|
15
|
+
*/
|
|
16
|
+
const repoNodeModules = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "..", "..", "node_modules");
|
|
17
|
+
|
|
18
|
+
/** Write a minimal CJS/ESM-agnostic package under `@intentius/chant-capability-<name>` in the real node_modules, for exercising the doctor's capability-plugin check end to end. Caller must remove it (see `finally` blocks below). */
|
|
19
|
+
function installFakeCapabilityPackage(name: string, indexSource: string): string {
|
|
20
|
+
const pkgDir = join(repoNodeModules, "@intentius", `chant-capability-${name}`);
|
|
21
|
+
mkdirSync(pkgDir, { recursive: true });
|
|
22
|
+
writeFileSync(join(pkgDir, "package.json"), JSON.stringify({ name: `@intentius/chant-capability-${name}`, version: "1.0.0", type: "module", main: "index.js" }));
|
|
23
|
+
writeFileSync(join(pkgDir, "index.js"), indexSource);
|
|
24
|
+
return pkgDir;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function removeFakeCapabilityPackage(name: string): void {
|
|
28
|
+
const pkgDir = join(repoNodeModules, "@intentius", `chant-capability-${name}`);
|
|
29
|
+
if (existsSync(pkgDir)) rmSync(pkgDir, { recursive: true, force: true });
|
|
30
|
+
}
|
|
6
31
|
|
|
7
32
|
describe("doctorCommand", () => {
|
|
8
33
|
test("config-exists fails when no config file present", async () => {
|
|
@@ -236,4 +261,93 @@ describe("doctorCommand", () => {
|
|
|
236
261
|
expect(check!.status).toBe("pass");
|
|
237
262
|
});
|
|
238
263
|
});
|
|
264
|
+
|
|
265
|
+
// ── Capability plugin checks (#559, epic #551) ─────────────────────────
|
|
266
|
+
|
|
267
|
+
test("capability plugin check fails when the named package cannot be found", async () => {
|
|
268
|
+
await withTestDir(async (testDir) => {
|
|
269
|
+
writeFileSync(
|
|
270
|
+
join(testDir, "chant.config.json"),
|
|
271
|
+
JSON.stringify({ capabilities: ["nonexistent-capability-package"] }),
|
|
272
|
+
);
|
|
273
|
+
const report = await doctorCommand(testDir);
|
|
274
|
+
const check = report.checks.find((c) => c.name === "capability-nonexistent-capability-package");
|
|
275
|
+
expect(check).toBeDefined();
|
|
276
|
+
expect(check!.status).toBe("fail");
|
|
277
|
+
expect(check!.message).toContain("could not be loaded");
|
|
278
|
+
expect(report.success).toBe(false);
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
test("capability plugin check fails for a malformed package (no CapabilityPlugin export)", async () => {
|
|
283
|
+
installFakeCapabilityPackage("broken", "export const notAPlugin = { oops: true };\n");
|
|
284
|
+
try {
|
|
285
|
+
await withTestDir(async (testDir) => {
|
|
286
|
+
writeFileSync(
|
|
287
|
+
join(testDir, "chant.config.json"),
|
|
288
|
+
JSON.stringify({ capabilities: ["broken"] }),
|
|
289
|
+
);
|
|
290
|
+
const report = await doctorCommand(testDir);
|
|
291
|
+
const check = report.checks.find((c) => c.name === "capability-broken");
|
|
292
|
+
expect(check).toBeDefined();
|
|
293
|
+
expect(check!.status).toBe("fail");
|
|
294
|
+
expect(check!.message).toMatch(/could not be loaded|does not export/);
|
|
295
|
+
expect(report.success).toBe(false);
|
|
296
|
+
});
|
|
297
|
+
} finally {
|
|
298
|
+
removeFakeCapabilityPackage("broken");
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
test("capability plugin check fails when capabilities() is not a function (malformed shape)", async () => {
|
|
303
|
+
installFakeCapabilityPackage(
|
|
304
|
+
"half-broken",
|
|
305
|
+
"export const plugin = { name: 'half-broken', version: '1.0.0', capabilities: 'not-a-function' };\n",
|
|
306
|
+
);
|
|
307
|
+
try {
|
|
308
|
+
await withTestDir(async (testDir) => {
|
|
309
|
+
writeFileSync(
|
|
310
|
+
join(testDir, "chant.config.json"),
|
|
311
|
+
JSON.stringify({ capabilities: ["half-broken"] }),
|
|
312
|
+
);
|
|
313
|
+
const report = await doctorCommand(testDir);
|
|
314
|
+
const check = report.checks.find((c) => c.name === "capability-half-broken");
|
|
315
|
+
expect(check).toBeDefined();
|
|
316
|
+
expect(check!.status).toBe("fail");
|
|
317
|
+
});
|
|
318
|
+
} finally {
|
|
319
|
+
removeFakeCapabilityPackage("half-broken");
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
test("capability plugin check passes for a well-formed package", async () => {
|
|
324
|
+
installFakeCapabilityPackage(
|
|
325
|
+
"good",
|
|
326
|
+
"export const plugin = { name: 'good', version: '1.0.0', capabilities: () => [{ kind: 'demo-verb', run: async () => ({}) }] };\n",
|
|
327
|
+
);
|
|
328
|
+
try {
|
|
329
|
+
await withTestDir(async (testDir) => {
|
|
330
|
+
writeFileSync(
|
|
331
|
+
join(testDir, "chant.config.json"),
|
|
332
|
+
JSON.stringify({ capabilities: ["good"] }),
|
|
333
|
+
);
|
|
334
|
+
const report = await doctorCommand(testDir);
|
|
335
|
+
const check = report.checks.find((c) => c.name === "capability-good");
|
|
336
|
+
expect(check).toBeDefined();
|
|
337
|
+
expect(check!.status).toBe("pass");
|
|
338
|
+
expect(check!.message).toContain("1 capability(ies) registered");
|
|
339
|
+
});
|
|
340
|
+
} finally {
|
|
341
|
+
removeFakeCapabilityPackage("good");
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
test("no capability checks are added when config.capabilities is absent", async () => {
|
|
346
|
+
await withTestDir(async (testDir) => {
|
|
347
|
+
writeFileSync(join(testDir, "chant.config.json"), "{}");
|
|
348
|
+
const report = await doctorCommand(testDir);
|
|
349
|
+
const capabilityChecks = report.checks.filter((c) => c.name.startsWith("capability-"));
|
|
350
|
+
expect(capabilityChecks.length).toBe(0);
|
|
351
|
+
});
|
|
352
|
+
});
|
|
239
353
|
});
|
|
@@ -5,6 +5,8 @@ import { fileURLToPath } from "url";
|
|
|
5
5
|
import { checkVersionCompatibility } from "../../lexicon-manifest";
|
|
6
6
|
import { debug } from "../debug";
|
|
7
7
|
import { loadPlugins, resolveProjectLexicons } from "../plugins";
|
|
8
|
+
import { loadCapabilityPlugin } from "../../components/capability-plugin-loader";
|
|
9
|
+
import { isCapabilityPlugin } from "../../components/capability-plugin";
|
|
8
10
|
|
|
9
11
|
export interface DoctorCheck {
|
|
10
12
|
name: string;
|
|
@@ -221,6 +223,50 @@ export async function doctorCommand(path: string): Promise<DoctorReport> {
|
|
|
221
223
|
debug("skills check failed:", e);
|
|
222
224
|
}
|
|
223
225
|
|
|
226
|
+
// Check: Capability plugin packages (#559, epic #551) — each name in
|
|
227
|
+
// config.capabilities must load and satisfy the CapabilityPlugin contract
|
|
228
|
+
// (../../components/capability-plugin.ts). A malformed capability package
|
|
229
|
+
// (missing/broken `capabilities()`, or the package failing to resolve at
|
|
230
|
+
// all) is reported as a `fail`, mirroring how a missing lexicon type
|
|
231
|
+
// directory fails above rather than warning.
|
|
232
|
+
const capabilityNames = config?.capabilities as string[] | undefined;
|
|
233
|
+
if (capabilityNames && Array.isArray(capabilityNames)) {
|
|
234
|
+
for (const name of capabilityNames) {
|
|
235
|
+
try {
|
|
236
|
+
const plugin = await loadCapabilityPlugin(name);
|
|
237
|
+
if (!isCapabilityPlugin(plugin)) {
|
|
238
|
+
checks.push({
|
|
239
|
+
name: `capability-${name}`,
|
|
240
|
+
status: "fail",
|
|
241
|
+
message: `Capability plugin "${name}" does not satisfy the CapabilityPlugin contract (missing name/version/capabilities())`,
|
|
242
|
+
});
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
const capabilities = plugin.capabilities();
|
|
246
|
+
if (!Array.isArray(capabilities)) {
|
|
247
|
+
checks.push({
|
|
248
|
+
name: `capability-${name}`,
|
|
249
|
+
status: "fail",
|
|
250
|
+
message: `Capability plugin "${name}": capabilities() did not return an array`,
|
|
251
|
+
});
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
checks.push({
|
|
255
|
+
name: `capability-${name}`,
|
|
256
|
+
status: "pass",
|
|
257
|
+
message: `${capabilities.length} capability(ies) registered`,
|
|
258
|
+
});
|
|
259
|
+
} catch (e) {
|
|
260
|
+
debug(`capability plugin check failed for ${name}:`, e);
|
|
261
|
+
checks.push({
|
|
262
|
+
name: `capability-${name}`,
|
|
263
|
+
status: "fail",
|
|
264
|
+
message: `Capability plugin "${name}" could not be loaded: ${e instanceof Error ? e.message : String(e)}`,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
224
270
|
return {
|
|
225
271
|
checks,
|
|
226
272
|
success: checks.every(c => c.status !== "fail"),
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant dev rolling-upgrade <lexicon-dir>` command implementation.
|
|
3
|
+
*
|
|
4
|
+
* Detects rolling-spec drift for the aws, azure, and github lexicons. These
|
|
5
|
+
* lexicons pin no version constant — "latest" is fetched on every regen. This
|
|
6
|
+
* command regenerates from current-latest, diffs the produced API surface
|
|
7
|
+
* against the committed baseline (surface.snapshot.json), and REPORTS the
|
|
8
|
+
* result. It is a dry run: it never opens a PR, updates a branch, or writes the
|
|
9
|
+
* baseline. PR automation and scheduling live in #527.
|
|
10
|
+
*
|
|
11
|
+
* The PR label an eventual automation would apply is derived from severity:
|
|
12
|
+
* additive → `minor`, breaking → `major`. This command only prints it.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { existsSync } from "fs";
|
|
16
|
+
import { resolve } from "path";
|
|
17
|
+
import {
|
|
18
|
+
checkRollingUpgrade,
|
|
19
|
+
type RollingUpgradeResult,
|
|
20
|
+
} from "../../codegen/rolling-upgrade";
|
|
21
|
+
|
|
22
|
+
// ── Types ─────────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
export interface RollingUpgradeCliOptions {
|
|
25
|
+
/** Resolved path to the lexicon directory. */
|
|
26
|
+
lexiconDir: string;
|
|
27
|
+
/** Force re-fetch of the upstream spec (bypass cache). */
|
|
28
|
+
force?: boolean;
|
|
29
|
+
/** Print subprocess output while running. */
|
|
30
|
+
verbose?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ── Main entry ────────────────────────────────────────────────────────
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Run the rolling-upgrade check and return the result.
|
|
37
|
+
* Returns a synthetic failed result when the directory is missing.
|
|
38
|
+
*/
|
|
39
|
+
export async function runRollingUpgrade(
|
|
40
|
+
opts: RollingUpgradeCliOptions,
|
|
41
|
+
): Promise<RollingUpgradeResult> {
|
|
42
|
+
const dir = resolve(opts.lexiconDir);
|
|
43
|
+
|
|
44
|
+
if (!existsSync(dir)) {
|
|
45
|
+
return {
|
|
46
|
+
lexicon: "aws",
|
|
47
|
+
hasUpgrade: false,
|
|
48
|
+
severity: "none",
|
|
49
|
+
delta: { added: [], changed: [], removed: [], severity: "none" },
|
|
50
|
+
deltaText: "",
|
|
51
|
+
validationOk: false,
|
|
52
|
+
failures: [{ step: "setup", output: `Lexicon directory not found: ${dir}` }],
|
|
53
|
+
apiVersionDelta: [],
|
|
54
|
+
freshSnapshot: null,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return checkRollingUpgrade({
|
|
59
|
+
lexiconDir: dir,
|
|
60
|
+
force: opts.force,
|
|
61
|
+
verbose: opts.verbose,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Map surface severity to the semver PR label an upgrade would carry.
|
|
67
|
+
* additive → minor, breaking → major, none → none.
|
|
68
|
+
*/
|
|
69
|
+
export function severityToLabel(severity: RollingUpgradeResult["severity"]): string {
|
|
70
|
+
if (severity === "breaking") return "major";
|
|
71
|
+
if (severity === "additive") return "minor";
|
|
72
|
+
return "none";
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ── Human-readable output ─────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
const COLORS = {
|
|
78
|
+
green: "\x1b[32m",
|
|
79
|
+
yellow: "\x1b[33m",
|
|
80
|
+
red: "\x1b[31m",
|
|
81
|
+
gray: "\x1b[90m",
|
|
82
|
+
bold: "\x1b[1m",
|
|
83
|
+
reset: "\x1b[0m",
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
function useColors(): boolean {
|
|
87
|
+
return !process.env.NO_COLOR && process.stdout.isTTY !== false;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function c(text: string, code: string): string {
|
|
91
|
+
return useColors() ? `${code}${text}${COLORS.reset}` : text;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Print the rolling-upgrade result to stdout.
|
|
96
|
+
*/
|
|
97
|
+
export function printRollingUpgradeResult(result: RollingUpgradeResult, json: boolean): void {
|
|
98
|
+
if (json) {
|
|
99
|
+
console.log(
|
|
100
|
+
JSON.stringify(
|
|
101
|
+
{
|
|
102
|
+
lexicon: result.lexicon,
|
|
103
|
+
hasUpgrade: result.hasUpgrade,
|
|
104
|
+
severity: result.severity,
|
|
105
|
+
label: severityToLabel(result.severity),
|
|
106
|
+
validationOk: result.validationOk,
|
|
107
|
+
delta: result.delta,
|
|
108
|
+
apiVersionDelta: result.apiVersionDelta,
|
|
109
|
+
failures: result.failures,
|
|
110
|
+
},
|
|
111
|
+
null,
|
|
112
|
+
2,
|
|
113
|
+
),
|
|
114
|
+
);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log(c(`Rolling upgrade check: ${result.lexicon}`, COLORS.bold));
|
|
119
|
+
console.log("");
|
|
120
|
+
|
|
121
|
+
// Surface delta — the review payload
|
|
122
|
+
if (result.deltaText) {
|
|
123
|
+
console.log(result.deltaText);
|
|
124
|
+
} else {
|
|
125
|
+
console.log(c("No surface changes.", COLORS.green));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// azure API-version delta
|
|
129
|
+
if (result.apiVersionDelta.length > 0) {
|
|
130
|
+
console.log("");
|
|
131
|
+
console.log(c(`API version changes (${result.apiVersionDelta.length}):`, COLORS.bold));
|
|
132
|
+
for (const v of result.apiVersionDelta) {
|
|
133
|
+
const arrow =
|
|
134
|
+
v.kind === "added"
|
|
135
|
+
? `+ ${v.provider} (${v.after})`
|
|
136
|
+
: v.kind === "removed"
|
|
137
|
+
? `- ${v.provider} (was ${v.before})`
|
|
138
|
+
: `~ ${v.provider}: ${v.before} -> ${v.after}`;
|
|
139
|
+
console.log(` ${arrow}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Failures
|
|
144
|
+
if (result.failures.length > 0) {
|
|
145
|
+
console.log("");
|
|
146
|
+
console.log(c(`${result.failures.length} step(s) failed:`, COLORS.bold));
|
|
147
|
+
for (const f of result.failures) {
|
|
148
|
+
console.log(
|
|
149
|
+
c(
|
|
150
|
+
` FAIL [${f.step}]${f.exitCode !== undefined ? ` (exit ${f.exitCode})` : ""}`,
|
|
151
|
+
COLORS.red,
|
|
152
|
+
),
|
|
153
|
+
);
|
|
154
|
+
if (f.output) {
|
|
155
|
+
const indented = f.output
|
|
156
|
+
.split("\n")
|
|
157
|
+
.map((l) => ` ${l}`)
|
|
158
|
+
.join("\n");
|
|
159
|
+
console.log(c(indented, COLORS.gray));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
console.log("");
|
|
165
|
+
|
|
166
|
+
// Decision line
|
|
167
|
+
const severityColor =
|
|
168
|
+
result.severity === "breaking"
|
|
169
|
+
? COLORS.red
|
|
170
|
+
: result.severity === "additive"
|
|
171
|
+
? COLORS.yellow
|
|
172
|
+
: COLORS.green;
|
|
173
|
+
|
|
174
|
+
const label = severityToLabel(result.severity);
|
|
175
|
+
const validationLabel = result.validationOk
|
|
176
|
+
? c("ok", COLORS.green)
|
|
177
|
+
: c("FAILED", COLORS.red);
|
|
178
|
+
|
|
179
|
+
console.log(
|
|
180
|
+
`Upgrade: ${result.hasUpgrade} Severity: ${c(result.severity, severityColor)} ` +
|
|
181
|
+
`Label: ${label} Validation: ${validationLabel}`,
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
if (result.hasUpgrade && result.validationOk) {
|
|
185
|
+
console.log(
|
|
186
|
+
c(
|
|
187
|
+
`A PR would be opened: chore(${result.lexicon}): regen from latest spec [${label}]`,
|
|
188
|
+
COLORS.gray,
|
|
189
|
+
),
|
|
190
|
+
);
|
|
191
|
+
} else if (result.hasUpgrade && !result.validationOk) {
|
|
192
|
+
console.log(
|
|
193
|
+
c("Surface moved but validation failed — no PR; surfaces as a report/issue (#527).", COLORS.yellow),
|
|
194
|
+
);
|
|
195
|
+
} else {
|
|
196
|
+
console.log(c("No surface change — no PR.", COLORS.gray));
|
|
197
|
+
}
|
|
198
|
+
}
|