@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,326 @@
1
+ #!/usr/bin/env node
2
+ import { createHash } from 'node:crypto'
3
+ import fs from 'node:fs'
4
+ import { execFileSync } from 'node:child_process'
5
+ import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
6
+ import { normalizeReleaseVerdict } from '../../resolve-issues/scripts/release-state-contract.mjs'
7
+
8
+ export const PRODUCTION_ENDPOINTS_SCHEMA_VERSION = 1
9
+ export const DEFAULT_FLOOR_FRESHNESS_MINUTES = 30
10
+
11
+ function nonEmpty(value) {
12
+ return typeof value === 'string' && value.trim().length > 0
13
+ }
14
+
15
+ export function normalizeProductionUrl(value) {
16
+ if (!nonEmpty(value)) throw new Error('endpoint URL must be a non-empty HTTPS URL')
17
+ let parsed
18
+ try {
19
+ parsed = new URL(value.trim())
20
+ } catch {
21
+ throw new Error('endpoint URL must be a non-empty HTTPS URL')
22
+ }
23
+ if (parsed.protocol !== 'https:' || parsed.username || parsed.password || parsed.search || parsed.hash) {
24
+ throw new Error('endpoint URL must use HTTPS and must not contain credentials, query, or fragment')
25
+ }
26
+ const pathname = parsed.pathname.replace(/\/+$/, '')
27
+ return `${parsed.origin}${pathname}`
28
+ }
29
+
30
+ function endpointRecord(canonicalProductionUrl, cloudRunServiceUrl, now) {
31
+ const canonical = normalizeProductionUrl(canonicalProductionUrl)
32
+ const service = normalizeProductionUrl(cloudRunServiceUrl)
33
+ const canonicalHost = new URL(canonical).hostname.toLowerCase()
34
+ const serviceHost = new URL(service).hostname.toLowerCase()
35
+ const configurationFingerprint = createHash('sha256')
36
+ .update(JSON.stringify({ canonicalProductionUrl: canonical, cloudRunServiceUrl: service }))
37
+ .digest('hex')
38
+ return {
39
+ schemaVersion: PRODUCTION_ENDPOINTS_SCHEMA_VERSION,
40
+ canonicalProductionUrl: canonical,
41
+ cloudRunServiceUrl: service,
42
+ distinctPublicEdgeHost: canonicalHost !== serviceHost,
43
+ publicEdgeHostname: canonicalHost !== serviceHost ? canonicalHost : null,
44
+ configurationFingerprint,
45
+ canonicalSource: "deploy-trigger-config",
46
+ serviceSource: "cloud-run-service",
47
+ checkedAt: new Date(now).toISOString(),
48
+ }
49
+ }
50
+
51
+ export function validateProductionEndpointRecord(record) {
52
+ if (!record || record.schemaVersion !== PRODUCTION_ENDPOINTS_SCHEMA_VERSION) {
53
+ return { ok: false, id: 'production-endpoints-missing', detail: 'preflight production endpoint record is missing or malformed' }
54
+ }
55
+ let expected
56
+ try { expected = endpointRecord(record.canonicalProductionUrl, record.cloudRunServiceUrl, Date.parse(record.checkedAt)) } catch (error) {
57
+ return { ok: false, id: 'production-endpoints-invalid', detail: error.message }
58
+ }
59
+ if (!Number.isFinite(Date.parse(record.checkedAt))
60
+ || record.canonicalSource !== expected.canonicalSource
61
+ || record.serviceSource !== expected.serviceSource
62
+ || record.canonicalProductionUrl !== expected.canonicalProductionUrl
63
+ || record.cloudRunServiceUrl !== expected.cloudRunServiceUrl
64
+ || record.distinctPublicEdgeHost !== expected.distinctPublicEdgeHost
65
+ || record.publicEdgeHostname !== expected.publicEdgeHostname
66
+ || record.configurationFingerprint !== expected.configurationFingerprint) {
67
+ return { ok: false, id: 'production-endpoints-invalid', detail: 'endpoint topology or fingerprint does not match the recorded URLs' }
68
+ }
69
+ return { ok: true, record }
70
+ }
71
+
72
+ function usableFreshness(value) {
73
+ return typeof value === "number" && Number.isFinite(value) && value > 0
74
+ ? value
75
+ : DEFAULT_FLOOR_FRESHNESS_MINUTES
76
+ }
77
+
78
+ function freshnessFailure(checkedAt, now, freshnessMinutes) {
79
+ const timestamp = typeof checkedAt === "string" ? Date.parse(checkedAt) : NaN
80
+ if (!Number.isFinite(timestamp)) return "floor-verdict-unstamped"
81
+ const ageMinutes = (now - timestamp) / 60_000
82
+ if (ageMinutes < 0 || ageMinutes > usableFreshness(freshnessMinutes)) return "floor-verdict-stale"
83
+ return null
84
+ }
85
+
86
+ export function evaluateProductionFloor(record, floorReadiness, {
87
+ now = Date.now(), freshnessMinutes = DEFAULT_FLOOR_FRESHNESS_MINUTES,
88
+ } = {}) {
89
+ const recordValidation = validateProductionEndpointRecord(record)
90
+ if (!recordValidation.ok) return recordValidation
91
+ if (!floorReadiness || typeof floorReadiness !== "object") {
92
+ return { ok: false, id: "floor-verdict-missing", detail: "floor readiness was not recorded at endpoint preflight" }
93
+ }
94
+ if (floorReadiness.endpointFingerprint !== record.configurationFingerprint) {
95
+ return { ok: false, id: "floor-endpoint-configuration-mismatch", detail: "floor readiness describes a different endpoint configuration" }
96
+ }
97
+
98
+ const status = String(floorReadiness.status || "").toLowerCase()
99
+ if (!record.distinctPublicEdgeHost) {
100
+ if (status !== "skipped" || !nonEmpty(floorReadiness.reason)) {
101
+ return { ok: false, id: "cloud-run-only-skip-missing", detail: "Cloud Run-only topology requires the reasoned preflight skip" }
102
+ }
103
+ return { ok: true, evidence: { floorReadiness } }
104
+ }
105
+
106
+ if (status !== "alive") {
107
+ return { ok: false, id: "floor-not-alive", detail: "a distinct public/edge host requires prod-active ALIVE and cannot be skipped" }
108
+ }
109
+ if (floorReadiness.profile !== "prod-active") {
110
+ return { ok: false, id: "floor-profile-mismatch", detail: "distinct-host floor evidence must use profile prod-active" }
111
+ }
112
+ let target
113
+ try { target = normalizeProductionUrl(floorReadiness.target) } catch {
114
+ return { ok: false, id: "floor-target-mismatch", detail: "floor target is not the canonical configured production URL" }
115
+ }
116
+ if (target !== record.canonicalProductionUrl) {
117
+ return { ok: false, id: "floor-target-mismatch", detail: "floor target is not the canonical configured production URL" }
118
+ }
119
+ if (floorReadiness.noMutations !== true) {
120
+ return { ok: false, id: "floor-not-read-only", detail: "prod-active floor evidence must be read-only" }
121
+ }
122
+ const freshness = freshnessFailure(floorReadiness.checkedAt, now, freshnessMinutes)
123
+ if (freshness) return { ok: false, id: freshness, detail: "prod-active floor evidence is missing a fresh timestamp" }
124
+ return { ok: true, evidence: { floorReadiness } }
125
+ }
126
+
127
+ export function buildProductionEndpointRecord({
128
+ canonicalProductionUrl, cloudRunServiceUrl, floorVerdict = null,
129
+ now = Date.now(), freshnessMinutes = DEFAULT_FLOOR_FRESHNESS_MINUTES,
130
+ } = {}) {
131
+ let record
132
+ try {
133
+ record = endpointRecord(canonicalProductionUrl, cloudRunServiceUrl, now)
134
+ } catch (error) {
135
+ return { ok: false, failed: ["endpoint-read-invalid"], detail: error.message }
136
+ }
137
+
138
+ if (!record.distinctPublicEdgeHost) {
139
+ const floorReadiness = {
140
+ status: "skipped",
141
+ reason: "canonical configured production URL has the same hostname as the Cloud Run service URL; no distinct public/edge hostname exists",
142
+ endpointFingerprint: record.configurationFingerprint,
143
+ checkedAt: record.checkedAt,
144
+ }
145
+ return { ok: true, record, floorReadiness, failed: [] }
146
+ }
147
+
148
+ const normalized = normalizeReleaseVerdict(floorVerdict)
149
+ const floorReadiness = normalized && {
150
+ status: String(normalized.state).toLowerCase(),
151
+ profile: normalized.profile,
152
+ target: normalized.target,
153
+ noMutations: normalized.noMutations,
154
+ checkedAt: normalized.generatedAt,
155
+ endpointFingerprint: record.configurationFingerprint,
156
+ }
157
+ const evaluation = evaluateProductionFloor(record, floorReadiness, { now, freshnessMinutes })
158
+ return evaluation.ok
159
+ ? { ok: true, record, floorReadiness, failed: [] }
160
+ : { ok: false, record, floorReadiness, failed: [evaluation.id], detail: evaluation.detail }
161
+ }
162
+
163
+ export function revalidateProductionEndpoints(stored, {
164
+ canonicalProductionUrl, cloudRunServiceUrl, now = Date.now(),
165
+ } = {}) {
166
+ const storedValidation = validateProductionEndpointRecord(stored)
167
+ if (!storedValidation.ok) return { ...storedValidation, detail: `resume requires a valid preflight endpoint record: ${storedValidation.detail}` }
168
+ let current
169
+ try { current = endpointRecord(canonicalProductionUrl, cloudRunServiceUrl, now) } catch (error) {
170
+ return { ok: false, id: "endpoint-read-invalid", detail: error.message }
171
+ }
172
+ if (stored.configurationFingerprint !== current.configurationFingerprint) {
173
+ return { ok: false, id: "endpoint-configuration-changed", previous: stored, current }
174
+ }
175
+ return { ok: true, id: null, previous: stored, current }
176
+ }
177
+
178
+ export function verifyCanonicalProductionTarget(record, target) {
179
+ const recordValidation = validateProductionEndpointRecord(record)
180
+ if (!recordValidation.ok) return recordValidation
181
+ let normalized
182
+ try { normalized = normalizeProductionUrl(target) } catch {
183
+ return { ok: false, id: "canonical-production-target-mismatch" }
184
+ }
185
+ if (normalized !== record.canonicalProductionUrl) {
186
+ return { ok: false, id: "canonical-production-target-mismatch", expected: record.canonicalProductionUrl, actual: normalized }
187
+ }
188
+ return { ok: true, target: normalized }
189
+ }
190
+
191
+ function runCommand(command) {
192
+ try {
193
+ const stdout = execFileSync('/bin/sh', ['-c', command], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], timeout: 60_000 })
194
+ const lines = stdout.split("\n").map((line) => line.trim()).filter(Boolean)
195
+ if (lines.length !== 1) return { ok: false, detail: `command must emit exactly one URL line (got ${lines.length})` }
196
+ return { ok: true, value: lines[0] }
197
+ } catch (error) {
198
+ return { ok: false, detail: error.stderr?.toString?.().trim() || error.message }
199
+ }
200
+ }
201
+
202
+ function readJson(file, label) {
203
+ try { return { ok: true, value: JSON.parse(fs.readFileSync(file, "utf8")) } } catch (error) {
204
+ return { ok: false, detail: `${label} is unreadable or invalid JSON: ${error.message}` }
205
+ }
206
+ }
207
+
208
+ const VALUE_FLAGS = new Set([
209
+ "canonical-url-command", "service-url-command", "floor-verdict", "manifest", "target",
210
+ "now", "freshness-minutes",
211
+ ])
212
+
213
+ function parseArgs(argv) {
214
+ const opts = {}, positional = [], errors = []
215
+ for (let i = 0; i < argv.length; i += 1) {
216
+ const arg = argv[i]
217
+ if (arg === "--help" || arg === "-h") opts.help = true
218
+ else if (arg.startsWith("--")) {
219
+ const key = arg.slice(2)
220
+ if (!VALUE_FLAGS.has(key)) { errors.push(`unknown flag ${arg}`); continue }
221
+ const value = argv[++i]
222
+ if (value == null || value.startsWith("--")) {
223
+ errors.push(`missing value for ${arg}`)
224
+ if (value != null) i -= 1
225
+ } else opts[key] = value
226
+ } else positional.push(arg)
227
+ }
228
+ return { command: positional[0], opts, extra: positional.slice(1), errors }
229
+ }
230
+
231
+ function help() {
232
+ return `production-endpoints — decide production floor applicability before RC mint.
233
+
234
+ Usage:
235
+ production-endpoints preflight --canonical-url-command <cmd> --service-url-command <cmd> [--floor-verdict <json>]
236
+ production-endpoints resume --manifest <json> --canonical-url-command <cmd> --service-url-command <cmd>
237
+ production-endpoints verify-live --manifest <json> --target <url>
238
+ production-endpoints live-target --manifest <json>
239
+
240
+ The canonical command reads the deploy trigger configured production URL (for example
241
+ _APP_BASE_URL). The service command independently reads the active Cloud Run service URL.
242
+ A distinct hostname requires a fresh read-only prod-active ALIVE verdict on the canonical
243
+ URL. Equal hostnames produce a reasoned Cloud Run-only skip. Resume re-runs both reads.
244
+
245
+ Output from preflight is a run-state merge patch. Record it before candidate deployment.
246
+
247
+ Exit: 0 pass; 1 hold/configuration changed; 2 usage or unreadable input.`
248
+ }
249
+
250
+ function loadManifest(file) {
251
+ const loaded = readJson(file, "manifest")
252
+ if (!loaded.ok) return loaded
253
+ if (loaded.value?.skill !== "resolve-release") return { ok: false, detail: "manifest is not a resolve-release run" }
254
+ return loaded
255
+ }
256
+
257
+ export function main(argv) {
258
+ const { command, opts, extra, errors } = parseArgs(argv)
259
+ if (opts.help || command === "help") { console.log(help()); return 0 }
260
+ if (errors.length || extra.length || !["preflight", "resume", "verify-live", "live-target"].includes(command)) {
261
+ if (errors.length) console.error(`production-endpoints: ${errors.join("; ")}`)
262
+ console.error(help())
263
+ return 2
264
+ }
265
+ const now = opts.now ? Date.parse(opts.now) : Date.now()
266
+ if (!Number.isFinite(now)) { console.error("production-endpoints: --now must be an ISO timestamp"); return 2 }
267
+
268
+ if (command === "live-target") {
269
+ if (!opts.manifest) { console.error(help()); return 2 }
270
+ const manifest = loadManifest(opts.manifest)
271
+ if (!manifest.ok) { console.error(`production-endpoints: ${manifest.detail}`); return 2 }
272
+ const record = manifest.value.release?.productionEndpoints
273
+ const result = verifyCanonicalProductionTarget(record, record?.canonicalProductionUrl)
274
+ if (!result.ok) { console.log(JSON.stringify(result, null, 2)); return 1 }
275
+ console.log(result.target)
276
+ return 0
277
+ }
278
+
279
+ if (command === "verify-live") {
280
+ if (!opts.manifest || !opts.target) { console.error(help()); return 2 }
281
+ const manifest = loadManifest(opts.manifest)
282
+ if (!manifest.ok) { console.error(`production-endpoints: ${manifest.detail}`); return 2 }
283
+ const result = verifyCanonicalProductionTarget(manifest.value.release?.productionEndpoints, opts.target)
284
+ console.log(JSON.stringify(result, null, 2))
285
+ return result.ok ? 0 : 1
286
+ }
287
+
288
+ if (!opts["canonical-url-command"] || !opts["service-url-command"]) { console.error(help()); return 2 }
289
+ const canonical = runCommand(opts["canonical-url-command"])
290
+ const service = runCommand(opts["service-url-command"])
291
+ if (!canonical.ok || !service.ok) {
292
+ console.error(`production-endpoints: endpoint read failed: ${canonical.detail || service.detail}`)
293
+ return 1
294
+ }
295
+
296
+ if (command === "resume") {
297
+ if (!opts.manifest) { console.error(help()); return 2 }
298
+ const manifest = loadManifest(opts.manifest)
299
+ if (!manifest.ok) { console.error(`production-endpoints: ${manifest.detail}`); return 2 }
300
+ const result = revalidateProductionEndpoints(manifest.value.release?.productionEndpoints, {
301
+ canonicalProductionUrl: canonical.value, cloudRunServiceUrl: service.value, now,
302
+ })
303
+ console.log(JSON.stringify(result, null, 2))
304
+ return result.ok ? 0 : 1
305
+ }
306
+
307
+ let floorVerdict = null
308
+ if (opts["floor-verdict"]) {
309
+ const loaded = readJson(opts["floor-verdict"], "floor verdict")
310
+ if (!loaded.ok) { console.error(`production-endpoints: ${loaded.detail}`); return 2 }
311
+ floorVerdict = loaded.value
312
+ }
313
+ const freshnessMinutes = opts["freshness-minutes"] == null ? DEFAULT_FLOOR_FRESHNESS_MINUTES : Number(opts["freshness-minutes"])
314
+ if (!usableFreshness(freshnessMinutes)) { console.error("production-endpoints: --freshness-minutes must be positive"); return 2 }
315
+ const result = buildProductionEndpointRecord({
316
+ canonicalProductionUrl: canonical.value, cloudRunServiceUrl: service.value,
317
+ floorVerdict, now, freshnessMinutes,
318
+ })
319
+ if (!result.ok) { console.log(JSON.stringify(result, null, 2)); return 1 }
320
+ console.log(JSON.stringify({ release: {
321
+ productionEndpoints: result.record, floorReadiness: result.floorReadiness,
322
+ } }, null, 2))
323
+ return 0
324
+ }
325
+
326
+ if (isMainModule(import.meta.url)) process.exitCode = main(process.argv.slice(2))
@@ -0,0 +1,272 @@
1
+ // rc-circuit-breaker — hold repeated release-tooling failures behind a circuit breaker (#962).
2
+ //
3
+ // WHY THIS EXISTS. Forex v0.1.12 minted NINE immutable RCs. After RC.2 and RC.3, two healthy
4
+ // candidates had reached 100% and been rolled back because the lane's own verifier misread valid
5
+ // platform state — and nothing stopped the larger loop in which tooling-only retries kept
6
+ // generating new production attempts. Each attempt's fail-closed behavior was correct; what was
7
+ // missing was a breaker over the LOOP: after enough failures owned by the release tooling or the
8
+ // gate environment, the next immutable RC is held for explicit release-design review instead of
9
+ // being minted on autopilot.
10
+ //
11
+ // WHAT IT READS. The durable evidence bundles only — the same immutable record
12
+ // version-postmortem.mjs aggregates — via `discoverVersionBundles`, classified by #961's
13
+ // `classifyFailureOwner`. It never reads a live service, never a run manifest, and it NEVER
14
+ // writes: the check is read-only over the durable dir, so a hold deletes nothing, moves no tag,
15
+ // and burns no version (the issue's AC). The release lane runs it at step 3, BEFORE
16
+ // `version.mjs rc` mints the next immutable RC (references/candidate.md), and records the
17
+ // decision JSON on the manifest (`release.circuitBreaker`) so the post-mortem can report whether
18
+ // the breaker fired and how it was resolved.
19
+ //
20
+ // THE COUNT. Prior NON-RELEASED attempts for the same proposed version whose normalized failure
21
+ // owner is `release-tooling` or `gate-environment` (BREAKER_OWNERS — the two lane-side owners of
22
+ // #961's taxonomy). Application, configuration and platform failures are real failures with
23
+ // their own routes; they are reported in `ownerCounts` but never consume this threshold, because
24
+ // this breaker exists for exactly one signal: the lane's own machinery failing repeatedly.
25
+ // `released` is not a failure; `revoked`/`blocked-manual` classify to no owner and never count.
26
+ //
27
+ // THE THRESHOLD. Default 2 prior qualifying failures (the issue's approved default).
28
+ // Configurable: `--threshold <n>` beats `$RC_CIRCUIT_BREAKER_THRESHOLD` beats the default, and
29
+ // the decision records which source set it — configuration is DECLARED IN THE RECORD, never
30
+ // silent. What no flag or env var can do is skip the check: the only way past a hold is the
31
+ // recorded human authorization below.
32
+ //
33
+ // THE HOLD. Crossing the threshold returns `hold-for-release-design-review` (exit 1) with the
34
+ // count, the per-owner breakdown, the qualifying attempt ids, their phases, and the bundle files
35
+ // as evidence links. Fail-closed both ways: an unreadable dir or an unparseable bundle is a
36
+ // refusal (exit 2, nothing on stdout) — the same reading evidence-bundle.mjs's mint takes —
37
+ // never an empty history.
38
+ //
39
+ // CONTINUING PAST A HOLD is a human's explicit, recorded decision — not an env bypass. The
40
+ // authorization is a structured JSON record (`--authorization <file>`):
41
+ // {
42
+ // "version": "<the proposed version>", // must match the check's version
43
+ // "againstCount": <current qualifyingCount>, // binds the record to THIS count: one
44
+ // // authorization covers exactly ONE
45
+ // // continuation; a further qualifying
46
+ // // failure re-holds and the stale record
47
+ // // does not carry
48
+ // "authorizedBy": "<the human>",
49
+ // "authorizedAt": "<ISO timestamp>",
50
+ // "rationale": "<why another RC is preferable to simplifying, removing, or externally
51
+ // repairing the gate>",
52
+ // "alternativesConsidered": { "simplify": …, "remove": …, "externalRepair": … } // optional
53
+ // }
54
+ // A valid record turns the hold into `authorized-continue` (exit 0) echoing the record, which
55
+ // the lane merges onto the manifest. An invalid or stale record leaves the hold standing and
56
+ // names why (`authorizationError`).
57
+
58
+ import fs from 'node:fs'
59
+
60
+ import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
61
+ import {
62
+ FAILURE_OWNERS,
63
+ classifyFailureOwner,
64
+ classifyFailurePhase,
65
+ discoverVersionBundles,
66
+ } from './version-postmortem.mjs'
67
+
68
+ // The contract surface. The two lane-side owners, the default of two, the env var name, and the
69
+ // decision strings are what the doctrine (references/candidate.md, references/postmortem.md)
70
+ // states — changing any of them is a breaking change to that contract.
71
+ export const BREAKER_OWNERS = ['release-tooling', 'gate-environment']
72
+ export const DEFAULT_THRESHOLD = 2
73
+ export const THRESHOLD_ENV = 'RC_CIRCUIT_BREAKER_THRESHOLD'
74
+ export const HOLD_DECISION = 'hold-for-release-design-review'
75
+ export const PROCEED_DECISION = 'proceed'
76
+ export const AUTHORIZED_DECISION = 'authorized-continue'
77
+
78
+ const nonEmpty = (v) => typeof v === 'string' && v.trim() !== ''
79
+
80
+ // Flag beats env beats default; an invalid value from any source is a refusal, never a silent
81
+ // fall-back — a threshold nobody can account for is the check not running.
82
+ export function resolveThreshold({ flag = null, env = process.env } = {}) {
83
+ const parse = (raw, source) => {
84
+ const n = Number(raw)
85
+ if (!Number.isInteger(n) || n < 1) {
86
+ throw new Error(`rc-circuit-breaker: invalid threshold ${JSON.stringify(raw)} from ${source} — an integer >= 1 is required`)
87
+ }
88
+ return { threshold: n, thresholdSource: source }
89
+ }
90
+ if (flag != null) return parse(flag, 'flag')
91
+ if (nonEmpty(env[THRESHOLD_ENV])) return parse(env[THRESHOLD_ENV], 'env')
92
+ return { threshold: DEFAULT_THRESHOLD, thresholdSource: 'default' }
93
+ }
94
+
95
+ // The evaluation: count prior non-released attempts for this proposed version by normalized
96
+ // failure owner, and decide. THROWS on an unreadable dir or an unparseable bundle — the caller
97
+ // (CLI) turns that into the exit-2 refusal; a gate that cannot establish the count does not get
98
+ // to answer "below threshold".
99
+ export function evaluateRcCircuitBreaker({ dir, version, threshold = DEFAULT_THRESHOLD, thresholdSource = 'default' } = {}) {
100
+ const { attempts, unreadable } = discoverVersionBundles(dir, version)
101
+ if (unreadable.length) {
102
+ throw new Error(`cannot establish the failure history for ${version} — ${unreadable.length} durable bundle(s) do not parse (${unreadable.join('; ')}). Repair the record; a gate that cannot read the history does not get to proceed.`)
103
+ }
104
+
105
+ const rows = attempts.map((a) => {
106
+ const failure = classifyFailureOwner(a.bundle)
107
+ return {
108
+ attemptId: a.attemptId,
109
+ ordinal: a.ordinal,
110
+ terminalState: a.terminalState,
111
+ failureOwner: failure?.owner ?? null,
112
+ failureBasis: failure?.basis ?? null,
113
+ failurePhase: classifyFailurePhase(a.bundle),
114
+ evidence: a.file,
115
+ }
116
+ })
117
+
118
+ const ownerCounts = Object.fromEntries(FAILURE_OWNERS.map((o) => [o, 0]))
119
+ for (const r of rows) if (r.failureOwner) ownerCounts[r.failureOwner] += 1
120
+ const qualifying = rows.filter((r) => r.failureOwner && BREAKER_OWNERS.includes(r.failureOwner))
121
+
122
+ const held = qualifying.length >= threshold
123
+ return {
124
+ kind: 'rc-circuit-breaker',
125
+ version: String(version),
126
+ threshold,
127
+ thresholdSource,
128
+ countedOwners: BREAKER_OWNERS,
129
+ attempts: rows.length,
130
+ nonReleased: rows.filter((r) => r.terminalState !== 'released').length,
131
+ ownerCounts,
132
+ qualifyingCount: qualifying.length,
133
+ qualifying,
134
+ decision: held ? HOLD_DECISION : PROCEED_DECISION,
135
+ decisionBasis: held
136
+ ? `${qualifying.length} prior non-released attempt(s) of ${version} owned by ${BREAKER_OWNERS.join('/')} reach the configured threshold ${threshold} — the loop #962 exists to stop`
137
+ : `${qualifying.length} prior non-released attempt(s) of ${version} owned by ${BREAKER_OWNERS.join('/')}, below the configured threshold ${threshold}`,
138
+ continue: held
139
+ ? 'Minting the next immutable RC requires an explicit human authorization (--authorization <file>) recording why another RC is preferable to simplifying, removing, or externally repairing the gate; record this decision JSON at release.circuitBreaker on the manifest. The hold deletes nothing, moves no tag, and burns no version.'
140
+ : null,
141
+ }
142
+ }
143
+
144
+ // Validates the human's continuation record against the CURRENT evaluation. `againstCount`
145
+ // binding is the anti-silent-carry rule: the record authorizes one continuation past exactly the
146
+ // count it was written against, so a further qualifying failure re-holds instead of inheriting
147
+ // yesterday's decision.
148
+ export function validateAuthorization(record, evaluation) {
149
+ const errors = []
150
+ const isObj = record != null && typeof record === 'object' && !Array.isArray(record)
151
+ if (!isObj) return { valid: false, errors: ['authorization must be a JSON object'] }
152
+ if (!nonEmpty(record.authorizedBy)) errors.push('authorizedBy is required (the human authorizing the continuation)')
153
+ if (!nonEmpty(record.authorizedAt) || !Number.isFinite(Date.parse(record.authorizedAt))) errors.push('authorizedAt is required and must be an ISO timestamp')
154
+ if (!nonEmpty(record.rationale)) errors.push('rationale is required — why another RC is preferable to simplifying, removing, or externally repairing the gate')
155
+ if (!nonEmpty(record.version)) errors.push('version is required')
156
+ else if (evaluation && record.version.trim().replace(/^v/, '') !== String(evaluation.version).replace(/^v/, '')) {
157
+ errors.push(`version ${record.version} does not match the held version ${evaluation.version}`)
158
+ }
159
+ if (!Number.isInteger(record.againstCount)) errors.push('againstCount is required (the qualifying count this record was written against)')
160
+ else if (evaluation && record.againstCount !== evaluation.qualifyingCount) {
161
+ errors.push(`againstCount ${record.againstCount} is stale — the current qualifying count is ${evaluation.qualifyingCount}; one authorization covers exactly one continuation`)
162
+ }
163
+ return { valid: errors.length === 0, errors }
164
+ }
165
+
166
+ // ---- CLI ----
167
+
168
+ const USAGE = `rc-circuit-breaker — the release-lane circuit breaker for repeated tooling failures (#962).
169
+
170
+ Run BEFORE minting the next immutable RC (step 3, references/candidate.md). Counts prior
171
+ non-released attempts for the proposed version whose normalized failure owner is release-tooling
172
+ or gate-environment (#961's taxonomy), and holds when the count reaches the threshold.
173
+
174
+ Usage:
175
+ rc-circuit-breaker check --dir <durable-evidence-dir> --version <v> [--threshold <n>] [--authorization <file.json>]
176
+
177
+ --threshold <n> qualifying failures that trip the hold (default ${DEFAULT_THRESHOLD};
178
+ env ${THRESHOLD_ENV}; flag beats env beats default; the source is
179
+ recorded in the decision). No flag or env var skips the check.
180
+ --authorization <f> a structured human authorization (see references/postmortem.md):
181
+ version, againstCount, authorizedBy, authorizedAt, rationale. Valid
182
+ only against the CURRENT count — one authorization, one continuation.
183
+
184
+ Exit codes:
185
+ 0 proceed (below threshold) or authorized-continue (record valid) — decision JSON on stdout
186
+ 1 hold-for-release-design-review — decision JSON on stdout, with count, owners, attempt ids
187
+ and evidence files
188
+ 2 cannot evaluate (usage, unreadable dir, unparseable bundle, invalid threshold) — stderr
189
+ only; fail closed, nothing is minted
190
+
191
+ The check is read-only: a hold deletes nothing, moves no immutable RC tag, and burns no version.`
192
+
193
+ function parseArgs(argv) {
194
+ const opts = { _: [] }
195
+ for (let i = 0; i < argv.length; i++) {
196
+ const a = argv[i]
197
+ if (a === '--help' || a === '-h') opts.help = true
198
+ else if (a.startsWith('--')) opts[a.slice(2)] = argv[++i]
199
+ else opts._.push(a)
200
+ }
201
+ return opts
202
+ }
203
+
204
+ export function main(argv, env = process.env) {
205
+ const opts = parseArgs(argv)
206
+ if (opts.help) {
207
+ console.log(USAGE)
208
+ return 0
209
+ }
210
+ const [cmd] = opts._
211
+ if (cmd !== 'check' || !nonEmpty(opts.dir) || !nonEmpty(opts.version)) {
212
+ console.error('rc-circuit-breaker: usage: check --dir <durable-evidence-dir> --version <v> are all required (see --help)')
213
+ return 2
214
+ }
215
+
216
+ let resolved
217
+ try {
218
+ resolved = resolveThreshold({ flag: opts.threshold ?? null, env })
219
+ } catch (e) {
220
+ console.error(e.message)
221
+ return 2
222
+ }
223
+
224
+ let evaluation
225
+ try {
226
+ evaluation = evaluateRcCircuitBreaker({
227
+ dir: opts.dir,
228
+ version: opts.version,
229
+ threshold: resolved.threshold,
230
+ thresholdSource: resolved.thresholdSource,
231
+ })
232
+ } catch (e) {
233
+ console.error(`rc-circuit-breaker: ${e.message}`)
234
+ return 2
235
+ }
236
+
237
+ if (evaluation.decision !== HOLD_DECISION) {
238
+ process.stdout.write(JSON.stringify(evaluation, null, 2) + '\n')
239
+ return 0
240
+ }
241
+
242
+ // The hold stands unless a valid human authorization is presented. A malformed or stale one
243
+ // never turns into a proceed — it is named and the hold stands.
244
+ if (opts.authorization != null) {
245
+ let record = null
246
+ try {
247
+ record = JSON.parse(fs.readFileSync(opts.authorization, 'utf8'))
248
+ } catch (e) {
249
+ process.stdout.write(JSON.stringify({ ...evaluation, authorizationError: `authorization file unreadable: ${e.message}` }, null, 2) + '\n')
250
+ return 1
251
+ }
252
+ const v = validateAuthorization(record, evaluation)
253
+ if (v.valid) {
254
+ process.stdout.write(JSON.stringify({
255
+ ...evaluation,
256
+ decision: AUTHORIZED_DECISION,
257
+ decisionBasis: `${evaluation.decisionBasis} — continued under a recorded human authorization`,
258
+ authorization: record,
259
+ }, null, 2) + '\n')
260
+ return 0
261
+ }
262
+ process.stdout.write(JSON.stringify({ ...evaluation, authorizationError: v.errors.join('; ') }, null, 2) + '\n')
263
+ return 1
264
+ }
265
+
266
+ process.stdout.write(JSON.stringify(evaluation, null, 2) + '\n')
267
+ return 1
268
+ }
269
+
270
+ if (isMainModule(import.meta.url)) {
271
+ process.exitCode = main(process.argv.slice(2))
272
+ }