@intentius/chant 0.13.1 → 0.15.1
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/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 +59 -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/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 +99 -0
- package/src/op/index.ts +3 -1
- package/src/ownership.test.ts +24 -26
- package/src/ownership.ts +26 -38
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { describe, test, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, writeFileSync, readFileSync, rmSync } from "fs";
|
|
3
|
+
import { tmpdir } from "os";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import type { RegenResult } from "../../codegen/lexicon-regen";
|
|
6
|
+
|
|
7
|
+
// Stub the heavy regen pipeline — these tests only exercise the re-baseline /
|
|
8
|
+
// version-bump wiring (#616), not the actual spec fetch + tsc build.
|
|
9
|
+
const regenLexicon = vi.fn<(...a: unknown[]) => Promise<RegenResult>>();
|
|
10
|
+
const writeSurfaceSnapshot = vi.fn();
|
|
11
|
+
vi.mock("../../codegen/lexicon-regen", () => ({
|
|
12
|
+
regenLexicon: (...args: unknown[]) => regenLexicon(...args),
|
|
13
|
+
writeSurfaceSnapshot: (...args: unknown[]) => writeSurfaceSnapshot(...args),
|
|
14
|
+
SNAPSHOT_FILENAME: "surface.snapshot.json",
|
|
15
|
+
}));
|
|
16
|
+
|
|
17
|
+
import { runSurfaceDiff } from "./lexicon-surface-diff";
|
|
18
|
+
|
|
19
|
+
function result(over: Partial<RegenResult>): RegenResult {
|
|
20
|
+
return {
|
|
21
|
+
ok: true,
|
|
22
|
+
changed: true,
|
|
23
|
+
severity: "additive",
|
|
24
|
+
delta: { added: [], changed: [], removed: [], severity: "additive" },
|
|
25
|
+
deltaText: "",
|
|
26
|
+
failures: [],
|
|
27
|
+
freshSnapshot: { surface: "x" } as unknown as RegenResult["freshSnapshot"],
|
|
28
|
+
...over,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function lexiconDir(version = "0.13.1"): string {
|
|
33
|
+
const dir = mkdtempSync(join(tmpdir(), "sd-"));
|
|
34
|
+
writeFileSync(join(dir, "package.json"), JSON.stringify({ name: "lex", version }, null, 2) + "\n");
|
|
35
|
+
return dir;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function readVersion(dir: string): string {
|
|
39
|
+
return (JSON.parse(readFileSync(join(dir, "package.json"), "utf-8")) as { version: string }).version;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
describe("runSurfaceDiff --bump (#616)", () => {
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
regenLexicon.mockReset();
|
|
45
|
+
writeSurfaceSnapshot.mockReset();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("additive drift with --update-snapshot --bump bumps the patch", async () => {
|
|
49
|
+
const dir = lexiconDir("0.13.1");
|
|
50
|
+
try {
|
|
51
|
+
regenLexicon.mockResolvedValue(result({ severity: "additive" }));
|
|
52
|
+
await runSurfaceDiff({ lexiconDir: dir, updateSnapshot: true, bump: true });
|
|
53
|
+
expect(readVersion(dir)).toBe("0.13.2");
|
|
54
|
+
expect(writeSurfaceSnapshot).toHaveBeenCalledOnce();
|
|
55
|
+
} finally {
|
|
56
|
+
rmSync(dir, { recursive: true, force: true });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("breaking drift bumps the minor (pre-1.0)", async () => {
|
|
61
|
+
const dir = lexiconDir("0.13.1");
|
|
62
|
+
try {
|
|
63
|
+
regenLexicon.mockResolvedValue(result({ severity: "breaking" }));
|
|
64
|
+
await runSurfaceDiff({ lexiconDir: dir, updateSnapshot: true, bump: true });
|
|
65
|
+
expect(readVersion(dir)).toBe("0.14.0");
|
|
66
|
+
} finally {
|
|
67
|
+
rmSync(dir, { recursive: true, force: true });
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("no --bump leaves the version untouched even when the surface changed", async () => {
|
|
72
|
+
const dir = lexiconDir("0.13.1");
|
|
73
|
+
try {
|
|
74
|
+
regenLexicon.mockResolvedValue(result({ severity: "additive" }));
|
|
75
|
+
await runSurfaceDiff({ lexiconDir: dir, updateSnapshot: true });
|
|
76
|
+
expect(readVersion(dir)).toBe("0.13.1");
|
|
77
|
+
} finally {
|
|
78
|
+
rmSync(dir, { recursive: true, force: true });
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("--bump with no surface change leaves the version untouched", async () => {
|
|
83
|
+
const dir = lexiconDir("0.13.1");
|
|
84
|
+
try {
|
|
85
|
+
regenLexicon.mockResolvedValue(result({ changed: false, severity: "none" }));
|
|
86
|
+
await runSurfaceDiff({ lexiconDir: dir, updateSnapshot: true, bump: true });
|
|
87
|
+
expect(readVersion(dir)).toBe("0.13.1");
|
|
88
|
+
} finally {
|
|
89
|
+
rmSync(dir, { recursive: true, force: true });
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("--bump without --update-snapshot does nothing (no re-baseline, no bump)", async () => {
|
|
94
|
+
const dir = lexiconDir("0.13.1");
|
|
95
|
+
try {
|
|
96
|
+
regenLexicon.mockResolvedValue(result({ severity: "additive" }));
|
|
97
|
+
await runSurfaceDiff({ lexiconDir: dir, bump: true });
|
|
98
|
+
expect(readVersion(dir)).toBe("0.13.1");
|
|
99
|
+
expect(writeSurfaceSnapshot).not.toHaveBeenCalled();
|
|
100
|
+
} finally {
|
|
101
|
+
rmSync(dir, { recursive: true, force: true });
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
});
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant dev surface-diff <lexicon-dir>` command implementation.
|
|
3
|
+
*
|
|
4
|
+
* Regenerates a lexicon from its spec, validates the result, extracts the
|
|
5
|
+
* public API surface, and diffs it against the committed baseline snapshot.
|
|
6
|
+
*
|
|
7
|
+
* Outputs a human-readable delta to stdout and optionally a machine-readable
|
|
8
|
+
* JSON result to a file. Never auto-fixes: failures are captured and reported.
|
|
9
|
+
*
|
|
10
|
+
* The snapshot file is written to `<lexicon-dir>/surface.snapshot.json`.
|
|
11
|
+
* Pass `--update-snapshot` to commit the fresh snapshot after a successful run.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { existsSync, readFileSync } from "fs";
|
|
15
|
+
import { resolve, join } from "path";
|
|
16
|
+
import { regenLexicon, writeSurfaceSnapshot, SNAPSHOT_FILENAME, type RegenResult } from "../../codegen/lexicon-regen";
|
|
17
|
+
import { bumpForSeverity, bumpPackageJsonVersion } from "../../codegen/version-bump";
|
|
18
|
+
|
|
19
|
+
// ── Types ─────────────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
export interface SurfaceDiffOptions {
|
|
22
|
+
/** Resolved path to the lexicon directory. */
|
|
23
|
+
lexiconDir: string;
|
|
24
|
+
/** Force re-fetch of upstream spec (bypass cache). */
|
|
25
|
+
force?: boolean;
|
|
26
|
+
/** Print subprocess output while running. */
|
|
27
|
+
verbose?: boolean;
|
|
28
|
+
/** Skip the bundle step. */
|
|
29
|
+
skipBundle?: boolean;
|
|
30
|
+
/** Skip the build (tsc) step. */
|
|
31
|
+
skipBuild?: boolean;
|
|
32
|
+
/** Skip chant lint on examples. */
|
|
33
|
+
skipLint?: boolean;
|
|
34
|
+
/** Run the example build harness (opt-in; needs cloud creds). */
|
|
35
|
+
runExamples?: boolean;
|
|
36
|
+
/** Path to a SHA-256 digest file pinning the spec. */
|
|
37
|
+
pinnedDigestPath?: string;
|
|
38
|
+
/** After a successful regen, write the fresh snapshot as the new baseline. */
|
|
39
|
+
updateSnapshot?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* When re-baselining (`updateSnapshot`), also bump the lexicon's package.json
|
|
42
|
+
* version by the drift severity so the accepted surface is publishable (#616).
|
|
43
|
+
*/
|
|
44
|
+
bump?: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ── Main entry ────────────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Run the surface-diff pipeline and return the result.
|
|
51
|
+
* Logs human-readable output to stderr; machine-readable JSON goes to the caller.
|
|
52
|
+
*/
|
|
53
|
+
export async function runSurfaceDiff(opts: SurfaceDiffOptions): Promise<RegenResult> {
|
|
54
|
+
const dir = resolve(opts.lexiconDir);
|
|
55
|
+
|
|
56
|
+
if (!existsSync(dir)) {
|
|
57
|
+
const failure = {
|
|
58
|
+
step: "setup",
|
|
59
|
+
output: `Lexicon directory not found: ${dir}`,
|
|
60
|
+
};
|
|
61
|
+
return {
|
|
62
|
+
ok: false,
|
|
63
|
+
changed: false,
|
|
64
|
+
severity: "none",
|
|
65
|
+
delta: { added: [], changed: [], removed: [], severity: "none" },
|
|
66
|
+
deltaText: "",
|
|
67
|
+
failures: [failure],
|
|
68
|
+
freshSnapshot: null,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const result = await regenLexicon({
|
|
73
|
+
lexiconDir: dir,
|
|
74
|
+
force: opts.force,
|
|
75
|
+
verbose: opts.verbose,
|
|
76
|
+
skipBundle: opts.skipBundle,
|
|
77
|
+
skipBuild: opts.skipBuild,
|
|
78
|
+
skipLint: opts.skipLint,
|
|
79
|
+
skipExamples: !opts.runExamples,
|
|
80
|
+
pinnedDigestPath: opts.pinnedDigestPath,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Update snapshot when requested and the run succeeded
|
|
84
|
+
if (opts.updateSnapshot && result.ok && result.freshSnapshot) {
|
|
85
|
+
writeSurfaceSnapshot(dir, result.freshSnapshot);
|
|
86
|
+
process.stderr.write(`Snapshot updated: ${dir}/${SNAPSHOT_FILENAME}\n`);
|
|
87
|
+
|
|
88
|
+
// #616: accepting drift on a rolling lexicon changes the surface but nothing
|
|
89
|
+
// bumps the version — so skip-if-unchanged would strand the new surface at
|
|
90
|
+
// publish time. `--bump` raises the version by the drift severity (0.x-aware)
|
|
91
|
+
// so the accepted drift actually ships.
|
|
92
|
+
if (opts.bump && result.changed && result.severity !== "none") {
|
|
93
|
+
const pkgPath = join(dir, "package.json");
|
|
94
|
+
if (existsSync(pkgPath)) {
|
|
95
|
+
const current = (JSON.parse(readFileSync(pkgPath, "utf-8")) as { version?: string }).version ?? "0.0.0";
|
|
96
|
+
const bumped = bumpForSeverity(current, result.severity);
|
|
97
|
+
if (bumped) {
|
|
98
|
+
bumpPackageJsonVersion(pkgPath, bumped);
|
|
99
|
+
process.stderr.write(`Version bumped: ${current} -> ${bumped} (${result.severity})\n`);
|
|
100
|
+
} else {
|
|
101
|
+
process.stderr.write(`Version unchanged: could not bump ${current} for severity ${result.severity}\n`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ── Human-readable output ─────────────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
const COLORS = {
|
|
113
|
+
green: "\x1b[32m",
|
|
114
|
+
yellow: "\x1b[33m",
|
|
115
|
+
red: "\x1b[31m",
|
|
116
|
+
gray: "\x1b[90m",
|
|
117
|
+
bold: "\x1b[1m",
|
|
118
|
+
reset: "\x1b[0m",
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
function useColors(): boolean {
|
|
122
|
+
return !process.env.NO_COLOR && process.stdout.isTTY !== false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function c(text: string, code: string): string {
|
|
126
|
+
return useColors() ? `${code}${text}${COLORS.reset}` : text;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Print the surface-diff result as human-readable text to stdout.
|
|
131
|
+
*/
|
|
132
|
+
export function printSurfaceDiffResult(result: RegenResult, json: boolean): void {
|
|
133
|
+
if (json) {
|
|
134
|
+
console.log(JSON.stringify(
|
|
135
|
+
{
|
|
136
|
+
ok: result.ok,
|
|
137
|
+
changed: result.changed,
|
|
138
|
+
severity: result.severity,
|
|
139
|
+
delta: result.delta,
|
|
140
|
+
failures: result.failures,
|
|
141
|
+
},
|
|
142
|
+
null,
|
|
143
|
+
2,
|
|
144
|
+
));
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Surface delta
|
|
149
|
+
if (result.deltaText) {
|
|
150
|
+
console.log(result.deltaText);
|
|
151
|
+
} else if (result.changed) {
|
|
152
|
+
console.log("Surface changed (no baseline to diff against).");
|
|
153
|
+
} else {
|
|
154
|
+
console.log(c("No surface changes.", COLORS.green));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Failures
|
|
158
|
+
if (result.failures.length > 0) {
|
|
159
|
+
console.log("");
|
|
160
|
+
console.log(c(`${result.failures.length} step(s) failed:`, COLORS.bold));
|
|
161
|
+
for (const f of result.failures) {
|
|
162
|
+
console.log(c(` FAIL [${f.step}]${f.exitCode !== undefined ? ` (exit ${f.exitCode})` : ""}`, COLORS.red));
|
|
163
|
+
if (f.output) {
|
|
164
|
+
const indented = f.output
|
|
165
|
+
.split("\n")
|
|
166
|
+
.map((l) => ` ${l}`)
|
|
167
|
+
.join("\n");
|
|
168
|
+
console.log(c(indented, COLORS.gray));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
console.log("");
|
|
174
|
+
|
|
175
|
+
// Summary line
|
|
176
|
+
const severityColor =
|
|
177
|
+
result.severity === "breaking" ? COLORS.red :
|
|
178
|
+
result.severity === "additive" ? COLORS.yellow :
|
|
179
|
+
COLORS.green;
|
|
180
|
+
|
|
181
|
+
const statusLabel = result.ok ? c("ok", COLORS.green) : c("FAILED", COLORS.red);
|
|
182
|
+
const severityLabel = c(result.severity, severityColor);
|
|
183
|
+
|
|
184
|
+
console.log(`Status: ${statusLabel} Severity: ${severityLabel} Changed: ${result.changed}`);
|
|
185
|
+
}
|