@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,68 @@
|
|
|
1
|
+
# Depth: Characterization — pin existing behavior before you change it
|
|
2
|
+
|
|
3
|
+
> Read when: a change **modifies existing behavior** (edits/deletes lines in a non-test source file) rather than adding a brand-new surface. Sibling: [grading.md](grading.md) (how each obligation is graded), [mock-policy.md](mock-policy.md) (the boundary). New-surface work is TDD red→green; *this* is the obligation for touching code that already runs in production.
|
|
4
|
+
|
|
5
|
+
Michael Feathers' rule: *"Characterization tests document the actual behavior of the code, not the intended behavior."* The common agent failure mode: it refactors or "fixes" a function, the existing tests stay green (they never covered the changed path), and an **observable behavior silently shifts**. A green suite after the change proves nothing if no test pinned the behavior *before* it.
|
|
6
|
+
|
|
7
|
+
So a modification carries a depth obligation a fresh feature does not: **before you change existing behavior, write a test that captures what the code does today, and make it pass against the unchanged tree.** That test becomes a boundary the change cannot silently cross — the seam ([below](#seams-where-to-pin)) at which you alter behavior deliberately.
|
|
8
|
+
|
|
9
|
+
## The obligation: when it is owed
|
|
10
|
+
|
|
11
|
+
A change owes a characterization test when **all** hold:
|
|
12
|
+
|
|
13
|
+
- It **edits or removes** existing lines of a non-test **source** file (a pure addition into a new file, or appended-only code, is new behavior → TDD path).
|
|
14
|
+
- The touched code has **observable behavior** — return value, durable-state effect, emitted event, HTTP contract, rendered output. (Internal-only renames with no behavioral surface don't.)
|
|
15
|
+
- The surface is **non-trivial** — anything carrying a Surface Baseline floor, or logic a user/caller depends on.
|
|
16
|
+
|
|
17
|
+
When owed, the test must: **(1) capture actual, not intended, behavior** including quirks/bugs (if current behavior is wrong, characterize it *then* fix it in a separate declared step); **(2) pass on the pre-change tree** (GREEN on `HEAD~`/base before your edit — capture as evidence); **(3) still pass after the change**, unless the change is a declared intended behavior change.
|
|
18
|
+
|
|
19
|
+
## When it is waived
|
|
20
|
+
|
|
21
|
+
Mark the waiver explicitly in the PR's evidence, never silently:
|
|
22
|
+
|
|
23
|
+
- **Already pinned** — an existing behavior test covers the exact changed path and still passes unchanged. Cite it (`file:line`); that test *is* the characterization.
|
|
24
|
+
- **Declared intended behavior change** — deliberately alters observable behavior per an AC/bug brief. The obligation inverts: update/author the test to assert the **new** behavior, and the diff must show the old assertion changing to the new (a behavior change with no test delta is the suspicious case). Cite the AC.
|
|
25
|
+
- **Trivial / generated / non-behavioral** — formatting, comments, type-only edits, generated code with no behavior delta.
|
|
26
|
+
|
|
27
|
+
## The `@characterizes` convention
|
|
28
|
+
|
|
29
|
+
Tag a characterization test so the gate can resolve it, parallel to `@covers`:
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
// @characterizes <surface-id> // pins prior behavior of a surface being modified
|
|
33
|
+
// @covers <surface-id> // (a characterization test usually also @covers it)
|
|
34
|
+
// @level <level>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`@characterizes` is the signal that *this* test exists to hold a modification's behavior boundary. A modifying diff with no `@characterizes` test and no declared waiver is the gap this obligation names.
|
|
38
|
+
|
|
39
|
+
## Grading
|
|
40
|
+
|
|
41
|
+
Characterization is a **depth** concern, graded with the [shared vocabulary](grading.md):
|
|
42
|
+
|
|
43
|
+
- A modifying diff whose changed behavior is pinned by a passing characterization test (or cited pre-existing behavior test) → that surface can reach `Covered` on the normal evidence rules.
|
|
44
|
+
- A modifying diff with **no** characterization test and **no** declared intended-change → `Partial` at best; the reviewer raises the `modifies-existing-behavior` lead (below). Not a hard `Missing` (existing tests may incidentally cover it) — a **lead to adjudicate**, because whether a characterization test is *needed and adequate* is judgment.
|
|
45
|
+
|
|
46
|
+
## Detection (mechanical) → adjudication (judgment)
|
|
47
|
+
|
|
48
|
+
The decidable half is mechanical: any non-test source file with **removed/changed** lines emits a `modifies-existing-behavior` **lead** ("look here and verify," never an auto-finding). The reviewer checks for a `@characterizes` test (or a declared change) and adjudicates, citing `file:line`. The reviewer resolves it with a locator, not prose. The split matches the GATE-vs-LEAD line everywhere in this skill: detecting *that behavior changed* is mechanical; deciding *whether the pinning test is adequate* is semantic.
|
|
49
|
+
|
|
50
|
+
## Seams: where to pin
|
|
51
|
+
|
|
52
|
+
A characterization test is writable only where you can observe behavior without rewriting the thing you're about to change — a **seam** (*"a place where you can alter behavior without editing the code in that place"*). Pin at the nearest observable seam: the public function's return/throw, the endpoint's HTTP contract, the rendered page's output, the emitted event. If there's no seam, that itself is the finding — introduce one first (extract the call, expose the boundary), pin, *then* change. Do not skip characterization because "it's hard to test as written"; hard-to-pin is the legacy-code smell the obligation exists to surface.
|
|
53
|
+
|
|
54
|
+
## Fails-first: bug-fix AND feature-AC — prove the test fails when the behavior is broken
|
|
55
|
+
|
|
56
|
+
The shared property: **a test is evidence for a behavior only if it would go red were that behavior broken.** A green test that passes with *and* without the behavior it claims is **vacuous coverage** — it locks in nothing. Two cases:
|
|
57
|
+
|
|
58
|
+
**Bug-fix sibling.** A bug fix changes behavior that's *already wrong*, so it owes the inverse of characterization: at least one test demonstrated to **fail on the unfixed code and pass on the fixed code** (RED→GREEN, run in that order), tagged `// @fails-without-fix <surface>`. Reverting the fix must turn the test red. Waive only with a cited reason the failure can't be reproduced in-suite (a tracked `Unverified` manual check, not a silent skip).
|
|
59
|
+
|
|
60
|
+
**Feature-AC sibling.** The same test applies to a *new feature's* AC, where it's most-missed: a green test cited for an AC clears it only if it would go red were the AC's behavior removed — it exercises the AC's real code path, not a proxy. Recurring vacuous forms:
|
|
61
|
+
- a fixture that **early-returns before the code runs** (a 0-step workflow "proving" a multi-step reset that never executes);
|
|
62
|
+
- a `.fill()`/`setValue` that sets state in one shot and so **masks a re-render/defocus bug** a character-by-character `pressSequentially` would expose;
|
|
63
|
+
- an assertion **pinned to a stand-in value the real producer never emits**;
|
|
64
|
+
- asserting **the mock was called** rather than that the outcome happened.
|
|
65
|
+
|
|
66
|
+
**Grading the two outcomes** (they differ from [grading.md](grading.md)'s `Unverified`): can't-yet-confirm it would go red → `Unverified` (a warning unless `unverifiedBlocks: true`); confirm it would **still pass** with the behavior gone → `Missing`/`Over-mocked` (a proven-vacuous test is *worse* than unchecked).
|
|
67
|
+
|
|
68
|
+
The two **decidable** vacuous forms (a swallowed assertion, a fixed timeout) are gated by `lint-tests`; the semantic "would it have been red?" property is verified at review and by running the test against the broken tree. Named incident: the login regression (#237), where a green sweep asserted nothing the bug could trip.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"//": "OPTIONAL. The mock-internal-seam lint rule is default-on and zero-tolerance (references/depth/mock-policy.md); a conventional @/-aliased repo needs NO config. Copy this to coverage.config.json at your repo root only to declare non-conventional TOPOLOGY (a monorepo's own package scope, generated dirs to exempt). It cannot disable the gate, and there is no waiver.",
|
|
3
|
+
"mockPolicy": {
|
|
4
|
+
"firstPartyAliasPrefixes": [
|
|
5
|
+
"@/",
|
|
6
|
+
"~/"
|
|
7
|
+
],
|
|
8
|
+
"firstPartyPackages": [
|
|
9
|
+
"@your-scope/"
|
|
10
|
+
],
|
|
11
|
+
"externals": [
|
|
12
|
+
"^@/generated/"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
"//requirementGlobs": "OPTIONAL. Turns on the acceptance gate: every accepted ADR/PRD under these directories must own a docs/tests/<source>/<id>-*.coverage.yml with `criteria` (or `gapIssue` / `gapDoc` for a tracked gap), unless the document states it has no runtime behavior. Without this key, validate prints 'acceptance gate not enforced'.",
|
|
16
|
+
"requirementGlobs": {
|
|
17
|
+
"adr": "docs/adr"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Depth: Proving Each Obligation
|
|
2
|
+
|
|
3
|
+
> Read when: grading whether a test actually proves the behavior against real state. Sibling: [mock-policy.md](mock-policy.md) (the boundary principle this grading enforces). Depth grades each `Aligned` row — and each `Orphan surface` carrying a [Surface Baseline Contract](../breadth/surface-baseline.md) floor — by inspecting its actual tests.
|
|
4
|
+
|
|
5
|
+
The canonical depth failure is **internal interception counted as behavior**: a Playwright `route.fulfill`/`page.route(` faking your own endpoint's response, or any substitute standing in for an internal seam. It makes a surface *look* covered while proving only proxy wiring — the boundary violation the [Mocking Stance](mock-policy.md) forbids. Classify it `Over-mocked`, never `Covered`.
|
|
6
|
+
|
|
7
|
+
**Separate browser routes from API routes; prove each with its own evidence kind.** Prove an API route (`route.*`) by hitting the endpoint and asserting the HTTP contract, auth, and durable state. Prove a browser route (`page.*`) by driving the rendered page: what it displays, what the user can do, and what happens when they do. Never grade a browser route `Covered` because its backing endpoints are covered (the `/settings/connectors` miss) — a green API test under a page is necessary but never sufficient.
|
|
8
|
+
|
|
9
|
+
**For any write form, require one test that fills the rendered UI and asserts the mutation end to end** — operator fills the actual form and submits → backend accepts → durable state changes. Keep the render-health watcher attached **through** the submit (compose with `presentation:render-health`, [../presentation/axis.md](../presentation/axis.md)), so an uncaught error / `console.error` / first-party 5xx fired *during* the write fails the test even when the durable-state assertion would pass — the "mutate-health" gap. Do not accept seam tests in its place: a schema endpoint returning fields, a validator rejecting bad input, and an API forwarding a hand-built payload all pass while the rendered form silently drops a backend-required field. This is acute for the **split-contract form**, whose fields come from one source (schema endpoint, config descriptor, generated form spec) and validation from another (the backend contract); only a rendered-form submission proves the form emits a payload the backend accepts.
|
|
10
|
+
|
|
11
|
+
## Evidence Hierarchy
|
|
12
|
+
|
|
13
|
+
Do not trust prior coverage documents, audit reports, PR summaries, issue comments, or agent claims as proof of coverage. Treat them only as leads to verify against current code.
|
|
14
|
+
|
|
15
|
+
Use evidence in this order:
|
|
16
|
+
|
|
17
|
+
1. Actual test code and assertions.
|
|
18
|
+
2. Test execution evidence: CI logs, local command output, traces, screenshots, or reports.
|
|
19
|
+
3. Runtime/code discovery: routes, endpoints, schemas, public interfaces, and changed code paths.
|
|
20
|
+
4. Prior docs/reports/PR summaries only as context to verify, never as authoritative evidence.
|
|
21
|
+
|
|
22
|
+
Classify coverage as `Covered` only after inspecting the relevant test file/case and confirming it asserts the required behavior at the required level. CI logs prove execution, not coverage quality. If actual test code cannot be inspected, classify as `BLOCKED` or `Unverified`, never `Covered`.
|
|
23
|
+
|
|
24
|
+
## Coverage classifications (the shared vocabulary)
|
|
25
|
+
|
|
26
|
+
A self-declared `@level` is a claim the validator must try to **refute**, and can never alone reach `Covered`. The three terminal states are marked below.
|
|
27
|
+
|
|
28
|
+
- `Covered` (green, terminal): inspected test code validates the AC at the right level with meaningful assertions and acceptable mock/fake use, **and** the test has been read and marked `verified: true`. A self-declared `@level` alone never reaches it.
|
|
29
|
+
- `Partial`: some behavior is tested, but edge cases, failures, permissions, state, or evidence are incomplete.
|
|
30
|
+
- `Missing`: no meaningful test maps to the AC.
|
|
31
|
+
- `Wrong Level`: test exists but is too shallow for the risk — e.g. unit-only for stateful workflow, API contract, auth, money movement, concurrency, or event behavior.
|
|
32
|
+
- `Over-mocked` (red, terminal): mocks bypass the behavior the AC must prove — a behavior/journey test that intercepts first-party traffic (`page.route`, `route.fulfill`, MSW, first-party fixtures), or a `mutation` journey that never resolves a real durable-state path. Proves only proxy wiring.
|
|
33
|
+
- `Unverified` (yellow, terminal): the level is satisfied statically (or claimed by docs/reports/CI) but nobody has read the test yet. It is a **warning** by default; it blocks only when the user sets `unverifiedBlocks: true`. Marking `verified: true` after reading the test promotes it to `Covered`; no evidence is required unless the user asks for it. The residual variance is over *quality of an existing test*, not *whether a surface exists*.
|
|
34
|
+
- `Excluded`: a human marked the surface out of scope with category + reason and the adapter signals permit it; surfaced in the exclusion census.
|
|
35
|
+
- `BLOCKED`: required source, code, tests, route discovery, environment, or product decision is unavailable.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Mock And Integration Policy (depth)
|
|
2
|
+
|
|
3
|
+
> Read when: deciding what may be substituted in a test. The boundary principle the [depth grading](grading.md) enforces.
|
|
4
|
+
|
|
5
|
+
## Mocking Stance
|
|
6
|
+
|
|
7
|
+
Default to real. The governing principle is **real internals, faked externals, nothing in between**:
|
|
8
|
+
|
|
9
|
+
- A test substitute is permitted **only at a trust boundary you do not own**: third-party HTTP APIs, payment/KYC providers, email/SMS, the clock, randomness.
|
|
10
|
+
- Everything **inside** your own system runs for real: database, repositories, service layer, internal endpoints, event bus. A substitute for an internal seam is a design smell or coverage gap, not a testing choice.
|
|
11
|
+
- The rule is **two-sided**: don't mock inward, don't reach outward — externals must be replaced by a fake/stub adapter so tests stay deterministic and never call a live third party in CI. "Be pure by calling the real provider" is the opposite failure, also rejected.
|
|
12
|
+
|
|
13
|
+
The problem we reject is **mock-only coverage of behavior that must be proven against real state** — not the presence of mocks. Fakes/stubs that keep failure-path and edge tests fast and deterministic are good and expected.
|
|
14
|
+
|
|
15
|
+
## Glossary
|
|
16
|
+
|
|
17
|
+
- **Dummy**: placeholder passed only to satisfy a signature; never exercised.
|
|
18
|
+
- **Stub**: returns canned data so the test can proceed; no assertions on it.
|
|
19
|
+
- **Spy**: a stub that also records calls, so the test can assert a call happened or did not happen.
|
|
20
|
+
- **Mock**: a pre-programmed object with expectations; the test fails if it is not called exactly as specified (behavior verification of internal call sequences).
|
|
21
|
+
- **Fake**: a real, lightweight working implementation (in-memory DB, fake HTTP adapter) — behaves like the real thing, just not production-grade.
|
|
22
|
+
|
|
23
|
+
Rule of thumb: prefer **fakes** at external boundaries; use **stub/spy** for failure injection and "was-not-called" assertions; avoid **mocks** that encode internal call sequences — that tests implementation, not behavior.
|
|
24
|
+
|
|
25
|
+
## Where substitutes are allowed
|
|
26
|
+
|
|
27
|
+
Use a fake/stub/spy at the external boundary for:
|
|
28
|
+
|
|
29
|
+
- External provider timeout, decline, malformed response, and rare failure paths (stub/fake the provider adapter).
|
|
30
|
+
- Isolating pure decision logic.
|
|
31
|
+
- Asserting an external provider or side effect was not called after validation failure (spy; there is no real call to observe).
|
|
32
|
+
- Keeping tests deterministic when the external system is not the subject under test.
|
|
33
|
+
|
|
34
|
+
These are **internal** and are therefore never covered by substitutes alone:
|
|
35
|
+
|
|
36
|
+
- Database transaction behavior.
|
|
37
|
+
- Idempotency and duplicate delivery.
|
|
38
|
+
- Concurrency/race conditions.
|
|
39
|
+
- Event publishing, outbox, retry, and recovery behavior.
|
|
40
|
+
- Auth, tenant isolation, and permission boundaries.
|
|
41
|
+
- Serialization, schema, and API compatibility.
|
|
42
|
+
- Orchestrator recovery after crash/retry.
|
|
43
|
+
|
|
44
|
+
Prefer integration tests with real app/service code, real DB or test containers with migrations, queue/pub-sub emulators where practical, fake external provider adapters, and assertions on final durable state, emitted events, and externally visible outcomes.
|
|
45
|
+
|
|
46
|
+
## Mechanized gate: `mock-internal-seam` (zero-tolerance)
|
|
47
|
+
|
|
48
|
+
The decidable core of the stance is a hard gate, because over-mock is the failure mode that shipped a production incident behind green tests. The trick that makes it decidable is the **externals-allowlist inversion**: internal seams are unbounded, but the set of things that may legitimately be faked is small and known. So a mock whose target resolves to first-party code is a defect; anything on the declared externals allowlist, a bare npm package, or the stdlib is exempt.
|
|
49
|
+
|
|
50
|
+
- **Default-on, no waiver, no grandfathering.** Config only declares topology; it cannot turn the gate off. A believed false positive is fixed by declaring the truth in `coverage.config.json`, never by waiving.
|
|
51
|
+
- **Both lanes.** Diff-scoped for new seams, whole-tree for inherited ones; a tree with existing over-mock stays red until it is removed.
|
|
52
|
+
- **Three resolutions, and "keep it" is not one:** replace with a real-boundary test, fake only the external behind it, or **delete** the test. Over-mock is worse than no test: an untested route is an honest gap, an over-mocked one is dishonest green. Deletion reverts the surface to its honest breadth status (`Missing` or `Excluded`).
|
|
53
|
+
- **In audit mode, run it whole-tree from this skill against the target repo** and count every hit as an `Over-mocked` row and a no-ship contributor. A missing `coverage.config.json` means "run on defaults", not "not applicable"; the scripts' absence from the audited repo means nothing.
|
|
54
|
+
|
|
55
|
+
What stays a review lead: whether a real-boundary sibling exists, shallow assertions, semantically wrong fakes. The gate proves the decidable shell; the reviewer judges the rest. The ledger also reports an over-mock *rate* as a trend signal; the merge bar stays "count is zero".
|
|
56
|
+
|
|
57
|
+
CLI, rules, and the `coverage.config.json` topology keys: [`scripts/README.md`](../../scripts/README.md).
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Depth: Test smells — the diagnostic vocabulary and where each is enforced
|
|
2
|
+
|
|
3
|
+
> Read when: deciding whether a smell belongs in a blocking lint rule or a review lead, or turning a test-quality finding into a coverage grade. Sibling: [grading.md](grading.md) (the coverage classifications), [mock-policy.md](mock-policy.md) (the boundary).
|
|
4
|
+
|
|
5
|
+
**Judging one test is `test-quality`'s job.** Its seven principles and labels (`Not coverage`, `Weak`, `Redundant`, `Lead`) are the single bar for whether a test catches real bugs; this file does not restate them. It maps each smell to where it is enforced, and each test-quality label to the coverage grade it produces (end of file).
|
|
6
|
+
|
|
7
|
+
A passing test is not automatically a good test. The classic catalog (Meszaros' *xUnit Test Patterns*, Martin's FIRST) names the ways a green suite still fails its job. Each smell maps to an enforcement point — and to **whether it is mechanically decidable (a gate) or judgment (a lead).** Same dividing line [lint-tests](../../scripts/lint-tests.mjs) draws everywhere: a check blocks only if a legitimate test could never trip it; otherwise it's a lead the reviewer adjudicates.
|
|
8
|
+
|
|
9
|
+
| Smell | What it is | Decidable? | Enforced as |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| **Erratic** (flaky) | Passes/fails non-deterministically — usually a fixed sleep instead of an explicit wait | **Yes** (the sleep forms) | **Gate**: `lint-tests` `no-fixed-timeout`. Genuine un-sandboxable flake → `@quarantine` lane (runs, non-blocking, graded `Unverified`), never `test.skip` ([test-strategy.md](../process/test-strategy.md)) |
|
|
12
|
+
| **Missing Assertion** | A test that runs but proves nothing | **Partly** | **Gate** for the decidable floors — an **empty body** (`it('x', () => {})`): `lint-tests` `no-empty-test`; and an **assertion whose rejection is swallowed** by a chained `.catch(...)` so it can never fail (`expect(...).not.toBeVisible().catch(() => {})`): `lint-tests` `no-swallowed-assertion`. **Lead** for the rest: a test with statements but no assertion *may still assert through a helper*, so "no `expect`/`assert` token" is not zero-FP — the reviewer reads it (`depth.asserts-something` checklist row) |
|
|
13
|
+
| **Slow** | Violates FIRST's *Fast* — too slow to run every loop | **No** (runtime is environment-sensitive) | **Lead**: a review observation, not a blocking gate — a threshold that fails on a loaded CI runner gets disabled. Flag a test that is slow *for its tier* (a unit test doing real IO, a journey with avoidable waits) and push it down the pyramid or fix the wait |
|
|
14
|
+
| **Fragile** | Breaks on unrelated/implementation changes — couples to structure, not behavior | **No** | **Principle**, not a gate: *test observable behavior, not internal structure* (test-quality principle 1). A test asserting private call-order/shape is the smell; a reviewer judgment |
|
|
15
|
+
| **Obscure** | You can't tell what it tests from reading it — non-DAMP name, hidden setup | **No** | **Lead**: the reviewer checks the test name describes the behavior it asserts (DAMP — Descriptive And Meaningful Phrases), and that a failure message would point at the cause |
|
|
16
|
+
| **Over-mocked** | Mocks bypass the behavior under test (first-party interception) | **Yes/Lead** | **Gate + lead**: ledger `Over-mocked` classification + `lint-tests` `mock-internal-seam` ([grading.md](grading.md), [mock-policy.md](mock-policy.md)) |
|
|
17
|
+
|
|
18
|
+
## The gate-vs-lead split, stated once
|
|
19
|
+
|
|
20
|
+
- **Missing Assertion** is the instructive case. Its decidable floor — a literal empty test body — is a gate (`no-empty-test`), because nothing legitimate is an empty-bodied `it(...)`. But the *general* form ("has code, asserts nothing") can't be a zero-FP gate: a test may assert entirely through a helper (`await verifyDashboard(page)`), so flagging "no `expect` on the test's own lines" would false-block it. That residual is a **lead** — the reviewer reads the test and the helper.
|
|
21
|
+
- **Slow** stays a lead for an orthogonal reason — not false positives but **non-determinism of the signal**: the same test's wall-clock varies with the runner. A hard threshold is enforcement built on sand.
|
|
22
|
+
|
|
23
|
+
## What the reviewer does with the leads
|
|
24
|
+
|
|
25
|
+
For the `lead` smells above, the reviewer carries them as named checks, each "look here and verify," resolved with a `file:line` + verdict — never prose. A smell that later becomes mechanizable is promoted to a `lint-tests`/ledger rule, the same promotion path every other lead follows.
|
|
26
|
+
|
|
27
|
+
## From a test-quality label to a coverage grade
|
|
28
|
+
|
|
29
|
+
A surface's grade comes from the best test that maps to it, after test-quality has judged that test:
|
|
30
|
+
|
|
31
|
+
| test-quality label on the proving test | Coverage grade for the surface |
|
|
32
|
+
|---|---|
|
|
33
|
+
| clean (no finding) | `Covered` once marked read (`verified: true`), else `Unverified` |
|
|
34
|
+
| `Not coverage` because a first-party fake hides the behavior (principle 3) | `Over-mocked` |
|
|
35
|
+
| `Not coverage` for any other reason (text match, tautology, can never fail) | `Missing` — the test counts as zero proof |
|
|
36
|
+
| `Weak` (proves less than its name, or at too low a level) | `Partial`, or `Wrong Level` when the level is the gap |
|
|
37
|
+
| `Redundant` | no change; the grade comes from the test it duplicates |
|
|
38
|
+
| `Lead` | no change until the lead is confirmed or cleared |
|
|
39
|
+
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# CI Contract: Golden-Path Smoke Only
|
|
2
|
+
|
|
3
|
+
> Read when: the user asks what this skill should require, wire, or audit in CI.
|
|
4
|
+
|
|
5
|
+
Curated golden-path smoke is the **only CI gate supported by this skill**. The coverage ledger, inventory freshness, presentation sweep, broad E2E suite, test lint, over-mock scan, design parity, and quarantine expiry remain local or review-time evidence. Do not propose, require, wire, or audit them as CI gates.
|
|
6
|
+
|
|
7
|
+
## What smoke proves
|
|
8
|
+
|
|
9
|
+
Smoke drives a small, human-curated contract (`golden-paths.json`) of do-not-ship journeys against the real running app. It proves those paths are alive through their owned internals:
|
|
10
|
+
|
|
11
|
+
- start from a real user entry point;
|
|
12
|
+
- use a real browser for browser journeys;
|
|
13
|
+
- do not intercept first-party requests or replace the database or service layer;
|
|
14
|
+
- seed deterministic test state and fake only external providers;
|
|
15
|
+
- pass only on ALIVE: `fail` is DEAD, and `blocked`, `cannot-run`, or `missing` is CANNOT-RUN;
|
|
16
|
+
- keep the contract deliberately small enough to run on every PR.
|
|
17
|
+
|
|
18
|
+
Smoke is liveness, not comprehensive coverage. A green smoke run does not prove every acceptance criterion, every route's presentation floor, tenant isolation, concurrency, recovery, or the quality of the broader test suite. Those remain obligations graded by the coverage audit.
|
|
19
|
+
|
|
20
|
+
## Reference command
|
|
21
|
+
|
|
22
|
+
The `golden-path` skill owns the job. On GitHub Actions it generates the workflow from the repo's `golden-paths.json`; elsewhere a job runs the engine copy it puts in the repo:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
node scripts/golden-paths/golden-path.mjs run --profile pr-local --boot
|
|
26
|
+
node scripts/golden-paths/golden-path.mjs verdict --profile pr-local
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`verdict` exits 0 only on ALIVE; that step is the gate.
|
|
30
|
+
|
|
31
|
+
## Checking smoke wiring
|
|
32
|
+
|
|
33
|
+
Run `ci-audit.mjs` only when the user asks to audit CI:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
node <ensure-coverage>/scripts/ci-audit.mjs \
|
|
37
|
+
--files .github/workflows/ci.yml,cloudbuild.yaml
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
It reports the smoke check as `present`, `warn-only`, or `absent`. It does not inspect or recommend any other CI gate. `--adoption` emits a focused issue body for adding or repairing smoke only.
|
|
41
|
+
|
|
42
|
+
## Production boundary
|
|
43
|
+
|
|
44
|
+
Do not run mutating smoke against production. Release smoke is read-only against a zero-traffic candidate before traffic shifts. A smoke run after traffic shifts is monitoring, not a release gate.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Coverage Ledger: Worked Example
|
|
2
|
+
|
|
3
|
+
> Read when: setting up or explaining the ledger's three layers and you want a concrete file layout to copy.
|
|
4
|
+
|
|
5
|
+
A concrete shape for the breadth-axis Coverage Ledger specced in [../breadth/coverage-ledger.md](../breadth/coverage-ledger.md). Paths and command names are illustrative — adapt to the repo. The pattern is what matters: a **generated inventory** from code, a **curated layer authored one file per requirement**, and a **generated aggregation** that dedups by surface and computes status.
|
|
6
|
+
|
|
7
|
+
## Why it exists
|
|
8
|
+
|
|
9
|
+
A test-outward audit (mock census → mocked files → gaps) cannot find a surface with no tests — absence produces no signal. The ledger flips direction: enumerate obligations from requirements *and* code, reconcile, let mismatches surface the gaps. The motivating case: a `/settings/models` page with accepted ADRs and a live route, whose only "tests" used Playwright `route.fulfill` to fake the response — proxy wiring counted as coverage. The ledger forces the surface to be owned and discovered; the depth axis then grades it `Over-mocked`.
|
|
10
|
+
|
|
11
|
+
## Layout
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
docs/tests/adr/0008-org-model-allowlist.criteria.md # ACs for the ADR
|
|
15
|
+
docs/tests/adr/0008-org-model-allowlist.coverage.yml # this ADR's owned surfaces
|
|
16
|
+
docs/tests/prd/<slug>.coverage.yml
|
|
17
|
+
docs/tests/_generated/surface-inventory.json # discovered from code
|
|
18
|
+
docs/tests/_generated/coverage-index.json # computed aggregation
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Layer 1 — generated inventory (never hand-edited)
|
|
22
|
+
|
|
23
|
+
Regenerated from routers/migrations/event registry, one entry per surface. The adapter emits `class` (mechanical) and `reachability`; the baseline floor is computed from `(kind, class)` **before any curated file exists**.
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
// docs/tests/_generated/surface-inventory.json
|
|
27
|
+
{ "surfaces": [
|
|
28
|
+
{ "id": "/settings/models", "kind": "route", "class": "mutation", "reachability": "reachable" },
|
|
29
|
+
{ "id": "/internal/debug-panel", "kind": "route", "class": "read", "reachability": "guarded" },
|
|
30
|
+
{ "id": "/api/settings/model-allowlist", "kind": "api", "class": "mutation" },
|
|
31
|
+
{ "id": "model_allowlist", "kind": "table" }
|
|
32
|
+
] }
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Layer 2 — curated coverage, one file per requirement (hand-maintained)
|
|
36
|
+
|
|
37
|
+
Each file declares only the surfaces that requirement **owns**, their required level, and the criteria link. **No status field** — so multiple owners of a surface can never disagree.
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
# docs/tests/adr/0008-org-model-allowlist.coverage.yml
|
|
41
|
+
criteria: docs/tests/adr/0008-org-model-allowlist.criteria.md
|
|
42
|
+
surfaces:
|
|
43
|
+
"/settings/models":
|
|
44
|
+
requiredLevels: [pg-api, browser-journey, no-secret-assertion]
|
|
45
|
+
"/api/settings/model-allowlist":
|
|
46
|
+
requiredLevels: [pg-api]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
A second requirement (`0030-model-dispatch.coverage.yml`) can own `/settings/models` too; `aggregate` unions their `requirementRefs` and takes the strictest level.
|
|
50
|
+
|
|
51
|
+
## Evidence — declared by tests, not hand-listed
|
|
52
|
+
|
|
53
|
+
Tests say what they prove with a `@covers` annotation (plus optional `@level`), so curated files never carry rot-prone paths. A test that fakes its own endpoint is detected as first-party interception → `Over-mocked`:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
// apps/web/e2e/models.spec.ts
|
|
57
|
+
// @covers /settings/models
|
|
58
|
+
// @level browser-journey
|
|
59
|
+
test('models page', async ({ page }) => {
|
|
60
|
+
await page.route('**/api/**', (r) => r.fulfill({ body: '{}' })) // -> Over-mocked
|
|
61
|
+
})
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Layer 3 — generated aggregation (never hand-edited)
|
|
65
|
+
|
|
66
|
+
Merges every curated file by surface, unions `requirementRefs`, takes the strictest level, diffs against the inventory, maps `@covers` → surface, and **computes** status.
|
|
67
|
+
|
|
68
|
+
```jsonc
|
|
69
|
+
// docs/tests/_generated/coverage-index.json
|
|
70
|
+
{
|
|
71
|
+
"/settings/models": {
|
|
72
|
+
"requirementRefs": ["adr:0008", "adr:0030"],
|
|
73
|
+
// every route also auto-carries the presentation floor (render-health + spatial + perceivability + reachability + temporal)
|
|
74
|
+
"requiredLevels": ["pg-api", "browser-journey", "no-secret-assertion", "presentation:render-health", "presentation:spatial", "presentation:perceivability", "presentation:reachability", "presentation:temporal"],
|
|
75
|
+
"alignment": "Aligned",
|
|
76
|
+
"depthStatus": "Over-mocked" // computed: only route.fulfill tests exist
|
|
77
|
+
},
|
|
78
|
+
"/internal/debug-panel": {
|
|
79
|
+
"requirementRefs": [],
|
|
80
|
+
"requiredLevels": ["browser-journey", "presentation:render-health", "presentation:spatial", "presentation:perceivability", "presentation:reachability", "presentation:temporal"],
|
|
81
|
+
"alignment": "Orphan surface", // warn: owned by no curated file
|
|
82
|
+
"depthStatus": "Missing" // error: baseline floor unmet
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`/internal/debug-panel` shows the decoupling: `Orphan surface` is only a **warn** (nobody owns it), but its baseline floor is still graded — `Missing` is the failing finding. To exclude it a curated file adds `exclude: { category: internal, reason: "..." }` — honored because it is a `read` route, but **rejected** if it were a `reachable` `mutation`.
|
|
88
|
+
|
|
89
|
+
## Alignment statuses (computed)
|
|
90
|
+
|
|
91
|
+
- `Aligned` — requirement ↔ surface present; grade depth next.
|
|
92
|
+
- `Orphan surface` — surface in inventory, owned by no curated file (`inventory − union(curated)`). A **warn**; the baseline floor is still enforced via depth status.
|
|
93
|
+
- `Excluded` — human-declared out of scope (category + reason), permitted by the reachability/class gate; printed in the census.
|
|
94
|
+
- `Unrealized requirement` — a curated surface absent from the inventory.
|
|
95
|
+
- `Stale link` — a curated surface or criteria link points at something gone.
|
|
96
|
+
|
|
97
|
+
Rows carrying a baseline floor (Aligned or Orphan) are graded by the depth classifications ([../depth/grading.md](../depth/grading.md)). Internal surfaces (`table`/`event`/`job`) instead resolve to `Reached` or `Dead`. `Covered` requires the test to be read and marked `verified: true`; `Unverified` is a warning by default and blocks only with `unverifiedBlocks: true`.
|
|
98
|
+
|
|
99
|
+
## How this caught `/settings/models`
|
|
100
|
+
|
|
101
|
+
1. The inventory adapter lists the route and its APIs/tables.
|
|
102
|
+
2. ADR-0008 and ADR-0030 each own it; `aggregate` merges them into one row, strictest level `pg-api + browser-journey` (plus the auto-applied presentation floor).
|
|
103
|
+
3. `validate` resolves status from tests: only a `route.fulfill` test exists → `Over-mocked`; required `pg-api`/`browser-journey` evidence is `Missing`.
|
|
104
|
+
|
|
105
|
+
And **even with no ADR at all**: the adapter tags `class: mutation`, the Surface Baseline Contract auto-applies a `browser-journey` floor, and the same `route.fulfill`-only test resolves to `Over-mocked` → the gate fails. The organically-added, un-ADR'd route closes by default.
|
|
106
|
+
|
|
107
|
+
## Presentation (worked shapes)
|
|
108
|
+
|
|
109
|
+
Every `kind: route` auto-carries the presentation floor on top of `browser-journey`; a real-browser spec tags each level it proves (`// @level presentation:spatial`, etc.) and calls the corresponding assertion (`assertNoHorizontalOverflow`, `assertContrast`, `assertTargetSizes`/`assertFocusVisible`, `assertNoFirstPartyShift`). A DOM-only test tagged with a presentation level grades `Over-mocked`; a `browser-journey` with no such checks leaves the level `Wrong Level`. Full instrument list and failure modes: [../presentation/axis.md](../presentation/axis.md).
|
|
110
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Refund Flow Test Criteria Example
|
|
2
|
+
|
|
3
|
+
> Read when: writing a criteria doc for money movement and you want a worked test matrix to pattern on.
|
|
4
|
+
|
|
5
|
+
A minimal worked criteria doc for a money-movement feature — shows ACs and a risk-classified test matrix. (Template: [../process/output-template.md](../process/output-template.md).)
|
|
6
|
+
|
|
7
|
+
## Example PRD
|
|
8
|
+
|
|
9
|
+
Merchant can request a refund for a settled payment. System validates eligibility, creates a refund record, calls the provider, updates payment/refund status, and emits refund events.
|
|
10
|
+
|
|
11
|
+
## Acceptance Criteria
|
|
12
|
+
|
|
13
|
+
- AC1: Merchant can refund a settled payment for an amount ≤ remaining refundable amount.
|
|
14
|
+
- AC2: Refund rejected if payment is not settled.
|
|
15
|
+
- AC3: Refund rejected if amount exceeds remaining refundable amount.
|
|
16
|
+
- AC4: Duplicate request with the same idempotency key returns the original refund, creates no second refund.
|
|
17
|
+
- AC5: Provider accepts → status `PROCESSING`, `refund.created` emitted.
|
|
18
|
+
- AC6: Provider rejects → status `FAILED`, normalized provider error stored.
|
|
19
|
+
- AC7: Remaining refundable amount updates only after successful creation.
|
|
20
|
+
- AC8: Unauthorized merchant cannot refund another merchant's payment.
|
|
21
|
+
- AC9: System recovers safely if the provider call succeeds but event publish fails.
|
|
22
|
+
- AC10: Refund APIs return stable error codes, not raw provider/internal errors.
|
|
23
|
+
|
|
24
|
+
## Test Matrix (representative rows)
|
|
25
|
+
|
|
26
|
+
| Scenario | ACs | Test Level | Setup/Input | Assertions | Evidence |
|
|
27
|
+
|---|---|---|---|---|---|
|
|
28
|
+
| Valid partial refund | AC1, AC5, AC7 | Integration/API | Settled payment, amount < remaining | Refund row created, `PROCESSING`, provider called once, event emitted, remaining updated | CI integration test |
|
|
29
|
+
| Duplicate request | AC4 | Integration | Same merchant/payment/idempotency key twice | One refund row, one provider call, same response | CI integration test |
|
|
30
|
+
| Unauthorized merchant | AC8 | API/security | Merchant B refunds Merchant A's payment | `403`/`404`, no provider call, no refund row | CI API/security test |
|
|
31
|
+
| Provider hard decline | AC6, AC10 | Integration + fake provider | Provider returns decline | `FAILED`, normalized error stored, no success event | CI integration test |
|
|
32
|
+
| Event publish failure | AC5, AC9 | Integration/recovery | DB commit succeeds, publish fails | Outbox retry emits event, no duplicate refund/provider call | CI recovery test |
|
|
33
|
+
| Concurrent refunds | AC3, AC4, AC7 | Integration/concurrency | Two requests race the same remaining amount | Valid total only, no over-refund | CI concurrency test |
|
|
34
|
+
|
|
35
|
+
Money/security ACs (AC1, AC4, AC7, AC8) are **never mock-only**, even with approval — they require integration/API/journey evidence against real state ([../process/test-strategy.md](../process/test-strategy.md)). The provider is the one external faked with a fake adapter; the DB, idempotency, concurrency, and outbox run for real.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Presentation Floor (browser routes)
|
|
2
|
+
|
|
3
|
+
> Read when: working any `presentation:*` invariant. Sibling: `e2e-test/references/presentation-sweep.md` (the runner and the result shape it emits). This skill *grades* the axis; the `e2e-test` sweep *runs* it.
|
|
4
|
+
|
|
5
|
+
The **Presentation** axis (third axis) rides the [Surface Baseline Contract](../breadth/surface-baseline.md) machinery as a per-route floor. Every live browser route auto-carries a presentation obligation *on top of* its `browser-journey` floor, checked at the viewport floor `[375, 1280]` (default theme, seeded data).
|
|
6
|
+
|
|
7
|
+
> **This skill grades the axis; it does not run it.** The tokens below are *graded* by the Coverage Ledger (does a qualifying real-render test exist, is it non-intercepting, is it attested). The *instruments* that open a browser and observe these invariants live in the **`e2e-test` skill's presentation sweep**. ensure-coverage owns the **obligation**; the runner and the per-`(route, level)` result shape the ledger consumes are documented with the runner (`e2e-test/references/presentation-sweep.md`). This mirrors how breadth delegates surface discovery to an inventory adapter ([../breadth/inventory-contract.md](../breadth/inventory-contract.md)).
|
|
8
|
+
|
|
9
|
+
Invariants, **spine first**:
|
|
10
|
+
|
|
11
|
+
- **`presentation:render-health`** *(spine)* — the page renders without a **`pageerror` (uncaught exception), a `console.error`, a rendered error boundary, or an HTTP `>= 500`** on the document or any first-party request it issues. The cheapest, most foundational check — an uncaught `TypeError` on mount fails here before any layout question is asked — so every other presentation level sits on it. A green functional journey sails past it when the route's only test intercepts its own API. **Continuous, not load-only**: it must also hold *through* the interactions the other instruments drive — a `presentation:temporal` trigger, a `presentation:perceivability` post-delete mutation, a mutation-form journey's submit — so an error / `console.error` / first-party 5xx fired *during a write* fails too. (This is "mutate-health": render-health composed with the trigger/mutation pattern, not a separate axis — compose with those checks rather than re-driving the form.)
|
|
12
|
+
- **`presentation:spatial`** — laid out without collision: no unintended horizontal overflow **and** no unintended element overlap (bounding-box intersection) at the floor viewports. Intentional z-stacks (carousels, badges, sticky headers) are suppressed only via a **gated allowlist** (`category` + `reason`, surfaced in a census); an overlap occluding a **reachable interactive element can never be allowlisted**.
|
|
13
|
+
- **`presentation:perceivability`** — controls are visible/distinguishable (WCAG contrast), and things that must be *absent* are gone (negative form: a role-gated control not visible to the wrong role; a deleted item does not linger).
|
|
14
|
+
- **`presentation:reachability`** — a user can get to the page and tell its controls are actionable: every manifest route is reachable by crawling the rendered nav (no **navigational orphan**), interactive controls show a visible focus indicator and meet the ≥44px target floor. Negative form: a modal traps focus (no click-through / focus escape); a privilege-gated route is not navigationally reachable for the wrong role.
|
|
15
|
+
- **`presentation:temporal`** — the layout holds still as things inject. **Split by who renders the shift** — *first-party* (lazy images, async data, our dynamic fields) is a **hermetic gate** (real render, no network; before/after geometry gated on a stable condition, never a fixed sleep, or a `PerformanceObserver` CLS score). *Third-party* (Stripe/Adyen payfields) runs against the provider **sandbox iframe** in a **non-blocking PR lane**: a failure posts a visible annotation and the surface stays `Unverified` until the test is read and marked `verified: true`. Top-page CLS is **structurally blind to cross-origin iframes** (WICG excludes descendant frames), so this is a before/after geometry assertion gated on a provider-ready signal, not CLS. The mobile **dynamic-viewport (`dvh`/`100vh`) cell** is gated via Playwright emulation with a tuned tolerance (staging fallback if flake is unmanageable).
|
|
16
|
+
|
|
17
|
+
"Graded" means the ledger marks a route's floor `Missing` / `Over-mocked` / `Unverified` / `Covered` from the tests that exist — it cannot itself detect a runtime crash, which is why the sweep is a **separate evidence run**, not a side effect of the functional E2E suite. It is not a CI gate; curated golden-path smoke is the sole CI gate ([CI contract](../enforcement/ci-contract.md)).
|
|
18
|
+
|
|
19
|
+
The floor runs at the screen viewport floor (`[375, 1280]`). The **`media=print` cell is warn-only by default** — a broken print stylesheet is logged in the census, not a blocking gate (lower-frequency, harder to assert deterministically). A surface may escalate it to a gate when print output is a real product surface (e.g. an invoice).
|
|
20
|
+
|
|
21
|
+
## Feature-derived escalation (the condition matrix grows itself)
|
|
22
|
+
|
|
23
|
+
The floor above is the fixed minimum; the adapter then *raises* it from deterministic code **signals**, adding cell-qualified obligations (e.g. `presentation:perceivability@dark`) so two agents on the same code compute the same set:
|
|
24
|
+
|
|
25
|
+
| signal (adapter-derived) | adds |
|
|
26
|
+
|---|---|
|
|
27
|
+
| a dark-mode/theme toggle | `presentation:perceivability@dark` (contrast must also hold in dark theme) |
|
|
28
|
+
| an i18n library | `presentation:spatial@long-locale`, `presentation:spatial@rtl` (layout must survive long locales + RTL) |
|
|
29
|
+
|
|
30
|
+
A cell-qualified level grades exactly like its base (real render, exact-match, DOM-only → `Over-mocked`). **Adding cells is free; a check can never be made weaker; a cell may be removed only through the gated `excludeCells` path** (`category` + `reason`, surfaced in the census); the base mechanical floor (unqualified levels) can never be removed. This mirrors the Surface Baseline Contract's raise-only + gated-exclusion rule.
|
|
31
|
+
|
|
32
|
+
> **Navigational vs guard-chain reachability.** `presentation:reachability` is **navigational** ("can a user *click* here from an entry point") — *not* the guard-chain [Route Discovery & Reachability Protocol](../breadth/surface-discovery.md) ("can the URL load past middleware/auth"). A route can be guard-reachable yet navigation-orphaned. Both matter; different checks.
|
|
33
|
+
|
|
34
|
+
> **Affordance ↔ `impeccable` boundary.** The *deterministic* affordance checks live here (focus-indicator **presence**, target size, nav-orphan). The *aesthetic/holistic* judgment (is the focus style good, is a11y resilient under zoom/AT) stays in `impeccable` (`reference/harden.md`). This axis proves the cue **exists**; impeccable judges whether it's good.
|
|
35
|
+
|
|
36
|
+
## Proven only against a real rendered page
|
|
37
|
+
|
|
38
|
+
A presentation level is **exact-match** and proven only against a **real rendered page**:
|
|
39
|
+
|
|
40
|
+
- A functional `browser-journey` does **not** satisfy a presentation level — a journey clicks the DOM; it never asserts no-overflow or perceivability. Each is required separately; one presentation level does not satisfy another.
|
|
41
|
+
- A DOM-only / JSDOM assertion of a presentation level grades **`Over-mocked`** — the axis's proxy-wiring (it can't see what a human sees). The proving test must drive a real browser.
|
|
42
|
+
- Like any obligation, a statically-satisfied presentation level lands at `Unverified` until the test is read and marked `verified: true`.
|
|
43
|
+
|
|
44
|
+
**State-aware, abstain-on-doubt.** A check is deterministic only where element state is unambiguous; where it cannot decide it **abstains → `Unverified`**, never a silent pass. Disabled controls are *intended* low-contrast (WCAG exempts them), so the perceivability check derives state (`aria-disabled`/`[disabled]`) and skips them. axe-core's contrast rule **abstains** ("incomplete") on text over a background-image/gradient — the invisible-control case — and that abstain stays `Unverified` until a manual check (`verified: true`) **or** escalation to a stronger instrument. **AI-vision is triage-only**: it may flag for human attestation but never promotes an obligation to `Covered` (run-to-run non-determinism).
|
|
45
|
+
|
|
46
|
+
Non-browser surfaces (`api`/`table`/`event`/`job`) carry **no** presentation floor.
|
|
47
|
+
|
|
48
|
+
## `presentation:fidelity` — does it match the design source it came from?
|
|
49
|
+
|
|
50
|
+
Every level above is **self-referential**: render-health asks whether the page renders, perceivability whether a human can act on it. None of them asks the question a unit built from a prototype, mockup or design doc actually owes: **does this match the thing it was supposed to be derived from?**
|
|
51
|
+
|
|
52
|
+
That gap is not theoretical. A baseline captured from a wrong implementation is green forever — in the incident below it would have locked in a card plane the design did not have and a flattened type scale, and reported success. Drift detection cannot substitute for fidelity, because it takes the implementation as its own authority.
|
|
53
|
+
|
|
54
|
+
**When it is owed.** A unit whose source cites a design artifact — a prototype branch/path, a mockup, a design doc that fixes layout — carries `presentation:fidelity` on the surfaces that artifact covers. A unit with no cited design source does not; this is not an auto-floor and inventing one for a CRUD tweak is ceremony.
|
|
55
|
+
|
|
56
|
+
**The rule that makes it fidelity.** Every expected value is read off the **source**, with it rendered, and cites the source line it came from. A value copied off the page you built is a baseline wearing a fidelity label.
|
|
57
|
+
|
|
58
|
+
**Why it is not a differ.** Diffing source against implementation only works when both are the same stack; an HTML prototype or a Figma frame against a React deliverable defeats it. So the work splits where it divides: **comparing across technologies is judgment; checking against an extracted spec is mechanical.** A human reads both, rendered, once, and writes the load-bearing properties down in units that survive a stack change (computed pixels, not `sm:text-3xl`). That **parity manifest** is the only step needing eyes; `design-parity.mjs` scaffolds it from a doctrine-fixed catalog, emits the probe that measures the built page, and validates the result ([`scripts/README.md`](../../scripts/README.md)).
|
|
59
|
+
|
|
60
|
+
**No rewriting the target to match the page.** The cheapest way to green this gate is to edit `expected` instead of fixing the page. Because the source is pinned, a changed `expected` under an unmoved `source.sha` is mechanically detectable and blocks; a genuine mis-read is declared with `rebase: <reason>`. The reviewer treats an undeclared rewrite as a blocker, exactly as it does a silent re-baseline.
|
|
61
|
+
|
|
62
|
+
**The render is not optional.** A property list catches what someone thought to list. Before the terminal review, render source and deliverable at the floor viewports side by side in the PR.
|
|
63
|
+
|
|
64
|
+
Two hard rules, from the named incident (fmm-express #521, 2026-08-06: a cited prototype was summarized once into four bullets, nothing downstream re-read or rendered it, and the criteria doc listed visual baselines under non-goals, so a green suite shipped a page that took four rounds of correction): a presentation-only unit **may not** list visual or parity evidence as a non-goal, and a cited design source is **consumed, not summarized**.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Audit Mode (process)
|
|
2
|
+
|
|
3
|
+
> Read when: auditing whether existing code/tests cover a requirement, PR, issue, feature, or bugfix. Audit current sufficiency against the behavior-first criteria; do not only generate ideal future criteria. Coverage classifications used here are defined in [../depth/grading.md](../depth/grading.md).
|
|
4
|
+
|
|
5
|
+
Audit steps:
|
|
6
|
+
|
|
7
|
+
1. Derive ACs from the source before inspecting implementation details.
|
|
8
|
+
2. Identify public interfaces, workflows, state transitions, side effects, code paths, and existing tests.
|
|
9
|
+
3. For E2E audit, run the [Route Discovery & Reachability Protocol](../breadth/surface-discovery.md) before judging coverage.
|
|
10
|
+
4. Identify critical journeys with actor/role, start state, trigger, major steps, expected end state, route reachability, and observable side effects.
|
|
11
|
+
5. Map each AC and journey to existing tests only after inspecting the actual test files/cases/assertions; prior docs, PR summaries, or agent reports are leads, not proof.
|
|
12
|
+
6. Reject coverage that only validates private functions, implementation structure, or shallow route render-health checks for business journeys.
|
|
13
|
+
7. Create follow-up items for every gap with required test level, setup/input, assertions, and mock/fake policy.
|
|
14
|
+
8. Reach a production-readiness verdict — an explicit ship / no-ship call, the specific scenarios a real user would hit in the first week, and the evidence that would raise confidence — and **put it at the TOP of the deliverable** (the reader's first question is "what's the call?"; the census and detail justify it below). Do not let mapped ACs alone earn a ship call. Separate **blocking decisions** (product/scope choices that change the verdict and need a human answer) from **follow-up actions** (work to schedule) — see the output template; don't dump both into one vague "open questions" list.
|
|
15
|
+
9. **Do not audit CI wiring** unless the user asks. A repo without coverage gates in CI is not a finding. When the user does ask, run `ci-audit.mjs` against the repo's CI config and report curated golden-path smoke as present / warn-only / absent. Do not turn the other audit checks into CI findings; they contribute directly to the coverage verdict.
|
|
16
|
+
10. **Run the over-mock scan whole-tree** (`lint-tests.mjs --rules mock-internal-seam`, no `--diff`) from this skill against the target repo. Every hit is an `Over-mocked` census row and a no-ship contributor; **count them in the verdict**. A missing `coverage.config.json` means "run on defaults", not "not applicable"; a non-conventional topology earns a "declare topology" follow-up, never a downgrade of the finding ([../depth/mock-policy.md](../depth/mock-policy.md)).
|
|
17
|
+
11. If code, tests, or route discovery cannot be inspected or run, mark the assessment `BLOCKED` and state the missing access or command failure. "The lint script isn't in the audited repo" is not `BLOCKED`: the scripts are part of this skill ([../../scripts/README.md](../../scripts/README.md)).
|
|
18
|
+
|
|
19
|
+
The coverage classifications (`Covered` / `Partial` / `Missing` / `Wrong Level` / `Over-mocked` / `Unverified` / `Excluded` / `BLOCKED`) are defined in [../depth/grading.md](../depth/grading.md). Use that vocabulary, not a vague "covered."
|
|
20
|
+
|
|
21
|
+
## Completeness: enumerate every surface, not just the salient gaps
|
|
22
|
+
|
|
23
|
+
**Gap-finding must be exhaustive, not a highlight reel.** An audit that lists "the top 3 problems" silently leaves the long tail uncovered — where the un-ACed orphan hides. Completeness comes from **closed-world enumeration**:
|
|
24
|
+
|
|
25
|
+
1. **Start from the full surface inventory** (every route, API, write form, table, event, job — from [surface discovery](../breadth/surface-discovery.md) / the generated inventory), not the list of things you happened to notice.
|
|
26
|
+
2. **Emit a complete surface census**: one row per inventoried surface with its status. `gaps = inventory − {surfaces at Covered}`, so every surface is accounted for *by construction*. The census is the deliverable's backbone (the **Surface Census** table in [output-template.md](output-template.md)); the prose highlights the worst rows, but the table proves nothing was skipped.
|
|
27
|
+
3. **Every non-`Covered`/non-`Excluded` row is a gap** with its own follow-up item. If the inventory cannot be fully enumerated (no adapter, partial access), say so and mark the unenumerated portion `BLOCKED`; do not silently scope to what was easy to see.
|