@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,659 @@
1
+ #!/usr/bin/env node
2
+ // ensure-target-green — mechanize the repair lane as a reusable pre-envelope phase (#807).
3
+ //
4
+ // Productizes the prose "repair lane" in SKILL.md + the `target-gate-colour` probe into a
5
+ // named, scripted path:
6
+ //
7
+ // 1. classify failures (required gates only when --gate is set)
8
+ // 2. if all failures ∈ allowlisted classes → open repair unit(s) via resolve-issues brief
9
+ // else → hand structured human brief (supervised) or block
10
+ // 3. land → re-run target-gate-colour on the NEW tip
11
+ // 4. only then propose/confirm envelope (or resume same attempt)
12
+ //
13
+ // SCOPE: tip check-runs only.
14
+ // - Live floor / public-host DEAD while CI green → #800 (floorReadiness / rollback-floor)
15
+ // - Tooling that lies about tip green (stale local main, tag push, blank percent) → #799
16
+ // Do not conflate those with this phase.
17
+ //
18
+ // Modes:
19
+ // supervised (default) — classify + structured brief; never auto-opens repair
20
+ // auto-repair-allowlist — auto-open repair only when every failure is allowlisted
21
+ //
22
+ // Budget: maxRepairRounds (default 2) + wallClockMinutes (default 60) so permanent flakes
23
+ // cannot thrash forever.
24
+ //
25
+ // JSON contract:
26
+ // { state: green|repairing|blocked|unknown, headSha, failing[{name,conclusion,class,allowlisted}],
27
+ // repair?, reprobe?, brief?, override?, attempts[], startedAt, finishedAt, durationMs }
28
+ //
29
+ // Manifest: release.ensureGreen = { startedAt, attempts[], finalHead, outcome, failingClasses[],
30
+ // repairPrs[], durationMs }
31
+
32
+ import { execFileSync } from 'node:child_process'
33
+ import { readFileSync } from 'node:fs'
34
+ import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
35
+
36
+ export const STATES = {
37
+ GREEN: 'green',
38
+ REPAIRING: 'repairing',
39
+ BLOCKED: 'blocked',
40
+ UNKNOWN: 'unknown',
41
+ }
42
+
43
+ export const MODES = {
44
+ SUPERVISED: 'supervised',
45
+ AUTO_REPAIR_ALLOWLIST: 'auto-repair-allowlist',
46
+ }
47
+
48
+ export const DEFAULT_MAX_REPAIR_ROUNDS = 2
49
+ export const DEFAULT_WALL_CLOCK_MINUTES = 60
50
+
51
+ /**
52
+ * Repo-declared allowlist / never-auto map. Callers may override via --classify-config.
53
+ * Order matters: first match wins. Critical / hazard patterns must outrank flake heuristics.
54
+ */
55
+ export const DEFAULT_CLASSIFY_CONFIG = {
56
+ optionalGates: [],
57
+ // Never auto without human — checked first.
58
+ neverAuto: [
59
+ { class: 'critical', pattern: /auth|authz|session|oauth|token|cookie|password|credential/i },
60
+ { class: 'critical', pattern: /money|payment|billing|tax|pricing|invoice|ledger|refund/i },
61
+ { class: 'critical', pattern: /tenant|tenancy|org[-_]?scope|multi[-_]?tenant/i },
62
+ { class: 'critical', pattern: /migrat|schema\.prisma|prisma migrate|alembic|flyway/i },
63
+ { class: 'critical', pattern: /post[-_]?deploy|prod[-_]?active|smoke|production/i },
64
+ { class: 'critical', pattern: /release[-_]?readiness|green[-_]?gate|traffic shift|expose/i },
65
+ ],
66
+ allowlist: [
67
+ { class: 'flake', pattern: /flak|intermittent|order.?dependent|race.?condition|retry/i },
68
+ { class: 'digest-drift', pattern: /contentDigest|digest drift|workflow.?digest|distribution/i },
69
+ { class: 'external-fetch', pattern: /ECONNRESET|ETIMEDOUT|ENOTFOUND|registry\.npmjs|fetch failed|network/i },
70
+ { class: 'missing-optional', pattern: /reported no check-run|absent check/i, onlyOptionalGate: true },
71
+ ],
72
+ }
73
+
74
+ /** Terminal conclusions that may count as green. Anything else is not-green. */
75
+ export const ALLOWED_TERMINAL_CONCLUSIONS = new Set(['SUCCESS', 'SKIPPED', 'NEUTRAL'])
76
+
77
+ /**
78
+ * A check is blocking when it is not completed with an allowed terminal conclusion.
79
+ * GitHub stores in-progress conclusions as null (fetchTip normalizes to ""); those
80
+ * must not silent-green. When `status` is present and not COMPLETED, block even if
81
+ * a conclusion string looks terminal.
82
+ */
83
+ export function isCheckBlocking(check) {
84
+ if (!check) return true
85
+ const conclusion = String(check.conclusion || '').toUpperCase()
86
+ const status = String(check.status || '').toUpperCase()
87
+ if (status && status !== 'COMPLETED') return true
88
+ if (!ALLOWED_TERMINAL_CONCLUSIONS.has(conclusion)) return true
89
+ return false
90
+ }
91
+
92
+ export function classifyFailure(check, config = DEFAULT_CLASSIFY_CONFIG) {
93
+ const name = String(check?.name || '')
94
+ const status = String(check?.status || '')
95
+ const rawConclusion = String(check?.conclusion || '')
96
+ // Present but incomplete checks often have conclusion:"" — surface status so briefs are readable.
97
+ const conclusion = rawConclusion
98
+ || (status && status.toUpperCase() !== 'COMPLETED' ? status : rawConclusion)
99
+ || 'PENDING'
100
+ const output = String(check?.output || check?.detail || '')
101
+ const text = `${name}\n${output}\n${conclusion}\n${status}`
102
+ const optionalGates = Array.isArray(config.optionalGates) ? config.optionalGates : []
103
+
104
+ for (const rule of config.neverAuto || []) {
105
+ if (rule.pattern.test(text)) {
106
+ return {
107
+ name,
108
+ conclusion,
109
+ status,
110
+ class: rule.class || 'critical',
111
+ allowlisted: false,
112
+ }
113
+ }
114
+ }
115
+
116
+ for (const rule of config.allowlist || []) {
117
+ if (!rule.pattern.test(text)) continue
118
+ if (rule.onlyOptionalGate) {
119
+ if (optionalGates.includes(name)) {
120
+ return { name, conclusion, status, class: rule.class, allowlisted: true }
121
+ }
122
+ // Missing *required* gate is critical, never allowlisted.
123
+ return { name, conclusion, status, class: 'critical', allowlisted: false }
124
+ }
125
+ return { name, conclusion, status, class: rule.class, allowlisted: true }
126
+ }
127
+
128
+ return { name, conclusion, status, class: 'unknown', allowlisted: false }
129
+ }
130
+
131
+ /**
132
+ * Classify every failing, incomplete, or missing-required check on the tip.
133
+ * A required check that is present but still in progress is blocked/not-green —
134
+ * never silent green on an empty conclusion.
135
+ */
136
+ export function classifyFailures({ checks, gates = [], config = DEFAULT_CLASSIFY_CONFIG } = {}) {
137
+ if (!Array.isArray(checks)) return []
138
+ const relevant = gates.length > 0 ? checks.filter((c) => gates.includes(c.name)) : checks
139
+ const failing = relevant.filter((c) => isCheckBlocking(c))
140
+ // Missing required gates also count as failures.
141
+ if (gates.length > 0) {
142
+ for (const g of gates) {
143
+ if (!checks.some((c) => c.name === g)) {
144
+ failing.push({
145
+ name: g,
146
+ conclusion: 'MISSING',
147
+ status: '',
148
+ output: 'required gate(s) reported no check-run on the target head',
149
+ })
150
+ }
151
+ }
152
+ }
153
+ return failing.map((c) => classifyFailure(c, config))
154
+ }
155
+
156
+ /**
157
+ * Core ensure path. All I/O is injectable so tests never hit the network.
158
+ *
159
+ * @param {object} opts
160
+ * @param {string|null} opts.headSha
161
+ * @param {Array|null} opts.checks
162
+ * @param {boolean} opts.readable
163
+ * @param {string[]} [opts.gates]
164
+ * @param {object} [opts.config]
165
+ * @param {'supervised'|'auto-repair-allowlist'} [opts.mode]
166
+ * @param {number} [opts.maxRepairRounds]
167
+ * @param {number} [opts.wallClockMinutes]
168
+ * @param {{recorded:boolean,by?:string,reason?:string}|null} [opts.humanOverride]
169
+ * @param {(brief:object)=>Promise<object>} opts.openRepair mockable resolve-issues handoff
170
+ * @param {()=>Promise<{headSha,checks,readable}>} opts.reProbe mandatory re-probe after repair
171
+ * @param {()=>number} [opts.now] ms since epoch (test clock)
172
+ */
173
+ export async function ensureTargetGreen(opts = {}) {
174
+ const {
175
+ headSha = null,
176
+ checks = null,
177
+ readable = true,
178
+ gates = [],
179
+ config = DEFAULT_CLASSIFY_CONFIG,
180
+ mode = MODES.SUPERVISED,
181
+ maxRepairRounds = DEFAULT_MAX_REPAIR_ROUNDS,
182
+ wallClockMinutes = DEFAULT_WALL_CLOCK_MINUTES,
183
+ humanOverride = null,
184
+ openRepair,
185
+ reProbe,
186
+ now = () => Date.now(),
187
+ } = opts
188
+
189
+ const startedAtMs = now()
190
+ const startedAt = new Date(startedAtMs).toISOString()
191
+ const deadline = startedAtMs + wallClockMinutes * 60_000
192
+ const attempts = []
193
+
194
+ const finish = (partial) => {
195
+ const finishedAtMs = now()
196
+ return {
197
+ ...partial,
198
+ startedAt,
199
+ finishedAt: new Date(finishedAtMs).toISOString(),
200
+ durationMs: finishedAtMs - startedAtMs,
201
+ attempts,
202
+ }
203
+ }
204
+
205
+ // Explicit human override recorded on the envelope may green without tip green.
206
+ if (humanOverride && humanOverride.recorded) {
207
+ attempts.push({ round: 0, state: STATES.GREEN, via: 'human-override' })
208
+ return finish({
209
+ state: STATES.GREEN,
210
+ headSha,
211
+ failing: [],
212
+ override: humanOverride,
213
+ reprobe: { required: false, skipped: 'human-override' },
214
+ })
215
+ }
216
+
217
+ if (!readable || !Array.isArray(checks)) {
218
+ attempts.push({ round: 0, state: STATES.UNKNOWN })
219
+ return finish({
220
+ state: STATES.UNKNOWN,
221
+ headSha,
222
+ failing: [],
223
+ brief: {
224
+ reason: 'unread-check-runs',
225
+ detail: 'the target branch check-runs could not be read — unknown is not green (#807 / principle 13)',
226
+ },
227
+ })
228
+ }
229
+
230
+ // classifyFailures is the source of truth for green — includes present-but-incomplete
231
+ // required gates (empty conclusion / non-COMPLETED status), not only terminal failures.
232
+ let currentHead = headSha
233
+ let currentChecks = checks
234
+ let failing = classifyFailures({ checks: currentChecks, gates, config })
235
+
236
+ if (failing.length === 0) {
237
+ attempts.push({ round: 0, state: STATES.GREEN, headSha: currentHead })
238
+ return finish({
239
+ state: STATES.GREEN,
240
+ headSha: currentHead,
241
+ failing: [],
242
+ })
243
+ }
244
+
245
+ // Tip red.
246
+ attempts.push({
247
+ round: 0,
248
+ state: STATES.BLOCKED,
249
+ headSha: currentHead,
250
+ failingClasses: failing.map((f) => f.class),
251
+ })
252
+
253
+ const allAllowlisted = failing.every((f) => f.allowlisted)
254
+
255
+ if (mode !== MODES.AUTO_REPAIR_ALLOWLIST) {
256
+ return finish({
257
+ state: STATES.BLOCKED,
258
+ headSha: currentHead,
259
+ failing,
260
+ brief: {
261
+ reason: 'supervised-mode',
262
+ strategy: 'resolve-issues',
263
+ failing,
264
+ detail:
265
+ 'tip is red; supervised mode hands a structured brief and holds the lease — do not auto-fix. ' +
266
+ 'Re-run ensure-target-green after repair lands, or pass humanOverride on the envelope.',
267
+ },
268
+ })
269
+ }
270
+
271
+ if (!allAllowlisted) {
272
+ return finish({
273
+ state: STATES.BLOCKED,
274
+ headSha: currentHead,
275
+ failing,
276
+ brief: {
277
+ reason: 'non-allowlisted-failure',
278
+ strategy: 'human',
279
+ failing,
280
+ detail:
281
+ 'at least one failure is critical/unknown — never auto-repair without a human ' +
282
+ '(auth/money/tenancy/migration, critical release gate, unknown class)',
283
+ },
284
+ })
285
+ }
286
+
287
+ // Allowlisted under auto-repair-allowlist: open repair, re-probe, loop under budget.
288
+ if (typeof openRepair !== 'function' || typeof reProbe !== 'function') {
289
+ return finish({
290
+ state: STATES.BLOCKED,
291
+ headSha: currentHead,
292
+ failing,
293
+ brief: {
294
+ reason: 'missing-handoff-seam',
295
+ detail: 'openRepair and reProbe seams are required for the auto-repair path',
296
+ },
297
+ })
298
+ }
299
+
300
+ let lastRepair = null
301
+ let lastReprobe = null
302
+ for (let round = 1; round <= maxRepairRounds; round += 1) {
303
+ if (now() > deadline) {
304
+ return finish({
305
+ state: STATES.BLOCKED,
306
+ headSha: currentHead,
307
+ failing,
308
+ repair: lastRepair,
309
+ reprobe: { required: true, ...(lastReprobe || {}) },
310
+ brief: {
311
+ reason: 'repair-budget-exhausted',
312
+ detail: `wall-clock budget of ${wallClockMinutes}m exhausted after ${round - 1} repair round(s)`,
313
+ },
314
+ })
315
+ }
316
+
317
+ const brief = {
318
+ strategy: 'resolve-issues',
319
+ headSha: currentHead,
320
+ failing,
321
+ lease: 'held', // same release attempt lease throughout
322
+ note: 'repair inside the attempt; do not open a second release behind it',
323
+ }
324
+ attempts.push({ round, state: STATES.REPAIRING, headSha: currentHead })
325
+ lastRepair = await openRepair(brief)
326
+ // Re-probe is mandatory after repair lands — never claim green on the old tip.
327
+ lastReprobe = await reProbe()
328
+ currentHead = lastReprobe?.headSha ?? currentHead
329
+ currentChecks = lastReprobe?.checks
330
+ const reReadable = lastReprobe?.readable !== false && Array.isArray(currentChecks)
331
+
332
+ if (!reReadable) {
333
+ attempts.push({ round, state: STATES.UNKNOWN, headSha: currentHead, phase: 'reprobe' })
334
+ return finish({
335
+ state: STATES.UNKNOWN,
336
+ headSha: currentHead,
337
+ failing,
338
+ repair: lastRepair,
339
+ reprobe: { required: true, readable: false },
340
+ brief: {
341
+ reason: 'reprobe-unread',
342
+ detail: 're-probe could not read check-runs on the new tip — unknown is not green',
343
+ },
344
+ })
345
+ }
346
+
347
+ failing = classifyFailures({ checks: currentChecks, gates, config })
348
+ if (failing.length === 0) {
349
+ attempts.push({ round, state: STATES.GREEN, headSha: currentHead, phase: 'reprobe' })
350
+ return finish({
351
+ state: STATES.GREEN,
352
+ headSha: currentHead,
353
+ failing: [],
354
+ repair: lastRepair,
355
+ reprobe: { required: true, headSha: currentHead, state: STATES.GREEN },
356
+ })
357
+ }
358
+
359
+ attempts.push({
360
+ round,
361
+ state: STATES.BLOCKED,
362
+ headSha: currentHead,
363
+ phase: 'reprobe',
364
+ failingClasses: failing.map((f) => f.class),
365
+ })
366
+
367
+ // Still red — only continue if still fully allowlisted.
368
+ if (!failing.every((f) => f.allowlisted)) {
369
+ return finish({
370
+ state: STATES.BLOCKED,
371
+ headSha: currentHead,
372
+ failing,
373
+ repair: lastRepair,
374
+ reprobe: { required: true, headSha: currentHead, state: STATES.BLOCKED },
375
+ brief: {
376
+ reason: 'non-allowlisted-failure',
377
+ failing,
378
+ detail: 're-probe still red with a non-allowlisted class — hand to human',
379
+ },
380
+ })
381
+ }
382
+ }
383
+
384
+ return finish({
385
+ state: STATES.BLOCKED,
386
+ headSha: currentHead,
387
+ failing,
388
+ repair: lastRepair,
389
+ reprobe: { required: true, ...(lastReprobe ? { headSha: lastReprobe.headSha } : {}) },
390
+ brief: {
391
+ reason: 'repair-budget-exhausted',
392
+ detail: `maxRepairRounds=${maxRepairRounds} exhausted; tip still red — permanent flake cannot thrash forever`,
393
+ },
394
+ })
395
+ }
396
+
397
+ /** Write release.ensureGreen onto a manifest (pure). */
398
+ export function recordEnsureGreen(manifest, result) {
399
+ const m = structuredClone(manifest || {})
400
+ if (!m.release || typeof m.release !== 'object') m.release = {}
401
+ m.release.ensureGreen = {
402
+ startedAt: result.startedAt,
403
+ finishedAt: result.finishedAt,
404
+ durationMs: result.durationMs,
405
+ attempts: result.attempts || [],
406
+ finalHead: result.headSha || null,
407
+ outcome: result.state,
408
+ failingClasses: (result.failing || []).map((f) => f.class),
409
+ repairPrs: result.repair?.prs || [],
410
+ repairIssues: result.repair?.issues || [],
411
+ override: result.override || null,
412
+ }
413
+ return m
414
+ }
415
+
416
+ export function parseArgs(argv) {
417
+ const args = {
418
+ gates: [],
419
+ mode: MODES.SUPERVISED,
420
+ maxRepairRounds: DEFAULT_MAX_REPAIR_ROUNDS,
421
+ wallClockMinutes: DEFAULT_WALL_CLOCK_MINUTES,
422
+ }
423
+ for (let i = 0; i < argv.length; i += 1) {
424
+ const a = argv[i]
425
+ if (a === '--repo') args.repo = argv[++i]
426
+ else if (a === '--target-branch') args.targetBranch = argv[++i]
427
+ else if (a === '--gate') args.gates.push(argv[++i])
428
+ else if (a === '--classify-config') args.classifyConfig = argv[++i]
429
+ else if (a === '--mode') args.mode = argv[++i]
430
+ else if (a === '--max-repair-rounds') args.maxRepairRounds = Number(argv[++i])
431
+ else if (a === '--wall-clock-minutes') args.wallClockMinutes = Number(argv[++i])
432
+ else if (a === '--json') args.json = true
433
+ else if (a === '--help' || a === '-h') args.help = true
434
+ else if (a === '--dry-classify') args.dryClassify = true
435
+ else if (a.startsWith('-')) {
436
+ // Keep the first unknown flag token (not a following value) so --gat x reports --gat.
437
+ if (!args.unknown) args.unknown = a
438
+ } else if (!args.unknown) {
439
+ // No positionals on this CLI — bare junk is also a usage error (exit 2).
440
+ args.unknown = a
441
+ }
442
+ }
443
+ return args
444
+ }
445
+
446
+ function help() {
447
+ return `ensure-target-green — tip check-runs repair phase (#807)
448
+
449
+ Standalone surface (Option 4). Classifies target-branch tip failures, optionally
450
+ opens allowlisted repair work via a resolve-issues brief, re-probes the NEW tip,
451
+ and only then reports green so the release envelope can proceed.
452
+
453
+ Usage:
454
+ node …/ensure-target-green.mjs \\
455
+ --repo <owner/name> --target-branch <prod> \\
456
+ [--gate <check-name>…] \\
457
+ [--classify-config <path>] \\
458
+ [--mode supervised|auto-repair-allowlist] \\
459
+ [--max-repair-rounds <n>] \\
460
+ [--wall-clock-minutes <n>] \\
461
+ [--json] [--dry-classify]
462
+
463
+ Modes:
464
+ supervised (default) classify + structured brief; never auto-opens repair
465
+ auto-repair-allowlist open repair only when every failure is allowlisted
466
+
467
+ Exit codes:
468
+ 0 state=green
469
+ 1 state=blocked|repairing|unknown (not green — do not confirm envelope)
470
+ 2 usage error
471
+
472
+ Non-overlap:
473
+ · tip check-runs only — live floor / public-host DEAD is #800 (floorReadiness)
474
+ · true remote tip / tag-push / blank-percent honesty is #799
475
+ · never skip/weaken required gates; never claim green on a different SHA
476
+ · never stuff tip repairs into the promotion PR
477
+
478
+ JSON: { state, headSha, failing[{name,conclusion,class,allowlisted}], repair?, reprobe?, brief? }`
479
+ }
480
+
481
+ const safeJson = (t) => { try { return JSON.parse(t) } catch { return null } }
482
+
483
+ /** owner/name only — rejects shell metacharacters before any process spawn. */
484
+ export const REPO_NAME_RE = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/
485
+
486
+ export function isValidRepo(repo) {
487
+ return REPO_NAME_RE.test(String(repo || ''))
488
+ }
489
+
490
+ /**
491
+ * Invoke `gh api` via argv (never /bin/sh -c). Path segments are validated/
492
+ * encoded so operator- or orchestrator-supplied --repo cannot inject shell.
493
+ */
494
+ function ghApi({ path, jq, timeout = 60_000 } = {}) {
495
+ try {
496
+ const args = ['api', path]
497
+ if (jq != null) args.push('--jq', jq)
498
+ const stdout = execFileSync('gh', args, {
499
+ encoding: 'utf8',
500
+ stdio: ['ignore', 'pipe', 'pipe'],
501
+ timeout,
502
+ })
503
+ return { ok: true, stdout, stderr: '' }
504
+ } catch (error) {
505
+ return {
506
+ ok: false,
507
+ stdout: error.stdout?.toString?.() || '',
508
+ stderr: error.stderr?.toString?.() || error.message || '',
509
+ }
510
+ }
511
+ }
512
+
513
+ function loadConfig(path) {
514
+ if (!path) return DEFAULT_CLASSIFY_CONFIG
515
+ const raw = JSON.parse(readFileSync(path, 'utf8'))
516
+ // Patterns arrive as strings in JSON; compile them.
517
+ const compile = (rules = []) => rules.map((r) => ({
518
+ ...r,
519
+ pattern: r.pattern instanceof RegExp ? r.pattern : new RegExp(r.pattern, r.flags || 'i'),
520
+ }))
521
+ return {
522
+ optionalGates: raw.optionalGates || [],
523
+ neverAuto: compile(raw.neverAuto || DEFAULT_CLASSIFY_CONFIG.neverAuto.map((r) => ({
524
+ class: r.class,
525
+ pattern: r.pattern.source,
526
+ flags: r.pattern.flags,
527
+ }))),
528
+ allowlist: compile(raw.allowlist || DEFAULT_CLASSIFY_CONFIG.allowlist.map((r) => ({
529
+ class: r.class,
530
+ pattern: r.pattern.source,
531
+ flags: r.pattern.flags,
532
+ onlyOptionalGate: r.onlyOptionalGate,
533
+ }))),
534
+ }
535
+ }
536
+
537
+ /**
538
+ * Fetch tip SHA + check-runs without a shell. Repo must be owner/name;
539
+ * branch is a single path segment (URI-encoded), never interpolated into sh -c.
540
+ * Exported for regression tests that assert argv form / validation.
541
+ */
542
+ export function fetchTip({ repo, targetBranch, api = ghApi } = {}) {
543
+ if (!isValidRepo(repo)) {
544
+ return {
545
+ headSha: null,
546
+ checks: null,
547
+ readable: false,
548
+ error: `invalid --repo ${repo}; expected owner/name`,
549
+ }
550
+ }
551
+ const branch = encodeURIComponent(String(targetBranch || ''))
552
+ const sha = api({ path: `repos/${repo}/commits/${branch}`, jq: '.sha' })
553
+ const checks = api({
554
+ path: `repos/${repo}/commits/${branch}/check-runs`,
555
+ jq: '[.check_runs[] | {name: .name, status: (.status // ""), conclusion: (.conclusion // ""), output: ((.output.summary // "") + " " + (.output.title // ""))}]',
556
+ })
557
+ return {
558
+ headSha: sha.ok ? String(sha.stdout || '').trim() : null,
559
+ checks: checks.ok ? safeJson(checks.stdout) : null,
560
+ readable: sha.ok && checks.ok,
561
+ }
562
+ }
563
+
564
+ /**
565
+ * Default openRepair: emit a structured resolve-issues brief to stdout/stderr and return
566
+ * a handoff record. Real spawn is the caller's job (agent / resolve-release phase); this
567
+ * seam is deliberately mockable and does not nest an orchestrator in v1.
568
+ */
569
+ export async function defaultOpenRepair(brief) {
570
+ // Structured brief the agent (or resolve-issues) consumes. We do not auto-merge anything.
571
+ return {
572
+ opened: true,
573
+ strategy: 'resolve-issues',
574
+ brief,
575
+ issues: [],
576
+ prs: [],
577
+ note: 'structured brief ready — open/land repair via resolve-issues while the release lease is held; re-probe before resume',
578
+ }
579
+ }
580
+
581
+ export async function runCli(argv) {
582
+ const args = parseArgs(argv)
583
+ if (args.help) {
584
+ console.log(help())
585
+ return 0
586
+ }
587
+ // Fail closed on any unknown flag BEFORE fetchTip/classification — a mistyped
588
+ // --gate / --classify-config must never silently skip the required-gate check
589
+ // or fall back to the default allowlist (exit 2 usage contract).
590
+ if (args.unknown) {
591
+ console.error(`ensure-target-green: unknown flag ${args.unknown} (see --help)`)
592
+ return 2
593
+ }
594
+ if (!args.repo || !args.targetBranch) {
595
+ console.error(help())
596
+ return 2
597
+ }
598
+ if (!isValidRepo(args.repo)) {
599
+ console.error(`ensure-target-green: invalid --repo ${args.repo}; expected owner/name`)
600
+ return 2
601
+ }
602
+ if (args.mode && !Object.values(MODES).includes(args.mode)) {
603
+ console.error(`unknown --mode ${args.mode}; expected ${Object.values(MODES).join('|')}`)
604
+ return 2
605
+ }
606
+
607
+ const config = loadConfig(args.classifyConfig)
608
+ const tip = fetchTip({ repo: args.repo, targetBranch: args.targetBranch })
609
+
610
+ if (args.dryClassify) {
611
+ const failing = tip.readable
612
+ ? classifyFailures({ checks: tip.checks, gates: args.gates, config })
613
+ : []
614
+ const out = {
615
+ state: !tip.readable ? STATES.UNKNOWN : failing.length === 0 ? STATES.GREEN : STATES.BLOCKED,
616
+ headSha: tip.headSha,
617
+ failing,
618
+ }
619
+ console.log(JSON.stringify(out, null, 2))
620
+ return out.state === STATES.GREEN ? 0 : 1
621
+ }
622
+
623
+ // Live CLI: supervised by default — classify + brief. Auto-repair opens a structured
624
+ // handoff but does not itself wait for land (the release agent holds the lease and
625
+ // re-invokes after repair lands, or supplies injectable seams when embedding).
626
+ const result = await ensureTargetGreen({
627
+ headSha: tip.headSha,
628
+ checks: tip.checks,
629
+ readable: tip.readable,
630
+ gates: args.gates,
631
+ config,
632
+ mode: args.mode,
633
+ maxRepairRounds: args.maxRepairRounds,
634
+ wallClockMinutes: args.wallClockMinutes,
635
+ openRepair: defaultOpenRepair,
636
+ reProbe: async () => fetchTip({ repo: args.repo, targetBranch: args.targetBranch }),
637
+ })
638
+
639
+ if (args.json) console.log(JSON.stringify(result, null, 2))
640
+ else {
641
+ console.log(`state=${result.state} head=${result.headSha || '(unknown)'}`)
642
+ if (result.failing?.length) {
643
+ for (const f of result.failing) {
644
+ console.log(` failing: ${f.name}=${f.conclusion} class=${f.class} allowlisted=${f.allowlisted}`)
645
+ }
646
+ }
647
+ if (result.brief) console.log(` brief: ${result.brief.reason} — ${result.brief.detail || ''}`)
648
+ if (result.repair) console.log(` repair: strategy=${result.repair.strategy || 'resolve-issues'}`)
649
+ if (result.reprobe) console.log(` reprobe: required=${result.reprobe.required !== false}`)
650
+ console.log(` durationMs=${result.durationMs}`)
651
+ }
652
+ return result.state === STATES.GREEN ? 0 : 1
653
+ }
654
+
655
+ if (isMainModule(import.meta.url)) {
656
+ runCli(process.argv.slice(2)).then((code) => {
657
+ process.exitCode = code
658
+ })
659
+ }