@1aboveio/skills 0.10.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/LICENSE +3 -0
- package/README.md +90 -0
- package/bin/1aboveio-skills.mjs +18 -0
- package/package.json +28 -0
- package/runtime/skills/distribution/generated/recipes.json +1189 -0
- package/runtime/skills/distribution/scripts/bundles.mjs +280 -0
- package/runtime/skills/engineering/engineering-runtime/scripts/main-module.mjs +80 -0
- package/skills/backend/airflow-dag-develop/LICENSE +3 -0
- package/skills/backend/airflow-dag-develop/SKILL.md +111 -0
- package/skills/backend/app-debug/LICENSE +3 -0
- package/skills/backend/app-debug/SKILL.md +109 -0
- package/skills/backend/app-debug/references/common-errors.md +128 -0
- package/skills/backend/python-backend/LICENSE +3 -0
- package/skills/backend/python-backend/SKILL.md +326 -0
- package/skills/cicd-pipeline/cloud-build/LICENSE +3 -0
- package/skills/cicd-pipeline/cloud-build/SKILL.md +707 -0
- package/skills/cicd-pipeline/cloud-debug/LICENSE +3 -0
- package/skills/cicd-pipeline/cloud-debug/SKILL.md +316 -0
- package/skills/cicd-pipeline/cloud-debug/references/build-failures.md +238 -0
- package/skills/cicd-pipeline/cloud-debug/references/deploy-failures.md +376 -0
- package/skills/cicd-pipeline/cloud-debug/references/pipeline-failures.md +378 -0
- package/skills/cicd-pipeline/cloud-deploy/LICENSE +3 -0
- package/skills/cicd-pipeline/cloud-deploy/SKILL.md +229 -0
- package/skills/cicd-pipeline/cloud-deploy/references/config-templates.md +257 -0
- package/skills/cicd-pipeline/docker/LICENSE +3 -0
- package/skills/cicd-pipeline/docker/SKILL.md +126 -0
- package/skills/cicd-pipeline/google-cloud/LICENSE +3 -0
- package/skills/cicd-pipeline/google-cloud/SKILL.md +118 -0
- package/skills/cicd-pipeline/google-cloud/references/gcs.md +469 -0
- package/skills/cicd-pipeline/google-cloud/references/iam.md +451 -0
- package/skills/cicd-pipeline/google-cloud/references/project.md +349 -0
- package/skills/cicd-pipeline/google-cloud/references/secrets.md +336 -0
- package/skills/cicd-pipeline/google-cloud/references/vpc.md +312 -0
- package/skills/cicd-pipeline/google-cloud/scripts/create-sa.sh +36 -0
- package/skills/cicd-pipeline/google-cloud/scripts/gcp-config.sh +31 -0
- package/skills/cicd-pipeline/google-cloud/scripts/grant-iap.sh +41 -0
- package/skills/cicd-pipeline/google-cloud/scripts/setup-secrets.sh +48 -0
- package/skills/cicd-pipeline/mergify/LICENSE +3 -0
- package/skills/cicd-pipeline/mergify/SKILL.md +138 -0
- package/skills/cicd-pipeline/mergify/assets/templates/mergify.yml +237 -0
- package/skills/cicd-pipeline/mergify/assets/templates/ruleset.json +46 -0
- package/skills/cicd-pipeline/mergify/references/branch-protection.md +277 -0
- package/skills/cicd-pipeline/mergify/references/configuration.md +183 -0
- package/skills/cicd-pipeline/mergify/references/diagnosis.md +73 -0
- package/skills/cicd-pipeline/mergify/references/traps.md +78 -0
- package/skills/cicd-pipeline/mergify/references/watch-contract.md +218 -0
- package/skills/cicd-pipeline/mergify/scripts/audit-core.mjs +131 -0
- package/skills/cicd-pipeline/mergify/scripts/audit.mjs +4 -0
- package/skills/cicd-pipeline/mergify/scripts/watch-pr-delivery-core.mjs +663 -0
- package/skills/cicd-pipeline/mergify/scripts/watch-pr-delivery.mjs +4 -0
- package/skills/cicd-pipeline/podman/LICENSE +3 -0
- package/skills/cicd-pipeline/podman/SKILL.md +70 -0
- package/skills/cicd-pipeline/podman/agents/openai.yaml +4 -0
- package/skills/cicd-pipeline/podman/assets/templates/podman-compose-socket-directory.yml +6 -0
- package/skills/cicd-pipeline/podman/assets/templates/podman-service-override.conf +3 -0
- package/skills/cicd-pipeline/podman/references/compose-compatibility.md +70 -0
- package/skills/cicd-pipeline/podman/references/networking-and-ports.md +74 -0
- package/skills/cicd-pipeline/podman/references/rootless-services-and-sockets.md +156 -0
- package/skills/cicd-pipeline/podman/references/troubleshooting.md +98 -0
- package/skills/engineering/e2e-test/LICENSE +3 -0
- package/skills/engineering/e2e-test/SKILL.md +156 -0
- package/skills/engineering/e2e-test/assets/ci-gates.cloudbuild.yaml +272 -0
- package/skills/engineering/e2e-test/assets/ci-gates.github.yml +451 -0
- package/skills/engineering/e2e-test/assets/e2e-workflow.yml +282 -0
- package/skills/engineering/e2e-test/references/authoring/auth-flows.md +159 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-config.md +71 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-patterns.md +219 -0
- package/skills/engineering/e2e-test/references/authoring/test-skipping.md +44 -0
- package/skills/engineering/e2e-test/references/ci-integration.md +121 -0
- package/skills/engineering/e2e-test/references/ci-playwright-container.md +280 -0
- package/skills/engineering/e2e-test/references/debugging.md +36 -0
- package/skills/engineering/e2e-test/references/presentation-sweep.md +131 -0
- package/skills/engineering/e2e-test/references/reviewing.md +39 -0
- package/skills/engineering/e2e-test/references/route-discovery.md +50 -0
- package/skills/engineering/e2e-test/references/route-manifest.md +44 -0
- package/skills/engineering/e2e-test/scripts/detect-routes-fastapi.py +290 -0
- package/skills/engineering/e2e-test/scripts/detect-routes-nextjs.mjs +200 -0
- package/skills/engineering/e2e-test/scripts/post-visual-evidence.mjs +158 -0
- package/skills/engineering/e2e-test/scripts/presentation-checks.mjs +171 -0
- package/skills/engineering/e2e-test/scripts/presentation-perceivability.mjs +179 -0
- package/skills/engineering/e2e-test/scripts/presentation-reachability.mjs +154 -0
- package/skills/engineering/e2e-test/scripts/presentation-render-health.mjs +141 -0
- package/skills/engineering/e2e-test/scripts/presentation-sweep.mjs +148 -0
- package/skills/engineering/e2e-test/scripts/presentation-temporal.mjs +127 -0
- package/skills/engineering/e2e-test/scripts/presentation-visual.mjs +84 -0
- package/skills/engineering/e2e-test/scripts/project-route-manifest.mjs +75 -0
- package/skills/engineering/e2e-test/scripts/validate-manifest.mjs +106 -0
- package/skills/engineering/engineering-runtime/LICENSE +3 -0
- package/skills/engineering/engineering-runtime/SKILL.md +10 -0
- package/skills/engineering/engineering-runtime/agents/openai.yaml +6 -0
- package/skills/engineering/engineering-runtime/coherence/workflow.json +553 -0
- package/skills/engineering/engineering-runtime/scripts/exact-head-artifact.mjs +131 -0
- package/skills/engineering/engineering-runtime/scripts/head-check-set.mjs +398 -0
- package/skills/engineering/engineering-runtime/scripts/main-module.mjs +80 -0
- package/skills/engineering/engineering-runtime/scripts/mergify-yaml.mjs +11 -0
- package/skills/engineering/engineering-runtime/scripts/package-lock.json +43 -0
- package/skills/engineering/engineering-runtime/scripts/package.json +10 -0
- package/skills/engineering/engineering-runtime/scripts/required-check-plan.mjs +223 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +576 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +166 -0
- package/skills/engineering/ensure-coverage/LICENSE +3 -0
- package/skills/engineering/ensure-coverage/SKILL.md +136 -0
- package/skills/engineering/ensure-coverage/evals/evals.json +125 -0
- package/skills/engineering/ensure-coverage/references/breadth/coverage-ledger.md +91 -0
- package/skills/engineering/ensure-coverage/references/breadth/inventory-contract.md +83 -0
- package/skills/engineering/ensure-coverage/references/breadth/surface-baseline.md +44 -0
- package/skills/engineering/ensure-coverage/references/breadth/surface-discovery.md +16 -0
- package/skills/engineering/ensure-coverage/references/depth/characterization.md +68 -0
- package/skills/engineering/ensure-coverage/references/depth/coverage.config.example.json +25 -0
- package/skills/engineering/ensure-coverage/references/depth/grading.md +35 -0
- package/skills/engineering/ensure-coverage/references/depth/mock-policy.md +87 -0
- package/skills/engineering/ensure-coverage/references/depth/test-smells.md +23 -0
- package/skills/engineering/ensure-coverage/references/enforcement/ci-contract.md +164 -0
- package/skills/engineering/ensure-coverage/references/enforcement/hooks.md +85 -0
- package/skills/engineering/ensure-coverage/references/examples/coverage-ledger.md +109 -0
- package/skills/engineering/ensure-coverage/references/examples/refund-flow.md +33 -0
- package/skills/engineering/ensure-coverage/references/presentation/axis.md +78 -0
- package/skills/engineering/ensure-coverage/references/presentation/runner-contract.md +74 -0
- package/skills/engineering/ensure-coverage/references/process/audit-mode.md +33 -0
- package/skills/engineering/ensure-coverage/references/process/output-template.md +139 -0
- package/skills/engineering/ensure-coverage/references/process/review-contract-template.md +119 -0
- package/skills/engineering/ensure-coverage/references/process/scope-class.md +178 -0
- package/skills/engineering/ensure-coverage/references/process/test-strategy.md +55 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-config.schema.json +45 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-file.schema.json +93 -0
- package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.mjs +178 -0
- package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.mjs +101 -0
- package/skills/engineering/ensure-coverage/scripts/ci-audit.mjs +358 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-checklist.mjs +494 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-ledger.mjs +663 -0
- package/skills/engineering/ensure-coverage/scripts/design-parity.mjs +591 -0
- package/skills/engineering/ensure-coverage/scripts/evidence-block.mjs +367 -0
- package/skills/engineering/ensure-coverage/scripts/lint-tests.mjs +269 -0
- package/skills/engineering/ensure-coverage/scripts/mock-policy-config.mjs +176 -0
- package/skills/engineering/ensure-coverage/scripts/package-lock.json +76 -0
- package/skills/engineering/ensure-coverage/scripts/package.json +19 -0
- package/skills/engineering/ensure-coverage/scripts/scope-class.mjs +554 -0
- package/skills/engineering/harness-runtime/LICENSE +3 -0
- package/skills/engineering/harness-runtime/SKILL.md +18 -0
- package/skills/engineering/harness-runtime/agents/openai.yaml +6 -0
- package/skills/engineering/harness-runtime/bin/discover-models.mjs +4 -0
- package/skills/engineering/harness-runtime/bin/model-catalog.mjs +4 -0
- package/skills/engineering/harness-runtime/contracts.md +15 -0
- package/skills/engineering/harness-runtime/discover-models.mjs +392 -0
- package/skills/engineering/harness-runtime/fixtures/native-question-schemas.json +33 -0
- package/skills/engineering/harness-runtime/fixtures/question-responses.json +54 -0
- package/skills/engineering/harness-runtime/index.mjs +767 -0
- package/skills/engineering/harness-runtime/model-catalog.mjs +787 -0
- package/skills/engineering/harness-runtime/native-question-contracts.md +37 -0
- package/skills/engineering/harness-runtime/references/model-catalog-seed.json +159 -0
- package/skills/engineering/harness-runtime/references/model-catalog.md +57 -0
- package/skills/engineering/implement-and-pr/LICENSE +3 -0
- package/skills/engineering/implement-and-pr/SKILL.md +176 -0
- package/skills/engineering/implement-and-pr/references/ci-iteration.md +10 -0
- package/skills/engineering/implement-and-pr/references/closeout.md +27 -0
- package/skills/engineering/implement-and-pr/references/contract-complete-fix-rounds.md +34 -0
- package/skills/engineering/implement-and-pr/references/evidence-rules.md +39 -0
- package/skills/engineering/implement-and-pr/references/incremental-plan.md +16 -0
- package/skills/engineering/implement-and-pr/references/self-review.md +23 -0
- package/skills/engineering/implement-and-pr/references/tdd-mode.md +18 -0
- package/skills/engineering/resolve-issues/LICENSE +3 -0
- package/skills/engineering/resolve-issues/SKILL.md +167 -0
- package/skills/engineering/resolve-issues/generated/workflow-repair-policy.json +448 -0
- package/skills/engineering/resolve-issues/references/breaker.md +82 -0
- package/skills/engineering/resolve-issues/references/deliverables.md +27 -0
- package/skills/engineering/resolve-issues/references/delivery.md +108 -0
- package/skills/engineering/resolve-issues/references/evidence-lane.md +21 -0
- package/skills/engineering/resolve-issues/references/exact-head-ci.md +287 -0
- package/skills/engineering/resolve-issues/references/fan-out.md +33 -0
- package/skills/engineering/resolve-issues/references/finalization.md +68 -0
- package/skills/engineering/resolve-issues/references/guarantees.md +10 -0
- package/skills/engineering/resolve-issues/references/high-risk.md +29 -0
- package/skills/engineering/resolve-issues/references/incidents/848/README.md +156 -0
- package/skills/engineering/resolve-issues/references/intake.md +86 -0
- package/skills/engineering/resolve-issues/references/integration-gate.md +53 -0
- package/skills/engineering/resolve-issues/references/interference.md +87 -0
- package/skills/engineering/resolve-issues/references/loop.md +134 -0
- package/skills/engineering/resolve-issues/references/model-catalog.md +9 -0
- package/skills/engineering/resolve-issues/references/postmortem.md +27 -0
- package/skills/engineering/resolve-issues/references/pre-flight-model-slots.md +41 -0
- package/skills/engineering/resolve-issues/references/pre-flight-recording-and-checkout.md +48 -0
- package/skills/engineering/resolve-issues/references/pre-flight.md +41 -0
- package/skills/engineering/resolve-issues/references/regression-checklist.md +26 -0
- package/skills/engineering/resolve-issues/references/run-state.md +288 -0
- package/skills/engineering/resolve-issues/references/sandboxed-testing.md +48 -0
- package/skills/engineering/resolve-issues/references/spawn-contract.md +96 -0
- package/skills/engineering/resolve-issues/references/terminal-evidence-journal.md +40 -0
- package/skills/engineering/resolve-issues/references/why.md +653 -0
- package/skills/engineering/resolve-issues/schemas/fix-round.schema.json +49 -0
- package/skills/engineering/resolve-issues/scripts/combine-and-verify.mjs +721 -0
- package/skills/engineering/resolve-issues/scripts/component-candidate.mjs +962 -0
- package/skills/engineering/resolve-issues/scripts/contract-revision.mjs +220 -0
- package/skills/engineering/resolve-issues/scripts/detect-delivery-mode.mjs +420 -0
- package/skills/engineering/resolve-issues/scripts/detect-target-branch.mjs +256 -0
- package/skills/engineering/resolve-issues/scripts/detect-workspace-mode.mjs +168 -0
- package/skills/engineering/resolve-issues/scripts/discover-models.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/doctrine.mjs +62 -0
- package/skills/engineering/resolve-issues/scripts/evidence-lifecycle-contract.mjs +191 -0
- package/skills/engineering/resolve-issues/scripts/exact-head-ci.mjs +413 -0
- package/skills/engineering/resolve-issues/scripts/exact-head-github-provider.mjs +332 -0
- package/skills/engineering/resolve-issues/scripts/finalize.mjs +488 -0
- package/skills/engineering/resolve-issues/scripts/fix-rounds.mjs +3307 -0
- package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-circular-1001.json +16 -0
- package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-valid-sequencing.json +51 -0
- package/skills/engineering/resolve-issues/scripts/fixtures/fmm-express-830-component-candidate.json +17 -0
- package/skills/engineering/resolve-issues/scripts/fixtures/head-check-set-1081.json +166 -0
- package/skills/engineering/resolve-issues/scripts/gate-value-series.mjs +92 -0
- package/skills/engineering/resolve-issues/scripts/guide-index.mjs +73 -0
- package/skills/engineering/resolve-issues/scripts/head-check-set.mjs +159 -0
- package/skills/engineering/resolve-issues/scripts/interference.mjs +427 -0
- package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/next-operations.mjs +419 -0
- package/skills/engineering/resolve-issues/scripts/postmortem.mjs +909 -0
- package/skills/engineering/resolve-issues/scripts/preflight-questions.mjs +322 -0
- package/skills/engineering/resolve-issues/scripts/reconcile-contained-unit-prs.mjs +415 -0
- package/skills/engineering/resolve-issues/scripts/release-state-contract.mjs +697 -0
- package/skills/engineering/resolve-issues/scripts/report.mjs +494 -0
- package/skills/engineering/resolve-issues/scripts/required-check-plan.mjs +172 -0
- package/skills/engineering/resolve-issues/scripts/round-metadata.mjs +79 -0
- package/skills/engineering/resolve-issues/scripts/run-state-review6-cases.mjs +334 -0
- package/skills/engineering/resolve-issues/scripts/run-state.mjs +4784 -0
- package/skills/engineering/resolve-issues/scripts/sandbox-selftest.mjs +395 -0
- package/skills/engineering/resolve-issues/scripts/spawn-contract.mjs +290 -0
- package/skills/engineering/resolve-issues/scripts/terminal-dispositions.mjs +170 -0
- package/skills/engineering/resolve-issues/scripts/terminal-evidence-journal.mjs +293 -0
- package/skills/engineering/resolve-issues/scripts/unit-kind.mjs +197 -0
- package/skills/engineering/resolve-issues/scripts/unit-lifecycle.mjs +127 -0
- package/skills/engineering/resolve-issues/scripts/watch-delivery.mjs +893 -0
- package/skills/engineering/resolve-issues/scripts/workspaces.mjs +829 -0
- package/skills/engineering/resolve-issues/workflows/independent-review.workflow.js +290 -0
- package/skills/engineering/resolve-issues/workflows/prior-art-scan.workflow.js +80 -0
- package/skills/engineering/resolve-issues/workflows/workflow-smoke.mjs +102 -0
- package/skills/engineering/resolve-release/LICENSE +3 -0
- package/skills/engineering/resolve-release/SKILL.md +112 -0
- package/skills/engineering/resolve-release/references/assembly.md +137 -0
- package/skills/engineering/resolve-release/references/auto-when-green.md +56 -0
- package/skills/engineering/resolve-release/references/candidate.md +167 -0
- package/skills/engineering/resolve-release/references/exposure.md +178 -0
- package/skills/engineering/resolve-release/references/handoff.md +24 -0
- package/skills/engineering/resolve-release/references/postmortem.md +230 -0
- package/skills/engineering/resolve-release/references/preflight.md +207 -0
- package/skills/engineering/resolve-release/references/principles.md +94 -0
- package/skills/engineering/resolve-release/references/regression-checklist.md +36 -0
- package/skills/engineering/resolve-release/references/related-skills.md +12 -0
- package/skills/engineering/resolve-release/references/routing.md +149 -0
- package/skills/engineering/resolve-release/references/verified-sha-github-flow.md +285 -0
- package/skills/engineering/resolve-release/references/versioning.md +202 -0
- package/skills/engineering/resolve-release/references/why.md +53 -0
- package/skills/engineering/resolve-release/scripts/adapter-completion-artifact.mjs +389 -0
- package/skills/engineering/resolve-release/scripts/build-changes.mjs +209 -0
- package/skills/engineering/resolve-release/scripts/candidate-hygiene.mjs +407 -0
- package/skills/engineering/resolve-release/scripts/candidate-identity.mjs +904 -0
- package/skills/engineering/resolve-release/scripts/candidate-traffic.mjs +81 -0
- package/skills/engineering/resolve-release/scripts/checked-adapter-loader.mjs +612 -0
- package/skills/engineering/resolve-release/scripts/close-attempt.mjs +135 -0
- package/skills/engineering/resolve-release/scripts/closeout-release.mjs +161 -0
- package/skills/engineering/resolve-release/scripts/doctrine.mjs +106 -0
- package/skills/engineering/resolve-release/scripts/durable-processing.mjs +522 -0
- package/skills/engineering/resolve-release/scripts/ensure-target-green.mjs +659 -0
- package/skills/engineering/resolve-release/scripts/evidence-bundle.mjs +1014 -0
- package/skills/engineering/resolve-release/scripts/finalize-release.mjs +526 -0
- package/skills/engineering/resolve-release/scripts/fixtures/durable-processing-adapter.mjs +169 -0
- package/skills/engineering/resolve-release/scripts/green-gate.mjs +599 -0
- package/skills/engineering/resolve-release/scripts/isolated-adapter-evaluator.mjs +752 -0
- package/skills/engineering/resolve-release/scripts/metadata-pr-status.mjs +56 -0
- package/skills/engineering/resolve-release/scripts/metadata-sync.mjs +1538 -0
- package/skills/engineering/resolve-release/scripts/postmortem.mjs +381 -0
- package/skills/engineering/resolve-release/scripts/preflight-probes.mjs +498 -0
- package/skills/engineering/resolve-release/scripts/production-endpoints.mjs +326 -0
- package/skills/engineering/resolve-release/scripts/rc-circuit-breaker.mjs +272 -0
- package/skills/engineering/resolve-release/scripts/report.mjs +417 -0
- package/skills/engineering/resolve-release/scripts/reprobe-credentials.mjs +114 -0
- package/skills/engineering/resolve-release/scripts/revalidate-candidate.mjs +238 -0
- package/skills/engineering/resolve-release/scripts/review-packet.mjs +503 -0
- package/skills/engineering/resolve-release/scripts/rollback-floor.mjs +263 -0
- package/skills/engineering/resolve-release/scripts/version-assert.mjs +339 -0
- package/skills/engineering/resolve-release/scripts/version-postmortem.mjs +485 -0
- package/skills/engineering/resolve-release/scripts/version.mjs +1199 -0
- package/skills/engineering/resolve-release/scripts/watch-candidate-delivery.mjs +449 -0
- package/skills/engineering/resolve-release/vendor/ACORN-LICENSE +21 -0
- package/skills/engineering/resolve-release/vendor/README.md +60 -0
- package/skills/engineering/resolve-release/vendor/acorn.mjs +6233 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/LICENSE +21 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/README.md +341 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/README.template.md +70 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs +7 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.mts +2033 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.ts +2033 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js +7 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/package.json +49 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/LICENSE +21 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/README.md +5 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.mts +549 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.ts +549 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/package.json +36 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/LICENSE +47 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/README.md +82 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.d.ts +11 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.mjs +22 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cjs +21 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.cjs +21 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.d.ts +11 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.d.ts +11 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.mjs +25 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.wasm +0 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.mts +85 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.ts +85 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.mts +20 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.ts +20 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/package.json +61 -0
- package/skills/engineering/review-pr/LICENSE +3 -0
- package/skills/engineering/review-pr/SKILL.md +123 -0
- package/skills/engineering/review-pr/references/adversarial-reviewer-prompt.md +42 -0
- package/skills/engineering/review-pr/references/code-correctness.md +5 -0
- package/skills/engineering/review-pr/references/contract-freshness.md +9 -0
- package/skills/engineering/review-pr/references/coordination.md +18 -0
- package/skills/engineering/review-pr/references/domain-hazards.md +123 -0
- package/skills/engineering/review-pr/references/finding-themes.md +7 -0
- package/skills/engineering/review-pr/references/github-posting.md +98 -0
- package/skills/engineering/review-pr/references/golden-path-smoke.md +5 -0
- package/skills/engineering/review-pr/references/incremental-output.md +16 -0
- package/skills/engineering/review-pr/references/inputs-and-discovery.md +31 -0
- package/skills/engineering/review-pr/references/output-format.md +99 -0
- package/skills/engineering/review-pr/references/over-mock-screen.md +7 -0
- package/skills/engineering/review-pr/references/promotion-prs.md +16 -0
- package/skills/engineering/review-pr/references/re-review.md +18 -0
- package/skills/engineering/review-pr/references/review-method.md +199 -0
- package/skills/engineering/review-pr/references/review-mode.md +30 -0
- package/skills/engineering/review-pr/references/review-posture.md +53 -0
- package/skills/engineering/review-pr/references/round1-depth.md +62 -0
- package/skills/engineering/review-pr/references/scripts.md +17 -0
- package/skills/engineering/review-pr/references/workflow.md +16 -0
- package/skills/engineering/review-pr/schemas/findings.schema.json +282 -0
- package/skills/engineering/review-pr/scripts/finding-contract.mjs +285 -0
- package/skills/engineering/review-pr/scripts/post-review.mjs +405 -0
- package/skills/engineering/review-pr/scripts/pr-context.mjs +207 -0
- package/skills/engineering/review-pr/scripts/scan-diff.mjs +365 -0
- package/skills/engineering/review-pr/scripts/theme-contract.mjs +57 -0
- package/skills/engineering/smoke/LICENSE +3 -0
- package/skills/engineering/smoke/SKILL.md +131 -0
- package/skills/engineering/smoke/assets/smoke.manifest.example.json +53 -0
- package/skills/engineering/smoke/references/manifest.md +192 -0
- package/skills/engineering/smoke/scripts/smoke.mjs +713 -0
- package/skills/fullstack/better-auth/LICENSE +3 -0
- package/skills/fullstack/better-auth/SKILL.md +601 -0
- package/skills/fullstack/better-auth/references/feishu-api.md +270 -0
- package/skills/fullstack/monorepo/LICENSE +3 -0
- package/skills/fullstack/monorepo/SKILL.md +465 -0
- package/skills/fullstack/nextjs-fullstack/LICENSE +3 -0
- package/skills/fullstack/nextjs-fullstack/SKILL.md +210 -0
- package/skills/fullstack/nextjs-fullstack/conventions.md +318 -0
- package/skills/fullstack/nextjs-fullstack/frontend-conventions.md +61 -0
- package/skills/fullstack/nextjs-fullstack/nextjs16.md +287 -0
- package/skills/fullstack/nextjs-fullstack/server-actions.md +409 -0
- package/skills/fullstack/prisma-setup/LICENSE +3 -0
- package/skills/fullstack/prisma-setup/SKILL.md +180 -0
- package/skills/fullstack/prisma-setup/nextjs.md +258 -0
- package/skills/fullstack/prisma-setup/turborepo.md +301 -0
- package/skills/fullstack/shadcn/LICENSE +3 -0
- package/skills/fullstack/shadcn/SKILL.md +119 -0
- package/skills/fullstack/shadcn/assets/shadcn-small.png +0 -0
- package/skills/fullstack/shadcn/assets/shadcn.png +0 -0
- package/skills/fullstack/shadcn/cli.md +411 -0
- package/skills/fullstack/shadcn/customization.md +224 -0
- package/skills/fullstack/shadcn/evals/evals.json +90 -0
- package/skills/fullstack/shadcn/mcp.md +101 -0
- package/skills/fullstack/shadcn/rules/base-vs-radix.md +323 -0
- package/skills/fullstack/shadcn/rules/component-selection.md +67 -0
- package/skills/fullstack/shadcn/rules/composition.md +195 -0
- package/skills/fullstack/shadcn/rules/data-table.md +201 -0
- package/skills/fullstack/shadcn/rules/forms.md +255 -0
- package/skills/fullstack/shadcn/rules/icons.md +103 -0
- package/skills/fullstack/shadcn/rules/styling.md +167 -0
- package/skills/fullstack/zod-v4/LICENSE +3 -0
- package/skills/fullstack/zod-v4/SKILL.md +287 -0
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
// coverage-checklist — the method-tagged coverage checklist for the Review Contract.
|
|
2
|
+
//
|
|
3
|
+
// node coverage-checklist.mjs generate [--diff <base>] [--ci <files>] [--ledger] [--sweep <results.json>] [--smoke <results.json>]
|
|
4
|
+
// [--parity <manifest> --parity-observed <results.json>]
|
|
5
|
+
// → emits the checklist markdown with GATE rows AUTO-FILLED (decision+evidence)
|
|
6
|
+
// from the tools, and lead/judgment rows as a skeleton to complete.
|
|
7
|
+
// node coverage-checklist.mjs validate <checklist.md> [--root <dir>] [--diff <base>] [--no-resolve]
|
|
8
|
+
// → the anti-ritual guard: fails if any PASS/FAIL row lacks an evidence
|
|
9
|
+
// locator (file:line / a `command` / #issue), or a gate row is left TODO,
|
|
10
|
+
// or a cited file:line does not RESOLVE in the tree, or a gate row cites
|
|
11
|
+
// its command without the result. Pass `--diff <base>` so deletions are
|
|
12
|
+
// exempt and outside-the-diff locators are warned; `--no-resolve` falls
|
|
13
|
+
// back to the shape-only check.
|
|
14
|
+
//
|
|
15
|
+
// The point (one rule for machine and model alike): EVERY row resolves to a
|
|
16
|
+
// decision backed by checkable evidence. The only thing that varies is who
|
|
17
|
+
// produces the evidence —
|
|
18
|
+
// gate-lint : a tool decides + blocks (evidence = its command/output)
|
|
19
|
+
// lead : a tool surfaces candidates; a human adjudicates each (evidence = lead + verdict + file:line)
|
|
20
|
+
// judgment : a human reasons from code (evidence = file:line + argument)
|
|
21
|
+
// The method per row is fixed HERE (doctrine), never chosen per-PR — otherwise a
|
|
22
|
+
// hard row gets self-classified as "lint ✓". A judgment row whose evidence later
|
|
23
|
+
// becomes mechanizable is promoted to gate-lint (and to a lint-tests/ledger rule).
|
|
24
|
+
|
|
25
|
+
import fs from 'node:fs'
|
|
26
|
+
import path from 'node:path'
|
|
27
|
+
import { execFileSync } from 'node:child_process'
|
|
28
|
+
import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
|
|
29
|
+
|
|
30
|
+
const HERE = path.dirname(new URL(import.meta.url).pathname)
|
|
31
|
+
|
|
32
|
+
// ---- The catalog (doctrine-fixed; method per row is not negotiable per-PR) ----
|
|
33
|
+
export const CHECKLIST = [
|
|
34
|
+
// Breadth — the surface set and its ownership.
|
|
35
|
+
{ id: 'breadth.inventory-fresh', axis: 'Breadth', check: 'Surface inventory + route manifest regenerated; no drift', method: 'gate-lint', cmd: 'gen-inventory + `git diff --exit-code` (CI gate 1)' },
|
|
36
|
+
{ id: 'breadth.ownership', axis: 'Breadth', check: 'Every changed surface is owned and proven at its floor (no Missing/Orphan)', method: 'gate-lint', cmd: '`coverage-ledger.mjs validate`' },
|
|
37
|
+
{ id: 'breadth.right-surfaces', axis: 'Breadth', check: 'No un-specced capability missed — the surfaces no AC mentions', method: 'judgment' },
|
|
38
|
+
{ id: 'breadth.reachability', axis: 'Breadth', check: 'Reachability/mutation classification is correct for changed surfaces', method: 'judgment' },
|
|
39
|
+
// Depth — test level, mocks, meaningfulness.
|
|
40
|
+
{ id: 'depth.no-skip', axis: 'Depth', check: 'No test skipped/focused/xfail added', method: 'gate-lint', cmd: '`lint-tests.mjs --rules no-skip --diff <base>`' },
|
|
41
|
+
{ id: 'depth.no-fixed-timeout', axis: 'Depth', check: 'No fixed sleep added (waitForTimeout / numeric cy.wait / time.sleep)', method: 'gate-lint', cmd: '`lint-tests.mjs --rules no-fixed-timeout --diff <base>`' },
|
|
42
|
+
{ id: 'depth.no-empty-test', axis: 'Depth', check: 'No empty/placeholder test body added (passes vacuously, asserts nothing)', method: 'gate-lint', cmd: '`lint-tests.mjs --rules no-empty-test --diff <base>`' },
|
|
43
|
+
{ id: 'depth.asserts-something', axis: 'Depth', check: 'Each added test actually asserts a behavior (not a no-op or helper-only render-health mislabeled as a journey)', method: 'lead', cmd: '`review-pr/scan-diff.mjs` / read the test' },
|
|
44
|
+
{ id: 'depth.level-meets-floor', axis: 'Depth', check: 'Declared @level meets each surface floor (no Wrong Level)', method: 'gate-lint', cmd: '`coverage-ledger.mjs validate`' },
|
|
45
|
+
{ id: 'depth.interception', axis: 'Depth', check: 'First-party interception in a behaviour/journey test is justified, not counted as real coverage', method: 'lead', cmd: '`review-pr/scan-diff.mjs` / ledger Over-mocked' },
|
|
46
|
+
// The decidable subset of over-mocking (a test that mocks a first-party seam module)
|
|
47
|
+
// is a default-on, zero-tolerance gate-lint: no opt-in, no waiver, no grandfathering.
|
|
48
|
+
// The cross-file "is there a real-boundary sibling?" judgment stays the
|
|
49
|
+
// depth.interception lead above.
|
|
50
|
+
{ id: 'depth.no-mock-internal-seam', axis: 'Depth', check: 'No mock of a first-party internal seam module (real internals, faked externals) — zero-tolerance: PR-lane (new) AND whole-tree (inherited); no `@mock-ok` waiver; resolve by making it real, faking the external, or DELETING the test (over-mock is worse than no test); a false positive is fixed by correcting topology in coverage.config.json', method: 'gate-lint', cmd: '`lint-tests.mjs --rules mock-internal-seam --diff <base>` (PR lane) + `lint-tests.mjs --rules mock-internal-seam` (whole-tree)' },
|
|
51
|
+
{ id: 'depth.mock-acceptable', axis: 'Depth', check: 'Mock use respects the boundary; money/auth/idempotency never mock-only', method: 'judgment' },
|
|
52
|
+
{ id: 'depth.assertions-meaningful', axis: 'Depth', check: 'Assertions are behavior-first; none pass on a 404 / empty / error page', method: 'judgment' },
|
|
53
|
+
{ id: 'depth.branch-coverage', axis: 'Depth', check: 'Every new branch / error path has a driving test', method: 'lead' },
|
|
54
|
+
{ id: 'depth.characterization', axis: 'Depth', check: 'Diffs that modify existing behavior are pinned by a characterization test (prior behavior) before the change — or an intended change is declared with its AC', method: 'lead', cmd: '`review-pr/scan-diff.mjs` modifies-existing-behavior' },
|
|
55
|
+
// Runtime smoke — the built thing actually runs. The non-browser counterpart to
|
|
56
|
+
// pres.sweep (which is the browser runtime gate). The repo/agent runs the surface
|
|
57
|
+
// however it boots (a run command, a curl, a CLI invocation) and writes a results
|
|
58
|
+
// file; this gate ingests it. Agent-agnostic: enforcement is the results file + CI,
|
|
59
|
+
// not any harness "run the app" feature.
|
|
60
|
+
{ id: 'depth.runtime-smoke', axis: 'Depth', check: 'Runtime smoke: each changed non-browser surface (service/API/CLI/job) was actually run via the repo run command and its happy path responded (boots, no 500/crash on first call) — green tests alone do not prove the thing runs; browser surfaces use the presentation sweep instead', method: 'gate-lint', cmd: 'runtime-smoke results (`--smoke <results.json>`)' },
|
|
61
|
+
// Presentation — real render.
|
|
62
|
+
{ id: 'pres.render-health-floor', axis: 'Presentation', check: 'render-health is in the floor for every changed browser route', method: 'gate-lint', cmd: '`coverage-ledger.mjs validate`' },
|
|
63
|
+
{ id: 'pres.sweep', axis: 'Presentation', check: 'Presentation sweep ran (runtime gate): no pageerror/overflow/overlap/shift; nothing blocked', method: 'gate-lint', cmd: 'presentation-sweep results (e2e-test)' },
|
|
64
|
+
{ id: 'pres.no-first-party-intercept', axis: 'Presentation', check: 'Sweep specs do not intercept first-party traffic', method: 'lead', cmd: '`review-pr/scan-diff.mjs` / ledger' },
|
|
65
|
+
{ id: 'pres.perceivability', axis: 'Presentation', check: 'Perceivability edge cases the instruments cannot score are checked', method: 'judgment' },
|
|
66
|
+
// Fidelity is the one presentation question that is NOT self-referential: every
|
|
67
|
+
// other row (and `presentation:visual`) takes the implementation as its own
|
|
68
|
+
// authority, so a page built wrong from a right design passes all of them.
|
|
69
|
+
// N/A when the unit cites no design source — mark it so, with the reason.
|
|
70
|
+
{ id: 'pres.fidelity', axis: 'Presentation', check: 'When the unit cites a design source (prototype/mockup/design doc): the parity manifest is complete, its citations resolve, and every pinned property holds against the rendered page', method: 'gate-lint', cmd: '`design-parity.mjs validate <manifest> --observed <results.json>`' },
|
|
71
|
+
{ id: 'pres.source-render', axis: 'Presentation', check: 'Design source and deliverable rendered side by side at the floor viewports — the check that fails when the parity manifest itself is incomplete', method: 'judgment' },
|
|
72
|
+
// Enforcement — the gates themselves.
|
|
73
|
+
{ id: 'enforce.gates-wired', axis: 'Enforcement', check: 'CI wires all required gates and keeps them blocking', method: 'gate-lint', cmd: '`ci-audit.mjs --files <ci>`' },
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
const AXES = ['Breadth', 'Depth', 'Presentation', 'Enforcement']
|
|
77
|
+
|
|
78
|
+
// ---- Pure: evidence locator check (the anti-ritual guard) ----
|
|
79
|
+
// A decision is only real if a second reader can re-check it: a file:line, an
|
|
80
|
+
// inline `command`, an http link, or a #issue. Prose alone is not evidence.
|
|
81
|
+
export function hasLocator(s = '') {
|
|
82
|
+
return /[\w./-]+\.\w+:\d+/.test(s) // path/to/file.ext:line
|
|
83
|
+
|| /`[^`]+`/.test(s) // inline command / code
|
|
84
|
+
|| /https?:\/\//.test(s) // link
|
|
85
|
+
|| /#\d+/.test(s) // issue/PR ref
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ---- Pure: locator RESOLUTION (the shape guard is not a truth guard) ----
|
|
89
|
+
//
|
|
90
|
+
// `hasLocator` above asks whether the evidence LOOKS like a locator. It cannot
|
|
91
|
+
// ask whether the locator is TRUE, so three shaped-but-false rows sail through
|
|
92
|
+
// it — and each one is an evidence-class review finding, which under
|
|
93
|
+
// `resolve-issues` costs a full fix + re-review round:
|
|
94
|
+
//
|
|
95
|
+
// PASS | `_run_ \`coverage-ledger.mjs validate\`` the skeleton, never run
|
|
96
|
+
// PASS | `src/gone.ts:9999 — looks fine` file/line does not exist
|
|
97
|
+
// PASS | `see #1` a ref to anything at all
|
|
98
|
+
//
|
|
99
|
+
// So `validate` now RESOLVES what it can decide. The checks below are the
|
|
100
|
+
// decidable subset only; each has a named incident behind it (see
|
|
101
|
+
// resolve-issues → references/why.md#the-checklist-screens-resolve-locators):
|
|
102
|
+
//
|
|
103
|
+
// A a cited path:line must exist in the tree, at a line inside the file
|
|
104
|
+
// (incident: a reviewer blocking solely on a checklist citing a pre-restack
|
|
105
|
+
// base, then spending the next round rejecting the checklist fix)
|
|
106
|
+
// B a gate-lint row must carry the gate's RESULT, not just its command
|
|
107
|
+
// (incident: a hand-written attestation claiming `leadCount=0` for a diff
|
|
108
|
+
// whose real scan had 1,749 leads — a full review round on a transcription)
|
|
109
|
+
// C a row citing only paths outside the net diff is WARNED, never blocked —
|
|
110
|
+
// the stale-locator smell, too false-positive-prone to be a violation
|
|
111
|
+
//
|
|
112
|
+
// Deleted-by-this-PR paths are exempt from A: "removed the over-mocked test at
|
|
113
|
+
// tests/foo.spec.ts:40" is a true locator that resolves to nothing on purpose.
|
|
114
|
+
// That exemption needs the diff, so WITHOUT `--diff` a missing file is downgraded
|
|
115
|
+
// to a warning — stale and deleted are indistinguishable there, and a screen that
|
|
116
|
+
// blocks honest evidence costs the round it exists to save. Paths are resolved
|
|
117
|
+
// against the git toplevel (not the cwd) and retried against the cwd, for the same
|
|
118
|
+
// reason: every wrong block is more expensive than a wrong pass here, because the
|
|
119
|
+
// reviewer is still downstream and catches what this misses.
|
|
120
|
+
|
|
121
|
+
// URLs carry `host.tld:port`, which is shaped exactly like `path.ext:line`.
|
|
122
|
+
// Strip them before extracting or every `https://ci:8080/x` reads as a dead file.
|
|
123
|
+
const LOCATOR_RE = /(^|[\s(<[`'",])([\w.][\w./-]*\.\w{1,12}):(\d+)/g
|
|
124
|
+
|
|
125
|
+
export function extractLocators(s = '') {
|
|
126
|
+
const text = String(s).replace(/https?:\/\/\S+/g, ' ')
|
|
127
|
+
const out = []
|
|
128
|
+
for (const m of text.matchAll(LOCATOR_RE)) {
|
|
129
|
+
const line = Number(m[3])
|
|
130
|
+
if (line > 0) out.push({ path: m[2], line })
|
|
131
|
+
}
|
|
132
|
+
return out
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// A gate row's evidence has to say what the gate RETURNED, not just which gate it
|
|
136
|
+
// was. The thing actually being caught is the generated SKELETON with a decision
|
|
137
|
+
// typed over it — so match on that rather than on how a result is phrased.
|
|
138
|
+
//
|
|
139
|
+
// An earlier version enumerated outcome markers (`→`, `exit N`, "0 findings"). That
|
|
140
|
+
// list rejected `\`coverage-ledger.mjs validate\` — clean` and `... passed`, which
|
|
141
|
+
// are ordinary honest results, and no list would ever be finished. The property
|
|
142
|
+
// that separates a skeleton from a result needs no vocabulary: strip the command
|
|
143
|
+
// (an inline code span) and the skeleton's own emphasis annotation (`_run_`,
|
|
144
|
+
// `_cite ..._`), and a skeleton has NOTHING left, while any real result does.
|
|
145
|
+
//
|
|
146
|
+
// Rows reaching here already passed `hasLocator`, so a gate row with no code span
|
|
147
|
+
// at all was caught upstream — this cannot be fooled by dropping the backticks.
|
|
148
|
+
//
|
|
149
|
+
// `cmd` is the row's catalog command when the caller knows it. With it, "is this
|
|
150
|
+
// the skeleton?" stops being a heuristic and becomes exact: the skeleton IS
|
|
151
|
+
// `_run_ ${cmd}` by construction, so subtracting the cmd leaves nothing. Without
|
|
152
|
+
// it the rule still works for the common `_run_ \`cmd\`` shape, but a catalog
|
|
153
|
+
// command carrying un-backticked text (`gen-inventory + \`git diff\` (CI gate 1)`)
|
|
154
|
+
// would leak its own prose through as if it were a result — which is exactly what
|
|
155
|
+
// the catalog-derived test in this suite exists to keep catching.
|
|
156
|
+
export function hasGateOutcome(s = '', cmd = '') {
|
|
157
|
+
const text = String(s)
|
|
158
|
+
if (extractLocators(text).length > 0) return true // a failing lint gate's hits ARE its result
|
|
159
|
+
// A verdict glyph is a terse but complete result, and the symbol-stripping below
|
|
160
|
+
// would otherwise eat it. This is a closed set of marks, not an open vocabulary
|
|
161
|
+
// of English words — which is the thing that made the first version unmaintainable.
|
|
162
|
+
if (/[✓✔✗✘❌✅]/u.test(text)) return true
|
|
163
|
+
let residue = text
|
|
164
|
+
if (cmd) residue = residue.split(String(cmd)).join(' ') // literal, never a regex — cmd contains + ( ) etc.
|
|
165
|
+
const cleaned = residue
|
|
166
|
+
.replace(/`[^`]*`/g, ' ') // the command itself
|
|
167
|
+
.replace(/_[^_]*_|\*[^*]*\*/g, ' ') // the skeleton's own _run_ / _cite …_ annotation
|
|
168
|
+
.replace(/[\s\p{P}\p{S}]+/gu, ' ') // punctuation and separators are not a result
|
|
169
|
+
.trim()
|
|
170
|
+
return cleaned.length > 0
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// The catalog command for a parsed row, matched on its check text — `parseChecklist`
|
|
174
|
+
// keeps the check column verbatim, so this is a lookup rather than a guess.
|
|
175
|
+
function catalogCmd(check, catalog) {
|
|
176
|
+
return catalog.find((r) => r.check === check)?.cmd || ''
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// ---- Pure: render the checklist (gate rows filled from results, rest skeleton) ----
|
|
180
|
+
function skeletonEvidence(row) {
|
|
181
|
+
if (row.method === 'gate-lint') return `_run_ ${row.cmd || '(tool)'}`
|
|
182
|
+
if (row.method === 'lead') return `_adjudicate the lead — cite \`file:line\` + verdict_`
|
|
183
|
+
return `_cite \`file:line\` + reasoning_`
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function renderChecklist(catalog, results = {}) {
|
|
187
|
+
const out = ['## Coverage Checklist', '', '_Every row = a decision (PASS / FAIL / N/A) backed by a checkable evidence locator (`file:line`, a rerunnable `command`, or #issue). Gate rows are auto-filled by `coverage-checklist.mjs generate`; lead/judgment rows are completed by the reviewer. `coverage-checklist.mjs validate` fails a PASS/FAIL row with no locator, a gate row left TODO, **a cited `file:line` that does not resolve in the tree**, and **a gate row citing its command without the result** — cite the outcome (exit code, `→ N findings`, or the hits), never the command alone._', '']
|
|
188
|
+
for (const axis of AXES) {
|
|
189
|
+
const rows = catalog.filter((r) => r.axis === axis)
|
|
190
|
+
if (!rows.length) continue
|
|
191
|
+
out.push(`### ${axis}`, '', '| Check | Method | Decision | Evidence |', '|---|---|---|---|')
|
|
192
|
+
for (const r of rows) {
|
|
193
|
+
const filled = results[r.id]
|
|
194
|
+
const decision = filled?.decision || 'TODO'
|
|
195
|
+
const evidence = filled?.evidence || skeletonEvidence(r)
|
|
196
|
+
out.push(`| ${r.check} | ${r.method} | ${decision} | ${evidence} |`)
|
|
197
|
+
}
|
|
198
|
+
out.push('')
|
|
199
|
+
}
|
|
200
|
+
return out.join('\n')
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ---- Pure: parse a (completed) checklist back into rows ----
|
|
204
|
+
export function parseChecklist(md) {
|
|
205
|
+
const rows = []
|
|
206
|
+
for (const line of (md || '').split(/\r?\n/)) {
|
|
207
|
+
if (!line.trim().startsWith('|')) continue
|
|
208
|
+
const cells = line.split('|').slice(1, -1).map((c) => c.trim())
|
|
209
|
+
if (cells.length < 4) continue
|
|
210
|
+
const [check, method, decision, evidence] = cells
|
|
211
|
+
if (/^-+$/.test(check) || method.toLowerCase() === 'method') continue // separator / header
|
|
212
|
+
if (!['gate-lint', 'lead', 'judgment'].includes(method)) continue
|
|
213
|
+
rows.push({ check, method, decision, evidence })
|
|
214
|
+
}
|
|
215
|
+
return rows
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ---- Pure: the anti-ritual guard ----
|
|
219
|
+
//
|
|
220
|
+
// opts (all optional — with none of them this is the pre-resolution shape check,
|
|
221
|
+
// which is what every existing caller gets):
|
|
222
|
+
// resolveFile(path) → { lines } | null how to look a cited path up in the tree
|
|
223
|
+
// deletedFiles: string[] paths this PR deletes (exempt from check A)
|
|
224
|
+
// changedFiles: string[] the net diff's paths (enables warning C)
|
|
225
|
+
// Returns violations; `warnings` ride on the array as a property so the
|
|
226
|
+
// exit-code contract (violations block, warnings do not) stays one call.
|
|
227
|
+
export function validateRows(rows, opts = {}) {
|
|
228
|
+
const { resolveFile, deletedFiles = [], changedFiles = null, catalog = CHECKLIST } = opts
|
|
229
|
+
const deleted = new Set(deletedFiles)
|
|
230
|
+
const changed = changedFiles && new Set(changedFiles)
|
|
231
|
+
// Whether the caller could supply the diff at all. It is what makes an
|
|
232
|
+
// unresolvable path decidable rather than ambiguous — see check A below.
|
|
233
|
+
const diffKnown = Array.isArray(changedFiles)
|
|
234
|
+
const violations = []
|
|
235
|
+
const warnings = []
|
|
236
|
+
for (const r of rows) {
|
|
237
|
+
const d = (r.decision || '').toUpperCase().replace(/[\[\]\s]/g, '')
|
|
238
|
+
const pass = d === 'PASS' || d === 'X' || d === '✓'
|
|
239
|
+
const fail = d === 'FAIL' || d === '✗'
|
|
240
|
+
const na = d === 'N/A' || d === 'NA'
|
|
241
|
+
if (pass || fail) {
|
|
242
|
+
if (!hasLocator(r.evidence)) {
|
|
243
|
+
violations.push({ check: r.check, problem: `${d} with no evidence locator — need a file:line, a rerunnable \`command\`, or #issue` })
|
|
244
|
+
continue
|
|
245
|
+
}
|
|
246
|
+
// B — a gate row that names its command but not its result is the skeleton
|
|
247
|
+
// with a decision typed over it. Nothing downstream can tell those apart.
|
|
248
|
+
if (r.method === 'gate-lint' && !hasGateOutcome(r.evidence, catalogCmd(r.check, catalog))) {
|
|
249
|
+
violations.push({ check: r.check, problem: `${d} cites the gate's command but not its result — paste the outcome (exit code, "→ N findings", or the file:line hits), not the command alone` })
|
|
250
|
+
}
|
|
251
|
+
// A — every cited path:line must resolve, unless this PR deleted the file.
|
|
252
|
+
//
|
|
253
|
+
// A MISSING file is only decidable with diff context. "removed the over-mocked
|
|
254
|
+
// test at tests/foo.spec.ts:40" is a true locator that resolves to nothing on
|
|
255
|
+
// purpose, and without the deletion set it is indistinguishable from a stale
|
|
256
|
+
// one. Blocking on it would cost the round this screen exists to save, so with
|
|
257
|
+
// no diff supplied it warns. A line PAST EOF needs no such care: the file is
|
|
258
|
+
// right there and is too short, which no deletion can explain.
|
|
259
|
+
const locators = extractLocators(r.evidence)
|
|
260
|
+
if (resolveFile) {
|
|
261
|
+
for (const loc of locators) {
|
|
262
|
+
if (deleted.has(loc.path)) continue
|
|
263
|
+
const found = resolveFile(loc.path)
|
|
264
|
+
if (!found) {
|
|
265
|
+
const problem = `evidence cites ${loc.path}:${loc.line}, which does not exist in the tree — a stale locator is not evidence`
|
|
266
|
+
if (diffKnown) violations.push({ check: r.check, problem })
|
|
267
|
+
else warnings.push({ check: r.check, problem: `${problem.replace(' — a stale locator is not evidence', '')}; with no --diff supplied this check cannot tell a stale locator from a deleted one, so it warns rather than blocks — re-run with --diff <merge-base> to decide it` })
|
|
268
|
+
} else if (loc.line > found.lines) {
|
|
269
|
+
violations.push({ check: r.check, problem: `evidence cites ${loc.path}:${loc.line}, but ${loc.path} has ${found.lines} line(s) — the locator points past the end of the file` })
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// C — smell, not a defect: every path this row cites sits outside the diff.
|
|
274
|
+
if (changed && locators.length && locators.every((l) => !changed.has(l.path) && !deleted.has(l.path))) {
|
|
275
|
+
warnings.push({ check: r.check, problem: `every cited path (${locators.map((l) => l.path).join(', ')}) is outside the net diff — check it is not a pre-rebase locator` })
|
|
276
|
+
}
|
|
277
|
+
} else if (na) {
|
|
278
|
+
if (!r.evidence || !r.evidence.replace(/[_*]/g, '').trim()) violations.push({ check: r.check, problem: 'N/A with no reason' })
|
|
279
|
+
} else {
|
|
280
|
+
violations.push({ check: r.check, problem: r.method === 'gate-lint' ? 'gate row left TODO — auto-fill it (coverage-checklist.mjs generate)' : 'undecided (TODO) — decide and cite evidence' })
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
// Non-enumerable on purpose: callers (and their assert.deepEqual) still see a
|
|
284
|
+
// plain array of violations, and the exit code stays a function of that array.
|
|
285
|
+
Object.defineProperty(violations, 'warnings', { value: warnings })
|
|
286
|
+
return violations
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// ---- CLI gathering (best-effort; a tool that errors → row stays skeleton) ----
|
|
290
|
+
function tryJSON(file, args) {
|
|
291
|
+
try { return JSON.parse(execFileSync('node', [path.join(HERE, file), ...args, '--json'], { encoding: 'utf8' })) }
|
|
292
|
+
catch (e) { try { return JSON.parse(e.stdout || '') } catch { return null } } // non-zero exit still prints JSON
|
|
293
|
+
}
|
|
294
|
+
function tryExit(file, args) {
|
|
295
|
+
try { execFileSync('node', [path.join(HERE, file), ...args], { encoding: 'utf8' }); return { code: 0 } }
|
|
296
|
+
catch (e) { return { code: e.status ?? 1, out: (e.stdout || '').trim() } }
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function gather(flags) {
|
|
300
|
+
const results = {}
|
|
301
|
+
// lint-tests (no-skip + no-fixed-timeout), diff or files
|
|
302
|
+
const scope = flags.diff ? ['--diff', flags.diff] : flags.files ? ['--files', flags.files] : null
|
|
303
|
+
if (scope) {
|
|
304
|
+
const lint = tryJSON('lint-tests.mjs', scope)
|
|
305
|
+
if (lint) {
|
|
306
|
+
for (const [rid, rule] of [['depth.no-skip', 'no-skip'], ['depth.no-fixed-timeout', 'no-fixed-timeout']]) {
|
|
307
|
+
const hits = lint.findings.filter((f) => f.rule === rule)
|
|
308
|
+
results[rid] = hits.length
|
|
309
|
+
? { decision: 'FAIL', evidence: hits.map((f) => `${f.file}:${f.line}`).join(', ') }
|
|
310
|
+
: { decision: 'PASS', evidence: `\`lint-tests.mjs --rules ${rule} ${scope.join(' ')}\` → 0 findings` }
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// ci-audit
|
|
315
|
+
if (flags.ci) {
|
|
316
|
+
const audit = tryJSON('ci-audit.mjs', ['--files', flags.ci])
|
|
317
|
+
if (audit) results['enforce.gates-wired'] = {
|
|
318
|
+
decision: audit.ok ? 'PASS' : 'FAIL',
|
|
319
|
+
evidence: `\`ci-audit.mjs --files ${flags.ci}\` → ${audit.gates.map((g) => `${g.key}:${g.status}`).join(', ')}`,
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// ledger validate (exit-code based) → fills the three ledger-backed rows
|
|
323
|
+
if (flags.ledger) {
|
|
324
|
+
const r = tryExit('coverage-ledger.mjs', ['validate'])
|
|
325
|
+
const summary = (r.out || '').split('\n').filter(Boolean).pop() || ''
|
|
326
|
+
const dec = r.code === 0 ? 'PASS' : 'FAIL'
|
|
327
|
+
const ev = `\`coverage-ledger.mjs validate\` (exit ${r.code})${summary ? ` — ${summary}` : ''}`
|
|
328
|
+
for (const rid of ['breadth.ownership', 'depth.level-meets-floor', 'pres.render-health-floor']) results[rid] = { decision: dec, evidence: ev }
|
|
329
|
+
}
|
|
330
|
+
// runtime-smoke results file (non-browser surfaces) — same shape as the sweep:
|
|
331
|
+
// a list of { surface|id|cmd, status } where status fail/blocked/error = not-ran.
|
|
332
|
+
if (flags.smoke && fs.existsSync(flags.smoke)) {
|
|
333
|
+
try {
|
|
334
|
+
const smoke = JSON.parse(fs.readFileSync(flags.smoke, 'utf8'))
|
|
335
|
+
const list = Array.isArray(smoke) ? smoke : smoke.results || []
|
|
336
|
+
const bad = list.filter((x) => x.status === 'fail' || x.status === 'blocked' || x.status === 'error')
|
|
337
|
+
results['depth.runtime-smoke'] = bad.length
|
|
338
|
+
? { decision: 'FAIL', evidence: `${flags.smoke}: ${bad.map((b) => `${b.surface || b.id || b.cmd}:${b.status}`).slice(0, 5).join(', ')}` }
|
|
339
|
+
: { decision: 'PASS', evidence: `\`${flags.smoke}\` → ${list.length} surface(s), 0 fail` }
|
|
340
|
+
} catch { /* leave skeleton */ }
|
|
341
|
+
}
|
|
342
|
+
// design-parity: fidelity against the cited design source. Deliberately fills
|
|
343
|
+
// only when BOTH the manifest and the observed results are supplied — a
|
|
344
|
+
// manifest-only run is design-parity's own "reduced form" (it never looks at the
|
|
345
|
+
// page), and auto-filling a gate row from it would launder that into a PASS.
|
|
346
|
+
if (flags.parity && fs.existsSync(flags.parity)) {
|
|
347
|
+
const args = ['validate', flags.parity]
|
|
348
|
+
if (flags.parityObserved) args.push('--observed', flags.parityObserved)
|
|
349
|
+
const r = tryExit('design-parity.mjs', args)
|
|
350
|
+
if (!flags.parityObserved) {
|
|
351
|
+
results['pres.fidelity'] = { decision: 'TODO', evidence: `\`design-parity.mjs validate ${flags.parity}\` ran WITHOUT --observed (reduced form: manifest checked, page not). Re-run with --parity-observed <results.json>.` }
|
|
352
|
+
} else {
|
|
353
|
+
const tail = (r.out || '').split('\n').filter(Boolean).slice(-3).join(' · ')
|
|
354
|
+
results['pres.fidelity'] = {
|
|
355
|
+
decision: r.code === 0 ? 'PASS' : 'FAIL',
|
|
356
|
+
evidence: `\`design-parity.mjs validate ${flags.parity} --observed ${flags.parityObserved}\` (exit ${r.code})${tail ? ` — ${tail}` : ''}`,
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
// presentation sweep results file
|
|
361
|
+
if (flags.sweep && fs.existsSync(flags.sweep)) {
|
|
362
|
+
try {
|
|
363
|
+
const sweep = JSON.parse(fs.readFileSync(flags.sweep, 'utf8'))
|
|
364
|
+
const list = Array.isArray(sweep) ? sweep : sweep.results || []
|
|
365
|
+
const bad = list.filter((x) => x.status === 'fail' || x.status === 'blocked')
|
|
366
|
+
results['pres.sweep'] = bad.length
|
|
367
|
+
? { decision: 'FAIL', evidence: `${flags.sweep}: ${bad.map((b) => `${b.route || b.id}:${b.status}`).slice(0, 5).join(', ')}` }
|
|
368
|
+
: { decision: 'PASS', evidence: `\`${flags.sweep}\` → ${list.length} routes, 0 fail/blocked` }
|
|
369
|
+
} catch { /* leave skeleton */ }
|
|
370
|
+
}
|
|
371
|
+
return results
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Checklist locators are REPO-relative — that is what every generator emits
|
|
375
|
+
// (`lint-tests` hits, ledger rows, sweep results). Anchoring them at `process.cwd()`
|
|
376
|
+
// means the same honest checklist passes from the repo root and fails from
|
|
377
|
+
// `apps/web/`, reporting real files as "does not exist in the tree": a screen that
|
|
378
|
+
// blocks a true claim, which is the failure mode this whole check is written
|
|
379
|
+
// around. So the default anchor is the git toplevel, and each path is tried
|
|
380
|
+
// against the cwd as well before it is called missing — on ambiguity this fails
|
|
381
|
+
// open, because the cost of a wrong block is a round and the cost of a wrong pass
|
|
382
|
+
// is one reviewer comment.
|
|
383
|
+
function repoRoot(explicit) {
|
|
384
|
+
if (explicit) return explicit
|
|
385
|
+
try {
|
|
386
|
+
return execFileSync('git', ['rev-parse', '--show-toplevel'], { encoding: 'utf8' }).trim() || process.cwd()
|
|
387
|
+
} catch { return process.cwd() } // not a git checkout — cwd is the only anchor there is
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// Resolve a cited path against the tree the producer is about to push — the
|
|
391
|
+
// working tree, not a git object: that is the code the reviewer will read.
|
|
392
|
+
function fileResolver(root) {
|
|
393
|
+
const cache = new Map()
|
|
394
|
+
const anchors = [...new Set([root, process.cwd()])]
|
|
395
|
+
return (p) => {
|
|
396
|
+
if (cache.has(p)) return cache.get(p)
|
|
397
|
+
const candidates = path.isAbsolute(p) ? [p] : anchors.map((a) => path.join(a, p))
|
|
398
|
+
let out = null
|
|
399
|
+
for (const abs of candidates) {
|
|
400
|
+
try {
|
|
401
|
+
if (!fs.statSync(abs).isFile()) continue
|
|
402
|
+
const text = fs.readFileSync(abs, 'utf8')
|
|
403
|
+
// A trailing newline does not make a final empty line citable.
|
|
404
|
+
out = { lines: text.length ? text.replace(/\n$/, '').split('\n').length : 0 }
|
|
405
|
+
break
|
|
406
|
+
} catch { /* try the next anchor */ }
|
|
407
|
+
}
|
|
408
|
+
cache.set(p, out)
|
|
409
|
+
return out
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// `git diff --name-status <base>...HEAD` → what this PR changed, and what it
|
|
414
|
+
// deleted. Deletions are the one class of unresolvable locator that is honest.
|
|
415
|
+
function diffFiles(base, root) {
|
|
416
|
+
try {
|
|
417
|
+
const out = execFileSync('git', ['diff', '--name-status', `${base}...HEAD`], { cwd: root, encoding: 'utf8' })
|
|
418
|
+
const changed = []
|
|
419
|
+
const deleted = []
|
|
420
|
+
for (const line of out.split('\n')) {
|
|
421
|
+
const [status, ...paths] = line.split('\t')
|
|
422
|
+
const p = paths[paths.length - 1]
|
|
423
|
+
if (!status || !p) continue
|
|
424
|
+
if (status.startsWith('D')) deleted.push(p)
|
|
425
|
+
else changed.push(p)
|
|
426
|
+
}
|
|
427
|
+
return { changed, deleted }
|
|
428
|
+
} catch (e) {
|
|
429
|
+
console.error(`coverage-checklist: could not read the diff against ${base} (${e.message.split('\n')[0]}) — resolving locators without deletion/diff context`)
|
|
430
|
+
return null
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function main() {
|
|
435
|
+
const [cmd, ...rest] = process.argv.slice(2)
|
|
436
|
+
if (cmd === 'validate') {
|
|
437
|
+
const file = rest.find((a) => !a.startsWith('--'))
|
|
438
|
+
if (!file || !fs.existsSync(file)) { console.error('usage: coverage-checklist.mjs validate <checklist.md> [--root <dir>] [--diff <base>] [--no-resolve]'); process.exit(2) }
|
|
439
|
+
const root = repoRoot(rest.includes('--root') ? rest[rest.indexOf('--root') + 1] : null)
|
|
440
|
+
const base = rest.includes('--diff') ? rest[rest.indexOf('--diff') + 1] : null
|
|
441
|
+
const diff = base ? diffFiles(base, root) : null
|
|
442
|
+
const opts = rest.includes('--no-resolve') ? {} : {
|
|
443
|
+
resolveFile: fileResolver(root),
|
|
444
|
+
deletedFiles: diff?.deleted || [],
|
|
445
|
+
changedFiles: diff?.changed || null,
|
|
446
|
+
}
|
|
447
|
+
// Without `--diff` this command answers a WEAKER question than its exit code
|
|
448
|
+
// suggests, and nothing said so. A missing locator downgrades from violation to
|
|
449
|
+
// warning (see warning B above) because a deletion and a stale reference are
|
|
450
|
+
// indistinguishable with no diff context, so the run exits 0 on rows a diffed run
|
|
451
|
+
// blocks. Measured on 1above-official issue #35 (2026-08-03): the producer ran
|
|
452
|
+
// `validate <checklist> --root .` → pass; the reviewer ran the same file with
|
|
453
|
+
// `--diff` → 9 PASS rows with no resolving locator, and the unit bought an
|
|
454
|
+
// evidence round for the difference. Two runs of one command, opposite verdicts,
|
|
455
|
+
// and no way to tell from the output which question had been asked. So the
|
|
456
|
+
// reduced form announces itself — on stderr, so a caller piping stdout still sees
|
|
457
|
+
// it, and on BOTH paths, since the pass is the one that misleads.
|
|
458
|
+
const reduced = opts.resolveFile && !opts.changedFiles
|
|
459
|
+
if (reduced) {
|
|
460
|
+
console.error('coverage-checklist: NOTE — running without --diff: this is the reduced form. A row whose cited file is MISSING warns instead of blocking, because with no diff a stale locator cannot be told from one this PR deleted. Re-run with `--diff <merge-base>` to decide those rows; a green run here is not the green the reviewer will get.')
|
|
461
|
+
}
|
|
462
|
+
const violations = validateRows(parseChecklist(fs.readFileSync(file, 'utf8')), opts)
|
|
463
|
+
for (const w of violations.warnings) console.log(` ! ${w.check}: ${w.problem}`)
|
|
464
|
+
if (!violations.length) {
|
|
465
|
+
const how = opts.resolveFile ? 'a decision + an evidence locator that resolves' : 'a decision + evidence locator'
|
|
466
|
+
const caveat = reduced ? ' — reduced form, no --diff: missing-file rows warned rather than blocked' : ''
|
|
467
|
+
console.log(`coverage-checklist: ✓ every row has ${how}${caveat}${violations.warnings.length ? ` (${violations.warnings.length} warning(s) above)` : ''}`)
|
|
468
|
+
process.exit(0)
|
|
469
|
+
}
|
|
470
|
+
console.log(`coverage-checklist: ✗ ${violations.length} row(s) without a real decision/evidence:\n`)
|
|
471
|
+
for (const v of violations) console.log(` • ${v.check}: ${v.problem}`)
|
|
472
|
+
process.exit(1)
|
|
473
|
+
}
|
|
474
|
+
if (cmd === 'generate' || cmd === undefined) {
|
|
475
|
+
const flags = {}
|
|
476
|
+
const a = cmd === undefined ? process.argv.slice(2) : rest
|
|
477
|
+
for (let i = 0; i < a.length; i++) {
|
|
478
|
+
if (a[i] === '--diff') flags.diff = a[++i]
|
|
479
|
+
else if (a[i] === '--files') flags.files = a[++i]
|
|
480
|
+
else if (a[i] === '--ci') flags.ci = a[++i]
|
|
481
|
+
else if (a[i] === '--ledger') flags.ledger = true
|
|
482
|
+
else if (a[i] === '--sweep') flags.sweep = a[++i]
|
|
483
|
+
else if (a[i] === '--smoke') flags.smoke = a[++i]
|
|
484
|
+
else if (a[i] === '--parity') flags.parity = a[++i]
|
|
485
|
+
else if (a[i] === '--parity-observed') flags.parityObserved = a[++i]
|
|
486
|
+
}
|
|
487
|
+
console.log(renderChecklist(CHECKLIST, gather(flags)))
|
|
488
|
+
process.exit(0)
|
|
489
|
+
}
|
|
490
|
+
console.error('usage: coverage-checklist.mjs <generate|validate>')
|
|
491
|
+
process.exit(2)
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if (isMainModule(import.meta.url)) main()
|