@1aboveio/skills 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +3 -0
- package/README.md +90 -0
- package/bin/1aboveio-skills.mjs +18 -0
- package/package.json +28 -0
- package/runtime/skills/distribution/generated/recipes.json +1189 -0
- package/runtime/skills/distribution/scripts/bundles.mjs +280 -0
- package/runtime/skills/engineering/engineering-runtime/scripts/main-module.mjs +80 -0
- package/skills/backend/airflow-dag-develop/LICENSE +3 -0
- package/skills/backend/airflow-dag-develop/SKILL.md +111 -0
- package/skills/backend/app-debug/LICENSE +3 -0
- package/skills/backend/app-debug/SKILL.md +109 -0
- package/skills/backend/app-debug/references/common-errors.md +128 -0
- package/skills/backend/python-backend/LICENSE +3 -0
- package/skills/backend/python-backend/SKILL.md +326 -0
- package/skills/cicd-pipeline/cloud-build/LICENSE +3 -0
- package/skills/cicd-pipeline/cloud-build/SKILL.md +707 -0
- package/skills/cicd-pipeline/cloud-debug/LICENSE +3 -0
- package/skills/cicd-pipeline/cloud-debug/SKILL.md +316 -0
- package/skills/cicd-pipeline/cloud-debug/references/build-failures.md +238 -0
- package/skills/cicd-pipeline/cloud-debug/references/deploy-failures.md +376 -0
- package/skills/cicd-pipeline/cloud-debug/references/pipeline-failures.md +378 -0
- package/skills/cicd-pipeline/cloud-deploy/LICENSE +3 -0
- package/skills/cicd-pipeline/cloud-deploy/SKILL.md +229 -0
- package/skills/cicd-pipeline/cloud-deploy/references/config-templates.md +257 -0
- package/skills/cicd-pipeline/docker/LICENSE +3 -0
- package/skills/cicd-pipeline/docker/SKILL.md +126 -0
- package/skills/cicd-pipeline/google-cloud/LICENSE +3 -0
- package/skills/cicd-pipeline/google-cloud/SKILL.md +118 -0
- package/skills/cicd-pipeline/google-cloud/references/gcs.md +469 -0
- package/skills/cicd-pipeline/google-cloud/references/iam.md +451 -0
- package/skills/cicd-pipeline/google-cloud/references/project.md +349 -0
- package/skills/cicd-pipeline/google-cloud/references/secrets.md +336 -0
- package/skills/cicd-pipeline/google-cloud/references/vpc.md +312 -0
- package/skills/cicd-pipeline/google-cloud/scripts/create-sa.sh +36 -0
- package/skills/cicd-pipeline/google-cloud/scripts/gcp-config.sh +31 -0
- package/skills/cicd-pipeline/google-cloud/scripts/grant-iap.sh +41 -0
- package/skills/cicd-pipeline/google-cloud/scripts/setup-secrets.sh +48 -0
- package/skills/cicd-pipeline/mergify/LICENSE +3 -0
- package/skills/cicd-pipeline/mergify/SKILL.md +138 -0
- package/skills/cicd-pipeline/mergify/assets/templates/mergify.yml +237 -0
- package/skills/cicd-pipeline/mergify/assets/templates/ruleset.json +46 -0
- package/skills/cicd-pipeline/mergify/references/branch-protection.md +277 -0
- package/skills/cicd-pipeline/mergify/references/configuration.md +183 -0
- package/skills/cicd-pipeline/mergify/references/diagnosis.md +73 -0
- package/skills/cicd-pipeline/mergify/references/traps.md +78 -0
- package/skills/cicd-pipeline/mergify/references/watch-contract.md +218 -0
- package/skills/cicd-pipeline/mergify/scripts/audit-core.mjs +131 -0
- package/skills/cicd-pipeline/mergify/scripts/audit.mjs +4 -0
- package/skills/cicd-pipeline/mergify/scripts/watch-pr-delivery-core.mjs +663 -0
- package/skills/cicd-pipeline/mergify/scripts/watch-pr-delivery.mjs +4 -0
- package/skills/cicd-pipeline/podman/LICENSE +3 -0
- package/skills/cicd-pipeline/podman/SKILL.md +70 -0
- package/skills/cicd-pipeline/podman/agents/openai.yaml +4 -0
- package/skills/cicd-pipeline/podman/assets/templates/podman-compose-socket-directory.yml +6 -0
- package/skills/cicd-pipeline/podman/assets/templates/podman-service-override.conf +3 -0
- package/skills/cicd-pipeline/podman/references/compose-compatibility.md +70 -0
- package/skills/cicd-pipeline/podman/references/networking-and-ports.md +74 -0
- package/skills/cicd-pipeline/podman/references/rootless-services-and-sockets.md +156 -0
- package/skills/cicd-pipeline/podman/references/troubleshooting.md +98 -0
- package/skills/engineering/e2e-test/LICENSE +3 -0
- package/skills/engineering/e2e-test/SKILL.md +156 -0
- package/skills/engineering/e2e-test/assets/ci-gates.cloudbuild.yaml +272 -0
- package/skills/engineering/e2e-test/assets/ci-gates.github.yml +451 -0
- package/skills/engineering/e2e-test/assets/e2e-workflow.yml +282 -0
- package/skills/engineering/e2e-test/references/authoring/auth-flows.md +159 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-config.md +71 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-patterns.md +219 -0
- package/skills/engineering/e2e-test/references/authoring/test-skipping.md +44 -0
- package/skills/engineering/e2e-test/references/ci-integration.md +121 -0
- package/skills/engineering/e2e-test/references/ci-playwright-container.md +280 -0
- package/skills/engineering/e2e-test/references/debugging.md +36 -0
- package/skills/engineering/e2e-test/references/presentation-sweep.md +131 -0
- package/skills/engineering/e2e-test/references/reviewing.md +39 -0
- package/skills/engineering/e2e-test/references/route-discovery.md +50 -0
- package/skills/engineering/e2e-test/references/route-manifest.md +44 -0
- package/skills/engineering/e2e-test/scripts/detect-routes-fastapi.py +290 -0
- package/skills/engineering/e2e-test/scripts/detect-routes-nextjs.mjs +200 -0
- package/skills/engineering/e2e-test/scripts/post-visual-evidence.mjs +158 -0
- package/skills/engineering/e2e-test/scripts/presentation-checks.mjs +171 -0
- package/skills/engineering/e2e-test/scripts/presentation-perceivability.mjs +179 -0
- package/skills/engineering/e2e-test/scripts/presentation-reachability.mjs +154 -0
- package/skills/engineering/e2e-test/scripts/presentation-render-health.mjs +141 -0
- package/skills/engineering/e2e-test/scripts/presentation-sweep.mjs +148 -0
- package/skills/engineering/e2e-test/scripts/presentation-temporal.mjs +127 -0
- package/skills/engineering/e2e-test/scripts/presentation-visual.mjs +84 -0
- package/skills/engineering/e2e-test/scripts/project-route-manifest.mjs +75 -0
- package/skills/engineering/e2e-test/scripts/validate-manifest.mjs +106 -0
- package/skills/engineering/engineering-runtime/LICENSE +3 -0
- package/skills/engineering/engineering-runtime/SKILL.md +10 -0
- package/skills/engineering/engineering-runtime/agents/openai.yaml +6 -0
- package/skills/engineering/engineering-runtime/coherence/workflow.json +553 -0
- package/skills/engineering/engineering-runtime/scripts/exact-head-artifact.mjs +131 -0
- package/skills/engineering/engineering-runtime/scripts/head-check-set.mjs +398 -0
- package/skills/engineering/engineering-runtime/scripts/main-module.mjs +80 -0
- package/skills/engineering/engineering-runtime/scripts/mergify-yaml.mjs +11 -0
- package/skills/engineering/engineering-runtime/scripts/package-lock.json +43 -0
- package/skills/engineering/engineering-runtime/scripts/package.json +10 -0
- package/skills/engineering/engineering-runtime/scripts/required-check-plan.mjs +223 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +576 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +166 -0
- package/skills/engineering/ensure-coverage/LICENSE +3 -0
- package/skills/engineering/ensure-coverage/SKILL.md +136 -0
- package/skills/engineering/ensure-coverage/evals/evals.json +125 -0
- package/skills/engineering/ensure-coverage/references/breadth/coverage-ledger.md +91 -0
- package/skills/engineering/ensure-coverage/references/breadth/inventory-contract.md +83 -0
- package/skills/engineering/ensure-coverage/references/breadth/surface-baseline.md +44 -0
- package/skills/engineering/ensure-coverage/references/breadth/surface-discovery.md +16 -0
- package/skills/engineering/ensure-coverage/references/depth/characterization.md +68 -0
- package/skills/engineering/ensure-coverage/references/depth/coverage.config.example.json +25 -0
- package/skills/engineering/ensure-coverage/references/depth/grading.md +35 -0
- package/skills/engineering/ensure-coverage/references/depth/mock-policy.md +87 -0
- package/skills/engineering/ensure-coverage/references/depth/test-smells.md +23 -0
- package/skills/engineering/ensure-coverage/references/enforcement/ci-contract.md +164 -0
- package/skills/engineering/ensure-coverage/references/enforcement/hooks.md +85 -0
- package/skills/engineering/ensure-coverage/references/examples/coverage-ledger.md +109 -0
- package/skills/engineering/ensure-coverage/references/examples/refund-flow.md +33 -0
- package/skills/engineering/ensure-coverage/references/presentation/axis.md +78 -0
- package/skills/engineering/ensure-coverage/references/presentation/runner-contract.md +74 -0
- package/skills/engineering/ensure-coverage/references/process/audit-mode.md +33 -0
- package/skills/engineering/ensure-coverage/references/process/output-template.md +139 -0
- package/skills/engineering/ensure-coverage/references/process/review-contract-template.md +119 -0
- package/skills/engineering/ensure-coverage/references/process/scope-class.md +178 -0
- package/skills/engineering/ensure-coverage/references/process/test-strategy.md +55 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-config.schema.json +45 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-file.schema.json +93 -0
- package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.mjs +178 -0
- package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.mjs +101 -0
- package/skills/engineering/ensure-coverage/scripts/ci-audit.mjs +358 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-checklist.mjs +494 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-ledger.mjs +663 -0
- package/skills/engineering/ensure-coverage/scripts/design-parity.mjs +591 -0
- package/skills/engineering/ensure-coverage/scripts/evidence-block.mjs +367 -0
- package/skills/engineering/ensure-coverage/scripts/lint-tests.mjs +269 -0
- package/skills/engineering/ensure-coverage/scripts/mock-policy-config.mjs +176 -0
- package/skills/engineering/ensure-coverage/scripts/package-lock.json +76 -0
- package/skills/engineering/ensure-coverage/scripts/package.json +19 -0
- package/skills/engineering/ensure-coverage/scripts/scope-class.mjs +554 -0
- package/skills/engineering/harness-runtime/LICENSE +3 -0
- package/skills/engineering/harness-runtime/SKILL.md +18 -0
- package/skills/engineering/harness-runtime/agents/openai.yaml +6 -0
- package/skills/engineering/harness-runtime/bin/discover-models.mjs +4 -0
- package/skills/engineering/harness-runtime/bin/model-catalog.mjs +4 -0
- package/skills/engineering/harness-runtime/contracts.md +15 -0
- package/skills/engineering/harness-runtime/discover-models.mjs +392 -0
- package/skills/engineering/harness-runtime/fixtures/native-question-schemas.json +33 -0
- package/skills/engineering/harness-runtime/fixtures/question-responses.json +54 -0
- package/skills/engineering/harness-runtime/index.mjs +767 -0
- package/skills/engineering/harness-runtime/model-catalog.mjs +787 -0
- package/skills/engineering/harness-runtime/native-question-contracts.md +37 -0
- package/skills/engineering/harness-runtime/references/model-catalog-seed.json +159 -0
- package/skills/engineering/harness-runtime/references/model-catalog.md +57 -0
- package/skills/engineering/implement-and-pr/LICENSE +3 -0
- package/skills/engineering/implement-and-pr/SKILL.md +176 -0
- package/skills/engineering/implement-and-pr/references/ci-iteration.md +10 -0
- package/skills/engineering/implement-and-pr/references/closeout.md +27 -0
- package/skills/engineering/implement-and-pr/references/contract-complete-fix-rounds.md +34 -0
- package/skills/engineering/implement-and-pr/references/evidence-rules.md +39 -0
- package/skills/engineering/implement-and-pr/references/incremental-plan.md +16 -0
- package/skills/engineering/implement-and-pr/references/self-review.md +23 -0
- package/skills/engineering/implement-and-pr/references/tdd-mode.md +18 -0
- package/skills/engineering/resolve-issues/LICENSE +3 -0
- package/skills/engineering/resolve-issues/SKILL.md +167 -0
- package/skills/engineering/resolve-issues/generated/workflow-repair-policy.json +448 -0
- package/skills/engineering/resolve-issues/references/breaker.md +82 -0
- package/skills/engineering/resolve-issues/references/deliverables.md +27 -0
- package/skills/engineering/resolve-issues/references/delivery.md +108 -0
- package/skills/engineering/resolve-issues/references/evidence-lane.md +21 -0
- package/skills/engineering/resolve-issues/references/exact-head-ci.md +287 -0
- package/skills/engineering/resolve-issues/references/fan-out.md +33 -0
- package/skills/engineering/resolve-issues/references/finalization.md +68 -0
- package/skills/engineering/resolve-issues/references/guarantees.md +10 -0
- package/skills/engineering/resolve-issues/references/high-risk.md +29 -0
- package/skills/engineering/resolve-issues/references/incidents/848/README.md +156 -0
- package/skills/engineering/resolve-issues/references/intake.md +86 -0
- package/skills/engineering/resolve-issues/references/integration-gate.md +53 -0
- package/skills/engineering/resolve-issues/references/interference.md +87 -0
- package/skills/engineering/resolve-issues/references/loop.md +134 -0
- package/skills/engineering/resolve-issues/references/model-catalog.md +9 -0
- package/skills/engineering/resolve-issues/references/postmortem.md +27 -0
- package/skills/engineering/resolve-issues/references/pre-flight-model-slots.md +41 -0
- package/skills/engineering/resolve-issues/references/pre-flight-recording-and-checkout.md +48 -0
- package/skills/engineering/resolve-issues/references/pre-flight.md +41 -0
- package/skills/engineering/resolve-issues/references/regression-checklist.md +26 -0
- package/skills/engineering/resolve-issues/references/run-state.md +288 -0
- package/skills/engineering/resolve-issues/references/sandboxed-testing.md +48 -0
- package/skills/engineering/resolve-issues/references/spawn-contract.md +96 -0
- package/skills/engineering/resolve-issues/references/terminal-evidence-journal.md +40 -0
- package/skills/engineering/resolve-issues/references/why.md +653 -0
- package/skills/engineering/resolve-issues/schemas/fix-round.schema.json +49 -0
- package/skills/engineering/resolve-issues/scripts/combine-and-verify.mjs +721 -0
- package/skills/engineering/resolve-issues/scripts/component-candidate.mjs +962 -0
- package/skills/engineering/resolve-issues/scripts/contract-revision.mjs +220 -0
- package/skills/engineering/resolve-issues/scripts/detect-delivery-mode.mjs +420 -0
- package/skills/engineering/resolve-issues/scripts/detect-target-branch.mjs +256 -0
- package/skills/engineering/resolve-issues/scripts/detect-workspace-mode.mjs +168 -0
- package/skills/engineering/resolve-issues/scripts/discover-models.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/doctrine.mjs +62 -0
- package/skills/engineering/resolve-issues/scripts/evidence-lifecycle-contract.mjs +191 -0
- package/skills/engineering/resolve-issues/scripts/exact-head-ci.mjs +413 -0
- package/skills/engineering/resolve-issues/scripts/exact-head-github-provider.mjs +332 -0
- package/skills/engineering/resolve-issues/scripts/finalize.mjs +488 -0
- package/skills/engineering/resolve-issues/scripts/fix-rounds.mjs +3307 -0
- package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-circular-1001.json +16 -0
- package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-valid-sequencing.json +51 -0
- package/skills/engineering/resolve-issues/scripts/fixtures/fmm-express-830-component-candidate.json +17 -0
- package/skills/engineering/resolve-issues/scripts/fixtures/head-check-set-1081.json +166 -0
- package/skills/engineering/resolve-issues/scripts/gate-value-series.mjs +92 -0
- package/skills/engineering/resolve-issues/scripts/guide-index.mjs +73 -0
- package/skills/engineering/resolve-issues/scripts/head-check-set.mjs +159 -0
- package/skills/engineering/resolve-issues/scripts/interference.mjs +427 -0
- package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/next-operations.mjs +419 -0
- package/skills/engineering/resolve-issues/scripts/postmortem.mjs +909 -0
- package/skills/engineering/resolve-issues/scripts/preflight-questions.mjs +322 -0
- package/skills/engineering/resolve-issues/scripts/reconcile-contained-unit-prs.mjs +415 -0
- package/skills/engineering/resolve-issues/scripts/release-state-contract.mjs +697 -0
- package/skills/engineering/resolve-issues/scripts/report.mjs +494 -0
- package/skills/engineering/resolve-issues/scripts/required-check-plan.mjs +172 -0
- package/skills/engineering/resolve-issues/scripts/round-metadata.mjs +79 -0
- package/skills/engineering/resolve-issues/scripts/run-state-review6-cases.mjs +334 -0
- package/skills/engineering/resolve-issues/scripts/run-state.mjs +4784 -0
- package/skills/engineering/resolve-issues/scripts/sandbox-selftest.mjs +395 -0
- package/skills/engineering/resolve-issues/scripts/spawn-contract.mjs +290 -0
- package/skills/engineering/resolve-issues/scripts/terminal-dispositions.mjs +170 -0
- package/skills/engineering/resolve-issues/scripts/terminal-evidence-journal.mjs +293 -0
- package/skills/engineering/resolve-issues/scripts/unit-kind.mjs +197 -0
- package/skills/engineering/resolve-issues/scripts/unit-lifecycle.mjs +127 -0
- package/skills/engineering/resolve-issues/scripts/watch-delivery.mjs +893 -0
- package/skills/engineering/resolve-issues/scripts/workspaces.mjs +829 -0
- package/skills/engineering/resolve-issues/workflows/independent-review.workflow.js +290 -0
- package/skills/engineering/resolve-issues/workflows/prior-art-scan.workflow.js +80 -0
- package/skills/engineering/resolve-issues/workflows/workflow-smoke.mjs +102 -0
- package/skills/engineering/resolve-release/LICENSE +3 -0
- package/skills/engineering/resolve-release/SKILL.md +112 -0
- package/skills/engineering/resolve-release/references/assembly.md +137 -0
- package/skills/engineering/resolve-release/references/auto-when-green.md +56 -0
- package/skills/engineering/resolve-release/references/candidate.md +167 -0
- package/skills/engineering/resolve-release/references/exposure.md +178 -0
- package/skills/engineering/resolve-release/references/handoff.md +24 -0
- package/skills/engineering/resolve-release/references/postmortem.md +230 -0
- package/skills/engineering/resolve-release/references/preflight.md +207 -0
- package/skills/engineering/resolve-release/references/principles.md +94 -0
- package/skills/engineering/resolve-release/references/regression-checklist.md +36 -0
- package/skills/engineering/resolve-release/references/related-skills.md +12 -0
- package/skills/engineering/resolve-release/references/routing.md +149 -0
- package/skills/engineering/resolve-release/references/verified-sha-github-flow.md +285 -0
- package/skills/engineering/resolve-release/references/versioning.md +202 -0
- package/skills/engineering/resolve-release/references/why.md +53 -0
- package/skills/engineering/resolve-release/scripts/adapter-completion-artifact.mjs +389 -0
- package/skills/engineering/resolve-release/scripts/build-changes.mjs +209 -0
- package/skills/engineering/resolve-release/scripts/candidate-hygiene.mjs +407 -0
- package/skills/engineering/resolve-release/scripts/candidate-identity.mjs +904 -0
- package/skills/engineering/resolve-release/scripts/candidate-traffic.mjs +81 -0
- package/skills/engineering/resolve-release/scripts/checked-adapter-loader.mjs +612 -0
- package/skills/engineering/resolve-release/scripts/close-attempt.mjs +135 -0
- package/skills/engineering/resolve-release/scripts/closeout-release.mjs +161 -0
- package/skills/engineering/resolve-release/scripts/doctrine.mjs +106 -0
- package/skills/engineering/resolve-release/scripts/durable-processing.mjs +522 -0
- package/skills/engineering/resolve-release/scripts/ensure-target-green.mjs +659 -0
- package/skills/engineering/resolve-release/scripts/evidence-bundle.mjs +1014 -0
- package/skills/engineering/resolve-release/scripts/finalize-release.mjs +526 -0
- package/skills/engineering/resolve-release/scripts/fixtures/durable-processing-adapter.mjs +169 -0
- package/skills/engineering/resolve-release/scripts/green-gate.mjs +599 -0
- package/skills/engineering/resolve-release/scripts/isolated-adapter-evaluator.mjs +752 -0
- package/skills/engineering/resolve-release/scripts/metadata-pr-status.mjs +56 -0
- package/skills/engineering/resolve-release/scripts/metadata-sync.mjs +1538 -0
- package/skills/engineering/resolve-release/scripts/postmortem.mjs +381 -0
- package/skills/engineering/resolve-release/scripts/preflight-probes.mjs +498 -0
- package/skills/engineering/resolve-release/scripts/production-endpoints.mjs +326 -0
- package/skills/engineering/resolve-release/scripts/rc-circuit-breaker.mjs +272 -0
- package/skills/engineering/resolve-release/scripts/report.mjs +417 -0
- package/skills/engineering/resolve-release/scripts/reprobe-credentials.mjs +114 -0
- package/skills/engineering/resolve-release/scripts/revalidate-candidate.mjs +238 -0
- package/skills/engineering/resolve-release/scripts/review-packet.mjs +503 -0
- package/skills/engineering/resolve-release/scripts/rollback-floor.mjs +263 -0
- package/skills/engineering/resolve-release/scripts/version-assert.mjs +339 -0
- package/skills/engineering/resolve-release/scripts/version-postmortem.mjs +485 -0
- package/skills/engineering/resolve-release/scripts/version.mjs +1199 -0
- package/skills/engineering/resolve-release/scripts/watch-candidate-delivery.mjs +449 -0
- package/skills/engineering/resolve-release/vendor/ACORN-LICENSE +21 -0
- package/skills/engineering/resolve-release/vendor/README.md +60 -0
- package/skills/engineering/resolve-release/vendor/acorn.mjs +6233 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/LICENSE +21 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/README.md +341 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/README.template.md +70 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs +7 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.mts +2033 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.ts +2033 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js +7 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/core/package.json +49 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/LICENSE +21 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/README.md +5 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.mts +549 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.ts +549 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/package.json +36 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/LICENSE +47 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/README.md +82 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.d.ts +11 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.mjs +22 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cjs +21 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.cjs +21 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.d.ts +11 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.d.ts +11 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.mjs +25 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.wasm +0 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.mts +85 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.ts +85 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.mts +20 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.ts +20 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs +2 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs.map +1 -0
- package/skills/engineering/resolve-release/vendor/quickjs/release-sync/package.json +61 -0
- package/skills/engineering/review-pr/LICENSE +3 -0
- package/skills/engineering/review-pr/SKILL.md +123 -0
- package/skills/engineering/review-pr/references/adversarial-reviewer-prompt.md +42 -0
- package/skills/engineering/review-pr/references/code-correctness.md +5 -0
- package/skills/engineering/review-pr/references/contract-freshness.md +9 -0
- package/skills/engineering/review-pr/references/coordination.md +18 -0
- package/skills/engineering/review-pr/references/domain-hazards.md +123 -0
- package/skills/engineering/review-pr/references/finding-themes.md +7 -0
- package/skills/engineering/review-pr/references/github-posting.md +98 -0
- package/skills/engineering/review-pr/references/golden-path-smoke.md +5 -0
- package/skills/engineering/review-pr/references/incremental-output.md +16 -0
- package/skills/engineering/review-pr/references/inputs-and-discovery.md +31 -0
- package/skills/engineering/review-pr/references/output-format.md +99 -0
- package/skills/engineering/review-pr/references/over-mock-screen.md +7 -0
- package/skills/engineering/review-pr/references/promotion-prs.md +16 -0
- package/skills/engineering/review-pr/references/re-review.md +18 -0
- package/skills/engineering/review-pr/references/review-method.md +199 -0
- package/skills/engineering/review-pr/references/review-mode.md +30 -0
- package/skills/engineering/review-pr/references/review-posture.md +53 -0
- package/skills/engineering/review-pr/references/round1-depth.md +62 -0
- package/skills/engineering/review-pr/references/scripts.md +17 -0
- package/skills/engineering/review-pr/references/workflow.md +16 -0
- package/skills/engineering/review-pr/schemas/findings.schema.json +282 -0
- package/skills/engineering/review-pr/scripts/finding-contract.mjs +285 -0
- package/skills/engineering/review-pr/scripts/post-review.mjs +405 -0
- package/skills/engineering/review-pr/scripts/pr-context.mjs +207 -0
- package/skills/engineering/review-pr/scripts/scan-diff.mjs +365 -0
- package/skills/engineering/review-pr/scripts/theme-contract.mjs +57 -0
- package/skills/engineering/smoke/LICENSE +3 -0
- package/skills/engineering/smoke/SKILL.md +131 -0
- package/skills/engineering/smoke/assets/smoke.manifest.example.json +53 -0
- package/skills/engineering/smoke/references/manifest.md +192 -0
- package/skills/engineering/smoke/scripts/smoke.mjs +713 -0
- package/skills/fullstack/better-auth/LICENSE +3 -0
- package/skills/fullstack/better-auth/SKILL.md +601 -0
- package/skills/fullstack/better-auth/references/feishu-api.md +270 -0
- package/skills/fullstack/monorepo/LICENSE +3 -0
- package/skills/fullstack/monorepo/SKILL.md +465 -0
- package/skills/fullstack/nextjs-fullstack/LICENSE +3 -0
- package/skills/fullstack/nextjs-fullstack/SKILL.md +210 -0
- package/skills/fullstack/nextjs-fullstack/conventions.md +318 -0
- package/skills/fullstack/nextjs-fullstack/frontend-conventions.md +61 -0
- package/skills/fullstack/nextjs-fullstack/nextjs16.md +287 -0
- package/skills/fullstack/nextjs-fullstack/server-actions.md +409 -0
- package/skills/fullstack/prisma-setup/LICENSE +3 -0
- package/skills/fullstack/prisma-setup/SKILL.md +180 -0
- package/skills/fullstack/prisma-setup/nextjs.md +258 -0
- package/skills/fullstack/prisma-setup/turborepo.md +301 -0
- package/skills/fullstack/shadcn/LICENSE +3 -0
- package/skills/fullstack/shadcn/SKILL.md +119 -0
- package/skills/fullstack/shadcn/assets/shadcn-small.png +0 -0
- package/skills/fullstack/shadcn/assets/shadcn.png +0 -0
- package/skills/fullstack/shadcn/cli.md +411 -0
- package/skills/fullstack/shadcn/customization.md +224 -0
- package/skills/fullstack/shadcn/evals/evals.json +90 -0
- package/skills/fullstack/shadcn/mcp.md +101 -0
- package/skills/fullstack/shadcn/rules/base-vs-radix.md +323 -0
- package/skills/fullstack/shadcn/rules/component-selection.md +67 -0
- package/skills/fullstack/shadcn/rules/composition.md +195 -0
- package/skills/fullstack/shadcn/rules/data-table.md +201 -0
- package/skills/fullstack/shadcn/rules/forms.md +255 -0
- package/skills/fullstack/shadcn/rules/icons.md +103 -0
- package/skills/fullstack/shadcn/rules/styling.md +167 -0
- package/skills/fullstack/zod-v4/LICENSE +3 -0
- package/skills/fullstack/zod-v4/SKILL.md +287 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# Playwright in CI Containers (the preferred default)
|
|
2
|
+
|
|
3
|
+
**Running Playwright in the official pinned container is the preferred way to run
|
|
4
|
+
every CI browser job** — not a fallback for special runners. Two sanctioned
|
|
5
|
+
options, in order:
|
|
6
|
+
|
|
7
|
+
1. **Docker (preferred):** the job runs in `mcr.microsoft.com/playwright:<version>`
|
|
8
|
+
— GitHub-hosted via `container:`, self-hosted via explicit `docker run` (below),
|
|
9
|
+
Cloud Build via the step's `name:`. Browsers and OS deps ship in the image, so
|
|
10
|
+
there is **no per-job `playwright install`**, the rendering environment is **pinned
|
|
11
|
+
and identical** across jobs and machines (what makes visual baselines viable), and
|
|
12
|
+
a version bump is one tag edit.
|
|
13
|
+
2. **Plain runner (alternative):** `ubuntu-latest` + `npx playwright install
|
|
14
|
+
--with-deps chromium` per job. Acceptable for a simple repo, but it re-downloads
|
|
15
|
+
browsers every job (cache `~/.cache/ms-playwright` if you keep this) and the
|
|
16
|
+
rendering environment drifts with the runner image. Prefer option 1.
|
|
17
|
+
|
|
18
|
+
The `ci-gates.*` templates default to option 1; `ci-audit.mjs` reports the pinned
|
|
19
|
+
container as a *preferred* convention (advisory — option 2 stays sanctioned).
|
|
20
|
+
**Keep every image pin in a workflow identical**, matching the repo's
|
|
21
|
+
`@playwright/test` version.
|
|
22
|
+
|
|
23
|
+
Also use this reference on self-hosted Docker/Podman runners, an intentionally
|
|
24
|
+
minimal runner image, or when CI fails with a browser shared-library error:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
error while loading shared libraries: libnspr4.so
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
That failure usually means Playwright is running directly in the runner
|
|
31
|
+
container/host image — the official GitHub runner image is not a browser runtime
|
|
32
|
+
and lacks Chromium dependencies. Do not fix it by installing random packages every
|
|
33
|
+
job. Put the Playwright job in the official Playwright container, and let the app
|
|
34
|
+
repo install its matching `@playwright/test` version via its package manager.
|
|
35
|
+
|
|
36
|
+
## Standard GitHub Actions Pattern
|
|
37
|
+
|
|
38
|
+
Prefer a normal self-hosted job that runs the official Playwright image manually
|
|
39
|
+
with `docker run`. On rootless Podman-backed GitHub runners, native Actions
|
|
40
|
+
`container:` jobs can fail before checkout because the runner auto-bind-mounts
|
|
41
|
+
`/var/run/docker.sock` into the job container:
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
Error response from daemon: container create: statfs /var/run/docker.sock: permission denied
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
That is runner/daemon plumbing, not a Playwright or app failure. The manual
|
|
48
|
+
`docker run` pattern below keeps checkout and Actions setup on the runner, runs the
|
|
49
|
+
browser work inside the Playwright image, and avoids mounting the Docker socket
|
|
50
|
+
into the Playwright container.
|
|
51
|
+
|
|
52
|
+
```yaml
|
|
53
|
+
jobs:
|
|
54
|
+
e2e:
|
|
55
|
+
runs-on: [self-hosted, linux, x64, docker]
|
|
56
|
+
timeout-minutes: 10
|
|
57
|
+
|
|
58
|
+
env:
|
|
59
|
+
E2E_WORKERS: "4"
|
|
60
|
+
PLAYWRIGHT_IMAGE: mcr.microsoft.com/playwright:v1.61.0-noble
|
|
61
|
+
|
|
62
|
+
steps:
|
|
63
|
+
- uses: actions/checkout@v4
|
|
64
|
+
- name: Run Playwright in the official image
|
|
65
|
+
run: |
|
|
66
|
+
docker run --rm \
|
|
67
|
+
--network host \
|
|
68
|
+
--ipc=host \
|
|
69
|
+
--cpus 4 \
|
|
70
|
+
--memory 16g \
|
|
71
|
+
-e CI=true \
|
|
72
|
+
-e E2E_WORKERS="${E2E_WORKERS}" \
|
|
73
|
+
-v "${GITHUB_WORKSPACE}:/work:z" \
|
|
74
|
+
-w /work \
|
|
75
|
+
"${PLAYWRIGHT_IMAGE}" \
|
|
76
|
+
bash -lc 'corepack enable && pnpm install --frozen-lockfile && pnpm exec playwright test'
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Choose the image tag to match the repo's `@playwright/test` version. If the
|
|
80
|
+
package version and image version differ, install the matching browsers inside
|
|
81
|
+
the Playwright container before the run:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pnpm exec playwright install chromium
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Prefer matching versions instead. It avoids network installs and prevents
|
|
88
|
+
browser/protocol mismatch failures.
|
|
89
|
+
|
|
90
|
+
## Native `container:` Jobs
|
|
91
|
+
|
|
92
|
+
Use native Actions `container:` only after the runner fleet has a passing smoke
|
|
93
|
+
test for GitHub's generated job-container mounts, including the automatic
|
|
94
|
+
`/var/run/docker.sock` bind. Useful on a compatible Docker runner, but not the
|
|
95
|
+
portable default for rootless Podman-backed runner containers.
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
container:
|
|
99
|
+
image: mcr.microsoft.com/playwright:v1.61.0-noble
|
|
100
|
+
options: --user 1001 --ipc=host --cpus 4 --memory 16g
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
If a native job-container workflow fails in `Initialize containers`, do not debug
|
|
104
|
+
application code or Playwright first. Read the generated `docker create` line in
|
|
105
|
+
the job log and verify every auto-mounted host path exists and can be `statfs`'d by
|
|
106
|
+
the daemon.
|
|
107
|
+
|
|
108
|
+
## Resource Envelope and Workers
|
|
109
|
+
|
|
110
|
+
Document the intended per-job resource envelope and make the Playwright container
|
|
111
|
+
enforce it. In the 1aboveio runner setup each slot is sized `4 CPU / 16 GB`, so
|
|
112
|
+
Playwright jobs use `--cpus 4`, `--memory 16g`, `--ipc=host`, and:
|
|
113
|
+
|
|
114
|
+
```yaml
|
|
115
|
+
env:
|
|
116
|
+
E2E_WORKERS: "4"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The runner container's compose limits do not reliably cap sibling job containers
|
|
120
|
+
created through the Docker/Podman socket. Put `--cpus`/`--memory` on the Playwright
|
|
121
|
+
`docker run` or native job container when you need deterministic limits.
|
|
122
|
+
|
|
123
|
+
Start with 4 Playwright workers for Chromium E2E on a `4 CPU / 16 GB` job. If the
|
|
124
|
+
app server is heavy, the suite launches multiple browser contexts per test, or CI
|
|
125
|
+
shows OOM/browser crashes under concurrent jobs, reduce PR-lane workers to 2 and
|
|
126
|
+
reserve 4 for manual/nightly/integration-lane runs. The Playwright config reads the
|
|
127
|
+
env rather than hardcoding:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
// `|| 4`, not `?? 4`: an empty/garbage E2E_WORKERS must fall back too
|
|
131
|
+
// (Number('') is 0, which Playwright rejects).
|
|
132
|
+
workers: process.env.CI ? Number(process.env.E2E_WORKERS) || 4 : undefined,
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Service Containers
|
|
136
|
+
|
|
137
|
+
With the recommended manual `docker run` pattern the Actions job does not use
|
|
138
|
+
`jobs.<job>.container`, so GitHub service containers publish dynamic ports to the
|
|
139
|
+
runner host. Run the Playwright container with `--network host` and connect through
|
|
140
|
+
`127.0.0.1:${{ job.services.<name>.ports[...] }}`:
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
jobs:
|
|
144
|
+
e2e:
|
|
145
|
+
runs-on: [self-hosted, linux, x64, docker]
|
|
146
|
+
timeout-minutes: 10
|
|
147
|
+
|
|
148
|
+
services:
|
|
149
|
+
postgres:
|
|
150
|
+
image: postgres:17
|
|
151
|
+
env:
|
|
152
|
+
POSTGRES_USER: test
|
|
153
|
+
POSTGRES_PASSWORD: test
|
|
154
|
+
POSTGRES_DB: app
|
|
155
|
+
ports:
|
|
156
|
+
- 5432/tcp
|
|
157
|
+
options: >-
|
|
158
|
+
--health-cmd pg_isready
|
|
159
|
+
--health-interval 10s
|
|
160
|
+
--health-timeout 5s
|
|
161
|
+
--health-retries 5
|
|
162
|
+
|
|
163
|
+
env:
|
|
164
|
+
PLAYWRIGHT_IMAGE: mcr.microsoft.com/playwright:v1.61.0-noble
|
|
165
|
+
E2E_WORKERS: "4"
|
|
166
|
+
DATABASE_URL: "postgresql://test:test@127.0.0.1:${{ job.services.postgres.ports[5432] }}/app"
|
|
167
|
+
|
|
168
|
+
steps:
|
|
169
|
+
- uses: actions/checkout@v4
|
|
170
|
+
- name: Run Playwright in the official image
|
|
171
|
+
run: |
|
|
172
|
+
docker run --rm \
|
|
173
|
+
--network host \
|
|
174
|
+
--ipc=host \
|
|
175
|
+
--cpus 4 \
|
|
176
|
+
--memory 16g \
|
|
177
|
+
-e CI=true \
|
|
178
|
+
-e E2E_WORKERS="${E2E_WORKERS}" \
|
|
179
|
+
-e DATABASE_URL="${DATABASE_URL}" \
|
|
180
|
+
-v "${GITHUB_WORKSPACE}:/work:z" \
|
|
181
|
+
-w /work \
|
|
182
|
+
"${PLAYWRIGHT_IMAGE}" \
|
|
183
|
+
bash -lc 'corepack enable && pnpm install --frozen-lockfile && pnpm prisma:migrate:deploy && pnpm exec playwright test'
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
GitHub Actions networking changes when `jobs.<job>.container` is present: service
|
|
187
|
+
containers are on the same Docker/Podman network as the job container. Reach them by
|
|
188
|
+
service label and container port:
|
|
189
|
+
|
|
190
|
+
```yaml
|
|
191
|
+
jobs:
|
|
192
|
+
e2e:
|
|
193
|
+
runs-on: [self-hosted, linux, x64, docker]
|
|
194
|
+
container:
|
|
195
|
+
image: mcr.microsoft.com/playwright:v1.61.0-noble
|
|
196
|
+
options: --user 1001 --ipc=host --cpus 4 --memory 16g
|
|
197
|
+
|
|
198
|
+
services:
|
|
199
|
+
postgres:
|
|
200
|
+
image: postgres:17
|
|
201
|
+
env:
|
|
202
|
+
POSTGRES_USER: test
|
|
203
|
+
POSTGRES_PASSWORD: test
|
|
204
|
+
POSTGRES_DB: app
|
|
205
|
+
options: >-
|
|
206
|
+
--health-cmd pg_isready
|
|
207
|
+
--health-interval 10s
|
|
208
|
+
--health-timeout 5s
|
|
209
|
+
--health-retries 5
|
|
210
|
+
|
|
211
|
+
env:
|
|
212
|
+
DATABASE_URL: postgresql://test:test@postgres:5432/app
|
|
213
|
+
|
|
214
|
+
steps:
|
|
215
|
+
- uses: actions/checkout@v4
|
|
216
|
+
- run: pnpm install --frozen-lockfile
|
|
217
|
+
- run: pnpm prisma:migrate:deploy
|
|
218
|
+
- run: pnpm exec playwright test
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Without a native job container, workflow steps run directly in the runner
|
|
222
|
+
environment; reach services through the mapped localhost port:
|
|
223
|
+
|
|
224
|
+
```yaml
|
|
225
|
+
DATABASE_URL: "postgresql://test:test@127.0.0.1:${{ job.services.postgres.ports[5432] }}/app"
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Do not mix the two models. A Playwright job container using
|
|
229
|
+
`127.0.0.1:${{ job.services.postgres.ports[5432] }}` will often fail because
|
|
230
|
+
`127.0.0.1` is the job container itself, not the host namespace where the port was
|
|
231
|
+
published.
|
|
232
|
+
|
|
233
|
+
## Self-Hosted Docker/Podman Runner Checks
|
|
234
|
+
|
|
235
|
+
Before blaming Playwright, verify the runner can create sibling job/service
|
|
236
|
+
containers. A rootless Podman-backed runner container needs: the Podman socket
|
|
237
|
+
mounted; `DOCKER_HOST=unix:///run/user/<uid>/podman/podman.sock`; user/group mapping
|
|
238
|
+
that can read the socket; SELinux labels disabled for the socket mount on SELinux
|
|
239
|
+
hosts. Equivalent smoke checks:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
# Runner container can reach the Docker-compatible Podman API.
|
|
243
|
+
docker ps
|
|
244
|
+
|
|
245
|
+
# A service container can publish a dynamic localhost port.
|
|
246
|
+
docker run -d --name pg-smoke \
|
|
247
|
+
-e POSTGRES_USER=test \
|
|
248
|
+
-e POSTGRES_PASSWORD=test \
|
|
249
|
+
-e POSTGRES_DB=testdb \
|
|
250
|
+
-p 127.0.0.1::5432 \
|
|
251
|
+
postgres:17
|
|
252
|
+
port="$(docker port pg-smoke 5432/tcp | sed 's/.*://')"
|
|
253
|
+
docker run --rm --network host postgres:17 \
|
|
254
|
+
pg_isready -h 127.0.0.1 -p "$port" -U test
|
|
255
|
+
docker rm -f pg-smoke
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
When this smoke passes but Playwright still fails with missing shared libraries,
|
|
259
|
+
the workflow is running Playwright in the wrong container. Move the Playwright steps
|
|
260
|
+
into the official Playwright image through `docker run` instead of adding browser
|
|
261
|
+
dependencies to the runner image.
|
|
262
|
+
|
|
263
|
+
## Review Checklist
|
|
264
|
+
|
|
265
|
+
When reviewing/writing CI for Playwright on self-hosted Docker runners:
|
|
266
|
+
|
|
267
|
+
- Playwright job runs `mcr.microsoft.com/playwright:<matching-version>-noble` through
|
|
268
|
+
explicit `docker run`, unless the fleet has proven native `container:` support.
|
|
269
|
+
- A native `container:` job failing `Initialize containers` with
|
|
270
|
+
`statfs /var/run/docker.sock: permission denied` → runner socket auto-mount
|
|
271
|
+
incompatibility; switch to the manual `docker run` pattern.
|
|
272
|
+
- The repo still runs `npm ci`/`pnpm install`; the image supplies browsers and OS
|
|
273
|
+
deps, not the app's node_modules.
|
|
274
|
+
- `@playwright/test` and the image tag are aligned, or the workflow explicitly
|
|
275
|
+
installs matching browsers.
|
|
276
|
+
- Manual `docker run` + `services.postgres`: `DATABASE_URL` uses
|
|
277
|
+
`${{ job.services.postgres.ports[5432] }}` on `127.0.0.1`, Playwright container uses
|
|
278
|
+
`--network host`. Native job container + `services.postgres`: `DATABASE_URL` uses
|
|
279
|
+
`postgres:5432`, not `127.0.0.1:<mapped-port>`.
|
|
280
|
+
- The runner setup has a smoke check proving sibling service containers work.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Debugging E2E Failures
|
|
2
|
+
|
|
3
|
+
## Quick Triage
|
|
4
|
+
|
|
5
|
+
1. Check the PR comment for which tests failed and why
|
|
6
|
+
2. Check the GH Actions run log (link in PR comment)
|
|
7
|
+
3. Download artifacts: `test-results/` and `playwright-report/`
|
|
8
|
+
|
|
9
|
+
## Common Failures
|
|
10
|
+
|
|
11
|
+
| Symptom | Cause | Fix |
|
|
12
|
+
|---------|-------|-----|
|
|
13
|
+
| Timeout waiting for selector | Page didn't load or element renamed | Check service URL reachable; run test locally |
|
|
14
|
+
| `ERR_TOO_MANY_REDIRECTS` | Auth cookie/secret mismatch | Verify E2E secrets match deployed service |
|
|
15
|
+
| `reference is not a tree` | Short SHA passed to checkout | Use full 40-char commit SHA or branch name |
|
|
16
|
+
| `ERR_CONNECTION_REFUSED` | Service not ready at test start | Add health-check wait loop before tests |
|
|
17
|
+
| Flaky pass/fail | `waitForTimeout` or shared state | Replace with explicit waits; isolate tests |
|
|
18
|
+
|
|
19
|
+
## Viewing Playwright Report Locally
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Download artifacts from GH Actions, then:
|
|
23
|
+
npx playwright show-report path/to/playwright-report
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Re-running Failed Tests
|
|
27
|
+
|
|
28
|
+
From GH Actions UI: click "Re-run failed jobs."
|
|
29
|
+
|
|
30
|
+
Or trigger manually:
|
|
31
|
+
```bash
|
|
32
|
+
gh workflow run e2e.yml --repo 1aboveio/<repo> \
|
|
33
|
+
-f environment=dev \
|
|
34
|
+
-f service_url=https://<service>.run.app \
|
|
35
|
+
-f sha=<commit>
|
|
36
|
+
```
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Presentation Sweep (the third coverage axis)
|
|
2
|
+
|
|
3
|
+
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 — see ensure-coverage `references/presentation/runner-contract.md`).
|
|
4
|
+
|
|
5
|
+
**It is a separate gate from the functional/journey suite, even though both use Playwright.** A passing functional E2E run is not the presentation gate.
|
|
6
|
+
|
|
7
|
+
## Instruments (import into a spec, or use the sweep)
|
|
8
|
+
|
|
9
|
+
| Level | Spine? | Instrument | Catches |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| `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) |
|
|
12
|
+
| `presentation:spatial` | | `scripts/presentation-checks.mjs` | horizontal overflow / element overlap |
|
|
13
|
+
| `presentation:perceivability` | | `scripts/presentation-perceivability.mjs` | contrast / invisible-but-present controls |
|
|
14
|
+
| `presentation:reachability` | | `scripts/presentation-reachability.mjs` | nav orphans / missing affordance cues |
|
|
15
|
+
| `presentation:temporal` | | `scripts/presentation-temporal.mjs` | layout shift |
|
|
16
|
+
| `presentation:visual` | | `scripts/presentation-visual.mjs` (Playwright `toHaveScreenshot()`) | **opt-in** pixel drift from a committed baseline — restyle/wrong-content/visually-broken |
|
|
17
|
+
|
|
18
|
+
Per-route spec usage (tag it so the Coverage Ledger resolves it):
|
|
19
|
+
```ts
|
|
20
|
+
// @covers /tasks
|
|
21
|
+
// @level presentation:render-health
|
|
22
|
+
import { test } from '@playwright/test'
|
|
23
|
+
import { assertRenderHealthy } from '<skill-dir>/scripts/presentation-render-health.mjs'
|
|
24
|
+
|
|
25
|
+
test('/tasks renders without error', async ({ page, baseURL }) => {
|
|
26
|
+
await assertRenderHealthy(page, '/tasks', { origin: baseURL }) // throws on pageerror/console.error/5xx
|
|
27
|
+
})
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## The sweep (mandatory for browser-route changes)
|
|
31
|
+
|
|
32
|
+
Run the whole-manifest sweep — this is the CI gate, not a per-route afterthought:
|
|
33
|
+
```bash
|
|
34
|
+
E2E_AUTH_BYPASS=1 node <skill-dir>/scripts/presentation-sweep.mjs \
|
|
35
|
+
--manifest e2e/route-manifest.json --base-url http://127.0.0.1:3000 \
|
|
36
|
+
--out docs/tests/_generated/presentation-results.json [--fixtures e2e/sweep-fixtures.mjs]
|
|
37
|
+
```
|
|
38
|
+
It exits non-zero on any `fail`/`blocked` and writes the per-`(route, level)` result the ledger consumes.
|
|
39
|
+
|
|
40
|
+
**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."
|
|
41
|
+
|
|
42
|
+
#### "No in-app way to view it" is not blocked
|
|
43
|
+
|
|
44
|
+
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:
|
|
45
|
+
|
|
46
|
+
- **Manifest route → `presentation-sweep.mjs`** (the canonical CI gate above) — the result the ledger and reviewer consume; run it whenever the route is in the manifest.
|
|
47
|
+
- **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."
|
|
48
|
+
- 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.
|
|
49
|
+
|
|
50
|
+
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.
|
|
51
|
+
|
|
52
|
+
## render-health is continuous (mutate-health)
|
|
53
|
+
|
|
54
|
+
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:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { assertHealthyThrough } from '<skill-dir>/scripts/presentation-render-health.mjs'
|
|
58
|
+
import { assertRemovedAfterMutation } from '<skill-dir>/scripts/presentation-perceivability.mjs'
|
|
59
|
+
|
|
60
|
+
// fill + submit, assert durable state changed (the depth journey) AND nothing threw:
|
|
61
|
+
await assertHealthyThrough(page, async () => {
|
|
62
|
+
await page.getByRole('button', { name: 'Delete' }).click()
|
|
63
|
+
await assertRemovedAfterMutation(page, row) // perceivability post-state
|
|
64
|
+
}, { origin: baseURL })
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
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."
|
|
68
|
+
|
|
69
|
+
## Visual regression (`presentation:visual`) — opt-in, CI-only, pinned container
|
|
70
|
+
|
|
71
|
+
The floor levels above auto-apply to every route and assert *structure* (renders, no overflow, perceivable). `presentation:visual` is the **opt-in** level that pins *appearance*: it snapshots the rendered page and fails on drift from a committed baseline — catching the restyle / wrong-content / looks-broken-but-doesn't-throw class the structural levels miss. ensure-coverage owns the contract and the determinism/CI doctrine ([`references/presentation/runner-contract.md`](../../ensure-coverage/references/presentation/runner-contract.md) → "the opt-in `presentation:visual` level"); this file is the runner's operational how-to and does **not** restate those rules.
|
|
72
|
+
|
|
73
|
+
**It is a per-opted-in-surface spec, not part of the whole-manifest sweep.** The sweep (`presentation-sweep.mjs`) opens *every* route for the floor levels; visual runs only for the handful of surfaces that raised `presentation:visual` in their `*.coverage.yml` (`requiredLevels: [presentation:visual]`, with a gated `visual.mask` list). Each gets its own `@visual`-tagged Playwright spec (the `visual-gate` CI job runs `playwright test --grep @visual`), because `toHaveScreenshot()` must execute inside a Playwright test, not a node script. Do **not** hand-roll a differ; baselines, the 3-up diff, masking, and `maxDiffPixelRatio` are native:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
// @covers /dashboard
|
|
77
|
+
// @level presentation:visual
|
|
78
|
+
import { test, expect } from '@playwright/test'
|
|
79
|
+
|
|
80
|
+
test('/dashboard matches visual baseline', async ({ page }) => {
|
|
81
|
+
await page.goto('/dashboard')
|
|
82
|
+
await page.getByRole('heading', { name: /dashboard/i }).waitFor() // gate on a stable condition, never a sleep
|
|
83
|
+
await expect(page).toHaveScreenshot('dashboard-1280.png', {
|
|
84
|
+
mask: [page.getByTestId('last-updated'), page.locator('.avatar')], // gated dynamic regions
|
|
85
|
+
maxDiffPixelRatio: 0.001,
|
|
86
|
+
animations: 'disabled',
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Two operational facts (the *why* is in the contracts):**
|
|
92
|
+
|
|
93
|
+
1. It runs **CI-only, in a pinned Playwright container** for both baseline generation and the gate. The two CI jobs (`visual-gate` blocking, `visual-baseline-regen` on-demand) are templated in `assets/ci-gates.{github.yml,cloudbuild.yaml}`; the determinism rules (animations/clock/seed/mask/threshold) and container rationale live in the runner contract + [`ci-contract.md`](../../ensure-coverage/references/enforcement/ci-contract.md) → "Visual regression jobs". The in-loop hooks never run visual.
|
|
94
|
+
2. After regen, **`scripts/post-visual-evidence.mjs`** upserts a marker-tagged comment to both the source issue and the PR (durable committed-baseline link at the SHA + ephemeral diff-artifact URL) and **returns** the same two URLs as a value — on stdout behind `visual-evidence:`, and to `--evidence-out <file>`. It does **not** write the `resolve-issues` run manifest: the orchestrator records the returned value on the unit, because it is the manifest's only writer (ADR 0001 decision 5 (`docs/adr/0001-interference-is-the-scheduling-primitive.md`)).
|
|
95
|
+
|
|
96
|
+
## Design fidelity (`presentation:fidelity`) — opt-in, one spec per cited design source
|
|
97
|
+
|
|
98
|
+
`presentation:visual` above pins a page against a baseline captured **from itself**, so it detects *drift* and can never detect *being wrong from the start* — a baseline shot of a page that never matched its design is green forever. `presentation:fidelity` is the opt-in level for a surface built from a cited design source (prototype, mockup, layout-fixing doc): it pins the load-bearing properties read off **the source** and fails when the built page disagrees. ensure-coverage owns the doctrine, the manifest format and the catalog ([`references/presentation/axis.md`](../../ensure-coverage/references/presentation/axis.md) → `presentation:fidelity`); this section is only the runner's how-to.
|
|
99
|
+
|
|
100
|
+
**Why a spec and not a node script**: reading `max-width` or a responsive `font-size` step requires a laid-out page at a real viewport, which is a browser. The measuring code is *generated* rather than hand-written — `design-parity.mjs probe` emits it from the manifest, so the spec never drifts from the properties the manifest pins:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
// @covers merchant-dashboard-charge-form
|
|
104
|
+
// @level presentation:fidelity
|
|
105
|
+
import { test, expect } from '@playwright/test'
|
|
106
|
+
import { execFileSync } from 'node:child_process'
|
|
107
|
+
|
|
108
|
+
const MANIFEST = 'docs/design/charge-form.parity.yml'
|
|
109
|
+
const parity = (...args: string[]) =>
|
|
110
|
+
execFileSync('node', [`${process.env.SKILL_DIR}/scripts/design-parity.mjs`, ...args], { encoding: 'utf8' })
|
|
111
|
+
|
|
112
|
+
test('the charge form matches the prototype it was derived from', async ({ page }) => {
|
|
113
|
+
const runs = []
|
|
114
|
+
for (const viewport of [375, 1280]) {
|
|
115
|
+
await page.setViewportSize({ width: viewport, height: 900 })
|
|
116
|
+
await page.goto('/dashboard')
|
|
117
|
+
await page.getByRole('heading', { name: /new payment/i }).waitFor() // a stable condition, never a sleep
|
|
118
|
+
runs.push((await page.evaluate(parity('probe', MANIFEST, '--viewport', String(viewport)))).runs[0])
|
|
119
|
+
}
|
|
120
|
+
fs.writeFileSync('parity-observed.json', JSON.stringify({ runs }))
|
|
121
|
+
// The gate is the script's verdict, not a re-implementation of it here: it also
|
|
122
|
+
// decides manifest completeness and citation resolution, which a spec cannot see.
|
|
123
|
+
expect(() => parity('validate', MANIFEST, '--observed', 'parity-observed.json')).not.toThrow()
|
|
124
|
+
})
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
**Three operational facts:**
|
|
128
|
+
|
|
129
|
+
1. **Both floor viewports in one spec.** A responsive step-up (`24px → 30px`) is the classic silent loss in a hand-port, so the manifest pins scale rows per viewport and the spec must measure at each. Measuring only the default width passes a page that lost the step.
|
|
130
|
+
2. **It runs in the ordinary browser lane**, not the pinned visual container. There are no pixels to compare — computed style is stable across OSes in a way anti-aliasing is not — so it needs no baseline image, no masking, and no `visual-baseline-regen` counterpart.
|
|
131
|
+
3. **Pass `--diff <merge-base>` in CI.** That is what catches an `expected` edited to match the page instead of the page fixed to match the design — the fidelity analogue of a silent `--update-snapshots`, and the failure mode this level is most likely to die of.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Reviewing PRs (E2E coverage)
|
|
2
|
+
|
|
3
|
+
Checklist:
|
|
4
|
+
|
|
5
|
+
- [ ] Route discovery and reachability analysis were run before coverage audit; output is included or summarized
|
|
6
|
+
- [ ] Route manifest regenerated (projection) if routes added/removed; no drift vs the surface inventory
|
|
7
|
+
- [ ] New routes have at least Tier 1 test
|
|
8
|
+
- [ ] Interactive routes have Tier 2 (success + error cases)
|
|
9
|
+
- [ ] Browser-route changes ran the presentation sweep (separate gate); 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 ([review-pr](../../review-pr/SKILL.md) § Verdicts and the blocking bar). Report the route and the error and take `BLOCKED` for that route's obligation; do not convert it into a finding against the diff
|
|
10
|
+
- [ ] No `waitForTimeout()` -- use explicit waits
|
|
11
|
+
- [ ] No CSS class assertions -- test user-visible behavior
|
|
12
|
+
- [ ] **No test skipped or disabled.** The PR adds no `test.skip` / `xit` / `describe.skip`, no conditional 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 (see [authoring/test-skipping.md](authoring/test-skipping.md))
|
|
13
|
+
- [ ] 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
|
|
14
|
+
- [ ] **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
|
|
15
|
+
- [ ] Auth in shared fixtures, not duplicated
|
|
16
|
+
- [ ] Bugfix PRs have regression test covering the exact failure
|
|
17
|
+
- [ ] Tier 3 journeys use real APIs (no mocking internal endpoints)
|
|
18
|
+
- [ ] Do-not-ship golden journeys (sign in → core action → pay) are tagged `@smoke` so the curated smoke gate selects them; a new critical flow with no `@smoke` tag / smoke-manifest entry is a gap
|
|
19
|
+
- [ ] Specs tagged `@covers`/`@level` so the ledger resolves them
|
|
20
|
+
|
|
21
|
+
**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, presentation sweep absent or warn-only 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).
|
|
22
|
+
|
|
23
|
+
**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.
|
|
24
|
+
|
|
25
|
+
**Comment template:**
|
|
26
|
+
```
|
|
27
|
+
### E2E Coverage
|
|
28
|
+
|
|
29
|
+
**Missing:**
|
|
30
|
+
- Route `/new-page` added but not in the surface inventory / route manifest
|
|
31
|
+
- No Tier 2 test for the date filter (need: valid range, invalid range, empty)
|
|
32
|
+
- `/tasks` has no presentation-sweep result (render unproven)
|
|
33
|
+
|
|
34
|
+
**Issues:**
|
|
35
|
+
- `line 42`: Uses `waitForTimeout(3000)` -- replace with `waitForResponse`
|
|
36
|
+
|
|
37
|
+
**Good:**
|
|
38
|
+
- Journey test covers the full flow
|
|
39
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Route Discovery And Reachability Protocol
|
|
2
|
+
|
|
3
|
+
> The framework-specific, executable form of route/surface discovery. `ensure-coverage`'s `references/breadth/surface-discovery.md` holds the same protocol as portable doctrine; this file adds the per-framework enumeration sources and is deliberately self-contained so e2e-test works standalone.
|
|
4
|
+
|
|
5
|
+
Never audit E2E coverage from memory, sampling, or manual file browsing. First produce a deterministic route/endpoint inventory, then verify reachability. Listing route files is not discovery — verify whether each route can actually be reached through layouts, middleware, redirects, guards, rewrites, and route groups. If discovery or reachability can't produce a credible result, mark the audit `BLOCKED` and state what prevented it.
|
|
6
|
+
|
|
7
|
+
Discovery order:
|
|
8
|
+
|
|
9
|
+
1. Run framework-specific discovery scripts when available.
|
|
10
|
+
2. Prefer runtime introspection for backends when the app can start (OpenAPI JSON, framework route registries).
|
|
11
|
+
3. Use static discovery as a fallback and cross-check, not the only source when runtime introspection is available.
|
|
12
|
+
4. For page routes, verify reachability through layout chains, middleware, guards, redirects, rewrites, route groups, and feature flags.
|
|
13
|
+
5. Compare discovered routes/endpoints against the manifest, product journeys, navigation links, design docs, and test files.
|
|
14
|
+
6. Compare changed files against affected routes/endpoints; call out newly added or changed entries.
|
|
15
|
+
|
|
16
|
+
Frontend discovery sources:
|
|
17
|
+
|
|
18
|
+
- Next.js App Router: enumerate `app/**/page.*` and `app/**/route.*`; include route groups, dynamic segments, parallel/intercepting routes, and exported HTTP methods for `route.*`.
|
|
19
|
+
- Next.js Pages Router: `pages/**/*` excluding API files when auditing UI routes; include `pages/api/**/*` when auditing endpoints.
|
|
20
|
+
- React Router: route config files, `createBrowserRouter`, `createRoutesFromElements`, `<Route path=...>`.
|
|
21
|
+
- For each Next.js page route, walk the layout chain from root → route group → segment layout; inspect `layout.*`, `middleware.*`, redirects, `notFound`, auth/session checks, role/tenant guards, feature flags, rewrites, and navigation entry points.
|
|
22
|
+
- Multiple apps (e.g. admin and portal) are discovered separately, with separate manifests.
|
|
23
|
+
|
|
24
|
+
Backend discovery sources:
|
|
25
|
+
|
|
26
|
+
- FastAPI: prefer runtime `app.routes` or `/openapi.json`; fallback to `@router.get/post/put/patch/delete` decorator scan.
|
|
27
|
+
- Express/Nest-style: scan router registration, controller decorators, mounted prefixes, method decorators.
|
|
28
|
+
- Include method + path and auth/permission metadata where available; distinguish health/internal from business endpoints without silently dropping them.
|
|
29
|
+
|
|
30
|
+
Reachability classification:
|
|
31
|
+
|
|
32
|
+
- `Reachable`: request/user can reach the route under documented conditions.
|
|
33
|
+
- `Redirected`: route exists but redirects before page behavior is available.
|
|
34
|
+
- `Guarded`: requires auth, role, tenant, feature flag, or other condition; state it.
|
|
35
|
+
- `Blocked`: exists but cannot be reached in current product flow or environment.
|
|
36
|
+
- `Unknown`: evidence insufficient; do not classify as covered without more inspection.
|
|
37
|
+
|
|
38
|
+
Do not classify a route as covered, missing, or a valid journey solely because a `page.*`/`route.*` file exists — a route file is only a declared route until its guard chain and journey validity are checked.
|
|
39
|
+
|
|
40
|
+
Required audit output:
|
|
41
|
+
|
|
42
|
+
- Discovery method and command/source used.
|
|
43
|
+
- Reachability classification and guard/layout/middleware evidence for relevant routes.
|
|
44
|
+
- Count of discovered routes/endpoints; count of manifest entries.
|
|
45
|
+
- Routes/endpoints missing from manifest; manifest entries not found in code.
|
|
46
|
+
- Uncovered surfaces per the ledger (`coverage-ledger.mjs` status; not a manifest `specs` count).
|
|
47
|
+
- Changed routes/endpoints and their coverage status.
|
|
48
|
+
- Routes that are unreachable, misplaced, stale, missing from the manifest, absent from code, or contradicting PRD/spec claims.
|
|
49
|
+
|
|
50
|
+
Discovery scripts: `scripts/detect-routes-nextjs.mjs`, `scripts/detect-routes-fastapi.py`.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Route Manifest
|
|
2
|
+
|
|
3
|
+
A **generated projection** of ensure-coverage's surface inventory — *not* hand-maintained, and *not* the coverage source of truth (coverage is computed by the ledger from `@covers` annotations). Its job is to be the route list the presentation sweep iterates, plus the E2E `tier`. Generate it so its route set can't drift from the inventory:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
node <skill-dir>/scripts/project-route-manifest.mjs \
|
|
7
|
+
--inventory docs/tests/_generated/surface-inventory.json \
|
|
8
|
+
--overlay e2e/route-manifest.overlay.json --out e2e/route-manifest.json
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`route-manifest.json` is `{ version, generated: true, routes: [{ path, tier }] }`. E2E-only curation lives in a small hand-authored **overlay** (`route-manifest.overlay.json`) — the manifest's analog of ensure-coverage's `*.coverage.yml` deviations:
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"routes": {
|
|
16
|
+
"/dashboard": { "tier": 3 },
|
|
17
|
+
"/legacy-print": { "ignore": true }
|
|
18
|
+
},
|
|
19
|
+
"spatialIgnore": [".sticky-header"]
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`tier` defaults from the inventory's `class` (read→1, detail/mutation→2); the overlay raises it (e.g. a route on a core journey → 3) or `ignore`s a route from the sweep (it still owes its ledger floor). `specs` is optional/informational only — do **not** use it as a coverage signal.
|
|
24
|
+
|
|
25
|
+
The backend `endpoint-manifest.json` is the API analog — likewise a projection of the inventory (`kind === 'api'`), with `method` + `tier`. Endpoint coverage is also the ledger's job, not a `specs` count.
|
|
26
|
+
|
|
27
|
+
## Single source of truth (no drift by construction)
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
detect-routes (one discovery pass)
|
|
31
|
+
│ writes
|
|
32
|
+
▼
|
|
33
|
+
surface-inventory.json ← canonical, generated, ALL surfaces (routes/api/table/event/job)
|
|
34
|
+
│ project-route-manifest.mjs (filter kind===route ⨝ curated overlay)
|
|
35
|
+
▼
|
|
36
|
+
route-manifest.json ← generated projection: the sweep's route list + tier
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- The **inventory** is the source of truth for *obligations* (every surface's `(kind, class)` floor), spanning APIs/tables/events too; the **manifest** is a *derived view* for the E2E runner.
|
|
40
|
+
- Because the manifest is **generated**, its route set cannot drift: regenerate both and `git diff --exit-code` is CI gate #1 (inventory freshness). A new route appears in the inventory (→ ledger obligation) and flows into the manifest (→ sweep) from the *same* discovery pass.
|
|
41
|
+
- Curation (tier, sweep `ignore`) lives only in the small hand-authored overlay; `staleOverlayEntries` warns when the overlay references a route the inventory no longer has.
|
|
42
|
+
- Inventory drives *what is owed*; manifest tracks *what the sweep visits*; the ledger tracks *what is proven* (via `@covers`). Three roles, one generated spine.
|
|
43
|
+
|
|
44
|
+
Scripts: `scripts/project-route-manifest.mjs` (projection), `scripts/validate-manifest.mjs` (entries valid).
|