@1aboveio/skills 0.0.0-stage → 1.0.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/README.md +30 -2
- package/bin/cli.mjs +14 -0
- package/bin/select-core.mjs +172 -0
- package/package.json +146 -4
- package/skills/app-dev/airflow/LICENSE +3 -0
- package/skills/app-dev/airflow/SKILL.md +199 -0
- package/skills/app-dev/airflow/release-check.mjs +93 -0
- package/skills/app-dev/android-foundation/LICENSE +3 -0
- package/skills/app-dev/android-foundation/SKILL.md +192 -0
- package/skills/app-dev/android-foundation/assets/android-ci-job.yml +217 -0
- package/skills/app-dev/android-foundation/references/ci.md +87 -0
- package/skills/app-dev/android-foundation/references/gotchas.md +221 -0
- package/skills/app-dev/android-foundation/references/setup.md +164 -0
- package/skills/app-dev/android-foundation/release-check.mjs +93 -0
- package/skills/app-dev/android-foundation/scripts/device-run.sh +176 -0
- package/skills/app-dev/android-foundation/scripts/device-run.test.mjs +172 -0
- package/skills/app-dev/app-debug/LICENSE +3 -0
- package/skills/app-dev/app-debug/SKILL.md +110 -0
- package/skills/app-dev/app-debug/references/common-errors.md +128 -0
- package/skills/app-dev/app-debug/release-check.mjs +93 -0
- package/skills/app-dev/better-auth/LICENSE +3 -0
- package/skills/app-dev/better-auth/SKILL.md +598 -0
- package/skills/app-dev/better-auth/references/feishu-api.md +270 -0
- package/skills/app-dev/better-auth/release-check.mjs +93 -0
- package/skills/app-dev/data-catalog/LICENSE +3 -0
- package/skills/app-dev/data-catalog/SKILL.md +204 -0
- package/skills/app-dev/data-catalog/agents/openai.yaml +3 -0
- package/skills/app-dev/data-catalog/references/data-catalog-conventions.md +75 -0
- package/skills/app-dev/data-catalog/references/field-definitions.md +116 -0
- package/skills/app-dev/data-catalog/references/format.md +121 -0
- package/skills/app-dev/data-catalog/release-check.mjs +93 -0
- package/skills/app-dev/data-catalog/scripts/data-catalog.test.mjs +36 -0
- package/skills/app-dev/data-catalog/scripts/data_catalog.py +1392 -0
- package/skills/app-dev/data-catalog/scripts/persist-conventions-core.mjs +117 -0
- package/skills/app-dev/data-catalog/scripts/persist-conventions.mjs +17 -0
- package/skills/app-dev/data-catalog/scripts/test_data_catalog.py +571 -0
- package/skills/app-dev/ios-foundation/LICENSE +3 -0
- package/skills/app-dev/ios-foundation/SKILL.md +184 -0
- package/skills/app-dev/ios-foundation/references/setup.md +243 -0
- package/skills/app-dev/ios-foundation/release-check.mjs +93 -0
- package/skills/app-dev/monorepo/LICENSE +3 -0
- package/skills/app-dev/monorepo/SKILL.md +462 -0
- package/skills/app-dev/monorepo/release-check.mjs +93 -0
- package/skills/app-dev/nextjs-fullstack/LICENSE +3 -0
- package/skills/app-dev/nextjs-fullstack/SKILL.md +211 -0
- package/skills/app-dev/nextjs-fullstack/conventions.md +318 -0
- package/skills/app-dev/nextjs-fullstack/frontend-conventions.md +61 -0
- package/skills/app-dev/nextjs-fullstack/nextjs16.md +287 -0
- package/skills/app-dev/nextjs-fullstack/release-check.mjs +93 -0
- package/skills/app-dev/nextjs-fullstack/server-actions.md +409 -0
- package/skills/app-dev/prisma-setup/LICENSE +3 -0
- package/skills/app-dev/prisma-setup/SKILL.md +181 -0
- package/skills/app-dev/prisma-setup/nextjs.md +258 -0
- package/skills/app-dev/prisma-setup/release-check.mjs +93 -0
- package/skills/app-dev/prisma-setup/turborepo.md +301 -0
- package/skills/app-dev/pyspark/LICENSE +3 -0
- package/skills/app-dev/pyspark/SKILL.md +127 -0
- package/skills/app-dev/pyspark/assets/templates/etl.py +748 -0
- package/skills/app-dev/pyspark/assets/templates/utils/__init__.py +1 -0
- package/skills/app-dev/pyspark/assets/templates/utils/hudi_metadata.py +14 -0
- package/skills/app-dev/pyspark/references/diagnosis-and-profiling.md +169 -0
- package/skills/app-dev/pyspark/references/etl-contract.md +129 -0
- package/skills/app-dev/pyspark/references/production-validation.md +131 -0
- package/skills/app-dev/pyspark/references/reconciliation.md +38 -0
- package/skills/app-dev/pyspark/references/transformation-design.md +190 -0
- package/skills/app-dev/pyspark/references/velocity-feature-calculation.md +193 -0
- package/skills/app-dev/pyspark/release-check.mjs +93 -0
- package/skills/app-dev/pyspark/scripts/spark_eventlog_summary.py +223 -0
- package/skills/app-dev/python-backend/LICENSE +3 -0
- package/skills/app-dev/python-backend/SKILL.md +325 -0
- package/skills/app-dev/python-backend/assets/uv-install.sh +48 -0
- package/skills/app-dev/python-backend/references/uv-installs.md +83 -0
- package/skills/app-dev/python-backend/release-check.mjs +93 -0
- package/skills/app-dev/shadcn/LICENSE +3 -0
- package/skills/app-dev/shadcn/SKILL.md +120 -0
- package/skills/app-dev/shadcn/assets/shadcn-small.png +0 -0
- package/skills/app-dev/shadcn/assets/shadcn.png +0 -0
- package/skills/app-dev/shadcn/cli.md +411 -0
- package/skills/app-dev/shadcn/customization.md +224 -0
- package/skills/app-dev/shadcn/mcp.md +101 -0
- package/skills/app-dev/shadcn/release-check.mjs +93 -0
- package/skills/app-dev/shadcn/rules/base-vs-radix.md +323 -0
- package/skills/app-dev/shadcn/rules/component-selection.md +67 -0
- package/skills/app-dev/shadcn/rules/composition.md +195 -0
- package/skills/app-dev/shadcn/rules/data-table.md +201 -0
- package/skills/app-dev/shadcn/rules/forms.md +255 -0
- package/skills/app-dev/shadcn/rules/icons.md +103 -0
- package/skills/app-dev/shadcn/rules/styling.md +167 -0
- package/skills/app-dev/zod-v4/LICENSE +3 -0
- package/skills/app-dev/zod-v4/SKILL.md +286 -0
- package/skills/app-dev/zod-v4/release-check.mjs +93 -0
- package/skills/cicd/cloud-build/LICENSE +3 -0
- package/skills/cicd/cloud-build/SKILL.md +707 -0
- package/skills/cicd/cloud-build/release-check.mjs +93 -0
- package/skills/cicd/cloud-debug/LICENSE +3 -0
- package/skills/cicd/cloud-debug/SKILL.md +315 -0
- package/skills/cicd/cloud-debug/references/build-failures.md +238 -0
- package/skills/cicd/cloud-debug/references/deploy-failures.md +376 -0
- package/skills/cicd/cloud-debug/references/pipeline-failures.md +378 -0
- package/skills/cicd/cloud-debug/release-check.mjs +93 -0
- package/skills/cicd/cloud-deploy/LICENSE +3 -0
- package/skills/cicd/cloud-deploy/SKILL.md +230 -0
- package/skills/cicd/cloud-deploy/references/config-templates.md +257 -0
- package/skills/cicd/cloud-deploy/release-check.mjs +93 -0
- package/skills/cicd/docker/LICENSE +3 -0
- package/skills/cicd/docker/SKILL.md +151 -0
- package/skills/cicd/docker/release-check.mjs +93 -0
- package/skills/cicd/github-actions/LICENSE +3 -0
- package/skills/cicd/github-actions/SKILL.md +111 -0
- package/skills/cicd/github-actions/references/audit-profile-optimize.md +150 -0
- package/skills/cicd/github-actions/references/ci-case-studies.md +141 -0
- package/skills/cicd/github-actions/references/conditional-ci.md +214 -0
- package/skills/cicd/github-actions/references/debugging.md +13 -0
- package/skills/cicd/github-actions/references/pipeline.md +87 -0
- package/skills/cicd/github-actions/references/post-deploy-and-publishing.md +33 -0
- package/skills/cicd/github-actions/references/runners.md +253 -0
- package/skills/cicd/github-actions/references/security.md +29 -0
- package/skills/cicd/github-actions/references/speed-and-audit.md +115 -0
- package/skills/cicd/github-actions/references/two-pass-reading.md +92 -0
- package/skills/cicd/github-actions/release-check.mjs +93 -0
- package/skills/cicd/github-actions/scripts/ci-run-audit-core.mjs +612 -0
- package/skills/cicd/github-actions/scripts/ci-run-audit.mjs +4 -0
- package/skills/cicd/github-actions/scripts/ci-run-audit.test.mjs +637 -0
- package/skills/cicd/github-flow/LICENSE +3 -0
- package/skills/cicd/github-flow/SKILL.md +123 -0
- package/skills/cicd/github-flow/references/ci-conventions.md +14 -0
- package/skills/cicd/github-flow/release-check.mjs +93 -0
- package/skills/cicd/github-flow/scripts/flow-core.mjs +105 -0
- package/skills/cicd/github-flow/scripts/flow.mjs +81 -0
- package/skills/cicd/github-flow/scripts/flow.test.mjs +114 -0
- package/skills/cicd/github-flow/scripts/persist-conventions-core.mjs +117 -0
- package/skills/cicd/github-flow/scripts/persist-conventions.mjs +49 -0
- package/skills/cicd/github-flow/scripts/persist-conventions.test.mjs +108 -0
- package/skills/cicd/google-cloud/LICENSE +3 -0
- package/skills/cicd/google-cloud/SKILL.md +119 -0
- package/skills/cicd/google-cloud/references/gcs.md +469 -0
- package/skills/cicd/google-cloud/references/iam.md +451 -0
- package/skills/cicd/google-cloud/references/project.md +349 -0
- package/skills/cicd/google-cloud/references/secrets.md +336 -0
- package/skills/cicd/google-cloud/references/vpc.md +312 -0
- package/skills/cicd/google-cloud/release-check.mjs +93 -0
- package/skills/cicd/google-cloud/scripts/create-sa.sh +36 -0
- package/skills/cicd/google-cloud/scripts/gcp-config.sh +31 -0
- package/skills/cicd/google-cloud/scripts/grant-iap.sh +41 -0
- package/skills/cicd/google-cloud/scripts/setup-secrets.sh +48 -0
- package/skills/cicd/mergify/LICENSE +3 -0
- package/skills/cicd/mergify/SKILL.md +102 -0
- package/skills/cicd/mergify/assets/templates/mergify.yml +215 -0
- package/skills/cicd/mergify/assets/templates/ruleset.json +46 -0
- package/skills/cicd/mergify/references/branch-protection.md +282 -0
- package/skills/cicd/mergify/references/configuration.md +274 -0
- package/skills/cicd/mergify/references/diagnosis.md +109 -0
- package/skills/cicd/mergify/references/stacks.md +84 -0
- package/skills/cicd/mergify/references/traps.md +119 -0
- package/skills/cicd/mergify/references/watch-contract.md +274 -0
- package/skills/cicd/mergify/release-check.mjs +93 -0
- package/skills/cicd/mergify/scripts/audit-core.mjs +208 -0
- package/skills/cicd/mergify/scripts/audit.mjs +4 -0
- package/skills/cicd/mergify/scripts/audit.test.mjs +201 -0
- package/skills/cicd/mergify/scripts/entrypoints.test.mjs +106 -0
- package/skills/cicd/mergify/scripts/pr-620-mergify-comments.fixture.json +30 -0
- package/skills/cicd/mergify/scripts/stack-push-core.mjs +258 -0
- package/skills/cicd/mergify/scripts/stack-push.mjs +4 -0
- package/skills/cicd/mergify/scripts/stack-push.test.mjs +233 -0
- package/skills/cicd/mergify/scripts/watch-pr-delivery-core.mjs +1065 -0
- package/skills/cicd/mergify/scripts/watch-pr-delivery.mjs +4 -0
- package/skills/cicd/mergify/scripts/watch-pr-delivery.test.mjs +1826 -0
- package/skills/cicd/podman/LICENSE +3 -0
- package/skills/cicd/podman/SKILL.md +71 -0
- package/skills/cicd/podman/agents/openai.yaml +4 -0
- package/skills/cicd/podman/assets/templates/podman-compose-socket-directory.yml +6 -0
- package/skills/cicd/podman/assets/templates/podman-service-override.conf +3 -0
- package/skills/cicd/podman/references/compose-compatibility.md +70 -0
- package/skills/cicd/podman/references/networking-and-ports.md +74 -0
- package/skills/cicd/podman/references/rootless-services-and-sockets.md +156 -0
- package/skills/cicd/podman/references/troubleshooting.md +98 -0
- package/skills/cicd/podman/release-check.mjs +93 -0
- package/skills/content/article-review/LICENSE +3 -0
- package/skills/content/article-review/SKILL.md +66 -0
- package/skills/content/article-review/references/report-format.md +68 -0
- package/skills/content/article-review/references/template-guide.md +79 -0
- package/skills/content/article-review/references/template-wechat-payments.md +125 -0
- package/skills/content/article-review/release-check.mjs +93 -0
- package/skills/content/article-to-image/LICENSE +3 -0
- package/skills/content/article-to-image/SKILL.md +91 -0
- package/skills/content/article-to-image/references/formats.md +53 -0
- package/skills/content/article-to-image/release-check.mjs +93 -0
- package/skills/content/flowchart-svg/LICENSE +3 -0
- package/skills/content/flowchart-svg/SKILL.md +43 -0
- package/skills/content/flowchart-svg/release-check.mjs +93 -0
- package/skills/content/flowchart-svg/scripts/export_png.sh +8 -0
- package/skills/content/image-gen/LICENSE +3 -0
- package/skills/content/image-gen/SKILL.md +192 -0
- package/skills/content/image-gen/release-check.mjs +93 -0
- package/skills/content/image-gen/scripts/credentials.mjs +217 -0
- package/skills/content/image-gen/scripts/credentials.test.mjs +212 -0
- package/skills/content/image-gen/scripts/generate.mjs +240 -0
- package/skills/content/image-gen/scripts/options.mjs +293 -0
- package/skills/content/image-gen/scripts/options.test.mjs +245 -0
- package/skills/content/mermaid/LICENSE +3 -0
- package/skills/content/mermaid/SKILL.md +635 -0
- package/skills/content/mermaid/release-check.mjs +93 -0
- package/skills/content/wechat-article-writer/LICENSE +3 -0
- package/skills/content/wechat-article-writer/SKILL.md +92 -0
- package/skills/content/wechat-article-writer/references/style-selector.md +133 -0
- package/skills/content/wechat-article-writer/references/writing-rules.md +152 -0
- package/skills/content/wechat-article-writer/release-check.mjs +93 -0
- package/skills/content/wechat-article-writer/templates/wechat-comparison.md +52 -0
- package/skills/content/wechat-article-writer/templates/wechat-howto.md +51 -0
- package/skills/content/wechat-article-writer/templates/wechat-insight.md +50 -0
- package/skills/content/wechat-article-writer/templates/wechat-pitfall.md +52 -0
- package/skills/content/wechat-publisher/LICENSE +3 -0
- package/skills/content/wechat-publisher/SKILL.md +171 -0
- package/skills/content/wechat-publisher/references/api.md +105 -0
- package/skills/content/wechat-publisher/references/layout-rules.md +57 -0
- package/skills/content/wechat-publisher/references/wechat-safe-template.html +86 -0
- package/skills/content/wechat-publisher/release-check.mjs +93 -0
- package/skills/content/wechat-publisher/scripts/md_to_wechat_html.py +194 -0
- package/skills/content/wechat-publisher/scripts/publish.py +239 -0
- package/skills/content/wechat-search/LICENSE +3 -0
- package/skills/content/wechat-search/SKILL.md +211 -0
- package/skills/content/wechat-search/release-check.mjs +93 -0
- package/skills/content/wechat-search/scripts/start-chrome.sh +83 -0
- package/skills/content/xai-search/LICENSE +3 -0
- package/skills/content/xai-search/SKILL.md +79 -0
- package/skills/content/xai-search/release-check.mjs +93 -0
- package/skills/content/xai-search/scripts/xai_search.sh +187 -0
- package/skills/content/xai-search/tests/smoke_test.sh +36 -0
- package/skills/core/distill-writing/LICENSE +3 -0
- package/skills/core/distill-writing/SKILL.md +74 -0
- package/skills/core/distill-writing/references/extraction.md +95 -0
- package/skills/core/distill-writing/references/updating.md +46 -0
- package/skills/core/distill-writing/release-check.mjs +93 -0
- package/skills/core/doc-to-md/LICENSE +3 -0
- package/skills/core/doc-to-md/SKILL.md +78 -0
- package/skills/core/doc-to-md/release-check.mjs +93 -0
- package/skills/core/doc-to-md/scripts/convert.py +157 -0
- package/skills/core/editorial-review/LICENSE +3 -0
- package/skills/core/editorial-review/SKILL.md +79 -0
- package/skills/core/editorial-review/references/checklist.md +94 -0
- package/skills/core/editorial-review/release-check.mjs +93 -0
- package/skills/core/house-style/LICENSE +3 -0
- package/skills/core/house-style/SKILL.md +33 -0
- package/skills/core/house-style/references/defaults.md +66 -0
- package/skills/core/house-style/references/rules.md +267 -0
- package/skills/core/house-style/references/sources.md +27 -0
- package/skills/core/house-style/references/style-en.md +131 -0
- package/skills/core/house-style/references/style-zh.md +141 -0
- package/skills/core/house-style/references/terminology-zh.md +223 -0
- package/skills/core/house-style/release-check.mjs +93 -0
- package/skills/core/house-style/templates/brd.md +103 -0
- package/skills/core/house-style/templates/commercial-proposal.md +93 -0
- package/skills/core/house-style/templates/compliance-policy.md +109 -0
- package/skills/core/house-style/templates/gap-analysis.md +105 -0
- package/skills/core/house-style/templates/general.md +63 -0
- package/skills/core/house-style/templates/integration-guide.md +98 -0
- package/skills/core/house-style/templates/prd.md +81 -0
- package/skills/core/house-style/templates/risk-operations-procedure.md +94 -0
- package/skills/core/house-style/templates/technical-spec.md +96 -0
- package/skills/core/polish-cn/LICENSE +3 -0
- package/skills/core/polish-cn/SKILL.md +102 -0
- package/skills/core/polish-cn/references/brief.md +93 -0
- package/skills/core/polish-cn/references/models.md +76 -0
- package/skills/core/polish-cn/release-check.mjs +93 -0
- package/skills/core/polish-cn/scripts/polish-cn.test.mjs +244 -0
- package/skills/core/polish-cn/scripts/polish_blocks.py +489 -0
- package/skills/core/reg-parser/LICENSE +3 -0
- package/skills/core/reg-parser/SKILL.md +212 -0
- package/skills/core/reg-parser/references/checklist-schema.md +223 -0
- package/skills/core/reg-parser/references/checklists/hk-amlo-checklist.json +1306 -0
- package/skills/core/reg-parser/references/checklists/hk-amlo-checklist.md +469 -0
- package/skills/core/reg-parser/references/checklists/hk-fi-corporate-onboarding-cdd-checklist.json +634 -0
- package/skills/core/reg-parser/references/checklists/hk-fi-corporate-onboarding-cdd-checklist.md +233 -0
- package/skills/core/reg-parser/references/checklists/hk-mso-guideline-checklist.json +2194 -0
- package/skills/core/reg-parser/references/checklists/hk-mso-guideline-checklist.md +771 -0
- package/skills/core/reg-parser/references/checklists/kyc-aml-checklist.md +258 -0
- package/skills/core/reg-parser/references/checklists/visa-vars-checklist.md +1058 -0
- package/skills/core/reg-parser/references/mandates/hk-amlo-cap615.md +389 -0
- package/skills/core/reg-parser/references/mandates/visa-vars.md +205 -0
- package/skills/core/reg-parser/release-check.mjs +93 -0
- package/skills/core/reg-parser/scripts/compare_checklist.py +230 -0
- package/skills/core/reg-parser/scripts/dump_checklist.py +361 -0
- package/skills/core/reg-parser/scripts/preprocess-mandate.sh +187 -0
- package/skills/core/reg-parser/scripts/reg-parser.test.mjs +165 -0
- package/skills/core/reg-parser/scripts/test_quarantine.sh +105 -0
- package/skills/core/reg-parser/scripts/validate_checklist.py +563 -0
- package/skills/core/reg-parser/scripts/validate_mandate.py +273 -0
- package/skills/core/terminology/LICENSE +3 -0
- package/skills/core/terminology/SKILL.md +62 -0
- package/skills/core/terminology/references/format.md +50 -0
- package/skills/core/terminology/references/init.md +32 -0
- package/skills/core/terminology/release-check.mjs +93 -0
- package/skills/core/write-doc/LICENSE +3 -0
- package/skills/core/write-doc/SKILL.md +141 -0
- package/skills/core/write-doc/references/bilingual.md +60 -0
- package/skills/core/write-doc/release-check.mjs +93 -0
- package/skills/engineering/better-review/LICENSE +3 -0
- package/skills/engineering/better-review/SKILL.md +249 -0
- package/skills/engineering/better-review/agents/openai.yaml +9 -0
- package/skills/engineering/better-review/references/domain-hazards.md +53 -0
- package/skills/engineering/better-review/references/passes.md +147 -0
- package/skills/engineering/better-review/references/result.md +151 -0
- package/skills/engineering/better-review/release-check.mjs +93 -0
- package/skills/engineering/better-review/scripts/pr-context.mjs +212 -0
- package/skills/engineering/better-review/scripts/pr-context.test.mjs +168 -0
- package/skills/engineering/better-review/scripts/rereview-scope.mjs +503 -0
- package/skills/engineering/better-review/scripts/rereview-scope.test.mjs +587 -0
- package/skills/engineering/better-review/scripts/scan-diff.mjs +365 -0
- package/skills/engineering/better-review/scripts/scan-diff.test.mjs +414 -0
- package/skills/engineering/better-review/scripts/vendor-sync.test.mjs +96 -0
- package/skills/engineering/e2e-test/LICENSE +3 -0
- package/skills/engineering/e2e-test/SKILL.md +98 -0
- package/skills/engineering/e2e-test/assets/ci-gates.cloudbuild.yaml +24 -0
- package/skills/engineering/e2e-test/references/authoring/auth-flows.md +159 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-config.md +73 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-patterns.md +144 -0
- package/skills/engineering/e2e-test/references/ci-integration.md +25 -0
- package/skills/engineering/e2e-test/references/ci-playwright-container.md +290 -0
- package/skills/engineering/e2e-test/references/presentation-sweep.md +104 -0
- package/skills/engineering/e2e-test/references/reviewing.md +41 -0
- package/skills/engineering/e2e-test/references/route-manifest.md +51 -0
- package/skills/engineering/e2e-test/release-check.mjs +93 -0
- package/skills/engineering/e2e-test/scripts/detect-routes-nextjs.mjs +200 -0
- package/skills/engineering/e2e-test/scripts/presentation-checks.mjs +171 -0
- package/skills/engineering/e2e-test/scripts/presentation-checks.test.mjs +106 -0
- package/skills/engineering/e2e-test/scripts/presentation-perceivability.mjs +179 -0
- package/skills/engineering/e2e-test/scripts/presentation-perceivability.test.mjs +117 -0
- package/skills/engineering/e2e-test/scripts/presentation-reachability.mjs +154 -0
- package/skills/engineering/e2e-test/scripts/presentation-reachability.test.mjs +69 -0
- package/skills/engineering/e2e-test/scripts/presentation-render-health.mjs +141 -0
- package/skills/engineering/e2e-test/scripts/presentation-render-health.test.mjs +98 -0
- package/skills/engineering/e2e-test/scripts/presentation-sweep.mjs +147 -0
- package/skills/engineering/e2e-test/scripts/presentation-sweep.test.mjs +71 -0
- package/skills/engineering/e2e-test/scripts/presentation-temporal.mjs +127 -0
- package/skills/engineering/e2e-test/scripts/presentation-temporal.test.mjs +59 -0
- package/skills/engineering/e2e-test/scripts/project-route-manifest.mjs +82 -0
- package/skills/engineering/e2e-test/scripts/project-route-manifest.test.mjs +76 -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 +11 -0
- package/skills/engineering/engineering-runtime/agents/openai.yaml +6 -0
- package/skills/engineering/engineering-runtime/coherence/workflow.json +597 -0
- package/skills/engineering/engineering-runtime/engineering-runtime.test.mjs +68 -0
- package/skills/engineering/engineering-runtime/release-check.mjs +93 -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/invocation-policy.mjs +187 -0
- package/skills/engineering/engineering-runtime/scripts/invocation-policy.test.mjs +95 -0
- package/skills/engineering/engineering-runtime/scripts/main-module.mjs +79 -0
- package/skills/engineering/engineering-runtime/scripts/main-module.test.mjs +288 -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/required-check-plan.test.mjs +96 -0
- package/skills/engineering/engineering-runtime/scripts/review-completion.mjs +56 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +595 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +189 -0
- package/skills/engineering/engineering-runtime/scripts/yaml-mapping.mjs +18 -0
- package/skills/engineering/ensure-coverage/LICENSE +3 -0
- package/skills/engineering/ensure-coverage/SKILL.md +129 -0
- package/skills/engineering/ensure-coverage/references/breadth/coverage-ledger.md +92 -0
- package/skills/engineering/ensure-coverage/references/breadth/inventory-contract.md +85 -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 +19 -0
- package/skills/engineering/ensure-coverage/references/depth/grading.md +35 -0
- package/skills/engineering/ensure-coverage/references/depth/mock-policy.md +57 -0
- package/skills/engineering/ensure-coverage/references/depth/test-smells.md +39 -0
- package/skills/engineering/ensure-coverage/references/enforcement/ci-contract.md +44 -0
- package/skills/engineering/ensure-coverage/references/examples/coverage-ledger.md +110 -0
- package/skills/engineering/ensure-coverage/references/examples/refund-flow.md +35 -0
- package/skills/engineering/ensure-coverage/references/presentation/axis.md +64 -0
- package/skills/engineering/ensure-coverage/references/process/audit-mode.md +27 -0
- package/skills/engineering/ensure-coverage/references/process/output-template.md +139 -0
- package/skills/engineering/ensure-coverage/references/process/test-strategy.md +56 -0
- package/skills/engineering/ensure-coverage/release-check.mjs +93 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-config.schema.json +67 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-file.schema.json +140 -0
- package/skills/engineering/ensure-coverage/scripts/README.md +99 -0
- package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.mjs +182 -0
- package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.test.mjs +96 -0
- package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.mjs +105 -0
- package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.test.mjs +47 -0
- package/skills/engineering/ensure-coverage/scripts/ci-audit.mjs +137 -0
- package/skills/engineering/ensure-coverage/scripts/ci-audit.test.mjs +86 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-ledger.mjs +674 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-ledger.test.mjs +447 -0
- package/skills/engineering/ensure-coverage/scripts/design-parity.mjs +591 -0
- package/skills/engineering/ensure-coverage/scripts/design-parity.test.mjs +552 -0
- package/skills/engineering/ensure-coverage/scripts/lint-tests.mjs +282 -0
- package/skills/engineering/ensure-coverage/scripts/lint-tests.test.mjs +289 -0
- package/skills/engineering/ensure-coverage/scripts/mock-policy-config.mjs +176 -0
- package/skills/engineering/ensure-coverage/scripts/mock-policy-config.test.mjs +119 -0
- package/skills/engineering/ensure-coverage/scripts/package.json +19 -0
- package/skills/engineering/golden-path/LICENSE +3 -0
- package/skills/engineering/golden-path/SKILL.md +230 -0
- package/skills/engineering/golden-path/agents/openai.yaml +3 -0
- package/skills/engineering/golden-path/assets/golden-paths.example.json +57 -0
- package/skills/engineering/golden-path/references/contract.md +239 -0
- package/skills/engineering/golden-path/references/migration.md +111 -0
- package/skills/engineering/golden-path/release-check.mjs +93 -0
- package/skills/engineering/golden-path/scripts/golden-path-core.mjs +1779 -0
- package/skills/engineering/golden-path/scripts/golden-path.mjs +6 -0
- package/skills/engineering/golden-path/scripts/golden-path.test.mjs +1457 -0
- package/skills/engineering/harness-runtime/LICENSE +3 -0
- package/skills/engineering/harness-runtime/SKILL.md +19 -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/discover-models.test.mjs +363 -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/harness-runtime.test.mjs +967 -0
- package/skills/engineering/harness-runtime/index.mjs +767 -0
- package/skills/engineering/harness-runtime/model-catalog-seed.test.mjs +829 -0
- package/skills/engineering/harness-runtime/model-catalog.mjs +787 -0
- package/skills/engineering/harness-runtime/model-catalog.test.mjs +366 -0
- package/skills/engineering/harness-runtime/native-question-contracts.md +37 -0
- package/skills/engineering/harness-runtime/references/model-catalog-seed.json +408 -0
- package/skills/engineering/harness-runtime/references/model-catalog.md +57 -0
- package/skills/engineering/harness-runtime/release-check.mjs +93 -0
- package/skills/engineering/resolve-issues/LICENSE +3 -0
- package/skills/engineering/resolve-issues/SKILL.md +250 -0
- package/skills/engineering/resolve-issues/agents/openai.yaml +9 -0
- package/skills/engineering/resolve-issues/plugin-hooks.json +17 -0
- package/skills/engineering/resolve-issues/references/canary.md +28 -0
- package/skills/engineering/resolve-issues/references/ci.md +105 -0
- package/skills/engineering/resolve-issues/references/done.md +25 -0
- package/skills/engineering/resolve-issues/references/dropbox.md +90 -0
- package/skills/engineering/resolve-issues/references/expire.md +318 -0
- package/skills/engineering/resolve-issues/references/exploration.md +202 -0
- package/skills/engineering/resolve-issues/references/implementation.md +303 -0
- package/skills/engineering/resolve-issues/references/preflight.md +445 -0
- package/skills/engineering/resolve-issues/references/review.md +228 -0
- package/skills/engineering/resolve-issues/references/shared-modules.md +44 -0
- package/skills/engineering/resolve-issues/references/task-plan.md +264 -0
- package/skills/engineering/resolve-issues/release-check.mjs +93 -0
- package/skills/engineering/resolve-issues/scripts/cleanup-runs.mjs +364 -0
- package/skills/engineering/resolve-issues/scripts/cleanup-runs.test.mjs +280 -0
- package/skills/engineering/resolve-issues/scripts/discover-models.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/dropbox.mjs +473 -0
- package/skills/engineering/resolve-issues/scripts/dropbox.test.mjs +346 -0
- package/skills/engineering/resolve-issues/scripts/findings-reuse.mjs +98 -0
- package/skills/engineering/resolve-issues/scripts/findings-reuse.test.mjs +88 -0
- package/skills/engineering/resolve-issues/scripts/github-reviews.mjs +384 -0
- package/skills/engineering/resolve-issues/scripts/github-reviews.test.mjs +264 -0
- package/skills/engineering/resolve-issues/scripts/install-hooks.mjs +135 -0
- package/skills/engineering/resolve-issues/scripts/install-hooks.test.mjs +79 -0
- package/skills/engineering/resolve-issues/scripts/issue-tree.mjs +162 -0
- package/skills/engineering/resolve-issues/scripts/issue-tree.test.mjs +107 -0
- package/skills/engineering/resolve-issues/scripts/manual-invocation.test.mjs +14 -0
- package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/next-actions-capacity.test.mjs +149 -0
- package/skills/engineering/resolve-issues/scripts/next-actions.mjs +856 -0
- package/skills/engineering/resolve-issues/scripts/next-actions.test.mjs +915 -0
- package/skills/engineering/resolve-issues/scripts/plan-sync.mjs +269 -0
- package/skills/engineering/resolve-issues/scripts/plan-sync.test.mjs +156 -0
- package/skills/engineering/resolve-issues/scripts/preflight-models.mjs +736 -0
- package/skills/engineering/resolve-issues/scripts/preflight-models.test.mjs +448 -0
- package/skills/engineering/resolve-issues/scripts/ready-check.mjs +185 -0
- package/skills/engineering/resolve-issues/scripts/ready-check.test.mjs +217 -0
- package/skills/engineering/resolve-issues/scripts/rehydrate.mjs +98 -0
- package/skills/engineering/resolve-issues/scripts/rehydrate.test.mjs +91 -0
- package/skills/engineering/resolve-issues/scripts/review-verdict.mjs +509 -0
- package/skills/engineering/resolve-issues/scripts/review-verdict.test.mjs +1060 -0
- package/skills/engineering/resolve-issues/scripts/size-check.mjs +492 -0
- package/skills/engineering/resolve-issues/scripts/size-check.test.mjs +458 -0
- package/skills/engineering/resolve-release/LICENSE +3 -0
- package/skills/engineering/resolve-release/SKILL.md +215 -0
- package/skills/engineering/resolve-release/agents/openai.yaml +8 -0
- package/skills/engineering/resolve-release/flows/cloud-run-canary.md +13 -0
- package/skills/engineering/resolve-release/flows/cloud-run.md +7 -0
- package/skills/engineering/resolve-release/flows/root-tag-npm.md +13 -0
- package/skills/engineering/resolve-release/flows/workspace-npm.md +22 -0
- package/skills/engineering/resolve-release/references/canary.md +51 -0
- package/skills/engineering/resolve-release/references/candidate.md +41 -0
- package/skills/engineering/resolve-release/references/cut.md +131 -0
- package/skills/engineering/resolve-release/references/dark-launch.md +66 -0
- package/skills/engineering/resolve-release/references/flows.md +150 -0
- package/skills/engineering/resolve-release/references/preflight.md +154 -0
- package/skills/engineering/resolve-release/references/prepared-metadata.md +260 -0
- package/skills/engineering/resolve-release/references/promotion.md +82 -0
- package/skills/engineering/resolve-release/references/publish.md +232 -0
- package/skills/engineering/resolve-release/references/workspace-npm.md +103 -0
- package/skills/engineering/resolve-release/release-check.mjs +93 -0
- package/skills/engineering/resolve-release/scripts/apply.mjs +212 -0
- package/skills/engineering/resolve-release/scripts/apply.test.mjs +99 -0
- package/skills/engineering/resolve-release/scripts/dark-flags.mjs +134 -0
- package/skills/engineering/resolve-release/scripts/dark-flags.test.mjs +100 -0
- package/skills/engineering/resolve-release/scripts/flow.mjs +500 -0
- package/skills/engineering/resolve-release/scripts/flow.test.mjs +340 -0
- package/skills/engineering/resolve-release/scripts/green-head.mjs +231 -0
- package/skills/engineering/resolve-release/scripts/green-head.test.mjs +101 -0
- package/skills/engineering/resolve-release/scripts/npm-version-absence.mjs +138 -0
- package/skills/engineering/resolve-release/scripts/npm-version-absence.test.mjs +426 -0
- package/skills/engineering/resolve-release/scripts/plan-npm.test.mjs +659 -0
- package/skills/engineering/resolve-release/scripts/plan-toml-boundary.test.mjs +317 -0
- package/skills/engineering/resolve-release/scripts/plan-uv.test.mjs +291 -0
- package/skills/engineering/resolve-release/scripts/plan.mjs +806 -0
- package/skills/engineering/resolve-release/scripts/plan.test.mjs +428 -0
- package/skills/engineering/rush-issues/LICENSE +3 -0
- package/skills/engineering/rush-issues/SKILL.md +58 -0
- package/skills/engineering/rush-issues/agents/openai.yaml +8 -0
- package/skills/engineering/rush-issues/rehydrate.mjs +10 -0
- package/skills/engineering/rush-issues/release-check.mjs +93 -0
- package/skills/engineering/rush-release/LICENSE +3 -0
- package/skills/engineering/rush-release/SKILL.md +35 -0
- package/skills/engineering/rush-release/agents/openai.yaml +8 -0
- package/skills/engineering/rush-release/release-check.mjs +93 -0
- package/skills/engineering/test-quality/LICENSE +3 -0
- package/skills/engineering/test-quality/SKILL.md +79 -0
- package/skills/engineering/test-quality/references/audit.md +80 -0
- package/skills/engineering/test-quality/references/lint.md +24 -0
- package/skills/engineering/test-quality/references/principles.md +143 -0
- package/skills/engineering/test-quality/references/testing-conventions.md +9 -0
- package/skills/engineering/test-quality/release-check.mjs +93 -0
- package/skills/engineering/test-quality/scripts/lint-tests.mjs +574 -0
- package/skills/engineering/test-quality/scripts/lint-tests.test.mjs +591 -0
- package/skills/engineering/test-quality/scripts/mock-policy-config.mjs +176 -0
- package/skills/engineering/test-quality/scripts/mock-policy-config.test.mjs +119 -0
- package/skills/engineering/test-quality/scripts/persist-conventions-core.mjs +117 -0
- package/skills/engineering/test-quality/scripts/persist-conventions.mjs +17 -0
- package/skills/engineering/test-quality/scripts/persist-conventions.test.mjs +104 -0
- package/skills/risk-compliance/compliance-audit/LICENSE +3 -0
- package/skills/risk-compliance/compliance-audit/SKILL.md +439 -0
- package/skills/risk-compliance/compliance-audit/references/findings-schema.md +293 -0
- package/skills/risk-compliance/compliance-audit/references/normalization-rules.md +45 -0
- package/skills/risk-compliance/compliance-audit/references/vars-checklist.md +1068 -0
- package/skills/risk-compliance/compliance-audit/references/vars-findings-schema.md +398 -0
- package/skills/risk-compliance/compliance-audit/release-check.mjs +93 -0
- package/skills/risk-compliance/compliance-audit/scripts/compliance-audit.test.mjs +14 -0
- package/skills/risk-compliance/compliance-audit/scripts/export_tracker_xlsx.py +221 -0
- package/skills/risk-compliance/compliance-audit/scripts/reconcile_tracker.py +458 -0
- package/skills/risk-compliance/compliance-audit/scripts/test_export_tracker_xlsx.py +97 -0
- package/skills/risk-compliance/compliance-audit/scripts/test_validate_tracker.py +157 -0
- package/skills/risk-compliance/compliance-audit/scripts/validate_tracker.py +829 -0
- package/skills/risk-compliance/contract-compare/LICENSE +3 -0
- package/skills/risk-compliance/contract-compare/SKILL.md +199 -0
- package/skills/risk-compliance/contract-compare/references/comparison-dimensions.md +209 -0
- package/skills/risk-compliance/contract-compare/release-check.mjs +93 -0
- package/skills/risk-compliance/contract-review/LICENSE +3 -0
- package/skills/risk-compliance/contract-review/SKILL.md +240 -0
- package/skills/risk-compliance/contract-review/references/review-criteria.md +223 -0
- package/skills/risk-compliance/contract-review/release-check.mjs +93 -0
- package/skills/risk-compliance/doc-authenticity/LICENSE +3 -0
- package/skills/risk-compliance/doc-authenticity/SKILL.md +160 -0
- package/skills/risk-compliance/doc-authenticity/agents/openai.yaml +8 -0
- package/skills/risk-compliance/doc-authenticity/manual-invocation.test.mjs +12 -0
- package/skills/risk-compliance/doc-authenticity/references/agreement.md +66 -0
- package/skills/risk-compliance/doc-authenticity/references/bank-statement.md +150 -0
- package/skills/risk-compliance/doc-authenticity/references/forensic-signals.md +157 -0
- package/skills/risk-compliance/doc-authenticity/references/image-signals.md +114 -0
- package/skills/risk-compliance/doc-authenticity/references/invoice.md +66 -0
- package/skills/risk-compliance/doc-authenticity/references/issuer-profiles.md +86 -0
- package/skills/risk-compliance/doc-authenticity/references/verdict-and-report.md +95 -0
- package/skills/risk-compliance/doc-authenticity/references/verdict.schema.json +81 -0
- package/skills/risk-compliance/doc-authenticity/release-check.mjs +93 -0
- package/skills/risk-compliance/doc-authenticity/scripts/image_forensics.py +294 -0
- package/skills/risk-compliance/doc-authenticity/scripts/pdf_forensics.py +401 -0
- package/skills/risk-compliance/doc-authenticity/scripts/validate_codes.py +224 -0
- package/skills/risk-compliance/doc-authenticity/scripts/validate_verdict.py +308 -0
- package/skills/risk-compliance/doc-authenticity/scripts/validate_verdict.test.mjs +212 -0
- package/skills/risk-compliance/fraud-analysis/LICENSE +3 -0
- package/skills/risk-compliance/fraud-analysis/SKILL.md +114 -0
- package/skills/risk-compliance/fraud-analysis/references/archetypes/authorized-payment-scam.md +41 -0
- package/skills/risk-compliance/fraud-analysis/references/archetypes/first-party-fraud.md +44 -0
- package/skills/risk-compliance/fraud-analysis/references/archetypes/third-party-fraud.md +27 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/bank-transfer.md +24 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/card-payment.md +30 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/payment-collection.md +20 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/payout.md +20 -0
- package/skills/risk-compliance/fraud-analysis/references/feature-engineering.md +158 -0
- package/skills/risk-compliance/fraud-analysis/references/mechanisms/account-takeover.md +36 -0
- package/skills/risk-compliance/fraud-analysis/references/report-rationale.md +45 -0
- package/skills/risk-compliance/fraud-analysis/references/report-template.md +190 -0
- package/skills/risk-compliance/fraud-analysis/references/review-checklist.md +175 -0
- package/skills/risk-compliance/fraud-analysis/references/taxonomy.md +79 -0
- package/skills/risk-compliance/fraud-analysis/references/terminology.md +108 -0
- package/skills/risk-compliance/fraud-analysis/references/workflow.md +175 -0
- package/skills/risk-compliance/fraud-analysis/release-check.mjs +93 -0
- package/skills/risk-compliance/payment-analysis/LICENSE +3 -0
- package/skills/risk-compliance/payment-analysis/SKILL.md +180 -0
- package/skills/risk-compliance/payment-analysis/references/auth-rate-actions.md +30 -0
- package/skills/risk-compliance/payment-analysis/references/chargebacks.md +208 -0
- package/skills/risk-compliance/payment-analysis/references/chinese-polish.md +51 -0
- package/skills/risk-compliance/payment-analysis/references/event-layers.md +127 -0
- package/skills/risk-compliance/payment-analysis/references/fx.md +59 -0
- package/skills/risk-compliance/payment-analysis/references/journey.md +79 -0
- package/skills/risk-compliance/payment-analysis/references/metrics.md +67 -0
- package/skills/risk-compliance/payment-analysis/references/report-template.md +119 -0
- package/skills/risk-compliance/payment-analysis/references/terminology.md +95 -0
- package/skills/risk-compliance/payment-analysis/references/visualization.md +56 -0
- package/skills/risk-compliance/payment-analysis/release-check.mjs +93 -0
- package/skills/risk-compliance/report-writing/LICENSE +3 -0
- package/skills/risk-compliance/report-writing/SKILL.md +220 -0
- package/skills/risk-compliance/report-writing/references/audit-report-template.md +121 -0
- package/skills/risk-compliance/report-writing/references/external-assessment-template.md +167 -0
- package/skills/risk-compliance/report-writing/references/management-report-template.md +145 -0
- package/skills/risk-compliance/report-writing/references/vars-report-template.md +224 -0
- package/skills/risk-compliance/report-writing/release-check.mjs +93 -0
- package/skills/risk-compliance/similar-domain/LICENSE +3 -0
- package/skills/risk-compliance/similar-domain/SKILL.md +203 -0
- package/skills/risk-compliance/similar-domain/references/entities.md +67 -0
- package/skills/risk-compliance/similar-domain/references/fingerprints.md +134 -0
- package/skills/risk-compliance/similar-domain/references/pivots.md +82 -0
- package/skills/risk-compliance/similar-domain/references/report-template.md +93 -0
- package/skills/risk-compliance/similar-domain/references/scoring.md +130 -0
- package/skills/risk-compliance/similar-domain/references/terminology.md +41 -0
- package/skills/risk-compliance/similar-domain/references/workflow.md +85 -0
- package/skills/risk-compliance/similar-domain/release-check.mjs +93 -0
- package/skills/risk-compliance/tld-detection/LICENSE +3 -0
- package/skills/risk-compliance/tld-detection/SKILL.md +245 -0
- package/skills/risk-compliance/tld-detection/agents/openai.yaml +9 -0
- package/skills/risk-compliance/tld-detection/references/chinese-polish.md +55 -0
- package/skills/risk-compliance/tld-detection/references/clean.md +51 -0
- package/skills/risk-compliance/tld-detection/references/clustering.md +235 -0
- package/skills/risk-compliance/tld-detection/references/decision.md +189 -0
- package/skills/risk-compliance/tld-detection/references/fx-conversion.md +232 -0
- package/skills/risk-compliance/tld-detection/references/report-template.md +272 -0
- package/skills/risk-compliance/tld-detection/references/streams.md +141 -0
- package/skills/risk-compliance/tld-detection/references/terminology.md +95 -0
- package/skills/risk-compliance/tld-detection/references/workflow.md +95 -0
- package/skills/risk-compliance/tld-detection/release-check.mjs +93 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_ladders.py +390 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_ladders.test.mjs +14 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_streams.py +650 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_streams.test.mjs +14 -0
- package/skills/risk-compliance/tld-detection/tests/test_detect_ladders.py +134 -0
- package/skills/risk-compliance/tld-detection/tests/test_detect_streams.py +520 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
// Cheap scan of a unified diff. It emits TWO channels, and the distinction is
|
|
2
|
+
// load-bearing:
|
|
3
|
+
// • LEADS (heuristic) — "look here and verify"; the reviewer reads the code and
|
|
4
|
+
// builds the counterexample before any becomes a finding (see references/passes.md).
|
|
5
|
+
// • FINDINGS (decidable) — near-zero-false-positive checks that ARE blockers on
|
|
6
|
+
// their own. Currently: `over-mock-internal-seam` (a vi/jest.mock of a
|
|
7
|
+
// first-party seam = Over-mocked, zero-tolerance). This makes better-review the
|
|
8
|
+
// standalone first line of enforcement — no dependency on ensure-coverage's
|
|
9
|
+
// gate being wired in the repo.
|
|
10
|
+
//
|
|
11
|
+
// git diff <merge-base>...HEAD | node scan-diff.mjs # leads + findings from stdin
|
|
12
|
+
// node scan-diff.mjs --diff changes.patch
|
|
13
|
+
//
|
|
14
|
+
// Best-effort and JS/TS-oriented (regex/branch heuristics are language-bound; the
|
|
15
|
+
// mock/interception checks are framework-specific). On other languages it simply
|
|
16
|
+
// finds fewer — it is additive, and absence means "the scanner found nothing,"
|
|
17
|
+
// not "the code is fine."
|
|
18
|
+
|
|
19
|
+
import fs from 'node:fs'
|
|
20
|
+
import path from 'node:path'
|
|
21
|
+
import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
|
|
22
|
+
|
|
23
|
+
// ---- pure core ----
|
|
24
|
+
|
|
25
|
+
// Parse a unified diff into added lines with their NEW-file line numbers.
|
|
26
|
+
export function parseAddedLines(diffText) {
|
|
27
|
+
const out = []
|
|
28
|
+
let file = null
|
|
29
|
+
let newLine = 0
|
|
30
|
+
for (const raw of (diffText || '').split(/\r?\n/)) {
|
|
31
|
+
if (raw.startsWith('+++ ')) {
|
|
32
|
+
const m = raw.match(/^\+\+\+ b\/(.+)$/)
|
|
33
|
+
file = m ? m[1] : raw.slice(4).replace(/^b\//, '')
|
|
34
|
+
continue
|
|
35
|
+
}
|
|
36
|
+
if (raw.startsWith('diff --git')) { file = null; continue }
|
|
37
|
+
const hm = raw.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/)
|
|
38
|
+
if (hm) { newLine = parseInt(hm[1], 10); continue }
|
|
39
|
+
if (raw.startsWith('+')) { out.push({ file, line: newLine, text: raw.slice(1) }); newLine++; continue }
|
|
40
|
+
if (raw.startsWith('-')) continue // removed line: no advance in new file
|
|
41
|
+
if (raw.startsWith('\\')) continue // ""
|
|
42
|
+
newLine++ // context line
|
|
43
|
+
}
|
|
44
|
+
return out
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const TEST_FILE = /\.(test|spec)\.[jt]sx?$/
|
|
48
|
+
const INTERCEPT = /\broute\.fulfill\b|\bpage\.route\s*\(|\bsetupServer\s*\(|\bsetupWorker\s*\(|from\s+['"]msw['"]/
|
|
49
|
+
|
|
50
|
+
export function interceptionLeads(added) {
|
|
51
|
+
return added
|
|
52
|
+
.filter((a) => a.file && TEST_FILE.test(a.file) && INTERCEPT.test(a.text))
|
|
53
|
+
.map((a) => ({ type: 'first-party-interception', file: a.file, line: a.line, snippet: a.text.trim(),
|
|
54
|
+
note: 'first-party interception in a test — over-mock risk; verify the real path is actually proven (browser/journey, not stub). Skip if: the route is a third-party/external boundary, or this is a Tier-2 functional failure-injection test (interception is correct there).' }))
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Regex literals / RegExp() added without ^ or $ anchors → boundary-leak risk.
|
|
58
|
+
export function regexLeads(added) {
|
|
59
|
+
const out = []
|
|
60
|
+
for (const a of added) {
|
|
61
|
+
for (const lit of a.text.match(/\/(?:[^/\n\\]|\\.){2,}\/[gimsuy]*/g) || []) {
|
|
62
|
+
const body = lit.replace(/\/[gimsuy]*$/, '').slice(1)
|
|
63
|
+
if (!/[\^$]/.test(body) && /[A-Za-z0-9]/.test(body)) {
|
|
64
|
+
out.push({ type: 'unanchored-pattern', file: a.file, line: a.line, snippet: lit,
|
|
65
|
+
note: 'regex without ^/$ anchors — verify prefix/substring leakage at boundaries (does /foo also match /foobar?). Skip if: inputs are a closed/validated set where leakage cannot occur, or a substring match is intended — produce the breaking input or drop it.' })
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const re = a.text.match(/new RegExp\(([^)]*)\)/)
|
|
69
|
+
if (re && !/[\^$]/.test(re[1])) {
|
|
70
|
+
out.push({ type: 'unanchored-pattern', file: a.file, line: a.line, snippet: re[0].trim(),
|
|
71
|
+
note: 'RegExp without ^/$ — verify boundary behavior.' })
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return out
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Weakened assertions in tests → a test that can't fail the way its name promises.
|
|
78
|
+
// Two tells from real "smoke wearing a journey label" specs:
|
|
79
|
+
// - `.catch(() => false)` (or null/undefined/0/'') swallows a locator/await throw
|
|
80
|
+
// into a falsy, defeating Playwright's web-first retry and any assertion on it.
|
|
81
|
+
// - `expect(a || b || c).toBeTruthy()` / `.toBe(true)` — a disjunctive truthiness
|
|
82
|
+
// assertion passes if ANY branch holds, so it pins down no specific behavior.
|
|
83
|
+
// Reviewer then checks the test's @level: a journey/functional test asserting only
|
|
84
|
+
// these is Wrong Level (references/passes.md → Spec).
|
|
85
|
+
const CATCH_SWALLOW = /\.catch\s*\(\s*\(\s*\)\s*=>\s*(?:false|null|undefined|0|''|""|``)\s*\)/
|
|
86
|
+
const DISJUNCTIVE_TRUTHY = /\bexpect\s*\([^;]*\|\|[^;]*\)\s*\.\s*(?:toBeTruthy\b|toBe\s*\(\s*true\s*\))/
|
|
87
|
+
export function weakAssertionLeads(added) {
|
|
88
|
+
const out = []
|
|
89
|
+
for (const a of added) {
|
|
90
|
+
if (!a.file || !TEST_FILE.test(a.file)) continue
|
|
91
|
+
if (CATCH_SWALLOW.test(a.text)) out.push({ type: 'swallowed-assertion', file: a.file, line: a.line, snippet: a.text.trim(),
|
|
92
|
+
note: 'catch swallows a locator/await throw into a falsy — defeats web-first retry and hides real failures; assert directly (web-first expect), do not catch-to-false. Skip if: the falsy genuinely feeds a non-assertion control-flow decision and the real outcome is asserted separately.' })
|
|
93
|
+
if (DISJUNCTIVE_TRUTHY.test(a.text)) out.push({ type: 'weak-assertion', file: a.file, line: a.line, snippet: a.text.trim(),
|
|
94
|
+
note: 'disjunctive truthiness — passes if any branch holds, so it proves nothing specific; if this is a @level journey/functional test it is Wrong Level (drive the flow to a concrete outcome). Skip if: this is a @level render-health test (alias: smoke) where "renders at all" is the whole contract.' })
|
|
95
|
+
}
|
|
96
|
+
return out
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// A test that *names itself* a race but reads state some earlier test already created
|
|
100
|
+
// cannot exercise the first-writer path: both "concurrent" callers take the
|
|
101
|
+
// already-exists early return, and the contended create never runs. The tell is a
|
|
102
|
+
// pre-existing capture (`x!.id`, `find*OrThrow`) reached before the `Promise.all`.
|
|
103
|
+
// Kept a LEAD, not a finding: post-seal/replay races legitimately look exactly like
|
|
104
|
+
// this. What makes it a defect is the test being cited as first-writer proof — a
|
|
105
|
+
// judgment about the AC mapping that no regex can make.
|
|
106
|
+
const ANY_TEST_TITLE = /\b(?:it|test)\s*(?:\.\w+)?\s*\(\s*['"`]/
|
|
107
|
+
const CONCURRENCY_TEST_TITLE = /\b(?:it|test)\s*(?:\.\w+)?\s*\(\s*['"`][^'"`]*\b(?:race|races|racing|concurrent|concurrently|simultaneous(?:ly)?|parallel)\b/i
|
|
108
|
+
const PREEXISTING_CAPTURE = /\w\s*!\s*\.\s*\w|\bfind(?:First|Unique)OrThrow\s*\(/
|
|
109
|
+
const CONCURRENT_CALL = /\bPromise\s*\.\s*(?:all|allSettled|race)\s*\(/
|
|
110
|
+
|
|
111
|
+
export function concurrencyFixtureLeads(added) {
|
|
112
|
+
const out = []
|
|
113
|
+
const byFile = new Map()
|
|
114
|
+
for (const a of added) {
|
|
115
|
+
if (!a.file || !TEST_FILE_ANY.test(a.file)) continue
|
|
116
|
+
if (!byFile.has(a.file)) byFile.set(a.file, [])
|
|
117
|
+
byFile.get(a.file).push(a)
|
|
118
|
+
}
|
|
119
|
+
for (const [, lines] of byFile) {
|
|
120
|
+
lines.sort((x, y) => x.line - y.line)
|
|
121
|
+
let title = null // the concurrency-named test we are inside
|
|
122
|
+
let capture = null // first pre-existing capture seen since that title
|
|
123
|
+
for (const a of lines) {
|
|
124
|
+
// Any test title closes the previous body. Tracking only concurrency titles
|
|
125
|
+
// would leave scope open across the rest of the file, so the next ordinary
|
|
126
|
+
// test's fixture would be attributed to a race test that already ended.
|
|
127
|
+
if (ANY_TEST_TITLE.test(a.text)) {
|
|
128
|
+
title = CONCURRENCY_TEST_TITLE.test(a.text) ? a : null
|
|
129
|
+
capture = null
|
|
130
|
+
continue
|
|
131
|
+
}
|
|
132
|
+
if (!title) continue
|
|
133
|
+
if (!capture && PREEXISTING_CAPTURE.test(a.text)) { capture = a; continue }
|
|
134
|
+
if (capture && CONCURRENT_CALL.test(a.text)) {
|
|
135
|
+
out.push({ type: 'concurrency-test-preexisting-fixture', file: capture.file, line: capture.line, snippet: capture.text.trim(),
|
|
136
|
+
note: `test named as a race/concurrent case reads pre-existing state before ${a.text.trim().slice(0, 40)}… — if that state is what the concurrent calls are supposed to be creating, every caller takes the already-exists path and the contended first-write is never exercised (a green test for an untested race). Verify the fixture starts from ABSENT, with independent clients/connections and a barrier. Skip if: this is deliberately a post-create replay/idempotency case AND a separate test covers the first-write race — then check that the AC cites that one, not this.` })
|
|
137
|
+
title = null; capture = null
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return out
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// New conditional branches → each needs a test (line coverage ≠ branch coverage).
|
|
145
|
+
export function branchLeads(added) {
|
|
146
|
+
return added
|
|
147
|
+
.filter((a) => /\b(if|else if|case)\b/.test(a.text) || /\?[^?]*:/.test(a.text))
|
|
148
|
+
.map((a) => ({ type: 'new-branch', file: a.file, line: a.line, snippet: a.text.trim(),
|
|
149
|
+
note: 'new branch — name a test that exercises it; line coverage is not branch coverage. Skip if: an integration/E2E test already drives it, or the branch is a trivial guard whose failure is inert.' }))
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Files whose EXISTING behavior is modified (edited/removed lines in a non-test
|
|
153
|
+
// SOURCE file) owe a characterization test pinning prior behavior before the
|
|
154
|
+
// change (ensure-coverage → depth/characterization.md). A new file or a test
|
|
155
|
+
// file is excluded; only changed/removed content in a non-test source file
|
|
156
|
+
// signals an existing-behavior modification. The *detection* is decidable; the
|
|
157
|
+
// adjudication ("is there an adequate @characterizes test, or a declared intended
|
|
158
|
+
// change?") is the reviewer's — hence a lead, not a finding.
|
|
159
|
+
const TEST_FILE_ANY = /\.(test|spec)\.[cm]?[jt]sx?$|(^|\/)(e2e|tests?|__tests__)\/|(^|\/)test_[^/]*\.py$|_test\.py$/
|
|
160
|
+
const NON_SOURCE = /\.(md|markdown|json|ya?ml|txt|lock|svg|png|jpe?g|gif|webp|ico|csv|tsv|toml|ini|cfg|snap)$/i
|
|
161
|
+
|
|
162
|
+
// Parse a diff into per-file change shape: { isNew, removed, added, firstLine }.
|
|
163
|
+
// `removed` counts changed/deleted content lines (the modify signal); a new file
|
|
164
|
+
// (--- /dev/null or `new file mode`) is flagged so it's treated as addition.
|
|
165
|
+
export function parseFileChanges(diffText) {
|
|
166
|
+
const files = new Map()
|
|
167
|
+
let file = null
|
|
168
|
+
let pendingNew = false
|
|
169
|
+
let newLine = 0
|
|
170
|
+
for (const raw of (diffText || '').split(/\r?\n/)) {
|
|
171
|
+
if (raw.startsWith('diff --git')) { file = null; pendingNew = false; continue }
|
|
172
|
+
if (raw.startsWith('new file mode')) { pendingNew = true; continue }
|
|
173
|
+
if (raw.startsWith('--- ')) { if (/\/dev\/null/.test(raw)) pendingNew = true; continue }
|
|
174
|
+
if (raw.startsWith('+++ ')) {
|
|
175
|
+
const m = raw.match(/^\+\+\+ (?:b\/)?(.+)$/)
|
|
176
|
+
file = m && m[1] !== '/dev/null' ? m[1] : null
|
|
177
|
+
if (file && !files.has(file)) files.set(file, { isNew: pendingNew, removed: 0, added: 0, firstLine: 0 })
|
|
178
|
+
pendingNew = false
|
|
179
|
+
continue
|
|
180
|
+
}
|
|
181
|
+
if (!file) continue
|
|
182
|
+
const hm = raw.match(/^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/)
|
|
183
|
+
if (hm) { newLine = parseInt(hm[1], 10); continue }
|
|
184
|
+
const rec = files.get(file)
|
|
185
|
+
if (!rec) continue
|
|
186
|
+
if (raw.startsWith('-')) { rec.removed++; if (!rec.firstLine) rec.firstLine = newLine; continue } // no new-line advance
|
|
187
|
+
if (raw.startsWith('+')) { rec.added++; if (!rec.firstLine) rec.firstLine = newLine; newLine++; continue }
|
|
188
|
+
if (raw.startsWith('\\')) continue
|
|
189
|
+
newLine++ // context
|
|
190
|
+
}
|
|
191
|
+
return files
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function characterizationLeads(diffText) {
|
|
195
|
+
const out = []
|
|
196
|
+
for (const [file, rec] of parseFileChanges(diffText)) {
|
|
197
|
+
if (rec.isNew) continue // new file = new behavior, not a modification
|
|
198
|
+
if (TEST_FILE_ANY.test(file)) continue // editing tests is not modifying production behavior
|
|
199
|
+
if (NON_SOURCE.test(file)) continue // docs/config/snapshots carry no behavior to pin
|
|
200
|
+
if (rec.removed === 0) continue // pure addition into an existing file = added behavior
|
|
201
|
+
out.push({ type: 'modifies-existing-behavior', file, line: rec.firstLine || 1,
|
|
202
|
+
snippet: `${rec.removed} existing line(s) changed/removed`,
|
|
203
|
+
note: 'existing behavior modified — verify a characterization test pins the PRIOR behavior (authored to pass on the pre-change tree) so this diff is proven not to shift observable behavior unintentionally; tag it `// @characterizes <surface>`. Skip if: an existing behavior test already covers this exact path and still passes unchanged (cite it), this is a declared intended behavior change with its AC and the assertion delta is in the diff, or the edit is trivial/generated/non-behavioral. See ensure-coverage depth/characterization.md.' })
|
|
204
|
+
}
|
|
205
|
+
return out
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// ---- VENDORED over-mock classifier — DECIDABLE FINDING, not a lead ----
|
|
209
|
+
//
|
|
210
|
+
// Self-contained copy of ensure-coverage's `mock-internal-seam` classifier
|
|
211
|
+
// (skills/engineering/ensure-coverage/scripts/mock-policy-config.mjs), vendored
|
|
212
|
+
// here so better-review enforces no-over-mock with ZERO dependency on ensure-coverage
|
|
213
|
+
// being installed/wired. ensure-coverage stays CANONICAL: if the two diverge,
|
|
214
|
+
// ensure-coverage wins and this copy is stale → resync. Kept tiny on purpose.
|
|
215
|
+
//
|
|
216
|
+
// The "externals-allowlist inversion": you can't enumerate internal seams, but
|
|
217
|
+
// the legitimately-fakeable set (third-party/stdlib) is small and known — so a
|
|
218
|
+
// mock whose target resolves to first-party code is a seam (a defect), and the
|
|
219
|
+
// declared externals / stdlib / bare packages are exempt. Unlike the heuristic
|
|
220
|
+
// leads above this is DECIDABLE, so its hits are emitted as `findings`.
|
|
221
|
+
|
|
222
|
+
export const DEFAULT_MOCK_TOPOLOGY = {
|
|
223
|
+
firstPartyAliasPrefixes: ['@/', '~/'],
|
|
224
|
+
firstPartyPackages: [], // e.g. a monorepo's own scope '@acme/'
|
|
225
|
+
externals: [], // regex SOURCES for first-party-looking-but-external targets
|
|
226
|
+
testUtilHints: ['__mocks__', '__fixtures__', 'fixtures', 'mocks', 'helpers',
|
|
227
|
+
'test-utils', 'testing', 'support', 'stubs', 'factories'],
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Best-effort read of coverage.config.json topology (so a monorepo's own @scope
|
|
231
|
+
// is recognized); never throws — defaults to conventional @/ ~/ when absent.
|
|
232
|
+
// Config declares TOPOLOGY only; it cannot disable the check (zero-tolerance).
|
|
233
|
+
export function loadMockTopology(cwd = process.cwd()) {
|
|
234
|
+
for (const name of ['coverage.config.json', '.coverage.config.json']) {
|
|
235
|
+
try {
|
|
236
|
+
const mp = (JSON.parse(fs.readFileSync(path.join(cwd, name), 'utf8')).mockPolicy) || {}
|
|
237
|
+
return {
|
|
238
|
+
firstPartyAliasPrefixes: mp.firstPartyAliasPrefixes ?? DEFAULT_MOCK_TOPOLOGY.firstPartyAliasPrefixes,
|
|
239
|
+
firstPartyPackages: mp.firstPartyPackages ?? DEFAULT_MOCK_TOPOLOGY.firstPartyPackages,
|
|
240
|
+
externals: mp.externals ?? DEFAULT_MOCK_TOPOLOGY.externals,
|
|
241
|
+
testUtilHints: mp.testUtilHints ?? DEFAULT_MOCK_TOPOLOGY.testUtilHints,
|
|
242
|
+
}
|
|
243
|
+
} catch { /* missing or malformed → try next, else defaults */ }
|
|
244
|
+
}
|
|
245
|
+
return { ...DEFAULT_MOCK_TOPOLOGY }
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Pull the mocked specifier from a vi/jest/vitest `.mock`/`.doMock(...)` call.
|
|
249
|
+
export function extractMockTarget(codeLine) {
|
|
250
|
+
const m = /\b(?:vi|jest|vitest)\s*\.\s*(?:mock|doMock)\s*\(\s*(['"`])([^'"`]+)\1/.exec(codeLine || '')
|
|
251
|
+
return m ? m[2] : null
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Classify a mock target as an internal seam (a defect) or an allowed external.
|
|
255
|
+
// Precedence: declared externals > stdlib > relative(util vs source) >
|
|
256
|
+
// first-party alias > first-party package > bare package (external default).
|
|
257
|
+
export function classifyMockTarget(target, topo = DEFAULT_MOCK_TOPOLOGY) {
|
|
258
|
+
if (!target) return { internal: false, reason: 'no target' }
|
|
259
|
+
for (const src of topo.externals || []) {
|
|
260
|
+
try { if (new RegExp(src).test(target)) return { internal: false, reason: 'declared external' } } catch { /* ignore bad regex */ }
|
|
261
|
+
}
|
|
262
|
+
if (target.startsWith('node:')) return { internal: false, reason: 'node builtin' }
|
|
263
|
+
if (target.startsWith('.')) {
|
|
264
|
+
if (target.split('/').some((s) => (topo.testUtilHints || []).includes(s))) return { internal: false, reason: 'relative test util/fixture/mock' }
|
|
265
|
+
return { internal: true, reason: 'relative import into first-party source' }
|
|
266
|
+
}
|
|
267
|
+
for (const pre of topo.firstPartyAliasPrefixes || []) {
|
|
268
|
+
if (target.startsWith(pre)) return { internal: true, reason: `first-party alias "${pre}"` }
|
|
269
|
+
}
|
|
270
|
+
for (const fp of topo.firstPartyPackages || []) {
|
|
271
|
+
const base = fp.endsWith('/') ? fp.slice(0, -1) : fp
|
|
272
|
+
if (target === base || target.startsWith(`${base}/`)) return { internal: true, reason: `first-party package "${fp}"` }
|
|
273
|
+
}
|
|
274
|
+
return { internal: false, reason: 'external package' }
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Diff-scoped over-mock FINDINGS: a vi/jest/vitest.mock of a first-party internal
|
|
278
|
+
// seam ADDED in a test file → Over-mocked (a blocker), not a lead. Diff-scoped is
|
|
279
|
+
// the right scope for a PR review (review the diff; pre-existing mocks are notes by
|
|
280
|
+
// diff-discipline) — the whole-tree inherited burndown is ensure-coverage's audit lint.
|
|
281
|
+
export function overMockFindings(added, topo = DEFAULT_MOCK_TOPOLOGY) {
|
|
282
|
+
const out = []
|
|
283
|
+
for (const a of added) {
|
|
284
|
+
if (!a.file || !TEST_FILE_ANY.test(a.file)) continue
|
|
285
|
+
const target = extractMockTarget(a.text)
|
|
286
|
+
if (!target) continue
|
|
287
|
+
const { internal, reason } = classifyMockTarget(target, topo)
|
|
288
|
+
if (!internal) continue
|
|
289
|
+
out.push({ type: 'over-mock-internal-seam', file: a.file, line: a.line, snippet: a.text.trim(), target, reason,
|
|
290
|
+
note: 'mocks a first-party internal seam → Over-mocked (dishonest green): zero-tolerance, NO @mock-ok waiver and no "approved with justification" (ensure-coverage depth/mock-policy.md). Resolve by making the test real, faking only the external, or DELETING it (over-mock is worse than no test). Only NOT a finding if the target is genuinely external — then declare it as topology in coverage.config.json.' })
|
|
291
|
+
}
|
|
292
|
+
return out
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export function scanDiff(diffText, topo = DEFAULT_MOCK_TOPOLOGY) {
|
|
296
|
+
const added = parseAddedLines(diffText)
|
|
297
|
+
const byPlace = (a, b) => (a.file || '').localeCompare(b.file || '') || a.line - b.line
|
|
298
|
+
const leads = [...interceptionLeads(added), ...regexLeads(added), ...weakAssertionLeads(added), ...branchLeads(added),
|
|
299
|
+
...concurrencyFixtureLeads(added), ...characterizationLeads(diffText)].sort(byPlace)
|
|
300
|
+
const findings = overMockFindings(added, topo).sort(byPlace)
|
|
301
|
+
const tally = (xs) => xs.reduce((m, l) => ((m[l.type] = (m[l.type] || 0) + 1), m), {})
|
|
302
|
+
// `counts`/`leads` kept for back-compat; `findings` is the decidable, blocker-grade channel.
|
|
303
|
+
return { kind: 'leads+findings', counts: tally(leads), leads, findingCounts: tally(findings), findings }
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ---- CLI ----
|
|
307
|
+
|
|
308
|
+
// Exit codes. Both are usage errors (distinct from 0 = scanned OK, and from a
|
|
309
|
+
// generic crash). NO_INPUT is the fail-open this tool exists NOT to have: a
|
|
310
|
+
// parity proof that returns "all clear" on zero bytes proved nothing about the
|
|
311
|
+
// diff (issue #416). USAGE catches the `--base/--head` invocation producers
|
|
312
|
+
// invented — flags this tool never had, which used to fall through to an empty
|
|
313
|
+
// stdin read and a vacuous clean result.
|
|
314
|
+
export const NO_INPUT_EXIT = 2
|
|
315
|
+
export const USAGE_EXIT = 2
|
|
316
|
+
|
|
317
|
+
// The ONE correct invocation, echoed in every error so a wrong call self-corrects.
|
|
318
|
+
const USAGE = 'Pipe the net diff: git diff <merge-base>...HEAD | node scan-diff.mjs (or: node scan-diff.mjs --diff <file>). This tool takes NO --base/--head.'
|
|
319
|
+
|
|
320
|
+
// A usage/no-input error carrying its own process exit code. Thrown by the arg
|
|
321
|
+
// parser and the empty-input guard; main() prints .message to stderr and exits.
|
|
322
|
+
export class ScanDiffCliError extends Error {
|
|
323
|
+
constructor(message, code = USAGE_EXIT) { super(message); this.name = 'ScanDiffCliError'; this.code = code }
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Parse argv (already sliced of node + script). Returns { diffPath } — null means
|
|
327
|
+
// read stdin. Anything that isn't `--diff <file>` HARD-FAILS: an unknown flag
|
|
328
|
+
// (the `--base/--head` mistake) or a stray positional would otherwise be silently
|
|
329
|
+
// ignored, dropping through to an empty stdin read and a false-clean proof.
|
|
330
|
+
export function parseCliArgs(argv) {
|
|
331
|
+
let diffPath = null
|
|
332
|
+
for (let i = 0; i < argv.length; i++) {
|
|
333
|
+
const arg = argv[i]
|
|
334
|
+
if (arg === '--diff') {
|
|
335
|
+
diffPath = argv[i + 1]
|
|
336
|
+
if (diffPath == null) throw new ScanDiffCliError(`scan-diff: --diff requires a file path. ${USAGE}`)
|
|
337
|
+
i++
|
|
338
|
+
continue
|
|
339
|
+
}
|
|
340
|
+
if (arg.startsWith('-')) throw new ScanDiffCliError(`scan-diff: unknown flag "${arg}". ${USAGE}`)
|
|
341
|
+
throw new ScanDiffCliError(`scan-diff: unexpected argument "${arg}". ${USAGE}`)
|
|
342
|
+
}
|
|
343
|
+
return { diffPath }
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function main() {
|
|
347
|
+
let diff
|
|
348
|
+
try {
|
|
349
|
+
const { diffPath } = parseCliArgs(process.argv.slice(2))
|
|
350
|
+
diff = diffPath != null ? fs.readFileSync(diffPath, 'utf8') : fs.readFileSync(0, 'utf8') // --diff <file> or stdin
|
|
351
|
+
// Fail LOUD on no input. Empty/whitespace-only means the diff never arrived
|
|
352
|
+
// (a non-piped context, or the `--base/--head` fall-through) — NOT a clean
|
|
353
|
+
// diff. A real diff with content but zero findings still exits 0 below;
|
|
354
|
+
// "no INPUT" and "input with no findings" are different answers.
|
|
355
|
+
if (!diff.trim()) throw new ScanDiffCliError(`scan-diff: no diff on stdin (or --diff <file> is empty). ${USAGE}`, NO_INPUT_EXIT)
|
|
356
|
+
} catch (err) {
|
|
357
|
+
if (err instanceof ScanDiffCliError) { process.stderr.write(`${err.message}\n`); process.exit(err.code) }
|
|
358
|
+
throw err
|
|
359
|
+
}
|
|
360
|
+
const result = scanDiff(diff, loadMockTopology())
|
|
361
|
+
result.disclaimer = 'TWO channels. `leads` = heuristic "look here and verify" (read the code, build the counterexample first). `findings` = DECIDABLE blockers (over-mock-internal-seam): a vi/jest.mock of a first-party seam is Over-mocked, zero-tolerance, no waiver — fix it, do not merge over it. Best-effort, JS/TS-oriented; absence != code is fine.'
|
|
362
|
+
console.log(JSON.stringify(result, null, 2))
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (isMainModule(import.meta.url)) main()
|