@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.
Files changed (397) hide show
  1. package/LICENSE +3 -0
  2. package/README.md +90 -0
  3. package/bin/1aboveio-skills.mjs +18 -0
  4. package/package.json +28 -0
  5. package/runtime/skills/distribution/generated/recipes.json +1189 -0
  6. package/runtime/skills/distribution/scripts/bundles.mjs +280 -0
  7. package/runtime/skills/engineering/engineering-runtime/scripts/main-module.mjs +80 -0
  8. package/skills/backend/airflow-dag-develop/LICENSE +3 -0
  9. package/skills/backend/airflow-dag-develop/SKILL.md +111 -0
  10. package/skills/backend/app-debug/LICENSE +3 -0
  11. package/skills/backend/app-debug/SKILL.md +109 -0
  12. package/skills/backend/app-debug/references/common-errors.md +128 -0
  13. package/skills/backend/python-backend/LICENSE +3 -0
  14. package/skills/backend/python-backend/SKILL.md +326 -0
  15. package/skills/cicd-pipeline/cloud-build/LICENSE +3 -0
  16. package/skills/cicd-pipeline/cloud-build/SKILL.md +707 -0
  17. package/skills/cicd-pipeline/cloud-debug/LICENSE +3 -0
  18. package/skills/cicd-pipeline/cloud-debug/SKILL.md +316 -0
  19. package/skills/cicd-pipeline/cloud-debug/references/build-failures.md +238 -0
  20. package/skills/cicd-pipeline/cloud-debug/references/deploy-failures.md +376 -0
  21. package/skills/cicd-pipeline/cloud-debug/references/pipeline-failures.md +378 -0
  22. package/skills/cicd-pipeline/cloud-deploy/LICENSE +3 -0
  23. package/skills/cicd-pipeline/cloud-deploy/SKILL.md +229 -0
  24. package/skills/cicd-pipeline/cloud-deploy/references/config-templates.md +257 -0
  25. package/skills/cicd-pipeline/docker/LICENSE +3 -0
  26. package/skills/cicd-pipeline/docker/SKILL.md +126 -0
  27. package/skills/cicd-pipeline/google-cloud/LICENSE +3 -0
  28. package/skills/cicd-pipeline/google-cloud/SKILL.md +118 -0
  29. package/skills/cicd-pipeline/google-cloud/references/gcs.md +469 -0
  30. package/skills/cicd-pipeline/google-cloud/references/iam.md +451 -0
  31. package/skills/cicd-pipeline/google-cloud/references/project.md +349 -0
  32. package/skills/cicd-pipeline/google-cloud/references/secrets.md +336 -0
  33. package/skills/cicd-pipeline/google-cloud/references/vpc.md +312 -0
  34. package/skills/cicd-pipeline/google-cloud/scripts/create-sa.sh +36 -0
  35. package/skills/cicd-pipeline/google-cloud/scripts/gcp-config.sh +31 -0
  36. package/skills/cicd-pipeline/google-cloud/scripts/grant-iap.sh +41 -0
  37. package/skills/cicd-pipeline/google-cloud/scripts/setup-secrets.sh +48 -0
  38. package/skills/cicd-pipeline/mergify/LICENSE +3 -0
  39. package/skills/cicd-pipeline/mergify/SKILL.md +138 -0
  40. package/skills/cicd-pipeline/mergify/assets/templates/mergify.yml +237 -0
  41. package/skills/cicd-pipeline/mergify/assets/templates/ruleset.json +46 -0
  42. package/skills/cicd-pipeline/mergify/references/branch-protection.md +277 -0
  43. package/skills/cicd-pipeline/mergify/references/configuration.md +183 -0
  44. package/skills/cicd-pipeline/mergify/references/diagnosis.md +73 -0
  45. package/skills/cicd-pipeline/mergify/references/traps.md +78 -0
  46. package/skills/cicd-pipeline/mergify/references/watch-contract.md +218 -0
  47. package/skills/cicd-pipeline/mergify/scripts/audit-core.mjs +131 -0
  48. package/skills/cicd-pipeline/mergify/scripts/audit.mjs +4 -0
  49. package/skills/cicd-pipeline/mergify/scripts/watch-pr-delivery-core.mjs +663 -0
  50. package/skills/cicd-pipeline/mergify/scripts/watch-pr-delivery.mjs +4 -0
  51. package/skills/cicd-pipeline/podman/LICENSE +3 -0
  52. package/skills/cicd-pipeline/podman/SKILL.md +70 -0
  53. package/skills/cicd-pipeline/podman/agents/openai.yaml +4 -0
  54. package/skills/cicd-pipeline/podman/assets/templates/podman-compose-socket-directory.yml +6 -0
  55. package/skills/cicd-pipeline/podman/assets/templates/podman-service-override.conf +3 -0
  56. package/skills/cicd-pipeline/podman/references/compose-compatibility.md +70 -0
  57. package/skills/cicd-pipeline/podman/references/networking-and-ports.md +74 -0
  58. package/skills/cicd-pipeline/podman/references/rootless-services-and-sockets.md +156 -0
  59. package/skills/cicd-pipeline/podman/references/troubleshooting.md +98 -0
  60. package/skills/engineering/e2e-test/LICENSE +3 -0
  61. package/skills/engineering/e2e-test/SKILL.md +156 -0
  62. package/skills/engineering/e2e-test/assets/ci-gates.cloudbuild.yaml +272 -0
  63. package/skills/engineering/e2e-test/assets/ci-gates.github.yml +451 -0
  64. package/skills/engineering/e2e-test/assets/e2e-workflow.yml +282 -0
  65. package/skills/engineering/e2e-test/references/authoring/auth-flows.md +159 -0
  66. package/skills/engineering/e2e-test/references/authoring/playwright-config.md +71 -0
  67. package/skills/engineering/e2e-test/references/authoring/playwright-patterns.md +219 -0
  68. package/skills/engineering/e2e-test/references/authoring/test-skipping.md +44 -0
  69. package/skills/engineering/e2e-test/references/ci-integration.md +121 -0
  70. package/skills/engineering/e2e-test/references/ci-playwright-container.md +280 -0
  71. package/skills/engineering/e2e-test/references/debugging.md +36 -0
  72. package/skills/engineering/e2e-test/references/presentation-sweep.md +131 -0
  73. package/skills/engineering/e2e-test/references/reviewing.md +39 -0
  74. package/skills/engineering/e2e-test/references/route-discovery.md +50 -0
  75. package/skills/engineering/e2e-test/references/route-manifest.md +44 -0
  76. package/skills/engineering/e2e-test/scripts/detect-routes-fastapi.py +290 -0
  77. package/skills/engineering/e2e-test/scripts/detect-routes-nextjs.mjs +200 -0
  78. package/skills/engineering/e2e-test/scripts/post-visual-evidence.mjs +158 -0
  79. package/skills/engineering/e2e-test/scripts/presentation-checks.mjs +171 -0
  80. package/skills/engineering/e2e-test/scripts/presentation-perceivability.mjs +179 -0
  81. package/skills/engineering/e2e-test/scripts/presentation-reachability.mjs +154 -0
  82. package/skills/engineering/e2e-test/scripts/presentation-render-health.mjs +141 -0
  83. package/skills/engineering/e2e-test/scripts/presentation-sweep.mjs +148 -0
  84. package/skills/engineering/e2e-test/scripts/presentation-temporal.mjs +127 -0
  85. package/skills/engineering/e2e-test/scripts/presentation-visual.mjs +84 -0
  86. package/skills/engineering/e2e-test/scripts/project-route-manifest.mjs +75 -0
  87. package/skills/engineering/e2e-test/scripts/validate-manifest.mjs +106 -0
  88. package/skills/engineering/engineering-runtime/LICENSE +3 -0
  89. package/skills/engineering/engineering-runtime/SKILL.md +10 -0
  90. package/skills/engineering/engineering-runtime/agents/openai.yaml +6 -0
  91. package/skills/engineering/engineering-runtime/coherence/workflow.json +553 -0
  92. package/skills/engineering/engineering-runtime/scripts/exact-head-artifact.mjs +131 -0
  93. package/skills/engineering/engineering-runtime/scripts/head-check-set.mjs +398 -0
  94. package/skills/engineering/engineering-runtime/scripts/main-module.mjs +80 -0
  95. package/skills/engineering/engineering-runtime/scripts/mergify-yaml.mjs +11 -0
  96. package/skills/engineering/engineering-runtime/scripts/package-lock.json +43 -0
  97. package/skills/engineering/engineering-runtime/scripts/package.json +10 -0
  98. package/skills/engineering/engineering-runtime/scripts/required-check-plan.mjs +223 -0
  99. package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +576 -0
  100. package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +166 -0
  101. package/skills/engineering/ensure-coverage/LICENSE +3 -0
  102. package/skills/engineering/ensure-coverage/SKILL.md +136 -0
  103. package/skills/engineering/ensure-coverage/evals/evals.json +125 -0
  104. package/skills/engineering/ensure-coverage/references/breadth/coverage-ledger.md +91 -0
  105. package/skills/engineering/ensure-coverage/references/breadth/inventory-contract.md +83 -0
  106. package/skills/engineering/ensure-coverage/references/breadth/surface-baseline.md +44 -0
  107. package/skills/engineering/ensure-coverage/references/breadth/surface-discovery.md +16 -0
  108. package/skills/engineering/ensure-coverage/references/depth/characterization.md +68 -0
  109. package/skills/engineering/ensure-coverage/references/depth/coverage.config.example.json +25 -0
  110. package/skills/engineering/ensure-coverage/references/depth/grading.md +35 -0
  111. package/skills/engineering/ensure-coverage/references/depth/mock-policy.md +87 -0
  112. package/skills/engineering/ensure-coverage/references/depth/test-smells.md +23 -0
  113. package/skills/engineering/ensure-coverage/references/enforcement/ci-contract.md +164 -0
  114. package/skills/engineering/ensure-coverage/references/enforcement/hooks.md +85 -0
  115. package/skills/engineering/ensure-coverage/references/examples/coverage-ledger.md +109 -0
  116. package/skills/engineering/ensure-coverage/references/examples/refund-flow.md +33 -0
  117. package/skills/engineering/ensure-coverage/references/presentation/axis.md +78 -0
  118. package/skills/engineering/ensure-coverage/references/presentation/runner-contract.md +74 -0
  119. package/skills/engineering/ensure-coverage/references/process/audit-mode.md +33 -0
  120. package/skills/engineering/ensure-coverage/references/process/output-template.md +139 -0
  121. package/skills/engineering/ensure-coverage/references/process/review-contract-template.md +119 -0
  122. package/skills/engineering/ensure-coverage/references/process/scope-class.md +178 -0
  123. package/skills/engineering/ensure-coverage/references/process/test-strategy.md +55 -0
  124. package/skills/engineering/ensure-coverage/schemas/coverage-config.schema.json +45 -0
  125. package/skills/engineering/ensure-coverage/schemas/coverage-file.schema.json +93 -0
  126. package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.mjs +178 -0
  127. package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.mjs +101 -0
  128. package/skills/engineering/ensure-coverage/scripts/ci-audit.mjs +358 -0
  129. package/skills/engineering/ensure-coverage/scripts/coverage-checklist.mjs +494 -0
  130. package/skills/engineering/ensure-coverage/scripts/coverage-ledger.mjs +663 -0
  131. package/skills/engineering/ensure-coverage/scripts/design-parity.mjs +591 -0
  132. package/skills/engineering/ensure-coverage/scripts/evidence-block.mjs +367 -0
  133. package/skills/engineering/ensure-coverage/scripts/lint-tests.mjs +269 -0
  134. package/skills/engineering/ensure-coverage/scripts/mock-policy-config.mjs +176 -0
  135. package/skills/engineering/ensure-coverage/scripts/package-lock.json +76 -0
  136. package/skills/engineering/ensure-coverage/scripts/package.json +19 -0
  137. package/skills/engineering/ensure-coverage/scripts/scope-class.mjs +554 -0
  138. package/skills/engineering/harness-runtime/LICENSE +3 -0
  139. package/skills/engineering/harness-runtime/SKILL.md +18 -0
  140. package/skills/engineering/harness-runtime/agents/openai.yaml +6 -0
  141. package/skills/engineering/harness-runtime/bin/discover-models.mjs +4 -0
  142. package/skills/engineering/harness-runtime/bin/model-catalog.mjs +4 -0
  143. package/skills/engineering/harness-runtime/contracts.md +15 -0
  144. package/skills/engineering/harness-runtime/discover-models.mjs +392 -0
  145. package/skills/engineering/harness-runtime/fixtures/native-question-schemas.json +33 -0
  146. package/skills/engineering/harness-runtime/fixtures/question-responses.json +54 -0
  147. package/skills/engineering/harness-runtime/index.mjs +767 -0
  148. package/skills/engineering/harness-runtime/model-catalog.mjs +787 -0
  149. package/skills/engineering/harness-runtime/native-question-contracts.md +37 -0
  150. package/skills/engineering/harness-runtime/references/model-catalog-seed.json +159 -0
  151. package/skills/engineering/harness-runtime/references/model-catalog.md +57 -0
  152. package/skills/engineering/implement-and-pr/LICENSE +3 -0
  153. package/skills/engineering/implement-and-pr/SKILL.md +176 -0
  154. package/skills/engineering/implement-and-pr/references/ci-iteration.md +10 -0
  155. package/skills/engineering/implement-and-pr/references/closeout.md +27 -0
  156. package/skills/engineering/implement-and-pr/references/contract-complete-fix-rounds.md +34 -0
  157. package/skills/engineering/implement-and-pr/references/evidence-rules.md +39 -0
  158. package/skills/engineering/implement-and-pr/references/incremental-plan.md +16 -0
  159. package/skills/engineering/implement-and-pr/references/self-review.md +23 -0
  160. package/skills/engineering/implement-and-pr/references/tdd-mode.md +18 -0
  161. package/skills/engineering/resolve-issues/LICENSE +3 -0
  162. package/skills/engineering/resolve-issues/SKILL.md +167 -0
  163. package/skills/engineering/resolve-issues/generated/workflow-repair-policy.json +448 -0
  164. package/skills/engineering/resolve-issues/references/breaker.md +82 -0
  165. package/skills/engineering/resolve-issues/references/deliverables.md +27 -0
  166. package/skills/engineering/resolve-issues/references/delivery.md +108 -0
  167. package/skills/engineering/resolve-issues/references/evidence-lane.md +21 -0
  168. package/skills/engineering/resolve-issues/references/exact-head-ci.md +287 -0
  169. package/skills/engineering/resolve-issues/references/fan-out.md +33 -0
  170. package/skills/engineering/resolve-issues/references/finalization.md +68 -0
  171. package/skills/engineering/resolve-issues/references/guarantees.md +10 -0
  172. package/skills/engineering/resolve-issues/references/high-risk.md +29 -0
  173. package/skills/engineering/resolve-issues/references/incidents/848/README.md +156 -0
  174. package/skills/engineering/resolve-issues/references/intake.md +86 -0
  175. package/skills/engineering/resolve-issues/references/integration-gate.md +53 -0
  176. package/skills/engineering/resolve-issues/references/interference.md +87 -0
  177. package/skills/engineering/resolve-issues/references/loop.md +134 -0
  178. package/skills/engineering/resolve-issues/references/model-catalog.md +9 -0
  179. package/skills/engineering/resolve-issues/references/postmortem.md +27 -0
  180. package/skills/engineering/resolve-issues/references/pre-flight-model-slots.md +41 -0
  181. package/skills/engineering/resolve-issues/references/pre-flight-recording-and-checkout.md +48 -0
  182. package/skills/engineering/resolve-issues/references/pre-flight.md +41 -0
  183. package/skills/engineering/resolve-issues/references/regression-checklist.md +26 -0
  184. package/skills/engineering/resolve-issues/references/run-state.md +288 -0
  185. package/skills/engineering/resolve-issues/references/sandboxed-testing.md +48 -0
  186. package/skills/engineering/resolve-issues/references/spawn-contract.md +96 -0
  187. package/skills/engineering/resolve-issues/references/terminal-evidence-journal.md +40 -0
  188. package/skills/engineering/resolve-issues/references/why.md +653 -0
  189. package/skills/engineering/resolve-issues/schemas/fix-round.schema.json +49 -0
  190. package/skills/engineering/resolve-issues/scripts/combine-and-verify.mjs +721 -0
  191. package/skills/engineering/resolve-issues/scripts/component-candidate.mjs +962 -0
  192. package/skills/engineering/resolve-issues/scripts/contract-revision.mjs +220 -0
  193. package/skills/engineering/resolve-issues/scripts/detect-delivery-mode.mjs +420 -0
  194. package/skills/engineering/resolve-issues/scripts/detect-target-branch.mjs +256 -0
  195. package/skills/engineering/resolve-issues/scripts/detect-workspace-mode.mjs +168 -0
  196. package/skills/engineering/resolve-issues/scripts/discover-models.mjs +9 -0
  197. package/skills/engineering/resolve-issues/scripts/doctrine.mjs +62 -0
  198. package/skills/engineering/resolve-issues/scripts/evidence-lifecycle-contract.mjs +191 -0
  199. package/skills/engineering/resolve-issues/scripts/exact-head-ci.mjs +413 -0
  200. package/skills/engineering/resolve-issues/scripts/exact-head-github-provider.mjs +332 -0
  201. package/skills/engineering/resolve-issues/scripts/finalize.mjs +488 -0
  202. package/skills/engineering/resolve-issues/scripts/fix-rounds.mjs +3307 -0
  203. package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-circular-1001.json +16 -0
  204. package/skills/engineering/resolve-issues/scripts/fixtures/evidence-lifecycle-valid-sequencing.json +51 -0
  205. package/skills/engineering/resolve-issues/scripts/fixtures/fmm-express-830-component-candidate.json +17 -0
  206. package/skills/engineering/resolve-issues/scripts/fixtures/head-check-set-1081.json +166 -0
  207. package/skills/engineering/resolve-issues/scripts/gate-value-series.mjs +92 -0
  208. package/skills/engineering/resolve-issues/scripts/guide-index.mjs +73 -0
  209. package/skills/engineering/resolve-issues/scripts/head-check-set.mjs +159 -0
  210. package/skills/engineering/resolve-issues/scripts/interference.mjs +427 -0
  211. package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +9 -0
  212. package/skills/engineering/resolve-issues/scripts/next-operations.mjs +419 -0
  213. package/skills/engineering/resolve-issues/scripts/postmortem.mjs +909 -0
  214. package/skills/engineering/resolve-issues/scripts/preflight-questions.mjs +322 -0
  215. package/skills/engineering/resolve-issues/scripts/reconcile-contained-unit-prs.mjs +415 -0
  216. package/skills/engineering/resolve-issues/scripts/release-state-contract.mjs +697 -0
  217. package/skills/engineering/resolve-issues/scripts/report.mjs +494 -0
  218. package/skills/engineering/resolve-issues/scripts/required-check-plan.mjs +172 -0
  219. package/skills/engineering/resolve-issues/scripts/round-metadata.mjs +79 -0
  220. package/skills/engineering/resolve-issues/scripts/run-state-review6-cases.mjs +334 -0
  221. package/skills/engineering/resolve-issues/scripts/run-state.mjs +4784 -0
  222. package/skills/engineering/resolve-issues/scripts/sandbox-selftest.mjs +395 -0
  223. package/skills/engineering/resolve-issues/scripts/spawn-contract.mjs +290 -0
  224. package/skills/engineering/resolve-issues/scripts/terminal-dispositions.mjs +170 -0
  225. package/skills/engineering/resolve-issues/scripts/terminal-evidence-journal.mjs +293 -0
  226. package/skills/engineering/resolve-issues/scripts/unit-kind.mjs +197 -0
  227. package/skills/engineering/resolve-issues/scripts/unit-lifecycle.mjs +127 -0
  228. package/skills/engineering/resolve-issues/scripts/watch-delivery.mjs +893 -0
  229. package/skills/engineering/resolve-issues/scripts/workspaces.mjs +829 -0
  230. package/skills/engineering/resolve-issues/workflows/independent-review.workflow.js +290 -0
  231. package/skills/engineering/resolve-issues/workflows/prior-art-scan.workflow.js +80 -0
  232. package/skills/engineering/resolve-issues/workflows/workflow-smoke.mjs +102 -0
  233. package/skills/engineering/resolve-release/LICENSE +3 -0
  234. package/skills/engineering/resolve-release/SKILL.md +112 -0
  235. package/skills/engineering/resolve-release/references/assembly.md +137 -0
  236. package/skills/engineering/resolve-release/references/auto-when-green.md +56 -0
  237. package/skills/engineering/resolve-release/references/candidate.md +167 -0
  238. package/skills/engineering/resolve-release/references/exposure.md +178 -0
  239. package/skills/engineering/resolve-release/references/handoff.md +24 -0
  240. package/skills/engineering/resolve-release/references/postmortem.md +230 -0
  241. package/skills/engineering/resolve-release/references/preflight.md +207 -0
  242. package/skills/engineering/resolve-release/references/principles.md +94 -0
  243. package/skills/engineering/resolve-release/references/regression-checklist.md +36 -0
  244. package/skills/engineering/resolve-release/references/related-skills.md +12 -0
  245. package/skills/engineering/resolve-release/references/routing.md +149 -0
  246. package/skills/engineering/resolve-release/references/verified-sha-github-flow.md +285 -0
  247. package/skills/engineering/resolve-release/references/versioning.md +202 -0
  248. package/skills/engineering/resolve-release/references/why.md +53 -0
  249. package/skills/engineering/resolve-release/scripts/adapter-completion-artifact.mjs +389 -0
  250. package/skills/engineering/resolve-release/scripts/build-changes.mjs +209 -0
  251. package/skills/engineering/resolve-release/scripts/candidate-hygiene.mjs +407 -0
  252. package/skills/engineering/resolve-release/scripts/candidate-identity.mjs +904 -0
  253. package/skills/engineering/resolve-release/scripts/candidate-traffic.mjs +81 -0
  254. package/skills/engineering/resolve-release/scripts/checked-adapter-loader.mjs +612 -0
  255. package/skills/engineering/resolve-release/scripts/close-attempt.mjs +135 -0
  256. package/skills/engineering/resolve-release/scripts/closeout-release.mjs +161 -0
  257. package/skills/engineering/resolve-release/scripts/doctrine.mjs +106 -0
  258. package/skills/engineering/resolve-release/scripts/durable-processing.mjs +522 -0
  259. package/skills/engineering/resolve-release/scripts/ensure-target-green.mjs +659 -0
  260. package/skills/engineering/resolve-release/scripts/evidence-bundle.mjs +1014 -0
  261. package/skills/engineering/resolve-release/scripts/finalize-release.mjs +526 -0
  262. package/skills/engineering/resolve-release/scripts/fixtures/durable-processing-adapter.mjs +169 -0
  263. package/skills/engineering/resolve-release/scripts/green-gate.mjs +599 -0
  264. package/skills/engineering/resolve-release/scripts/isolated-adapter-evaluator.mjs +752 -0
  265. package/skills/engineering/resolve-release/scripts/metadata-pr-status.mjs +56 -0
  266. package/skills/engineering/resolve-release/scripts/metadata-sync.mjs +1538 -0
  267. package/skills/engineering/resolve-release/scripts/postmortem.mjs +381 -0
  268. package/skills/engineering/resolve-release/scripts/preflight-probes.mjs +498 -0
  269. package/skills/engineering/resolve-release/scripts/production-endpoints.mjs +326 -0
  270. package/skills/engineering/resolve-release/scripts/rc-circuit-breaker.mjs +272 -0
  271. package/skills/engineering/resolve-release/scripts/report.mjs +417 -0
  272. package/skills/engineering/resolve-release/scripts/reprobe-credentials.mjs +114 -0
  273. package/skills/engineering/resolve-release/scripts/revalidate-candidate.mjs +238 -0
  274. package/skills/engineering/resolve-release/scripts/review-packet.mjs +503 -0
  275. package/skills/engineering/resolve-release/scripts/rollback-floor.mjs +263 -0
  276. package/skills/engineering/resolve-release/scripts/version-assert.mjs +339 -0
  277. package/skills/engineering/resolve-release/scripts/version-postmortem.mjs +485 -0
  278. package/skills/engineering/resolve-release/scripts/version.mjs +1199 -0
  279. package/skills/engineering/resolve-release/scripts/watch-candidate-delivery.mjs +449 -0
  280. package/skills/engineering/resolve-release/vendor/ACORN-LICENSE +21 -0
  281. package/skills/engineering/resolve-release/vendor/README.md +60 -0
  282. package/skills/engineering/resolve-release/vendor/acorn.mjs +6233 -0
  283. package/skills/engineering/resolve-release/vendor/quickjs/core/LICENSE +21 -0
  284. package/skills/engineering/resolve-release/vendor/quickjs/core/README.md +341 -0
  285. package/skills/engineering/resolve-release/vendor/quickjs/core/README.template.md +70 -0
  286. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs +2 -0
  287. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-TAV5CUKK.mjs.map +1 -0
  288. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs +7 -0
  289. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/chunk-V2S4ZYJR.mjs.map +1 -0
  290. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.mts +2033 -0
  291. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.d.ts +2033 -0
  292. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js +7 -0
  293. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.js.map +1 -0
  294. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs +2 -0
  295. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/index.mjs.map +1 -0
  296. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs +2 -0
  297. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-ES6BEMUI.mjs.map +1 -0
  298. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs +2 -0
  299. package/skills/engineering/resolve-release/vendor/quickjs/core/dist/module-asyncify-2EFITU5U.mjs.map +1 -0
  300. package/skills/engineering/resolve-release/vendor/quickjs/core/package.json +49 -0
  301. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/LICENSE +21 -0
  302. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/README.md +5 -0
  303. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.mts +549 -0
  304. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.d.ts +549 -0
  305. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js +2 -0
  306. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.js.map +1 -0
  307. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs +2 -0
  308. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/dist/index.mjs.map +1 -0
  309. package/skills/engineering/resolve-release/vendor/quickjs/ffi-types/package.json +36 -0
  310. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/LICENSE +47 -0
  311. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/README.md +82 -0
  312. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.d.ts +11 -0
  313. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.browser.mjs +22 -0
  314. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cjs +21 -0
  315. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.cjs +21 -0
  316. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.cloudflare.d.ts +11 -0
  317. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.d.ts +11 -0
  318. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.mjs +25 -0
  319. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/emscripten-module.wasm +0 -0
  320. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.mts +85 -0
  321. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.d.ts +85 -0
  322. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js +2 -0
  323. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.js.map +1 -0
  324. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs +2 -0
  325. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/ffi.mjs.map +1 -0
  326. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.mts +20 -0
  327. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.d.ts +20 -0
  328. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js +2 -0
  329. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.js.map +1 -0
  330. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs +2 -0
  331. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/dist/index.mjs.map +1 -0
  332. package/skills/engineering/resolve-release/vendor/quickjs/release-sync/package.json +61 -0
  333. package/skills/engineering/review-pr/LICENSE +3 -0
  334. package/skills/engineering/review-pr/SKILL.md +123 -0
  335. package/skills/engineering/review-pr/references/adversarial-reviewer-prompt.md +42 -0
  336. package/skills/engineering/review-pr/references/code-correctness.md +5 -0
  337. package/skills/engineering/review-pr/references/contract-freshness.md +9 -0
  338. package/skills/engineering/review-pr/references/coordination.md +18 -0
  339. package/skills/engineering/review-pr/references/domain-hazards.md +123 -0
  340. package/skills/engineering/review-pr/references/finding-themes.md +7 -0
  341. package/skills/engineering/review-pr/references/github-posting.md +98 -0
  342. package/skills/engineering/review-pr/references/golden-path-smoke.md +5 -0
  343. package/skills/engineering/review-pr/references/incremental-output.md +16 -0
  344. package/skills/engineering/review-pr/references/inputs-and-discovery.md +31 -0
  345. package/skills/engineering/review-pr/references/output-format.md +99 -0
  346. package/skills/engineering/review-pr/references/over-mock-screen.md +7 -0
  347. package/skills/engineering/review-pr/references/promotion-prs.md +16 -0
  348. package/skills/engineering/review-pr/references/re-review.md +18 -0
  349. package/skills/engineering/review-pr/references/review-method.md +199 -0
  350. package/skills/engineering/review-pr/references/review-mode.md +30 -0
  351. package/skills/engineering/review-pr/references/review-posture.md +53 -0
  352. package/skills/engineering/review-pr/references/round1-depth.md +62 -0
  353. package/skills/engineering/review-pr/references/scripts.md +17 -0
  354. package/skills/engineering/review-pr/references/workflow.md +16 -0
  355. package/skills/engineering/review-pr/schemas/findings.schema.json +282 -0
  356. package/skills/engineering/review-pr/scripts/finding-contract.mjs +285 -0
  357. package/skills/engineering/review-pr/scripts/post-review.mjs +405 -0
  358. package/skills/engineering/review-pr/scripts/pr-context.mjs +207 -0
  359. package/skills/engineering/review-pr/scripts/scan-diff.mjs +365 -0
  360. package/skills/engineering/review-pr/scripts/theme-contract.mjs +57 -0
  361. package/skills/engineering/smoke/LICENSE +3 -0
  362. package/skills/engineering/smoke/SKILL.md +131 -0
  363. package/skills/engineering/smoke/assets/smoke.manifest.example.json +53 -0
  364. package/skills/engineering/smoke/references/manifest.md +192 -0
  365. package/skills/engineering/smoke/scripts/smoke.mjs +713 -0
  366. package/skills/fullstack/better-auth/LICENSE +3 -0
  367. package/skills/fullstack/better-auth/SKILL.md +601 -0
  368. package/skills/fullstack/better-auth/references/feishu-api.md +270 -0
  369. package/skills/fullstack/monorepo/LICENSE +3 -0
  370. package/skills/fullstack/monorepo/SKILL.md +465 -0
  371. package/skills/fullstack/nextjs-fullstack/LICENSE +3 -0
  372. package/skills/fullstack/nextjs-fullstack/SKILL.md +210 -0
  373. package/skills/fullstack/nextjs-fullstack/conventions.md +318 -0
  374. package/skills/fullstack/nextjs-fullstack/frontend-conventions.md +61 -0
  375. package/skills/fullstack/nextjs-fullstack/nextjs16.md +287 -0
  376. package/skills/fullstack/nextjs-fullstack/server-actions.md +409 -0
  377. package/skills/fullstack/prisma-setup/LICENSE +3 -0
  378. package/skills/fullstack/prisma-setup/SKILL.md +180 -0
  379. package/skills/fullstack/prisma-setup/nextjs.md +258 -0
  380. package/skills/fullstack/prisma-setup/turborepo.md +301 -0
  381. package/skills/fullstack/shadcn/LICENSE +3 -0
  382. package/skills/fullstack/shadcn/SKILL.md +119 -0
  383. package/skills/fullstack/shadcn/assets/shadcn-small.png +0 -0
  384. package/skills/fullstack/shadcn/assets/shadcn.png +0 -0
  385. package/skills/fullstack/shadcn/cli.md +411 -0
  386. package/skills/fullstack/shadcn/customization.md +224 -0
  387. package/skills/fullstack/shadcn/evals/evals.json +90 -0
  388. package/skills/fullstack/shadcn/mcp.md +101 -0
  389. package/skills/fullstack/shadcn/rules/base-vs-radix.md +323 -0
  390. package/skills/fullstack/shadcn/rules/component-selection.md +67 -0
  391. package/skills/fullstack/shadcn/rules/composition.md +195 -0
  392. package/skills/fullstack/shadcn/rules/data-table.md +201 -0
  393. package/skills/fullstack/shadcn/rules/forms.md +255 -0
  394. package/skills/fullstack/shadcn/rules/icons.md +103 -0
  395. package/skills/fullstack/shadcn/rules/styling.md +167 -0
  396. package/skills/fullstack/zod-v4/LICENSE +3 -0
  397. package/skills/fullstack/zod-v4/SKILL.md +287 -0
