@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,290 @@
|
|
|
1
|
+
# Playwright in Containers
|
|
2
|
+
|
|
3
|
+
> Read when: running Playwright on a self-hosted Docker/Podman runner, choosing the container image, or a run fails on a missing browser shared library.
|
|
4
|
+
|
|
5
|
+
**Running Playwright in the official pinned container is the preferred way to run
|
|
6
|
+
browser automation** — not a fallback for special runners. Two sanctioned
|
|
7
|
+
options, in order:
|
|
8
|
+
|
|
9
|
+
1. **Docker (preferred):** the job runs in `mcr.microsoft.com/playwright:<version>`
|
|
10
|
+
— GitHub-hosted via `container:`, self-hosted via explicit `docker run` (below),
|
|
11
|
+
Cloud Build via the step's `name:`. Browsers and OS deps ship in the image, so
|
|
12
|
+
there is **no per-job `playwright install`**, the rendering environment is **pinned
|
|
13
|
+
and identical** across jobs and machines (what makes visual baselines viable), and
|
|
14
|
+
a version bump is one tag edit.
|
|
15
|
+
2. **Plain runner (alternative):** `ubuntu-latest` + `npx playwright install
|
|
16
|
+
--with-deps chromium` per job. Acceptable for a simple repo, but it re-downloads
|
|
17
|
+
browsers every job (cache `~/.cache/ms-playwright` if you keep this) and the
|
|
18
|
+
rendering environment drifts with the runner image. Prefer option 1.
|
|
19
|
+
|
|
20
|
+
The Cloud Build template defaults to option 1. The generated golden-path workflow
|
|
21
|
+
uses option 2 (a GitHub-hosted runner with `playwright install --with-deps`).
|
|
22
|
+
`ci-audit.mjs` checks only that the golden-path verdict is present and blocking; container choice remains operational guidance.
|
|
23
|
+
**Keep every image pin in a workflow identical**, matching the repo's
|
|
24
|
+
`@playwright/test` version.
|
|
25
|
+
|
|
26
|
+
Also use this reference on self-hosted Docker/Podman runners, an intentionally
|
|
27
|
+
minimal runner image, or when CI fails with a browser shared-library error:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
error while loading shared libraries: libnspr4.so
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
That failure usually means Playwright is running directly in the runner
|
|
34
|
+
container/host image — the official GitHub runner image is not a browser runtime
|
|
35
|
+
and lacks Chromium dependencies. Do not fix it by installing random packages every
|
|
36
|
+
job. Put the Playwright job in the official Playwright container, and let the app
|
|
37
|
+
repo install its matching `@playwright/test` version via its package manager.
|
|
38
|
+
|
|
39
|
+
The same rule covers a browser that the **app** launches, not the test runner. For
|
|
40
|
+
example, a Backend that renders PDFs with Puppeteer while it runs on the runner for
|
|
41
|
+
an emulator or device journey. That fails with `Browser was not found at the
|
|
42
|
+
configured executablePath`. Keep that process on the host and give it a wrapper
|
|
43
|
+
that runs this image's browser: `github-actions` → `references/runners.md`, "A host
|
|
44
|
+
process that needs a browser binary".
|
|
45
|
+
|
|
46
|
+
## Standard GitHub Actions Pattern
|
|
47
|
+
|
|
48
|
+
Prefer a normal self-hosted job that runs the official Playwright image manually
|
|
49
|
+
with `docker run`. On rootless Podman-backed GitHub runners, native Actions
|
|
50
|
+
`container:` jobs can fail before checkout because the runner auto-bind-mounts
|
|
51
|
+
`/var/run/docker.sock` into the job container:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
Error response from daemon: container create: statfs /var/run/docker.sock: permission denied
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
That is runner/daemon plumbing, not a Playwright or app failure. The manual
|
|
58
|
+
`docker run` pattern below keeps checkout and Actions setup on the runner, runs the
|
|
59
|
+
browser work inside the Playwright image, and avoids mounting the Docker socket
|
|
60
|
+
into the Playwright container.
|
|
61
|
+
|
|
62
|
+
```yaml
|
|
63
|
+
jobs:
|
|
64
|
+
e2e:
|
|
65
|
+
runs-on: [self-hosted, linux, x64, docker]
|
|
66
|
+
timeout-minutes: 10
|
|
67
|
+
|
|
68
|
+
env:
|
|
69
|
+
E2E_WORKERS: "4"
|
|
70
|
+
PLAYWRIGHT_IMAGE: mcr.microsoft.com/playwright:v1.61.0-noble
|
|
71
|
+
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@v4
|
|
74
|
+
- name: Run Playwright in the official image
|
|
75
|
+
run: |
|
|
76
|
+
docker run --rm \
|
|
77
|
+
--network host \
|
|
78
|
+
--ipc=host \
|
|
79
|
+
--cpus 4 \
|
|
80
|
+
--memory 16g \
|
|
81
|
+
-e CI=true \
|
|
82
|
+
-e E2E_WORKERS="${E2E_WORKERS}" \
|
|
83
|
+
-v "${GITHUB_WORKSPACE}:/work:z" \
|
|
84
|
+
-w /work \
|
|
85
|
+
"${PLAYWRIGHT_IMAGE}" \
|
|
86
|
+
bash -lc 'corepack enable && pnpm install --frozen-lockfile && pnpm exec playwright test'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Choose the image tag to match the repo's `@playwright/test` version. If the
|
|
90
|
+
package version and image version differ, install the matching browsers inside
|
|
91
|
+
the Playwright container before the run:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pnpm exec playwright install chromium
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Prefer matching versions instead. It avoids network installs and prevents
|
|
98
|
+
browser/protocol mismatch failures.
|
|
99
|
+
|
|
100
|
+
## Native `container:` Jobs
|
|
101
|
+
|
|
102
|
+
Use native Actions `container:` only after the runner fleet has a passing smoke
|
|
103
|
+
test for GitHub's generated job-container mounts, including the automatic
|
|
104
|
+
`/var/run/docker.sock` bind. Useful on a compatible Docker runner, but not the
|
|
105
|
+
portable default for rootless Podman-backed runner containers.
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
container:
|
|
109
|
+
image: mcr.microsoft.com/playwright:v1.61.0-noble
|
|
110
|
+
options: --user 1001 --ipc=host --cpus 4 --memory 16g
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
If a native job-container workflow fails in `Initialize containers`, do not debug
|
|
114
|
+
application code or Playwright first. Read the generated `docker create` line in
|
|
115
|
+
the job log and verify every auto-mounted host path exists and can be `statfs`'d by
|
|
116
|
+
the daemon.
|
|
117
|
+
|
|
118
|
+
## Resource Envelope and Workers
|
|
119
|
+
|
|
120
|
+
Document the intended per-job resource envelope and make the Playwright container
|
|
121
|
+
enforce it. In the 1aboveio runner setup each slot is sized `4 CPU / 16 GB`, so
|
|
122
|
+
Playwright jobs use `--cpus 4`, `--memory 16g`, `--ipc=host`, and:
|
|
123
|
+
|
|
124
|
+
```yaml
|
|
125
|
+
env:
|
|
126
|
+
E2E_WORKERS: "4"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The runner container's compose limits do not reliably cap sibling job containers
|
|
130
|
+
created through the Docker/Podman socket. Put `--cpus`/`--memory` on the Playwright
|
|
131
|
+
`docker run` or native job container when you need deterministic limits.
|
|
132
|
+
|
|
133
|
+
Start with 4 Playwright workers for Chromium E2E on a `4 CPU / 16 GB` job. If the
|
|
134
|
+
app server is heavy, the suite launches multiple browser contexts per test, or CI
|
|
135
|
+
shows OOM/browser crashes under concurrent jobs, reduce PR-lane workers to 2 and
|
|
136
|
+
reserve 4 for manual/nightly/integration-lane runs. The Playwright config reads the
|
|
137
|
+
env rather than hardcoding:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
// `|| 4`, not `?? 4`: an empty/garbage E2E_WORKERS must fall back too
|
|
141
|
+
// (Number('') is 0, which Playwright rejects).
|
|
142
|
+
workers: process.env.CI ? Number(process.env.E2E_WORKERS) || 4 : undefined,
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Service Containers
|
|
146
|
+
|
|
147
|
+
With the recommended manual `docker run` pattern the Actions job does not use
|
|
148
|
+
`jobs.<job>.container`, so GitHub service containers publish dynamic ports to the
|
|
149
|
+
runner host. Run the Playwright container with `--network host` and connect through
|
|
150
|
+
`127.0.0.1:${{ job.services.<name>.ports[...] }}`:
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
jobs:
|
|
154
|
+
e2e:
|
|
155
|
+
runs-on: [self-hosted, linux, x64, docker]
|
|
156
|
+
timeout-minutes: 10
|
|
157
|
+
|
|
158
|
+
services:
|
|
159
|
+
postgres:
|
|
160
|
+
image: postgres:17
|
|
161
|
+
env:
|
|
162
|
+
POSTGRES_USER: test
|
|
163
|
+
POSTGRES_PASSWORD: test
|
|
164
|
+
POSTGRES_DB: app
|
|
165
|
+
ports:
|
|
166
|
+
- 5432/tcp
|
|
167
|
+
options: >-
|
|
168
|
+
--health-cmd pg_isready
|
|
169
|
+
--health-interval 10s
|
|
170
|
+
--health-timeout 5s
|
|
171
|
+
--health-retries 5
|
|
172
|
+
|
|
173
|
+
env:
|
|
174
|
+
PLAYWRIGHT_IMAGE: mcr.microsoft.com/playwright:v1.61.0-noble
|
|
175
|
+
E2E_WORKERS: "4"
|
|
176
|
+
DATABASE_URL: "postgresql://test:test@127.0.0.1:${{ job.services.postgres.ports[5432] }}/app"
|
|
177
|
+
|
|
178
|
+
steps:
|
|
179
|
+
- uses: actions/checkout@v4
|
|
180
|
+
- name: Run Playwright in the official image
|
|
181
|
+
run: |
|
|
182
|
+
docker run --rm \
|
|
183
|
+
--network host \
|
|
184
|
+
--ipc=host \
|
|
185
|
+
--cpus 4 \
|
|
186
|
+
--memory 16g \
|
|
187
|
+
-e CI=true \
|
|
188
|
+
-e E2E_WORKERS="${E2E_WORKERS}" \
|
|
189
|
+
-e DATABASE_URL="${DATABASE_URL}" \
|
|
190
|
+
-v "${GITHUB_WORKSPACE}:/work:z" \
|
|
191
|
+
-w /work \
|
|
192
|
+
"${PLAYWRIGHT_IMAGE}" \
|
|
193
|
+
bash -lc 'corepack enable && pnpm install --frozen-lockfile && pnpm prisma:migrate:deploy && pnpm exec playwright test'
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
GitHub Actions networking changes when `jobs.<job>.container` is present: service
|
|
197
|
+
containers are on the same Docker/Podman network as the job container. Reach them by
|
|
198
|
+
service label and container port:
|
|
199
|
+
|
|
200
|
+
```yaml
|
|
201
|
+
jobs:
|
|
202
|
+
e2e:
|
|
203
|
+
runs-on: [self-hosted, linux, x64, docker]
|
|
204
|
+
container:
|
|
205
|
+
image: mcr.microsoft.com/playwright:v1.61.0-noble
|
|
206
|
+
options: --user 1001 --ipc=host --cpus 4 --memory 16g
|
|
207
|
+
|
|
208
|
+
services:
|
|
209
|
+
postgres:
|
|
210
|
+
image: postgres:17
|
|
211
|
+
env:
|
|
212
|
+
POSTGRES_USER: test
|
|
213
|
+
POSTGRES_PASSWORD: test
|
|
214
|
+
POSTGRES_DB: app
|
|
215
|
+
options: >-
|
|
216
|
+
--health-cmd pg_isready
|
|
217
|
+
--health-interval 10s
|
|
218
|
+
--health-timeout 5s
|
|
219
|
+
--health-retries 5
|
|
220
|
+
|
|
221
|
+
env:
|
|
222
|
+
DATABASE_URL: postgresql://test:test@postgres:5432/app
|
|
223
|
+
|
|
224
|
+
steps:
|
|
225
|
+
- uses: actions/checkout@v4
|
|
226
|
+
- run: pnpm install --frozen-lockfile
|
|
227
|
+
- run: pnpm prisma:migrate:deploy
|
|
228
|
+
- run: pnpm exec playwright test
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Without a native job container, workflow steps run directly in the runner
|
|
232
|
+
environment; reach services through the mapped localhost port:
|
|
233
|
+
|
|
234
|
+
```yaml
|
|
235
|
+
DATABASE_URL: "postgresql://test:test@127.0.0.1:${{ job.services.postgres.ports[5432] }}/app"
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Do not mix the two models. A Playwright job container using
|
|
239
|
+
`127.0.0.1:${{ job.services.postgres.ports[5432] }}` will often fail because
|
|
240
|
+
`127.0.0.1` is the job container itself, not the host namespace where the port was
|
|
241
|
+
published.
|
|
242
|
+
|
|
243
|
+
## Self-Hosted Docker/Podman Runner Checks
|
|
244
|
+
|
|
245
|
+
Before blaming Playwright, verify the runner can create sibling job/service
|
|
246
|
+
containers. A rootless Podman-backed runner container needs: the Podman socket
|
|
247
|
+
mounted; `DOCKER_HOST=unix:///run/user/<uid>/podman/podman.sock`; user/group mapping
|
|
248
|
+
that can read the socket; SELinux labels disabled for the socket mount on SELinux
|
|
249
|
+
hosts. Equivalent smoke checks:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
# Runner container can reach the Docker-compatible Podman API.
|
|
253
|
+
docker ps
|
|
254
|
+
|
|
255
|
+
# A service container can publish a dynamic localhost port.
|
|
256
|
+
docker run -d --name pg-smoke \
|
|
257
|
+
-e POSTGRES_USER=test \
|
|
258
|
+
-e POSTGRES_PASSWORD=test \
|
|
259
|
+
-e POSTGRES_DB=testdb \
|
|
260
|
+
-p 127.0.0.1::5432 \
|
|
261
|
+
postgres:17
|
|
262
|
+
port="$(docker port pg-smoke 5432/tcp | sed 's/.*://')"
|
|
263
|
+
docker run --rm --network host postgres:17 \
|
|
264
|
+
pg_isready -h 127.0.0.1 -p "$port" -U test
|
|
265
|
+
docker rm -f pg-smoke
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
When this smoke passes but Playwright still fails with missing shared libraries,
|
|
269
|
+
the workflow is running Playwright in the wrong container. Move the Playwright steps
|
|
270
|
+
into the official Playwright image through `docker run` instead of adding browser
|
|
271
|
+
dependencies to the runner image.
|
|
272
|
+
|
|
273
|
+
## Review Checklist
|
|
274
|
+
|
|
275
|
+
When reviewing/writing CI for Playwright on self-hosted Docker runners:
|
|
276
|
+
|
|
277
|
+
- Playwright job runs `mcr.microsoft.com/playwright:<matching-version>-noble` through
|
|
278
|
+
explicit `docker run`, unless the fleet has proven native `container:` support.
|
|
279
|
+
- A native `container:` job failing `Initialize containers` with
|
|
280
|
+
`statfs /var/run/docker.sock: permission denied` → runner socket auto-mount
|
|
281
|
+
incompatibility; switch to the manual `docker run` pattern.
|
|
282
|
+
- The repo still runs `npm ci`/`pnpm install`; the image supplies browsers and OS
|
|
283
|
+
deps, not the app's node_modules.
|
|
284
|
+
- `@playwright/test` and the image tag are aligned, or the workflow explicitly
|
|
285
|
+
installs matching browsers.
|
|
286
|
+
- Manual `docker run` + `services.postgres`: `DATABASE_URL` uses
|
|
287
|
+
`${{ job.services.postgres.ports[5432] }}` on `127.0.0.1`, Playwright container uses
|
|
288
|
+
`--network host`. Native job container + `services.postgres`: `DATABASE_URL` uses
|
|
289
|
+
`postgres:5432`, not `127.0.0.1:<mapped-port>`.
|
|
290
|
+
- The runner setup has a smoke check proving sibling service containers work.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Presentation Sweep (the third coverage axis)
|
|
2
|
+
|
|
3
|
+
> Read when: running or wiring the presentation sweep, writing a spec that uses the instruments, or reading the results file the ledger consumes.
|
|
4
|
+
|
|
5
|
+
A green functional suite can pass while a route throws on render — when the only spec for that route **intercepts its own API** (`page.route('**/api/**')`), it never exercises the real render path that crashes. The presentation sweep catches this: it opens **every manifest route** in a real browser over the real render path (no first-party interception) and asserts the presentation floor **spine first**. It is the runner half of ensure-coverage's presentation axis (that skill *grades* the axis; this skill *runs* it and owns the result shape below).
|
|
6
|
+
|
|
7
|
+
**It is separate evidence from the functional/journey suite, even though both use Playwright.** A passing functional E2E run is not presentation proof.
|
|
8
|
+
|
|
9
|
+
## Instruments (import into a spec, or use the sweep)
|
|
10
|
+
|
|
11
|
+
| Level | Spine? | Instrument | Catches |
|
|
12
|
+
|---|---|---|---|
|
|
13
|
+
| `presentation:render-health` | **yes** | `scripts/presentation-render-health.mjs` | `pageerror` / `console.error` / error boundary / HTTP ≥500 on render — **and through interactions** (mutate-health, see below) |
|
|
14
|
+
| `presentation:spatial` | | `scripts/presentation-checks.mjs` | horizontal overflow / element overlap |
|
|
15
|
+
| `presentation:perceivability` | | `scripts/presentation-perceivability.mjs` | contrast / invisible-but-present controls |
|
|
16
|
+
| `presentation:reachability` | | `scripts/presentation-reachability.mjs` | nav orphans / missing affordance cues |
|
|
17
|
+
| `presentation:temporal` | | `scripts/presentation-temporal.mjs` | layout shift |
|
|
18
|
+
|
|
19
|
+
Per-route spec usage (tag it so the Coverage Ledger resolves it):
|
|
20
|
+
```ts
|
|
21
|
+
// @covers /tasks
|
|
22
|
+
// @level presentation:render-health
|
|
23
|
+
import { test } from '@playwright/test'
|
|
24
|
+
import { assertRenderHealthy } from '<skill-dir>/scripts/presentation-render-health.mjs'
|
|
25
|
+
|
|
26
|
+
test('/tasks renders without error', async ({ page, baseURL }) => {
|
|
27
|
+
await assertRenderHealthy(page, '/tasks', { origin: baseURL }) // throws on pageerror/console.error/5xx
|
|
28
|
+
})
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## The sweep (mandatory for browser-route changes)
|
|
32
|
+
|
|
33
|
+
Run the whole-manifest sweep as review evidence, not a per-route afterthought:
|
|
34
|
+
```bash
|
|
35
|
+
E2E_AUTH_BYPASS=1 node <skill-dir>/scripts/presentation-sweep.mjs \
|
|
36
|
+
--manifest e2e/route-manifest.json --base-url http://127.0.0.1:3000 \
|
|
37
|
+
--out docs/tests/_generated/presentation-results.json [--fixtures e2e/sweep-fixtures.mjs]
|
|
38
|
+
```
|
|
39
|
+
It exits non-zero on any `fail`/`blocked` and writes the per-`(route, level)` result the ledger consumes.
|
|
40
|
+
|
|
41
|
+
**Fixtures the repo supplies** (`--fixtures` default export): `applyAuth(context)` (a seeded/bypass session so guarded routes render as a real user), `paramResolver(route)` (a concrete seeded id per dynamic segment like `/tasks/[id]`), and optional `ignoreRoutes` / `spatialIgnore` allowlists. **A route the harness cannot render** (no `DATABASE_URL`, auth unavailable, unresolved param) is reported `blocked` — never silently skipped or passed. "Could not check" is not "checked and fine."
|
|
42
|
+
|
|
43
|
+
#### "No in-app way to view it" is not blocked
|
|
44
|
+
|
|
45
|
+
Reaching the route is your job. The sweep navigates *by URL*, so a route with no nav link or in-app entry point is still fully reachable. `blocked` is reserved for the genuinely un-renderable conditions above; "I had no convenient route to it" is never an excuse to skip the gate or merge without it. Stand up the local build (dev server + disposable DB + seeded/bypass auth) and drive the route's URL directly:
|
|
46
|
+
|
|
47
|
+
- **Manifest route → `presentation-sweep.mjs`** — the result the ledger and reviewer consume; run it whenever the route is in the manifest.
|
|
48
|
+
- **Ad-hoc one-route check → `agent-browser` (preferred).** Navigate, screenshot the states that matter (expanded/collapsed/popover), read the console, clean up. The default for "is this one route OK before I merge."
|
|
49
|
+
- When agent-browser doesn't fit: **chrome-devtools MCP** for devtools surfaces (console, network, a perf/Lighthouse trace) alongside the render; **raw Playwright** (`page.goto(url)`) when scripting navigation into an authored spec.
|
|
50
|
+
|
|
51
|
+
All load the **real render path** (no first-party interception) — the whole point. Do this *before* merging; "there was no route to view it" before that build exists means the build was never stood up, not that the check was impossible.
|
|
52
|
+
|
|
53
|
+
## render-health is continuous (mutate-health)
|
|
54
|
+
|
|
55
|
+
The sweep only proves the **load** path — it never clicks submit (write paths are destructive and need valid domain input). But render-health must also hold **through** a write. Reuse the same watcher in authored mutation journeys and interaction-driven checks so an uncaught error / `console.error` / first-party 5xx fired *during* the action fails too — composed, not a re-driven form:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { assertHealthyThrough } from '<skill-dir>/scripts/presentation-render-health.mjs'
|
|
59
|
+
import { assertRemovedAfterMutation } from '<skill-dir>/scripts/presentation-perceivability.mjs'
|
|
60
|
+
|
|
61
|
+
// fill + submit, assert durable state changed (the depth journey) AND nothing threw:
|
|
62
|
+
await assertHealthyThrough(page, async () => {
|
|
63
|
+
await page.getByRole('button', { name: 'Delete' }).click()
|
|
64
|
+
await assertRemovedAfterMutation(page, row) // perceivability post-state
|
|
65
|
+
}, { origin: baseURL })
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This is "mutate-health" — render-health × the trigger/mutation pattern `presentation:temporal` (`assertNoFirstPartyShift({ trigger })`) and `presentation:perceivability` (`assertRemovedAfterMutation`) already use. The journey's durable-state assertion stays as-is; this adds "…and nothing threw while it happened."
|
|
69
|
+
|
|
70
|
+
## Design fidelity (`presentation:fidelity`)
|
|
71
|
+
|
|
72
|
+
Opt-in, for a surface built from a cited design source. ensure-coverage owns the doctrine and the parity manifest (`references/presentation/axis.md` → `presentation:fidelity`, `scripts/design-parity.mjs`). The runner is an ordinary Playwright spec that measures at both floor viewports with the probe `design-parity.mjs probe` emits, then calls `design-parity.mjs validate --observed … --diff <merge-base>`; computed style is stable across OSes, so it needs no pinned container and no baseline image.
|
|
73
|
+
|
|
74
|
+
## What the sweep must do, and the result shape the ledger consumes
|
|
75
|
+
|
|
76
|
+
`coverage-ledger.mjs` is a static analyzer: it proves a qualifying real-browser, non-intercepting, attested test was *authored*. It cannot observe a `pageerror`, an overflow, or a layout shift. The coverage verdict therefore needs two evidence sources: **accounting** (the ledger) and **rendering** (this sweep). Neither is a CI gate; curated golden-path smoke is the sole CI gate.
|
|
77
|
+
|
|
78
|
+
Given the generated route manifest (the `kind: "route"` surfaces from the surface inventory), the sweep must:
|
|
79
|
+
|
|
80
|
+
1. **Open every manifest route in a real browser** at the viewport floor `[375, 1280]`. Never sample or top-N silently; if coverage is bounded, log what was dropped.
|
|
81
|
+
2. **Drive the real render path.** `page.route('**/api/**')`, `route.fulfill`, MSW for owned paths, or first-party fixtures disqualify the run for that route. Externals may be faked.
|
|
82
|
+
3. **Assert the floor invariants, spine first**, one result per `(route, level, viewport)`: `render-health`, `spatial`, `perceivability`, `reachability`, `temporal`. The sweep proves the load path; write paths are destructive and need authored journeys with the render-health watcher kept attached.
|
|
83
|
+
4. **Abstain, never silently pass.** Ambiguous state (contrast over a gradient, a route whose seed failed) is `unverified` (a warning unless the user made it blocking), never `pass`. An environment that cannot render at all (no `DATABASE_URL`, no auth) is `blocked`, never `pass`.
|
|
84
|
+
|
|
85
|
+
Repo-supplied fixtures: a deterministic **auth** bypass or seeded session (a login wall is not a render pass); **seed** data so `read` / `detail` routes render real content; **param substitution** for dynamic segments (an unresolvable param is `blocked`, not skipped); and a gated **allowlist** for intentional overlap (`category` + `reason`, surfaced in a census; an overlap occluding a reachable control can never be allowlisted).
|
|
86
|
+
|
|
87
|
+
Emit JSON to `docs/tests/_generated/presentation-results.json`:
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"viewportFloor": [375, 1280],
|
|
92
|
+
"results": [
|
|
93
|
+
{ "route": "/tasks", "level": "presentation:render-health", "status": "fail",
|
|
94
|
+
"evidence": "pageerror: Cannot read properties of undefined (reading 'id') at TasksToolbar" },
|
|
95
|
+
{ "route": "/tasks", "level": "presentation:spatial", "status": "blocked",
|
|
96
|
+
"evidence": "render-health failed; layout not assessable" },
|
|
97
|
+
{ "route": "/dashboard", "level": "presentation:render-health", "status": "pass" }
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
- `status` is `pass | fail | unverified | blocked`. `fail` and `blocked` exit the sweep non-zero. `unverified` is a ledger warning by default.
|
|
103
|
+
- `evidence` names the concrete observation: the `pageerror` text, the offending selector and overflow px, the unreachable param.
|
|
104
|
+
- The ledger reconciles these against each route's required levels: a `fail` / `blocked` / missing result on a required level is a finding; a `pass` still needs a clean authored test, read and marked `verified: true`, to reach `Covered`.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Reviewing PRs (E2E coverage)
|
|
2
|
+
|
|
3
|
+
> Read when: reviewing a PR for E2E coverage. The checklist, the red flags, and the comment template.
|
|
4
|
+
|
|
5
|
+
Checklist:
|
|
6
|
+
|
|
7
|
+
- [ ] Route discovery and reachability analysis were run before coverage audit
|
|
8
|
+
- [ ] Route manifest regenerated (projection) if routes added/removed; no drift vs the surface inventory
|
|
9
|
+
- [ ] New routes have render-health proof (Tier 1, or a Tier 2/3 test calling `assertRenderHealthy`); no duplicate Tier 1 for a route already proven
|
|
10
|
+
- [ ] Interactive routes have Tier 2 (success + error cases)
|
|
11
|
+
- [ ] Browser-route changes ran the presentation sweep (a separate run); no `fail` results. **A `blocked` result depends on who is running this list.** Producing the work (fixtures yours to supply), `blocked` is a genuine gap — a route the harness cannot render is a route nobody proved renders, so it blocks. *Reviewing* a diff from a read-only sandbox, `blocked` usually means your environment lacks a `DATABASE_URL`, an auth session, or a resolvable param — an inability to verify, which is never evidence of absence. Report the route and the error and take `BLOCKED` for that route's obligation; do not convert it into a finding against the diff
|
|
12
|
+
- [ ] No `waitForTimeout()` -- use explicit waits
|
|
13
|
+
- [ ] No CSS class assertions -- test user-visible behavior
|
|
14
|
+
- [ ] **No test skipped or disabled.** The PR adds no `test.skip` / `xit` / `describe.skip`, no conditional skip unless CI still runs the test where the condition is false (a platform or optional-dependency skip), no disguised `if (!x) return` guard. A missing precondition is **seeded**; an un-sandboxable/flaky case goes to the **quarantine lane** (non-blocking, graded `Unverified`), never skipped. A `TODO`/issue link does **not** authorize a skip (policy: `ensure-coverage/references/process/test-strategy.md`)
|
|
15
|
+
- [ ] No assertion that passes on a **404 / not-found / empty / error** page where the test name promises a real render — that goes green when the feature is broken or unseeded; a route returning HTTP 200 with not-found content is itself a status-code bug to file
|
|
16
|
+
- [ ] **Each authorized lane asserts a positive marker unique to its subject having rendered.** The row above rejects a *negative* (an assertion that survives a degraded page) and is the half a reviewer can see; this one requires a *positive* — a row, a heading, a seeded value the real producer emits — and is the half that fails **silently**. "Didn't crash" and "didn't 404" are not "rendered". A lane whose tenant/auth is misconfigured fails closed and dies on a timeout with **no assertion in the diff to catch**: see [authoring/auth-flows.md](authoring/auth-flows.md) § A session fixture asserts its own preconditions
|
|
17
|
+
- [ ] Auth in shared fixtures, not duplicated
|
|
18
|
+
- [ ] Bugfix PRs have regression test covering the exact failure
|
|
19
|
+
- [ ] Tier 3 journeys use real APIs (no mocking internal endpoints)
|
|
20
|
+
- [ ] Do-not-ship golden journeys (sign in → core action → pay) are tagged `@golden-path` so the golden-path check selects them; a new critical flow with no `@golden-path` tag / `golden-paths.json` entry is a gap
|
|
21
|
+
- [ ] Specs tagged `@covers`/`@level` so the ledger resolves them
|
|
22
|
+
|
|
23
|
+
**Red flags (block PR):** route discovery/reachability not run before audit, route treated as valid only because a file exists, tests assert implementation details, fixed sleeps, new route without manifest entry, copy-pasted auth setup, happy-path-only Tier 2, no presentation sweep run for a browser-route change (a sweep you could not *run* is a `BLOCKED`, not a red flag — the distinction is whether the sweep is missing or your environment is), **any test skipped/disabled/guarded** instead of seeded-or-quarantined, an assertion that passes on a 404/not-found/empty page where a real render is expected, **an authorized lane whose only observed failure mode is a timeout** (it is failing closed before it renders, not asserting).
|
|
24
|
+
|
|
25
|
+
**Lead with the verdict, then follow-ups.** Put the verdict at the **top** of the review (and any coverage `notes.md`) — *is this surface covered / ship-ready, or do gaps remain?* — then what the tests prove and deliberately don't, and concrete follow-up action items (owner/level where known) for anything uncovered.
|
|
26
|
+
|
|
27
|
+
**Comment template:**
|
|
28
|
+
```
|
|
29
|
+
### E2E Coverage
|
|
30
|
+
|
|
31
|
+
**Missing:**
|
|
32
|
+
- Route `/new-page` added but not in the surface inventory / route manifest
|
|
33
|
+
- No Tier 2 test for the date filter (need: valid range, invalid range, empty)
|
|
34
|
+
- `/tasks` has no presentation-sweep result (render unproven)
|
|
35
|
+
|
|
36
|
+
**Issues:**
|
|
37
|
+
- `line 42`: Uses `waitForTimeout(3000)` -- replace with `waitForResponse`
|
|
38
|
+
|
|
39
|
+
**Good:**
|
|
40
|
+
- Journey test covers the full flow
|
|
41
|
+
```
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Route Discovery and the Route Manifest
|
|
2
|
+
|
|
3
|
+
> Read when: a route was added or removed, the manifest is stale, or an audit needs the route inventory before it can grade anything.
|
|
4
|
+
|
|
5
|
+
## Discover first, never audit from memory
|
|
6
|
+
|
|
7
|
+
Never audit E2E coverage from memory, sampling, or browsing files. Produce a deterministic route inventory, then classify reachability. A `page.*` file is a declared route, not a reachable one, until its guard chain is checked.
|
|
8
|
+
|
|
9
|
+
Discovery order: run the framework's discovery script when there is one; prefer runtime introspection for backends when the app can start (OpenAPI JSON, route registries); use static discovery as the fallback and cross-check; then walk each page route's layout chain, middleware, redirects, guards, rewrites, route groups and feature flags.
|
|
10
|
+
|
|
11
|
+
- Next.js App Router: `app/**/page.*` and `app/**/route.*`, including route groups, dynamic segments, parallel and intercepting routes, and the HTTP methods a `route.*` exports (`scripts/detect-routes-nextjs.mjs`).
|
|
12
|
+
- Next.js Pages Router: `pages/**/*`, with `pages/api/**` when auditing endpoints.
|
|
13
|
+
- React Router: route config files, `createBrowserRouter`, `createRoutesFromElements`, `<Route path=…>`.
|
|
14
|
+
- Backends: runtime `app.routes` or `/openapi.json` first; decorator or router-registration scan as the fallback. Keep method, path and auth metadata; do not drop health or internal endpoints silently.
|
|
15
|
+
- Multiple apps (admin, portal) are discovered separately with separate manifests.
|
|
16
|
+
|
|
17
|
+
Reachability: `Reachable`, `Redirected`, `Guarded` (say by what), `Blocked`, `Unknown`. Never grade `Unknown` as covered. The portable doctrine is ensure-coverage's `references/breadth/surface-discovery.md`; this is its executable form.
|
|
18
|
+
|
|
19
|
+
An audit reports: the discovery method, reachability with guard evidence, discovered count versus manifest count, routes missing from the manifest and manifest entries absent from code, changed routes and their coverage status, and uncovered surfaces per the ledger (never a manifest `specs` count).
|
|
20
|
+
|
|
21
|
+
## The manifest is a generated projection
|
|
22
|
+
|
|
23
|
+
`e2e/route-manifest.json` is derived from ensure-coverage's surface inventory, never hand-maintained, and never the coverage source of truth (the ledger computes that from `@covers`). Its job is to be the route list the sweep iterates, with an E2E `tier`.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
node <skill-dir>/scripts/project-route-manifest.mjs \
|
|
27
|
+
--inventory docs/tests/_generated/surface-inventory.json \
|
|
28
|
+
--overlay e2e/route-manifest.overlay.json --out e2e/route-manifest.json
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Shape: `{ version, generated: true, routes: [{ path, tier }] }`. Curation lives in the small hand-authored overlay:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"routes": {
|
|
36
|
+
"/dashboard": { "tier": 3 },
|
|
37
|
+
"/legacy-print": { "ignore": true }
|
|
38
|
+
},
|
|
39
|
+
"spatialIgnore": [".sticky-header"]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`tier` defaults from the inventory's `class` (read → 1, detail/mutation → 2); the overlay raises it or `ignore`s a route from the sweep (it still owes its ledger floor). `specs` is informational only.
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
detect-routes → surface-inventory.json → project-route-manifest.mjs (+ overlay) → route-manifest.json
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Because the manifest is generated, its route set cannot drift: regenerate both during the audit and compare the result with the committed files. A new route appears in the inventory (a ledger obligation) and flows into the manifest (a sweep visit) from the same discovery pass. `staleOverlayEntries` warns when the overlay names a route the inventory no longer has. The backend `endpoint-manifest.json` is the API analog, projected from `kind === 'api'` with `method` and `tier`.
|
|
50
|
+
|
|
51
|
+
Scripts: `scripts/project-route-manifest.mjs`, `scripts/validate-manifest.mjs`.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
9
|
+
const WEEK_MS = 7 * DAY_MS;
|
|
10
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
|
|
12
|
+
function readJson(path, fallback = {}) {
|
|
13
|
+
try { return JSON.parse(readFileSync(path, 'utf8')); } catch { return fallback; }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function frontmatterValue(text, key) {
|
|
17
|
+
const frontmatter = /^---\n([\s\S]*?)\n---/.exec(text)?.[1] ?? '';
|
|
18
|
+
const match = new RegExp('^' + key + ':\\s*([^\\n]+)$', 'm').exec(frontmatter);
|
|
19
|
+
return match?.[1].trim().replace(/^['"]|['"]$/g, '') ?? null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function repositoryOf(source) {
|
|
23
|
+
const value = String(source ?? '').trim();
|
|
24
|
+
const match = /^(?:git@github\.com:|https:\/\/github\.com\/)?([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?$/.exec(value);
|
|
25
|
+
return match?.[1] ?? null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function stableVersion(value) {
|
|
29
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(String(value ?? '').trim());
|
|
30
|
+
return match ? match.slice(1).map(Number) : null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function newer(left, right) {
|
|
34
|
+
for (let index = 0; index < 3; index += 1) {
|
|
35
|
+
if (left[index] !== right[index]) return left[index] > right[index];
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function writeCache(path, value) {
|
|
41
|
+
try {
|
|
42
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
43
|
+
writeFileSync(path, JSON.stringify(value));
|
|
44
|
+
} catch { /* A read-only cache must not block skill use. */ }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function main(now = Date.now()) {
|
|
48
|
+
if (process.env.ONEABOVEIO_NO_UPDATE_CHECK) return;
|
|
49
|
+
const skill = readFileSync(join(here, 'SKILL.md'), 'utf8');
|
|
50
|
+
const name = frontmatterValue(skill, 'name');
|
|
51
|
+
const localVersion = stableVersion(frontmatterValue(skill, 'release-version'));
|
|
52
|
+
if (!name || !localVersion) return;
|
|
53
|
+
|
|
54
|
+
const lock = readJson(join(process.env.HOME || homedir(), '.agents', '.skill-lock.json'));
|
|
55
|
+
const entry = lock.skills?.[name];
|
|
56
|
+
const repository = repositoryOf(entry?.sourceUrl || entry?.source);
|
|
57
|
+
if (!repository) return;
|
|
58
|
+
|
|
59
|
+
const cacheRoot = process.env.XDG_CACHE_HOME || join(process.env.HOME || homedir(), '.cache');
|
|
60
|
+
const cachePath = join(cacheRoot, '1aboveio-skills', 'release-check.json');
|
|
61
|
+
const all = readJson(cachePath);
|
|
62
|
+
const cache = all[repository] && typeof all[repository] === 'object' ? all[repository] : {};
|
|
63
|
+
|
|
64
|
+
if (!cache.lastCheck || now - cache.lastCheck >= DAY_MS) {
|
|
65
|
+
const result = spawnSync('gh', ['api', 'repos/' + repository + '/releases/latest', '--jq', '.tag_name'], {
|
|
66
|
+
encoding: 'utf8',
|
|
67
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
68
|
+
timeout: 1500,
|
|
69
|
+
});
|
|
70
|
+
cache.lastCheck = now;
|
|
71
|
+
if (result.status === 0 && stableVersion(result.stdout)) cache.latestTag = result.stdout.trim();
|
|
72
|
+
else delete cache.latestTag;
|
|
73
|
+
all[repository] = cache;
|
|
74
|
+
writeCache(cachePath, all);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const latestVersion = stableVersion(cache.latestTag);
|
|
78
|
+
if (!latestVersion || !newer(latestVersion, localVersion)) return;
|
|
79
|
+
if (cache.notifiedTag === cache.latestTag && cache.notifiedAt && now - cache.notifiedAt < WEEK_MS) return;
|
|
80
|
+
|
|
81
|
+
cache.notifiedTag = cache.latestTag;
|
|
82
|
+
cache.notifiedAt = now;
|
|
83
|
+
all[repository] = cache;
|
|
84
|
+
writeCache(cachePath, all);
|
|
85
|
+
const command = `npx skills@1.5.23 add '${repository}#${cache.latestTag}' --global --agent universal claude-code --skill ${name} --yes`;
|
|
86
|
+
process.stdout.write(
|
|
87
|
+
`UPDATE_AVAILABLE: A newer 1AboveIO skills release (${cache.latestTag}) is available; this skill is `
|
|
88
|
+
+ `v${localVersion.join('.')}. Ask once whether to refresh ${name}. On approval run \`${command}\`. `
|
|
89
|
+
+ 'The refreshed instructions apply next session. Either way, continue the current task and do not ask again this session.\n',
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
try { main(); } catch { /* Update checks are advisory and always fail silent. */ }
|