@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,526 @@
1
+ #!/usr/bin/env node
2
+ // finalize-release — record a verified release's closure as ONE durable transition (#963).
3
+ //
4
+ // The failure this exists for. Forex v0.1.12 passed serving identity and the prod-active smoke,
5
+ // and the attempt was closed `released` — but the run manifest still read `step: verify` with no
6
+ // top-level `verification`, because assembling that record was a manual act nobody performed.
7
+ // The mandatory post-mortem then raised HIGH stopped-mid-machine and MEDIUM
8
+ // no-verification-record on a release production had already verified: the lease said free, the
9
+ // resume key said mid-exposure, and a resumed session had to reconcile live production to learn
10
+ // a state the standard workflow could have recorded atomically.
11
+ //
12
+ // What this operation is. One standard finalization: it VALIDATES every observation the released
13
+ // path owes — the candidate verdict, the post-authorization fence readings, the serving
14
+ // identity/digest confirmation, the durable-processing quiescence/resume where declared, the
15
+ // live (prod-active) verdict, and the attempt's `released` close — and then, in a single atomic
16
+ // manifest write, records the attempt close (when still open), the top-level `verification`
17
+ // block, and the terminal `step: done`. Any observation missing, stale, mismatched, or
18
+ // internally inconsistent REFUSES, and a refusal writes nothing.
19
+ //
20
+ // Resume. The write is one `writeManifest` rename, so a crash leaves exactly one of two states:
21
+ // `step: verify` with no `verification` (finalize has not happened — run it) or `step: done`
22
+ // with `verification` (it has — re-running re-validates the recorded transition against the
23
+ // `release.*` evidence and no-ops byte-identically; a recorded terminal state that no longer
24
+ // matches the evidence refuses rather than re-asserting it). Any other combination —
25
+ // done-without-verification, verify-with-verification — is a hand-assembled ambiguity and
26
+ // refuses.
27
+ //
28
+ // What it deliberately does NOT do (issue non-goals): the final tag, the GitHub Release, and
29
+ // the evidence-bundle emit/attach are network/durable-artifact operations that stay OUTSIDE
30
+ // this filesystem transaction, and nothing here weakens the observed-production exit criteria —
31
+ // every check below is a comparison against recorded observations, which is what makes a
32
+ // refusal a statement about evidence rather than about the world.
33
+
34
+ import { isMainModule } from '../../engineering-runtime/scripts/main-module.mjs'
35
+ import {
36
+ ATTEMPT_CLOSE_CAUSES,
37
+ appendReleaseStateTransition,
38
+ readManifest,
39
+ recordReleaseAttemptState,
40
+ validate,
41
+ writeManifest,
42
+ } from '../../resolve-issues/scripts/run-state.mjs'
43
+ import { verifyCompletionArtifact } from './adapter-completion-artifact.mjs'
44
+ import { evaluateFloorReadiness } from './green-gate.mjs'
45
+
46
+ export const FINALIZER = 'finalize-release.mjs'
47
+
48
+ const SHA = /^[0-9a-f]{40}$/i
49
+ const nonEmpty = (v) => typeof v === 'string' && v.trim() !== ''
50
+ const isObject = (v) => v != null && typeof v === 'object' && !Array.isArray(v)
51
+
52
+ function canonical(value) {
53
+ if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`
54
+ if (isObject(value)) {
55
+ const keys = Object.keys(value).filter((k) => value[k] !== undefined).sort()
56
+ return `{${keys.map((k) => `${JSON.stringify(k)}:${canonical(value[k])}`).join(',')}}`
57
+ }
58
+ return JSON.stringify(value)
59
+ }
60
+
61
+ const equivalent = (a, b) => canonical(a) === canonical(b)
62
+
63
+ function requireTime(value, label) {
64
+ const t = typeof value === 'string' ? Date.parse(value) : NaN
65
+ if (!Number.isFinite(t)) throw new Error(`${label} must be an ISO timestamp (got ${JSON.stringify(value)})`)
66
+ return t
67
+ }
68
+
69
+ function requireObject(value, label) {
70
+ if (!isObject(value)) throw new Error(`${label} is required and must be an object`)
71
+ return value
72
+ }
73
+
74
+ function shaEqual(a, b) {
75
+ return SHA.test(a) && SHA.test(b) && String(a).toLowerCase() === String(b).toLowerCase()
76
+ }
77
+
78
+ function digestEqual(a, b) {
79
+ return nonEmpty(a) && nonEmpty(b) && String(a).toLowerCase() === String(b).toLowerCase()
80
+ }
81
+
82
+ // ---- the validations ----
83
+
84
+ function validateAttempt(release) {
85
+ const attempt = requireObject(release.attempt, 'release.attempt')
86
+ if (attempt.state === 'open' || attempt.state === 'released') return attempt
87
+ throw new Error(
88
+ `release.attempt.state is ${JSON.stringify(attempt.state)} — the finalizer records only the `
89
+ + 'verified released transition; failed-pre-promotion, rolled-back, revoked and blocked-manual '
90
+ + 'exits have their own closes (routing.md step 5)',
91
+ )
92
+ }
93
+
94
+ function validateCandidate(release) {
95
+ const identity = requireObject(release.candidateIdentity, 'release.candidateIdentity')
96
+ if (!SHA.test(identity.sourceSha)) {
97
+ throw new Error('release.candidateIdentity.sourceSha must be one exact 40-character SHA')
98
+ }
99
+ for (const field of ['revision', 'url', 'imageDigest']) {
100
+ if (!nonEmpty(identity[field])) throw new Error(`release.candidateIdentity.${field} is required`)
101
+ }
102
+ if (identity.revision !== release.candidateRevision) {
103
+ throw new Error(`release.candidateIdentity.revision (${identity.revision}) does not match release.candidateRevision (${release.candidateRevision})`)
104
+ }
105
+ if (identity.url !== release.candidateUrl) {
106
+ throw new Error(`release.candidateIdentity.url (${identity.url}) does not match release.candidateUrl (${release.candidateUrl})`)
107
+ }
108
+ const sha = release.candidateSha || release.tagSha || identity.sourceSha
109
+ if (!SHA.test(sha)) throw new Error('release.candidateSha must be one exact 40-character SHA')
110
+ if (!shaEqual(identity.sourceSha, sha)) {
111
+ throw new Error('release.candidateIdentity.sourceSha does not match the recorded candidateSha/tagSha')
112
+ }
113
+ if (nonEmpty(release.tagSha) && !shaEqual(release.tagSha, sha)) {
114
+ throw new Error('release.tagSha does not match the candidate SHA — the final tag must name the verified SHA (principle 10)')
115
+ }
116
+
117
+ const verdict = requireObject(release.candidateVerdict, 'release.candidateVerdict')
118
+ if (verdict.state !== 'ALIVE') {
119
+ throw new Error(`release.candidateVerdict.state must be ALIVE on the released path (got ${JSON.stringify(verdict.state)})`)
120
+ }
121
+ if (!nonEmpty(verdict.artifactPath)) throw new Error('release.candidateVerdict.artifactPath is required — the verdict names its durable artifact')
122
+ requireTime(verdict.generatedAt, 'release.candidateVerdict.generatedAt')
123
+ if (!nonEmpty(verdict.target) || verdict.target !== release.candidateUrl) {
124
+ throw new Error('release.candidateVerdict.target must be the exact recorded candidateUrl')
125
+ }
126
+ return { identity, sha, verdict, verdictAt: Date.parse(verdict.generatedAt) }
127
+ }
128
+
129
+ function validateFence(manifest, candidate) {
130
+ const release = manifest.release
131
+ const fence = requireObject(release.recheckFence, 'release.recheckFence')
132
+ const gate = requireObject(fence.gate, 'release.recheckFence.gate')
133
+ if (gate.decision !== 'fire' || gate.phase !== 'shift') {
134
+ throw new Error(`release.recheckFence.gate must record decision "fire" at phase "shift" (got ${JSON.stringify(gate.decision)}/${JSON.stringify(gate.phase)}) — the pre-exposure gate did not authorize this shift`)
135
+ }
136
+ if (!Array.isArray(gate.failed) || gate.failed.length !== 0) {
137
+ throw new Error(`release.recheckFence.gate.failed must be empty on an authorized shift (got ${JSON.stringify(gate.failed)})`)
138
+ }
139
+ const evidence = requireObject(gate.evidence, 'release.recheckFence.gate.evidence')
140
+ if (evidence.verdict !== 'ALIVE' || evidence.verdictTarget !== release.candidateUrl || evidence.noMutations !== true) {
141
+ throw new Error('release.recheckFence.gate.evidence must record a read-only ALIVE verdict on the exact candidate URL (verdict, verdictTarget, noMutations)')
142
+ }
143
+ if (evidence.generatedAt !== candidate.verdict.generatedAt) {
144
+ throw new Error('release.recheckFence.gate.evidence.generatedAt does not match the recorded candidateVerdict — the fence evaluated a different verdict artifact')
145
+ }
146
+
147
+ // Freshness as the fence recorded it — a historical reading, re-checked for internal
148
+ // consistency rather than re-taken: the age must sit inside the recorded window AND agree
149
+ // with the verdict stamp and the fence's own checkedAt.
150
+ const age = evidence.verdictAgeMinutes
151
+ const window = evidence.verdictFreshnessMinutes
152
+ if (!Number.isFinite(age) || !Number.isFinite(window) || window <= 0) {
153
+ throw new Error('release.recheckFence.gate.evidence must record verdictAgeMinutes and a positive verdictFreshnessMinutes')
154
+ }
155
+ if (age < 0 || age > window) {
156
+ throw new Error(`the fence recorded a stale verdict: age ${age}m outside the ${window}m window — an expired verdict routes back to 4a, never onward to the shift`)
157
+ }
158
+ const fenceAt = requireTime(fence.checkedAt, 'release.recheckFence.checkedAt')
159
+ const observedAge = (fenceAt - candidate.verdictAt) / 60_000
160
+ if (observedAge < 0 || observedAge > window || Math.abs(observedAge - age) > 0.01) {
161
+ throw new Error(`the fence freshness record is inconsistent: recorded age ${age}m but the verdict stamp and fence checkedAt give ${observedAge.toFixed(2)}m`)
162
+ }
163
+
164
+ // The floor the fence recorded must be the floor the manifest still declares — a floor that
165
+ // moved between the shift and the finalization is exactly the staleness this operation refuses.
166
+ const floor = evaluateFloorReadiness(manifest, fenceAt)
167
+ if (!floor.ok) throw new Error(`production floor was not ready at the traffic fence: ${floor.detail}`)
168
+ if (!equivalent(evidence.floorReadiness, floor.evidence.floorReadiness)) {
169
+ throw new Error('release.recheckFence.gate.evidence.floorReadiness does not match the manifest\'s current floor readiness record')
170
+ }
171
+
172
+ if (fence.candidateResolvesTo !== candidate.identity.revision) {
173
+ throw new Error(`release.recheckFence.candidateResolvesTo (${JSON.stringify(fence.candidateResolvesTo)}) does not match the verified candidate revision — the fence must record what the URL resolved to, not a judgment`)
174
+ }
175
+ if (fence.candidatePercent !== 0 || fence.previousRevisionPercent !== 100) {
176
+ throw new Error('release.recheckFence must record the candidate at 0% and the previous revision at exactly 100%')
177
+ }
178
+ return { fence, fenceAt }
179
+ }
180
+
181
+ function validateServing(release, candidate) {
182
+ const serving = requireObject(release.servingConfirmation, 'release.servingConfirmation')
183
+ const gate = requireObject(serving.gate, 'release.servingConfirmation.gate')
184
+ if (gate.decision !== 'accept' || gate.phase !== 'serving') {
185
+ throw new Error(`release.servingConfirmation.gate must record decision "accept" at phase "serving" (got ${JSON.stringify(gate.decision)}/${JSON.stringify(gate.phase)})`)
186
+ }
187
+ if (!Array.isArray(gate.failed) || gate.failed.length !== 0) {
188
+ throw new Error(`release.servingConfirmation.gate.failed must be empty on an accepted serving confirmation (got ${JSON.stringify(gate.failed)})`)
189
+ }
190
+ const evidence = requireObject(gate.evidence, 'release.servingConfirmation.gate.evidence')
191
+ if (!equivalent(evidence.recorded, candidate.identity)) {
192
+ throw new Error('release.servingConfirmation.gate.evidence.recorded must be the complete candidateIdentity tuple the serving check ran against')
193
+ }
194
+ if (isObject(evidence.serving)) {
195
+ const live = evidence.serving
196
+ if (!shaEqual(live.sourceSha, candidate.sha)
197
+ || live.revision !== candidate.identity.revision
198
+ || !digestEqual(live.imageDigest, candidate.identity.imageDigest)) {
199
+ throw new Error('release.servingConfirmation serving tuple does not exactly match the candidate identity (sourceSha, revision, imageDigest)')
200
+ }
201
+ } else if (isObject(evidence.fallback)) {
202
+ // The declared no-attesting-endpoint weakening (pre-flight item 3): the serving revision's
203
+ // configured digest against the candidate's — a comparison, never a revision-name read.
204
+ if (!digestEqual(evidence.fallback.servingImageDigest, candidate.identity.imageDigest)) {
205
+ throw new Error('release.servingConfirmation fallback serving image digest does not match the candidate identity digest')
206
+ }
207
+ } else {
208
+ throw new Error('release.servingConfirmation.gate.evidence records no serving observation — neither the re-attested tuple nor the declared digest fallback')
209
+ }
210
+ if (serving.candidatePercent !== 100 || serving.previousRevisionPercent !== 0) {
211
+ throw new Error('release.servingConfirmation must record the candidate at 100% and the previous revision at 0%')
212
+ }
213
+ const servingAt = requireTime(serving.checkedAt, 'release.servingConfirmation.checkedAt')
214
+ return { serving, servingAt }
215
+ }
216
+
217
+ function validateQuiescence(manifest, candidate, fenceAt, servingAt, liveAt) {
218
+ const declared = manifest.envelope && manifest.envelope.durableProcessing
219
+ if (!isObject(declared) || typeof declared.present !== 'boolean') {
220
+ throw new Error('envelope.durableProcessing must explicitly declare present true or false — an unasked question is not an absent record (pre-flight item 6)')
221
+ }
222
+ const recorded = manifest.release.quiescence
223
+ if (declared.present === false) {
224
+ if (recorded !== undefined && recorded !== null) {
225
+ throw new Error('release.quiescence must be absent when durable processing is declared absent — a record here contradicts the declaration')
226
+ }
227
+ return null
228
+ }
229
+
230
+ const q = requireObject(recorded, 'release.quiescence')
231
+ if (!Array.isArray(q.pauseOrder) || q.pauseOrder.length === 0 || q.pauseOrder.some((s) => !nonEmpty(s))) {
232
+ throw new Error('release.quiescence.pauseOrder must record the non-empty pause order as executed')
233
+ }
234
+ if (!equivalent(q.pauseOrder, declared.pauseOrder)) {
235
+ throw new Error('release.quiescence.pauseOrder does not match the order declared at pre-flight (envelope.durableProcessing.pauseOrder)')
236
+ }
237
+ if (!Array.isArray(q.resumeOrder) || !equivalent(q.resumeOrder, [...q.pauseOrder].reverse())) {
238
+ throw new Error('release.quiescence.resumeOrder must be the exact reverse of the executed pause order (principle 14)')
239
+ }
240
+ const proof = requireObject(q.proof, 'release.quiescence.proof')
241
+ const readings = Object.entries(proof).filter(([k]) => k !== 'checkedAt')
242
+ if (readings.length === 0 || 'quiesced' in proof || readings.every(([, v]) => typeof v === 'boolean')) {
243
+ throw new Error('release.quiescence.proof must record the observed processing-state value (an in-flight count, a queue depth), never `quiesced: true` — the judgment one field deeper')
244
+ }
245
+ const pausedAt = requireTime(q.pausedAt, 'release.quiescence.pausedAt')
246
+ const proofAt = requireTime(proof.checkedAt, 'release.quiescence.proof.checkedAt')
247
+ const resumedAt = requireTime(q.resumedAt, 'release.quiescence.resumedAt')
248
+ if (!(pausedAt <= proofAt && proofAt <= fenceAt && fenceAt <= servingAt && servingAt <= resumedAt && resumedAt <= liveAt)) {
249
+ throw new Error('release.quiescence is not in the durable order pause -> prove-quiescent -> fence -> serving-identity -> reverse-resume -> live (principle 14)')
250
+ }
251
+ if (q.servingRevisionAtResume !== candidate.identity.revision) {
252
+ throw new Error(`release.quiescence.servingRevisionAtResume (${JSON.stringify(q.servingRevisionAtResume)}) must be the verified candidate revision — processing was resumed against a revision nobody confirmed`)
253
+ }
254
+ return q
255
+ }
256
+
257
+ function validateLiveVerdict(manifest, release, fenceAt) {
258
+ const verdict = requireObject(release.liveVerdict, 'release.liveVerdict')
259
+ if (verdict.state !== 'ALIVE') {
260
+ throw new Error(`release.liveVerdict.state must be ALIVE on the released path (got ${JSON.stringify(verdict.state)})`)
261
+ }
262
+ if (!nonEmpty(verdict.artifactPath)) throw new Error('release.liveVerdict.artifactPath is required — the active verdict names its durable artifact')
263
+ const liveAt = requireTime(verdict.generatedAt, 'release.liveVerdict.generatedAt')
264
+ if (!nonEmpty(verdict.target)) throw new Error('release.liveVerdict.target is required')
265
+ const floor = evaluateFloorReadiness(manifest, fenceAt)
266
+ const floorTarget = floor.ok && floor.evidence.floorReadiness && floor.evidence.floorReadiness.target
267
+ if (nonEmpty(floorTarget) && verdict.target !== floorTarget) {
268
+ throw new Error(`release.liveVerdict.target (${verdict.target}) does not match the declared prod-active floor target (${floorTarget})`)
269
+ }
270
+ return { verdict, liveAt }
271
+ }
272
+
273
+ // ---- the one transition ----
274
+
275
+ // The checked completion record and observation blocks the one transition assembles into `verification` — the REQUIRED keys
276
+ // of the terminal record. report.mjs's step-5 reader checks this exact list (via
277
+ // isFinalizedVerification below) instead of accepting any object-valued verification, so the
278
+ // writer's shape and the reader's question share one source.
279
+ const VERIFICATION_OBSERVATIONS = ['adapterCompletion', 'candidate', 'candidateVerdict', 'recheckFence', 'servingConfirmation', 'liveVerdict']
280
+
281
+ function assembleVerification(release, now, quiescence, adapterCompletion) {
282
+ return {
283
+ finalizedAt: now,
284
+ finalizedBy: FINALIZER,
285
+ adapterCompletion,
286
+ candidate: release.candidateIdentity,
287
+ candidateVerdict: release.candidateVerdict,
288
+ recheckFence: release.recheckFence,
289
+ servingConfirmation: release.servingConfirmation,
290
+ liveVerdict: release.liveVerdict,
291
+ ...(quiescence ? { quiescence } : {}),
292
+ }
293
+ }
294
+
295
+ // The reader-level half of the terminal record: is this the verification block the one
296
+ // transition writes? Presence and shape only — full cross-field consistency is validateAll's
297
+ // job on the write/resume path; a checkpoint reader owes "the required observations are
298
+ // recorded", not a re-verdict. A hand-assembled or empty `verification` (the
299
+ // release-finalization-terminal-proof review finding: `{}` rendered report.mjs's Step 5 done
300
+ // while this finalizer refused the same state) fails here exactly as it fails finalize.
301
+ export function isFinalizedVerification(verification) {
302
+ if (!isObject(verification)) return false
303
+ if (verification.finalizedBy !== FINALIZER) return false
304
+ if (!Number.isFinite(Date.parse(verification.finalizedAt || ''))) return false
305
+ return VERIFICATION_OBSERVATIONS.every((key) => {
306
+ const block = verification[key]
307
+ return isObject(block) && Object.keys(block).length > 0
308
+ })
309
+ }
310
+
311
+ function validateAll(manifest) {
312
+ if (manifest.skill !== 'resolve-release') {
313
+ throw new Error(`finalize-release requires a resolve-release manifest (got skill ${JSON.stringify(manifest.skill)})`)
314
+ }
315
+ const check = validate(manifest)
316
+ if (!check.ok) throw new Error(`release manifest is invalid before finalization: ${check.errors.join('; ')}`)
317
+ const release = requireObject(manifest.release, 'release')
318
+ const attempt = validateAttempt(release)
319
+ const candidate = validateCandidate(release)
320
+ const { fenceAt } = validateFence(manifest, candidate)
321
+ const { servingAt } = validateServing(release, candidate)
322
+ const { liveAt } = validateLiveVerdict(manifest, release, fenceAt)
323
+ if (!(candidate.verdictAt <= fenceAt && fenceAt <= servingAt && servingAt <= liveAt)) {
324
+ throw new Error('the verification evidence is not in the durable order candidate-verdict → fence → serving → live')
325
+ }
326
+ const quiescence = validateQuiescence(manifest, candidate, fenceAt, servingAt, liveAt)
327
+ return { release, attempt, candidate, quiescence }
328
+ }
329
+
330
+ // Acquires completion evidence, validates, then returns the finalized manifest; the CLI owns the manifest write.
331
+ // Throws with a named reason on any missing, stale, mismatched, or inconsistent observation.
332
+ export function finalizeRelease(manifest, {
333
+ now = new Date().toISOString(),
334
+ adapterCompletionArtifact,
335
+ adapterComponentHead,
336
+ adapterCompletionSha256,
337
+ } = {}) {
338
+ requireTime(now, 'now')
339
+ if (!isObject(manifest)) throw new Error('the manifest must be a JSON object')
340
+ const adapterCompletion = verifyCompletionArtifact(adapterCompletionArtifact, {
341
+ expectedComponentHead: adapterComponentHead,
342
+ expectedSha256: adapterCompletionSha256,
343
+ })
344
+ const hasVerification = isObject(manifest.verification)
345
+
346
+ if (manifest.step === 'done') {
347
+ if (!hasVerification) {
348
+ throw new Error('step is "done" but no top-level verification block is recorded — an ambiguous hand-assembled state; reconcile the manifest by hand, the finalizer will not guess at it')
349
+ }
350
+ // Resume: re-validate every observation, then require the recorded terminal state to be
351
+ // exactly what this operation would have written — anything less is drift, not a resume.
352
+ const { release, attempt, candidate, quiescence } = validateAll(manifest)
353
+ if (attempt.state !== 'released' || attempt.closedBy !== ATTEMPT_CLOSE_CAUSES.released) {
354
+ throw new Error('a finalized manifest must carry the attempt closed released by verified-release')
355
+ }
356
+ const expected = assembleVerification(release, null, quiescence, adapterCompletion)
357
+ const recorded = { ...manifest.verification }
358
+ delete recorded.finalizedAt
359
+ delete expected.finalizedAt
360
+ if (!equivalent(recorded, expected)) {
361
+ throw new Error('the recorded verification block does not match the re-verified release.* evidence — the terminal state drifted from its observations; reconcile by hand')
362
+ }
363
+ if (nonEmpty(manifest.shippedSha) && !shaEqual(manifest.shippedSha, candidate.sha)) {
364
+ throw new Error('shippedSha does not match the verified candidate SHA')
365
+ }
366
+ return { manifest, resumed: true, finalizedAt: manifest.verification.finalizedAt }
367
+ }
368
+
369
+ if (manifest.step !== 'verify') {
370
+ throw new Error(`finalize-release runs at step "verify" (or "done" on resume); got step ${JSON.stringify(manifest.step)}`)
371
+ }
372
+ if (hasVerification) {
373
+ throw new Error('step is "verify" but a verification block is already recorded — an ambiguous hand-assembled state; reconcile the manifest by hand')
374
+ }
375
+
376
+ const { release, attempt, candidate, quiescence } = validateAll(manifest)
377
+
378
+ let out = manifest
379
+ if (attempt.state === 'open') {
380
+ // Use the canonical attempt writer for the closure shape and invariants. Its intermediate
381
+ // history event is intentionally not persisted: finalization is one atomic transition from
382
+ // verify/open directly to done/released, so the combined event is appended after the full
383
+ // terminal manifest has been assembled.
384
+ const evidence = `serving ${candidate.identity.revision} at 100% for ${candidate.sha}; prod-active ALIVE (${release.liveVerdict.artifactPath})`
385
+ out = recordReleaseAttemptState(out, {
386
+ state: 'released',
387
+ closedBy: ATTEMPT_CLOSE_CAUSES.released,
388
+ evidence,
389
+ }, { at: now })
390
+ // #963's transaction clock owns the terminal attempt record; #913's writer clock
391
+ // independently owns the history event timestamp.
392
+ out.release.attempt.closedAt = now
393
+ if (manifest.releaseHistory === undefined) delete out.releaseHistory
394
+ else out.releaseHistory = structuredClone(manifest.releaseHistory)
395
+ }
396
+ out = {
397
+ ...structuredClone(out),
398
+ verification: assembleVerification(out.release, now, quiescence, adapterCompletion),
399
+ step: 'done',
400
+ shippedSha: candidate.sha,
401
+ updatedAt: now,
402
+ }
403
+ out = appendReleaseStateTransition(manifest, out)
404
+ const check = validate(out)
405
+ if (!check.ok) throw new Error(`the finalized manifest is invalid: ${check.errors.join('; ')}`)
406
+ return { manifest: out, resumed: false, finalizedAt: now }
407
+ }
408
+
409
+ // ---- CLI ----
410
+
411
+ const USAGE = `finalize-release — validate a verified release's observations and record the
412
+ terminal closure as one durable transition.
413
+
414
+ Usage:
415
+ finalize-release.mjs <run-manifest.json> --adapter-completion-artifact <path>
416
+ --adapter-component-head <40-hex-sha> --adapter-completion-sha256 <64-hex-sha256>
417
+ [--now <iso>]
418
+
419
+ Runs at step "verify" on the released path: validates the candidate verdict, the checked
420
+ isolated-adapter completion artifact under the finalizer-owned suite policy, the
421
+ post-authorization re-check fence, the serving identity/digest confirmation, the
422
+ durable-processing quiescence/resume where declared, and the live prod-active verdict; then, in
423
+ one atomic manifest write, closes the attempt released/verified-release (when still open),
424
+ records the top-level verification block, and advances step to done.
425
+
426
+ Any missing, stale, mismatched, or inconsistent observation refuses (exit 1) and writes
427
+ nothing. Re-running after success re-validates and no-ops. The final tag, GitHub Release, and
428
+ evidence-bundle emit/attach are separate operations (routing.md step 5); report.mjs runs after
429
+ this transition on the released path.`
430
+
431
+ export function main(argv, deps = {}) {
432
+ const args = [...argv]
433
+ const options = {
434
+ manifestPath: null,
435
+ now: null,
436
+ adapterCompletionArtifact: null,
437
+ adapterComponentHead: null,
438
+ adapterCompletionSha256: null,
439
+ }
440
+ const positional = []
441
+ for (let i = 0; i < args.length; i += 1) {
442
+ const arg = args[i]
443
+ if (arg === '--help' || arg === '-h') {
444
+ console.log(USAGE)
445
+ return 0
446
+ } else if (arg === '--adapter-completion-artifact') {
447
+ const value = args[++i]
448
+ if (value === undefined || value.startsWith('--')) {
449
+ throw new Error('--adapter-completion-artifact needs a path value')
450
+ }
451
+ options.adapterCompletionArtifact = value
452
+ } else if (arg === '--adapter-component-head') {
453
+ const value = args[++i]
454
+ if (value === undefined || value.startsWith('--')) {
455
+ throw new Error('--adapter-component-head needs a SHA value')
456
+ }
457
+ options.adapterComponentHead = value
458
+ } else if (arg === '--adapter-completion-sha256') {
459
+ const value = args[++i]
460
+ if (value === undefined || value.startsWith('--')) {
461
+ throw new Error('--adapter-completion-sha256 needs a SHA-256 value')
462
+ }
463
+ options.adapterCompletionSha256 = value
464
+ } else if (arg === '--now') {
465
+ const value = args[++i]
466
+ if (value === undefined || value.startsWith('--')) throw new Error('--now needs an ISO timestamp value')
467
+ options.now = value
468
+ } else if (arg.startsWith('--')) {
469
+ throw new Error(`unknown argument ${arg}\n\n${USAGE}`)
470
+ } else {
471
+ positional.push(arg)
472
+ }
473
+ }
474
+ if (positional.length !== 1) {
475
+ console.error(USAGE)
476
+ return 2
477
+ }
478
+ if (options.adapterCompletionArtifact == null || options.adapterComponentHead == null
479
+ || options.adapterCompletionSha256 == null) {
480
+ console.error(USAGE)
481
+ return 2
482
+ }
483
+ const [manifestPath] = positional
484
+ const read = deps.readManifest || readManifest
485
+ const write = deps.writeManifest || writeManifest
486
+ let manifest
487
+ try {
488
+ manifest = read(manifestPath)
489
+ } catch (error) {
490
+ console.error(`finalize-release: manifest is not readable JSON: ${manifestPath} — ${error.message || error}`)
491
+ return 1
492
+ }
493
+ if (!isObject(manifest)) {
494
+ console.error(`finalize-release: manifest is not readable JSON: ${manifestPath}`)
495
+ return 1
496
+ }
497
+ try {
498
+ const result = finalizeRelease(manifest, {
499
+ now: options.now || new Date().toISOString(),
500
+ adapterCompletionArtifact: options.adapterCompletionArtifact,
501
+ adapterComponentHead: options.adapterComponentHead,
502
+ adapterCompletionSha256: options.adapterCompletionSha256,
503
+ })
504
+ if (!result.resumed) write(manifestPath, result.manifest)
505
+ console.log(JSON.stringify({
506
+ ok: true,
507
+ manifestPath,
508
+ step: result.manifest.step,
509
+ resumed: result.resumed,
510
+ finalizedAt: result.finalizedAt,
511
+ }, null, 2))
512
+ return 0
513
+ } catch (error) {
514
+ console.error(`finalize-release: ${error.message || error}`)
515
+ return 1
516
+ }
517
+ }
518
+
519
+ if (isMainModule(import.meta.url)) {
520
+ try {
521
+ process.exitCode = main(process.argv.slice(2))
522
+ } catch (error) {
523
+ console.error(`finalize-release: ${error.message || error}`)
524
+ process.exitCode = 1
525
+ }
526
+ }