@@ -0,0 +1,282 @@
1
+ # E2E Tests — GitHub Actions Workflow
2
+ #
3
+ # Triggered by Cloud Build via repository_dispatch after successful deployment.
4
+ # Posts structured results as PR comment + sets commit status.
5
+ #
6
+ # To use: copy to .github/workflows/e2e.yml and customize marked sections.
7
+
8
+ name: E2E Tests
9
+
10
+ on:
11
+ repository_dispatch:
12
+ types: [deploy-complete]
13
+
14
+ workflow_dispatch:
15
+ inputs:
16
+ environment:
17
+ description: 'Environment (dev/prod)'
18
+ required: true
19
+ type: choice
20
+ options:
21
+ - dev
22
+ - prod
23
+ service_url:
24
+ description: 'Deployed service URL'
25
+ required: true
26
+ type: string
27
+ sha:
28
+ description: 'Git commit SHA'
29
+ required: false
30
+ type: string
31
+ pr_number:
32
+ description: 'PR number to comment on'
33
+ required: false
34
+ type: string
35
+
36
+ permissions:
37
+ contents: read
38
+ statuses: write
39
+ pull-requests: write
40
+
41
+ jobs:
42
+ e2e:
43
+ runs-on: ubuntu-latest
44
+ if: github.event.client_payload.commit != '' || github.event_name == 'workflow_dispatch'
45
+ timeout-minutes: 15
46
+ # DOCKER-PREFERRED: run in the official pinned Playwright container — browsers and
47
+ # OS deps ship in the image, so there is no per-run browser install. Keep the tag
48
+ # aligned with the repo's @playwright/test version and with ci-gates.github.yml.
49
+ # Alternative (plain runner): drop `container:` and add a step
50
+ # `npx playwright install --with-deps chromium` after the dependency install.
51
+ container:
52
+ image: mcr.microsoft.com/playwright:v1.61.0-noble
53
+ options: --ipc=host
54
+
55
+ env:
56
+ ENV: ${{ github.event.client_payload.env || inputs.environment }}
57
+ SERVICE_URL: ${{ github.event.client_payload.service_url || inputs.service_url }}
58
+ SHA: ${{ github.event.client_payload.commit || inputs.sha || github.sha }}
59
+ PR_NUMBER: ${{ github.event.client_payload.pr_number || inputs.pr_number }}
60
+
61
+ steps:
62
+ - name: Determine checkout ref
63
+ id: ref
64
+ run: |
65
+ if [[ "$ENV" == "dev" ]]; then
66
+ echo "ref=dev" >> $GITHUB_OUTPUT
67
+ else
68
+ echo "ref=$SHA" >> $GITHUB_OUTPUT
69
+ fi
70
+
71
+ - name: Checkout
72
+ uses: actions/checkout@v4
73
+ with:
74
+ ref: ${{ steps.ref.outputs.ref }}
75
+ fetch-depth: 0
76
+
77
+ # ── CUSTOMIZE: Node version and package manager ──
78
+ - name: Setup Node
79
+ uses: actions/setup-node@v4
80
+ with:
81
+ node-version: 22
82
+ cache: npm
83
+ cache-dependency-path: package-lock.json
84
+
85
+ - name: Install dependencies
86
+ run: npm ci
87
+ # No browser install: the job container ships the browsers. If the image tag
88
+ # and @playwright/test versions can't be aligned, add
89
+ # `npx playwright install chromium` here (prefer aligning instead).
90
+
91
+ - name: Wait for service readiness
92
+ run: |
93
+ echo "Waiting for $SERVICE_URL to be ready..."
94
+ for i in $(seq 1 30); do
95
+ if curl -sf -o /dev/null "$SERVICE_URL"; then
96
+ echo "Service is ready"
97
+ exit 0
98
+ fi
99
+ echo "Attempt $i/30 — retrying in 10s..."
100
+ sleep 10
101
+ done
102
+ echo "Service not ready after 5 minutes"
103
+ exit 1
104
+
105
+ # ── CUSTOMIZE: test command and env vars ──
106
+ - name: Run E2E tests
107
+ id: run_tests
108
+ run: npm run test:e2e
109
+ continue-on-error: true # Phase 1: non-blocking. Remove for Phase 2.
110
+ env:
111
+ BASE_URL: ${{ env.SERVICE_URL }}
112
+ CI: true
113
+ # Add repo-specific secrets:
114
+ # E2E_DASHBOARD_TOKEN: ${{ secrets.E2E_DASHBOARD_TOKEN }}
115
+
116
+ - name: Post E2E results to PR
117
+ if: always() && env.PR_NUMBER != ''
118
+ uses: actions/github-script@v7
119
+ with:
120
+ script: |
121
+ const fs = require('fs');
122
+
123
+ // Parse Playwright JSON results
124
+ let results = { total: 0, passed: 0, failed: 0, skipped: 0, duration: 0, failures: [] };
125
+ try {
126
+ const raw = JSON.parse(fs.readFileSync('e2e-results.json', 'utf8'));
127
+ const suites = raw.suites || [];
128
+ function walk(suite) {
129
+ for (const spec of (suite.specs || [])) {
130
+ for (const test of (spec.tests || [])) {
131
+ results.total++;
132
+ const status = test.results?.[test.results.length - 1]?.status || 'unknown';
133
+ if (status === 'passed' || status === 'expected') results.passed++;
134
+ else if (status === 'skipped') results.skipped++;
135
+ else {
136
+ results.failed++;
137
+ const err = test.results?.[test.results.length - 1]?.error?.message || 'Unknown error';
138
+ results.failures.push({ title: spec.title + ' › ' + test.title, error: err.slice(0, 200) });
139
+ }
140
+ results.duration += (test.results?.[test.results.length - 1]?.duration || 0);
141
+ }
142
+ }
143
+ for (const child of (suite.suites || [])) walk(child);
144
+ }
145
+ suites.forEach(walk);
146
+ } catch (e) {
147
+ console.log('Could not parse e2e-results.json:', e.message);
148
+ }
149
+
150
+ // Parse route manifest for coverage
151
+ let coverage = { covered: 0, total: 0 };
152
+ try {
153
+ const manifest = JSON.parse(fs.readFileSync('e2e/route-manifest.json', 'utf8'));
154
+ const routes = manifest.routes || manifest.endpoints || [];
155
+ coverage.total = routes.length;
156
+ coverage.covered = routes.filter(r => (r.specs || []).length > 0).length;
157
+ } catch (e) {
158
+ console.log('No route manifest found:', e.message);
159
+ }
160
+
161
+ const icon = results.failed > 0 ? '❌' : '✅';
162
+ const status = results.failed > 0 ? 'FAILED' : 'PASSED';
163
+ const durationStr = `${Math.floor(results.duration / 60000)}m ${Math.floor((results.duration % 60000) / 1000)}s`;
164
+ const coverageStr = coverage.total > 0
165
+ ? `${Math.round(coverage.covered / coverage.total * 100)}% (${coverage.covered}/${coverage.total})`
166
+ : 'N/A (no manifest)';
167
+
168
+ let body = `## 🧪 E2E ${status} — ${process.env.ENV}\n\n`;
169
+ body += `| Metric | Value |\n|--------|-------|\n`;
170
+ body += `| Total | ${results.total} |\n`;
171
+ body += `| ✅ Passed | ${results.passed} |\n`;
172
+ body += `| ❌ Failed | ${results.failed} |\n`;
173
+ body += `| ⏭️ Skipped | ${results.skipped} |\n`;
174
+ body += `| ⏱️ Duration | ${durationStr} |\n`;
175
+ body += `| 📊 Route coverage | ${coverageStr} |\n\n`;
176
+
177
+ if (results.failures.length > 0) {
178
+ body += `<details><summary>❌ Failed (${results.failures.length})</summary>\n\n`;
179
+ for (const f of results.failures) {
180
+ body += `- \`${f.title}\` — ${f.error}\n`;
181
+ }
182
+ body += `\n</details>\n\n`;
183
+ }
184
+
185
+ body += `> Commit: ${process.env.SHA?.slice(0, 7)} | [Workflow run](${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID})`;
186
+
187
+ // Post or update PR comment
188
+ const prNumber = parseInt(process.env.PR_NUMBER);
189
+ if (prNumber) {
190
+ const { data: comments } = await github.rest.issues.listComments({
191
+ owner: context.repo.owner,
192
+ repo: context.repo.repo,
193
+ issue_number: prNumber,
194
+ });
195
+ const existing = comments.find(c => c.body?.startsWith('## 🧪 E2E'));
196
+ if (existing) {
197
+ await github.rest.issues.updateComment({
198
+ owner: context.repo.owner,
199
+ repo: context.repo.repo,
200
+ comment_id: existing.id,
201
+ body,
202
+ });
203
+ } else {
204
+ await github.rest.issues.createComment({
205
+ owner: context.repo.owner,
206
+ repo: context.repo.repo,
207
+ issue_number: prNumber,
208
+ body,
209
+ });
210
+ }
211
+ }
212
+
213
+ - name: Set commit status
214
+ if: always()
215
+ uses: actions/github-script@v7
216
+ with:
217
+ script: |
218
+ const state = '${{ steps.run_tests.outcome }}' === 'success' ? 'success' : 'failure';
219
+ const env = '${{ env.ENV }}';
220
+ await github.rest.repos.createCommitStatus({
221
+ owner: context.repo.owner,
222
+ repo: context.repo.repo,
223
+ sha: '${{ env.SHA }}',
224
+ state,
225
+ target_url: `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`,
226
+ description: state === 'success' ? `E2E ${env}: all tests passed` : `E2E ${env}: tests failed`,
227
+ context: 'e2e',
228
+ });
229
+
230
+ - name: Report to Discord
231
+ if: always() && github.event_name == 'repository_dispatch'
232
+ env:
233
+ DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
234
+ run: |
235
+ if [[ -z "$DISCORD_WEBHOOK_URL" ]]; then
236
+ echo "DISCORD_WEBHOOK_URL not set — skipping"
237
+ exit 0
238
+ fi
239
+
240
+ OUTCOME="${{ steps.run_tests.outcome }}"
241
+ RUN_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
242
+ COMMIT_URL="https://github.com/${GITHUB_REPOSITORY}/commit/${SHA}"
243
+ REPO_NAME="${GITHUB_REPOSITORY#*/}"
244
+
245
+ if [[ "$OUTCOME" == "success" ]]; then
246
+ ICON="✅"; STATUS="PASSED"; COLOR=3066993
247
+ else
248
+ ICON="❌"; STATUS="FAILED"; COLOR=15158332
249
+ fi
250
+
251
+ # Built with node (always present in the Playwright image), not jq (not installed there).
252
+ PAYLOAD=$(node -e '
253
+ const [icon, status, env, commit, commitUrl, serviceUrl, runUrl, repo, color] = process.argv.slice(1);
254
+ console.log(JSON.stringify({ embeds: [{
255
+ title: `${icon} E2E ${status} — ${repo} (${env})`,
256
+ url: runUrl, color: Number(color),
257
+ fields: [
258
+ { name: "Commit", value: `[${commit}](${commitUrl})`, inline: true },
259
+ { name: "Environment", value: env, inline: true },
260
+ { name: "Service", value: serviceUrl, inline: false },
261
+ ],
262
+ footer: { text: `${repo} CI` },
263
+ }]}));
264
+ ' "$ICON" "$STATUS" "$ENV" "${SHA:0:7}" "$COMMIT_URL" "$SERVICE_URL" "$RUN_URL" "$REPO_NAME" "$COLOR")
265
+
266
+ curl -sf -X POST -H "Content-Type: application/json" -d "$PAYLOAD" "$DISCORD_WEBHOOK_URL" || true
267
+
268
+ # Phase 2: uncomment to make E2E blocking
269
+ # - name: Fail if tests failed
270
+ # if: steps.run_tests.outcome == 'failure'
271
+ # run: exit 1
272
+
273
+ - name: Upload artifacts on failure
274
+ if: failure() || steps.run_tests.outcome == 'failure'
275
+ uses: actions/upload-artifact@v4
276
+ with:
277
+ name: e2e-results-${{ github.run_id }}
278
+ path: |
279
+ test-results/
280
+ playwright-report/
281
+ e2e-results.json
282
+ retention-days: 7
@@ -0,0 +1,159 @@
1
+ # Auth Flows (login, signup, forgot-password)
2
+
3
+ > Read when: testing authentication surfaces — login, signup, password reset, magic link, OAuth callback. These span three tiers and cross an external boundary (email/SMS), which is why they are the most commonly mis-tested feature in a codebase.
4
+
5
+ Auth is special on two counts, both easy to get wrong:
6
+
7
+ 1. **It spans all three tiers** — the same feature owes a render-health test, functional negatives, *and* a real journey. Confusing them produces a test that looks like a journey but proves nothing.
8
+ 2. **It crosses an external boundary you don't own** — reset/verification email. The token round-trip is the whole point, and must be proven without calling a live provider.
9
+
10
+ ## The anti-pattern this exists to kill
11
+
12
+ A test tagged `@level journey` that only checks *a form element is visible*:
13
+
14
+ ```typescript
15
+ // ✗ A smoke test wearing a journey label. Proves nothing; can't fail the way the
16
+ // name promises. When the form fails to render at all (e.g. a seed/cache race),
17
+ // the disjunction just goes falsy with no specific signal.
18
+ test('Customer login page loads and renders login form', async ({ page }) => {
19
+ const response = await page.goto(`/${MERCHANT}/account/login`);
20
+ expect(response?.ok()).toBeTruthy();
21
+ const hasEmail = await page.getByLabel(/email/i).isVisible().catch(() => false);
22
+ const hasPassword = await page.getByLabel(/password/i).isVisible().catch(() => false);
23
+ const hasButton = await page.getByRole('button', { name: /login/i }).isVisible().catch(() => false);
24
+ expect(hasEmail || hasPassword || hasButton).toBeTruthy(); // weak disjunction
25
+ });
26
+ ```
27
+
28
+ Two syntactic tells — `.catch(() => false)` (swallows a locator throw, defeating web-first retry) and `expect(a || b || c).toBeTruthy()` (passes if *any* branch holds) — are flagged as leads by `review-pr`'s `scan-diff.mjs` (`swallowed-assertion`, `weak-assertion`). Writing them means a vacuous check, not a journey — replace with a real journey below.
29
+
30
+ ## Login
31
+
32
+ Separate two jobs that get conflated:
33
+
34
+ ### 1. Proving the login flow itself
35
+
36
+ A Tier-3 journey drives credentials to an **authenticated outcome** (not form presence), backed by Tier-2 functional negatives where most real bugs live.
37
+
38
+ ```typescript
39
+ // @covers /[merchant]/account/login
40
+ // @level journey
41
+ test('customer logs in and lands authenticated', async ({ page }) => {
42
+ const user = await factory.customer({ password: 'Correct-horse-9' }); // seed real state
43
+ await page.goto(`/${MERCHANT}/account/login`);
44
+ await page.getByLabel(/email/i).fill(user.email);
45
+ await page.getByLabel(/password/i).fill('Correct-horse-9');
46
+ await page.getByRole('button', { name: /log in|sign in/i }).click();
47
+ // Assert a CONCRETE post-login signal — redirect + authed-only content:
48
+ await expect(page).toHaveURL(new RegExp(`/${MERCHANT}/account$`));
49
+ await expect(page.getByRole('heading', { name: /my account/i })).toBeVisible();
50
+ });
51
+ ```
52
+
53
+ Back it with **Tier-2 functional negatives** where most real bugs live — e.g. `@level functional` "wrong password shows error and stays unauthenticated": fill a bad password, assert the error text is visible *and* `toHaveURL(/login/)` (did NOT get in).
54
+
55
+ Rules:
56
+
57
+ - **Seed the user** with a factory/seed script — never depend on ambient data. Missing state is the test's *arrange* step, never a skip reason ([test-skipping.md](test-skipping.md)).
58
+ - **Name every seeded account with the `e2e-` prefix** (see [the naming convention](#the-e2e--account-naming-convention) below) — the factory should emit it by default, not leave it to each call site.
59
+ - **Assert authenticated state**, not form presence: a redirect to an authed route, an authed-only element, or the session cookie. "A button is visible" is Tier-1 render-health.
60
+ - **Don't mock first-party auth endpoints** in the journey — real DB, real session. Intercepting `/api/auth/*` makes it `Over-mocked` (`ensure-coverage` → `references/depth/mock-policy.md`).
61
+
62
+ ### 2. Login as a precondition for other journeys
63
+
64
+ Don't re-type credentials in every test. Log in once and reuse the session via a shared auth fixture (`storageState`) or `E2E_AUTH_BYPASS`; other journeys start already-authed and only the login spec proves login itself. This is the "Seed auth" path in [test-skipping.md](test-skipping.md) — the cure for "no session" is to seed it, never skip.
65
+
66
+ ## A session fixture asserts its own preconditions, and throws
67
+
68
+ A minted session the app then rejects is the worst failure mode in this file: the request fails closed, nothing renders, and the spec dies on an **undiagnostic timeout**. Nothing in the diff looks wrong — there is no assertion against a 404 to spot, because the assertion was never reached. The lane goes on reporting green-or-flaky while proving nothing.
69
+
70
+ The recurring cause is a value the **app and the harness each default independently**: a tenant/org slug, an auth secret, a base URL, an API version. They agree until one side's default moves.
71
+
72
+ **Rules, in the order they close the hole:**
73
+
74
+ - **One owner per shared value.** A single constant mirrors the app's own resolver (`getRequiredOrgSlug()`, not a re-typed `?? "skyee"`), and the Playwright config sets the env var *from that constant* — in `webServer.env` **and** any inline command string, which drift apart otherwise.
75
+ - **Make the wrong value inexpressible.** Identities come from constructor functions (`authorizedIdentity()`, `denyOnlyIdentity()`) that fill the shared value themselves. If no call site can state it, no call site can state it wrongly — a rule prose cannot enforce, structure can.
76
+ - **Assert at mint time and throw with a diagnosis.** The fixture checks the value as it mints and, on mismatch, throws naming the identity id, *both* values, and the owning constant's file path. A loud throw is the entire difference between a five-minute fix and a five-round one; a timeout names nothing.
77
+ - **Close the vacuous-pass hole in deny fixtures.** A fixture that deliberately uses a wrong value opts in explicitly (`{ allowWrongOrg: true }`), and that flag is **rejected on a right-value identity** — otherwise a denial assertion passes for the wrong reason, and the negative test is as vacuous as the positive one.
78
+
79
+ The first two rules are what make this stick: a value no call site can express is a value no call site can get wrong. (Named incident: `skyee-ai-risk` #1144 — a tenant slug defaulted independently in four files left authorized journeys minting sessions the app rejected, so the endpoint 403'd before any row rendered and those lanes **stayed green for five review rounds** while exercising nothing. Fixed in `f97f879e`, whose message records why structure rather than a fourth sentence: *"prose had already failed at this twice in these exact files."*)
80
+
81
+ ## The `e2e-*` account naming convention
82
+
83
+ Every account, email, and tenant a test seeds carries an **`e2e-` prefix**:
84
+
85
+ ```
86
+ account e2e-<role>-<runid>@<test-domain> e2e-customer-x7f2@example.test
87
+ tenant e2e-<name> e2e-synthetic
88
+ username e2e-<role>-<runid> e2e-admin-x7f2
89
+ ```
90
+
91
+ Bake it into the **factory default** — `factory.customer()` emits a conforming email without the call site asking — so the convention can't erode one test at a time. Why a naming convention and not just "use seeded data":
92
+
93
+ - **Identifiable at a glance.** In a DB dump, log line, admin UI, or bug report, `e2e-` says "test artifact" with no lookup.
94
+ - **Bulk-cleanable.** `DELETE FROM users WHERE email LIKE 'e2e-%'` is a safe janitor job; without the prefix, cleanup needs a bookkeeping table that drifts.
95
+ - **Mechanically guarded.** The app/monitoring can special-case the prefix (exclude from analytics/emails/billing), and `smoke`'s deployed-target rule builds on it: a mutating golden path off-`local` runs only against a declared synthetic tenant, and `smoke.mjs validate` warns when a tenant is not `e2e-`-prefixed. (Production is governed by the stricter **read-only production profile** (`prod-preview`/`prod-active`), where a tenant grants nothing — this convention is what makes *staging* runs safe, not prod ones.)
96
+ - **Unambiguous in shared environments.** On staging/preview where real-ish data coexists, the prefix keeps a cleanup script or mutating smoke run from touching anything live.
97
+
98
+ Use a **run-scoped suffix** (a short random id per run) so parallel workers and repeated CI runs never collide on unique columns — never a fixed `e2e-test@example.com` singleton, which serializes workers and flakes on re-runs.
99
+
100
+ ## Forgot password — the email boundary is the whole flow
101
+
102
+ Email/SMS is an **external boundary you don't own** → *real internals, faked externals, nothing in between* (`mock-policy.md`).
103
+
104
+ - ✗ Don't call a live email provider in CI (non-deterministic, flaky, leaks keys).
105
+ - ✗ Don't skip it because "email is external" — the exact rationalization the no-skip policy forbids; **sandbox the boundary** instead.
106
+ - ✗ Don't assert "the form renders" and call it a journey.
107
+
108
+ ✓ Fake the mail adapter so the app writes to a test outbox, then drive the **full durable-state** round-trip:
109
+
110
+ ```typescript
111
+ // @covers /[merchant]/account/forgot-password
112
+ // @level journey
113
+ test('reset password end to end', async ({ page }) => {
114
+ const user = await factory.customer({ password: 'old-pass-1' });
115
+
116
+ // 1. Request reset
117
+ await page.goto(`/${MERCHANT}/account/forgot-password`);
118
+ await page.getByLabel(/email/i).fill(user.email);
119
+ await page.getByRole('button', { name: /reset|send/i }).click();
120
+ await expect(page.getByText(/check your (email|inbox)/i)).toBeVisible();
121
+
122
+ // 2. Read the token from the FAKE outbox (or directly from the DB token table —
123
+ // both are real internals; live SMTP is the banned outward reach)
124
+ const link = await fakeMail.lastResetLink(user.email);
125
+
126
+ // 3. Complete the reset
127
+ await page.goto(link);
128
+ await page.getByLabel(/new password/i).fill('new-pass-2');
129
+ await page.getByRole('button', { name: /set|update/i }).click();
130
+
131
+ // 4. Prove the durable change: new password works
132
+ await login(page, { email: user.email, password: 'new-pass-2' });
133
+ await expect(page.getByRole('heading', { name: /my account/i })).toBeVisible();
134
+ });
135
+ ```
136
+
137
+ - Reading the token from the **fake outbox** also proves the send wiring; reading it from the **DB token table** proves only the token logic. Either is real-internal and valid — pick based on whether email dispatch is part of the contract you're proving.
138
+ - Cover the negatives as Tier-2 functional against the real DB: **expired token**, **already-used token**, **unknown email** (should not reveal account existence).
139
+
140
+ ## CI wiring
141
+
142
+ | Concern | Practice |
143
+ |---|---|
144
+ | **Where they run** | The **blocking** E2E lane. Once email is faked, both flows are fully hermetic — *no quarantine*. Quarantine is only for genuinely un-sandboxable externals (e.g. a real-provider deliverability check), which is a separate secret-gated test with a dedicated mailbox ([ci-integration.md](../ci-integration.md) → Quarantine lane). |
145
+ | **Seed timing** | Migrate → seed → **start servers** → run. Seed the user/tenant *before* servers boot, or bypass caches for E2E (e.g. an `ALLOW_E2E_ROUTES` flag). A freshly-seeded row a cached read can't yet see is a classic auth-journey flake. |
146
+ | **Email adapter** | Inject a fake/in-memory mail adapter via env in CI; never real keys, never a live provider. |
147
+ | **Presentation** | The presentation sweep ([presentation-sweep.md](../presentation-sweep.md)) catches "the form didn't render at all" — the bug a green functional run sails past. It is a **separate gate**; the journey assertion is not a substitute. |
148
+ | **Getting to green** | Never weaken assertions or skip to pass — `review-pr`'s manufactured-green check and the `weak-assertion`/`swallowed-assertion` leads flag exactly that. |
149
+
150
+ ## Checklist
151
+
152
+ - [ ] Login journey asserts **authenticated state** (redirect / authed element / session cookie), not form presence.
153
+ - [ ] User/session **seeded** before server boot; caches bypassed for E2E.
154
+ - [ ] Values the app and harness share (tenant/org, secret, base URL) have **one owner**, and the session fixture **throws** on mismatch rather than letting the lane time out.
155
+ - [ ] Seeded accounts/tenants carry the **`e2e-` prefix** with a run-scoped suffix (factory default, not per-call-site).
156
+ - [ ] Forgot-password drives the **full reset → new-password-works** loop with a **faked mail boundary**.
157
+ - [ ] Negatives (wrong password, expired/used token, unknown email) are **Tier-2 functional** against the real DB.
158
+ - [ ] No first-party `page.route`/MSW interception in the journeys; no `.catch(() => false)`; no disjunctive `toBeTruthy()`.
159
+ - [ ] Everything in the **blocking lane**; no skips; presentation sweep is a separate job.
@@ -0,0 +1,71 @@
1
+ # Playwright Config
2
+
3
+ ```typescript
4
+ import { defineConfig, devices } from '@playwright/test';
5
+
6
+ export default defineConfig({
7
+ testDir: './e2e',
8
+ // Timeout convention: 15s for any single action/assertion — a real state change
9
+ // arrives in seconds; anything slower is a bug the test should surface, not wait out.
10
+ // The per-test ceiling stays higher (a journey is many 15s-bounded steps).
11
+ timeout: 60_000,
12
+ expect: { timeout: 15_000 },
13
+ fullyParallel: true,
14
+ forbidOnly: !!process.env.CI,
15
+ retries: process.env.CI ? 2 : 0,
16
+ // Parallel in CI too — wall clock ≈ slowest spec, not the sum. E2E_WORKERS is the
17
+ // CI-side knob (see ../ci-playwright-container.md → Resource Envelope and Workers);
18
+ // 4 fits a 4 CPU / 16 GB job. Drop to 2 only on OOM/browser crashes.
19
+ workers: process.env.CI ? Number(process.env.E2E_WORKERS) || 4 : undefined,
20
+ reporter: process.env.CI
21
+ ? [['github'], ['json', { outputFile: 'e2e-results.json' }], ['html', { open: 'never' }]]
22
+ : [['list'], ['html', { open: 'never' }]],
23
+ use: {
24
+ baseURL: process.env.BASE_URL || 'http://localhost:3000',
25
+ actionTimeout: 15_000,
26
+ navigationTimeout: 15_000,
27
+ trace: 'retain-on-failure',
28
+ screenshot: 'only-on-failure',
29
+ ignoreHTTPSErrors: true,
30
+ },
31
+ projects: [{ name: 'chromium', use: { ...devices['Desktop Chrome'] } }],
32
+ webServer: {
33
+ command: 'npm run dev',
34
+ url: process.env.BASE_URL || 'http://localhost:3000',
35
+ timeout: 120_000,
36
+ reuseExistingServer: !process.env.CI,
37
+ },
38
+ });
39
+ ```
40
+
41
+ ## Time budget (the 5-minute PR lane)
42
+
43
+ The per-PR browser gates (render sweep, curated smoke) target **≤5 min wall clock**, enforced by `timeout-minutes: 5` / `timeout: 300s` on the CI job (`ci-gates.*` templates carry it; `ci-audit.mjs` checks it). The levers: **parallel workers** (above — wall clock is the slowest spec, not the sum); **curation** (the floor runs the `@smoke` subset + the sweep, never the broad suite — gate 4 is demoted to the integration lane, see [../ci-integration.md](../ci-integration.md)); the **15s action timeout** (a hung step fails fast); **matrix fan-out** if the curated set still can't fit (the commented `smoke-drive` variant in `assets/ci-gates.github.yml`). Longer leashes belong to the integration-lane suite (`timeout-minutes: 30`) and auxiliary quarantine/visual jobs (10–15) — never the PR-lane gates.
44
+
45
+ ## AGENTS.md section
46
+
47
+ Drop into each repo's AGENTS.md or CLAUDE.md:
48
+
49
+ ```markdown
50
+ ## E2E Testing
51
+
52
+ ### Rules
53
+ 1. Every new route/endpoint MUST be added to `e2e/route-manifest.json` (CI will fail otherwise)
54
+ 2. Every new route needs at least a Tier 1 render-health test
55
+ 3. Interactive routes need Tier 2 functional tests (success + error + edge cases)
56
+ 4. Core business flows need Tier 3 journey tests — the golden paths (multi-step, real API); tag the do-not-ship subset `@smoke`
57
+ 5. Directory: `render/`, `functional/`, `journeys/`
58
+ 6. Use `getByRole`/`getByLabel`/`getByText` -- not CSS selectors
59
+ 7. No `waitForTimeout()` -- wait for real state
60
+ 8. Run route discovery and reachability analysis before E2E coverage audits; do not audit from memory, sampling, or file enumeration alone
61
+ 9. No `test.skip()` unless it matches the Test Skipping Policy: allowed category, GitHub issue/blocker link, and replacement verification
62
+ 10. Auth in shared fixtures (`e2e/fixtures/auth.ts`); test accounts and synthetic tenants carry the `e2e-` prefix (e.g. `e2e-customer-x1@example.test`, tenant `e2e-synthetic`)
63
+ 11. Timeouts: 15s per action/assertion (`actionTimeout`/`expect.timeout`); no per-test timeout raises without justification
64
+
65
+ ### CI Enforcement
66
+ - Route detection runs on every PR -- adding a page/endpoint without a manifest entry fails CI
67
+ - The presentation sweep runs as a separate blocking job -- a route that throws on render fails CI even when a functional spec passes
68
+ - Browser jobs run in the pinned official Playwright container (docker-preferred); PR-lane jobs carry a 5-minute timeout
69
+ - Branch protection requires only the `all-gates` umbrella job
70
+ - Reviewer will block PRs with uncovered interactive routes without justification
71
+ ```