dsh-compound-engineering 0.0.0-stage → 0.1.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 (461) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +160 -2
  3. package/README.zh.md +161 -0
  4. package/cordis.patch.yml +6 -0
  5. package/lib/frontmatter.js +167 -0
  6. package/lib/index.js +46 -0
  7. package/lib/provider.js +201 -0
  8. package/package.json +62 -4
  9. package/skills/CODING_STANDARDS.md +68 -0
  10. package/skills/ce-babysit-pr/SKILL.md +59 -0
  11. package/skills/ce-babysit-pr/references/branch-currency.md +22 -0
  12. package/skills/ce-babysit-pr/references/envelope.md +44 -0
  13. package/skills/ce-babysit-pr/references/pipeline.md +15 -0
  14. package/skills/ce-babysit-pr/references/report.md +20 -0
  15. package/skills/ce-babysit-pr/references/settle.md +37 -0
  16. package/skills/ce-babysit-pr/references/setup.md +33 -0
  17. package/skills/ce-babysit-pr/references/stack-commands.md +39 -0
  18. package/skills/ce-babysit-pr/references/stack.md +43 -0
  19. package/skills/ce-babysit-pr/references/tick.md +102 -0
  20. package/skills/ce-babysit-pr/references/watch-loop.md +222 -0
  21. package/skills/ce-babysit-pr/scripts/pr-snapshot +3656 -0
  22. package/skills/ce-bakeoff/SKILL.md +48 -0
  23. package/skills/ce-bakeoff/references/candidates.md +37 -0
  24. package/skills/ce-bakeoff/references/judging.md +19 -0
  25. package/skills/ce-bakeoff/references/output.md +11 -0
  26. package/skills/ce-bakeoff/references/verification.md +15 -0
  27. package/skills/ce-brainstorm/SKILL.md +69 -0
  28. package/skills/ce-brainstorm/references/agents/slack-researcher.md +127 -0
  29. package/skills/ce-brainstorm/references/approaches.md +57 -0
  30. package/skills/ce-brainstorm/references/bakeoff.md +9 -0
  31. package/skills/ce-brainstorm/references/blindspot-pass.md +70 -0
  32. package/skills/ce-brainstorm/references/brainstorm-sections.md +458 -0
  33. package/skills/ce-brainstorm/references/dialogue.md +89 -0
  34. package/skills/ce-brainstorm/references/handoff.md +187 -0
  35. package/skills/ce-brainstorm/references/html-rendering.md +638 -0
  36. package/skills/ce-brainstorm/references/interaction-rules.md +33 -0
  37. package/skills/ce-brainstorm/references/markdown-rendering.md +242 -0
  38. package/skills/ce-brainstorm/references/model-tiers.md +13 -0
  39. package/skills/ce-brainstorm/references/output-mode.md +26 -0
  40. package/skills/ce-brainstorm/references/phase-0.md +104 -0
  41. package/skills/ce-brainstorm/references/plan-write.md +32 -0
  42. package/skills/ce-brainstorm/references/product-pressure-test.md +42 -0
  43. package/skills/ce-brainstorm/references/reasoning-elevation.md +124 -0
  44. package/skills/ce-brainstorm/references/settled-decisions.md +45 -0
  45. package/skills/ce-brainstorm/references/synthesis-summary.md +149 -0
  46. package/skills/ce-brainstorm/references/universal-brainstorming.md +72 -0
  47. package/skills/ce-brainstorm/references/verdict-routing.md +26 -0
  48. package/skills/ce-brainstorm/references/visual-probes.md +164 -0
  49. package/skills/ce-brainstorm/scripts/elevation-dispatch.sh +288 -0
  50. package/skills/ce-brainstorm/scripts/light-webserver.js +1275 -0
  51. package/skills/ce-brainstorm/scripts/packs-resolve.py +737 -0
  52. package/skills/ce-brainstorm/scripts/peer-job-runner.py +2594 -0
  53. package/skills/ce-code-review/SKILL.md +40 -0
  54. package/skills/ce-code-review/references/action-class-rubric.md +67 -0
  55. package/skills/ce-code-review/references/cross-model-recovery.md +38 -0
  56. package/skills/ce-code-review/references/cross-model-review.md +191 -0
  57. package/skills/ce-code-review/references/depth-paths.md +32 -0
  58. package/skills/ce-code-review/references/diff-scope.md +59 -0
  59. package/skills/ce-code-review/references/dispatch-reviewers.md +135 -0
  60. package/skills/ce-code-review/references/findings-schema.json +125 -0
  61. package/skills/ce-code-review/references/finish-input.md +118 -0
  62. package/skills/ce-code-review/references/finish-review.md +202 -0
  63. package/skills/ce-code-review/references/intent-and-plan.md +73 -0
  64. package/skills/ce-code-review/references/modes-and-output.md +156 -0
  65. package/skills/ce-code-review/references/persona-catalog.md +66 -0
  66. package/skills/ce-code-review/references/personas/adversarial-reviewer.md +111 -0
  67. package/skills/ce-code-review/references/personas/agent-native-reviewer.md +173 -0
  68. package/skills/ce-code-review/references/personas/api-contract-reviewer.md +44 -0
  69. package/skills/ce-code-review/references/personas/correctness-reviewer.md +48 -0
  70. package/skills/ce-code-review/references/personas/data-migration-reviewer.md +111 -0
  71. package/skills/ce-code-review/references/personas/deployment-verification-agent.md +157 -0
  72. package/skills/ce-code-review/references/personas/julik-frontend-races-reviewer.md +45 -0
  73. package/skills/ce-code-review/references/personas/learnings-researcher.md +260 -0
  74. package/skills/ce-code-review/references/personas/maintainability-reviewer.md +85 -0
  75. package/skills/ce-code-review/references/personas/performance-reviewer.md +45 -0
  76. package/skills/ce-code-review/references/personas/previous-comments-reviewer.md +59 -0
  77. package/skills/ce-code-review/references/personas/project-standards-reviewer.md +77 -0
  78. package/skills/ce-code-review/references/personas/reliability-reviewer.md +49 -0
  79. package/skills/ce-code-review/references/personas/security-reviewer.md +50 -0
  80. package/skills/ce-code-review/references/personas/swift-ios-reviewer.md +99 -0
  81. package/skills/ce-code-review/references/personas/testing-reviewer.md +51 -0
  82. package/skills/ce-code-review/references/review-output-template.md +172 -0
  83. package/skills/ce-code-review/references/scope.md +176 -0
  84. package/skills/ce-code-review/references/select-and-route.md +93 -0
  85. package/skills/ce-code-review/references/subagent-template.md +206 -0
  86. package/skills/ce-code-review/references/validator-batch-template.md +67 -0
  87. package/skills/ce-code-review/scripts/cross-model-adversarial-review.sh +1275 -0
  88. package/skills/ce-code-review/scripts/findings-mechanics.py +274 -0
  89. package/skills/ce-code-review/scripts/packs-resolve.py +737 -0
  90. package/skills/ce-code-review/scripts/peer-job-runner.py +2594 -0
  91. package/skills/ce-code-review/scripts/review-scope.py +419 -0
  92. package/skills/ce-code-review/scripts/run-log.py +280 -0
  93. package/skills/ce-commit/SKILL.md +60 -0
  94. package/skills/ce-commit-push-pr/SKILL.md +69 -0
  95. package/skills/ce-commit-push-pr/references/apply-and-handoff.md +79 -0
  96. package/skills/ce-commit-push-pr/references/branch-creation.md +47 -0
  97. package/skills/ce-commit-push-pr/references/commit-and-push.md +26 -0
  98. package/skills/ce-commit-push-pr/references/compose.md +29 -0
  99. package/skills/ce-commit-push-pr/references/context.md +42 -0
  100. package/skills/ce-commit-push-pr/references/gh-stack-cli.md +83 -0
  101. package/skills/ce-commit-push-pr/references/pr-description-writing.md +208 -0
  102. package/skills/ce-commit-push-pr/references/stack-submit.md +81 -0
  103. package/skills/ce-compound/SKILL.md +79 -0
  104. package/skills/ce-compound/assets/resolution-template.md +96 -0
  105. package/skills/ce-compound/references/agents/best-practices-researcher.md +115 -0
  106. package/skills/ce-compound/references/agents/data-integrity-guardian.md +68 -0
  107. package/skills/ce-compound/references/agents/framework-docs-researcher.md +93 -0
  108. package/skills/ce-compound/references/agents/pattern-recognition-specialist.md +55 -0
  109. package/skills/ce-compound/references/agents/performance-oracle.md +108 -0
  110. package/skills/ce-compound/references/agents/security-sentinel.md +91 -0
  111. package/skills/ce-compound/references/agents/session-historian.md +82 -0
  112. package/skills/ce-compound/references/assembly.md +127 -0
  113. package/skills/ce-compound/references/concepts-vocabulary.md +98 -0
  114. package/skills/ce-compound/references/enhancement.md +42 -0
  115. package/skills/ce-compound/references/grounding-validation.md +89 -0
  116. package/skills/ce-compound/references/lightweight.md +56 -0
  117. package/skills/ce-compound/references/modes.md +13 -0
  118. package/skills/ce-compound/references/refresh-and-discoverability.md +96 -0
  119. package/skills/ce-compound/references/report.md +115 -0
  120. package/skills/ce-compound/references/research.md +144 -0
  121. package/skills/ce-compound/references/schema.yaml +236 -0
  122. package/skills/ce-compound/references/session-history.md +73 -0
  123. package/skills/ce-compound/references/yaml-schema.md +130 -0
  124. package/skills/ce-compound/scripts/packs-resolve.py +737 -0
  125. package/skills/ce-compound/scripts/session-history/__pycache__/dsh_session.cpython-314.pyc +0 -0
  126. package/skills/ce-compound/scripts/session-history/discover-sessions.sh +290 -0
  127. package/skills/ce-compound/scripts/session-history/discover_dsh.py +123 -0
  128. package/skills/ce-compound/scripts/session-history/dsh_session.py +225 -0
  129. package/skills/ce-compound/scripts/session-history/extract-errors.py +178 -0
  130. package/skills/ce-compound/scripts/session-history/extract-metadata.py +301 -0
  131. package/skills/ce-compound/scripts/session-history/extract-skeleton.py +346 -0
  132. package/skills/ce-compound/scripts/validate-doc-claims.py +497 -0
  133. package/skills/ce-compound/scripts/validate-frontmatter.py +137 -0
  134. package/skills/ce-compound-refresh/SKILL.md +88 -0
  135. package/skills/ce-compound-refresh/assets/resolution-template.md +96 -0
  136. package/skills/ce-compound-refresh/references/classify.md +42 -0
  137. package/skills/ce-compound-refresh/references/commit.md +7 -0
  138. package/skills/ce-compound-refresh/references/concepts-vocabulary.md +116 -0
  139. package/skills/ce-compound-refresh/references/discoverability.md +15 -0
  140. package/skills/ce-compound-refresh/references/investigate.md +23 -0
  141. package/skills/ce-compound-refresh/references/modes.md +27 -0
  142. package/skills/ce-compound-refresh/references/per-action-flows.md +142 -0
  143. package/skills/ce-compound-refresh/references/report.md +23 -0
  144. package/skills/ce-compound-refresh/references/schema.yaml +236 -0
  145. package/skills/ce-compound-refresh/references/scope.md +18 -0
  146. package/skills/ce-compound-refresh/references/worth-audit.md +35 -0
  147. package/skills/ce-compound-refresh/references/yaml-schema.md +130 -0
  148. package/skills/ce-compound-refresh/scripts/validate-doc-claims.py +497 -0
  149. package/skills/ce-compound-refresh/scripts/validate-frontmatter.py +137 -0
  150. package/skills/ce-debug/SKILL.md +122 -0
  151. package/skills/ce-debug/references/anti-patterns.md +91 -0
  152. package/skills/ce-debug/references/defense-in-depth.md +39 -0
  153. package/skills/ce-debug/references/fix.md +21 -0
  154. package/skills/ce-debug/references/investigate.md +114 -0
  155. package/skills/ce-debug/references/investigation-techniques.md +384 -0
  156. package/skills/ce-debug/references/pipeline-mode.md +78 -0
  157. package/skills/ce-debug/references/post-fix-handoff.md +60 -0
  158. package/skills/ce-debug/references/return-to-caller.md +57 -0
  159. package/skills/ce-doc-review/SKILL.md +75 -0
  160. package/skills/ce-doc-review/references/bulk-preview.md +146 -0
  161. package/skills/ce-doc-review/references/cross-model-review.md +207 -0
  162. package/skills/ce-doc-review/references/decision-primer.md +47 -0
  163. package/skills/ce-doc-review/references/dispatch.md +56 -0
  164. package/skills/ce-doc-review/references/document-intake.md +44 -0
  165. package/skills/ce-doc-review/references/findings-schema.json +85 -0
  166. package/skills/ce-doc-review/references/modes.md +20 -0
  167. package/skills/ce-doc-review/references/open-questions-defer.md +158 -0
  168. package/skills/ce-doc-review/references/persona-selection.md +41 -0
  169. package/skills/ce-doc-review/references/personas/adversarial-document-reviewer.md +109 -0
  170. package/skills/ce-doc-review/references/personas/coherence-reviewer.md +69 -0
  171. package/skills/ce-doc-review/references/personas/design-lens-reviewer.md +48 -0
  172. package/skills/ce-doc-review/references/personas/feasibility-reviewer.md +50 -0
  173. package/skills/ce-doc-review/references/personas/product-lens-reviewer.md +85 -0
  174. package/skills/ce-doc-review/references/personas/scope-guardian-reviewer.md +83 -0
  175. package/skills/ce-doc-review/references/personas/security-lens-reviewer.md +41 -0
  176. package/skills/ce-doc-review/references/personas/whole-doc-reviewer.md +25 -0
  177. package/skills/ce-doc-review/references/rendering-floor.md +175 -0
  178. package/skills/ce-doc-review/references/review-output-template.md +123 -0
  179. package/skills/ce-doc-review/references/subagent-template.md +188 -0
  180. package/skills/ce-doc-review/references/synthesis-and-presentation.md +350 -0
  181. package/skills/ce-doc-review/references/walkthrough.md +347 -0
  182. package/skills/ce-doc-review/scripts/cross-model-doc-review.sh +1270 -0
  183. package/skills/ce-doc-review/scripts/packs-resolve.py +737 -0
  184. package/skills/ce-doc-review/scripts/peer-job-runner.py +2594 -0
  185. package/skills/ce-dogfood/SKILL.md +66 -0
  186. package/skills/ce-dogfood/agents/openai.yaml +2 -0
  187. package/skills/ce-dogfood/references/dogfood-report-template.md +97 -0
  188. package/skills/ce-dogfood/references/phases.md +167 -0
  189. package/skills/ce-dogfood/references/test-matrix-taxonomy.md +62 -0
  190. package/skills/ce-dogfood/scripts/packs-resolve.py +737 -0
  191. package/skills/ce-explain/SKILL.md +81 -0
  192. package/skills/ce-explain/references/agents/behavior-trace-scout.md +19 -0
  193. package/skills/ce-explain/references/agents/work-recap-scout.md +23 -0
  194. package/skills/ce-explain/references/check-in.md +18 -0
  195. package/skills/ce-explain/references/destinations.md +35 -0
  196. package/skills/ce-explain/references/explainer-html.md +29 -0
  197. package/skills/ce-explain/references/explainer-markdown.md +24 -0
  198. package/skills/ce-explain/references/intake.md +50 -0
  199. package/skills/ce-explain/references/orchestration.md +46 -0
  200. package/skills/ce-handoff/SKILL.md +54 -0
  201. package/skills/ce-handoff/references/create.md +88 -0
  202. package/skills/ce-handoff/references/resume.md +46 -0
  203. package/skills/ce-ideate/SKILL.md +75 -0
  204. package/skills/ce-ideate/references/agents/issue-intelligence-analyst.md +166 -0
  205. package/skills/ce-ideate/references/agents/learnings-researcher.md +247 -0
  206. package/skills/ce-ideate/references/agents/slack-researcher.md +127 -0
  207. package/skills/ce-ideate/references/agents/web-researcher.md +121 -0
  208. package/skills/ce-ideate/references/decomposition.md +39 -0
  209. package/skills/ce-ideate/references/divergent-ideation.md +112 -0
  210. package/skills/ce-ideate/references/grounding.md +138 -0
  211. package/skills/ce-ideate/references/html-rendering.md +638 -0
  212. package/skills/ce-ideate/references/ideation-sections.md +191 -0
  213. package/skills/ce-ideate/references/issue-intelligence.md +44 -0
  214. package/skills/ce-ideate/references/markdown-rendering.md +242 -0
  215. package/skills/ce-ideate/references/output-mode.md +34 -0
  216. package/skills/ce-ideate/references/post-ideation-workflow.md +169 -0
  217. package/skills/ce-ideate/references/scope-gates.md +148 -0
  218. package/skills/ce-ideate/references/universal-ideation.md +119 -0
  219. package/skills/ce-ideate/references/user-research-artifacts.md +28 -0
  220. package/skills/ce-ideate/references/web-research-cache.md +56 -0
  221. package/skills/ce-noslop/SKILL.md +45 -0
  222. package/skills/ce-noslop/references/patterns.md +61 -0
  223. package/skills/ce-noslop/references/terminology.md +3 -0
  224. package/skills/ce-optimize/SKILL.md +64 -0
  225. package/skills/ce-optimize/references/agents/learnings-researcher.md +247 -0
  226. package/skills/ce-optimize/references/agents/repo-research-analyst.md +258 -0
  227. package/skills/ce-optimize/references/example-expensive-benchmark-spec.yaml +88 -0
  228. package/skills/ce-optimize/references/example-hard-spec.yaml +64 -0
  229. package/skills/ce-optimize/references/example-judge-spec.yaml +83 -0
  230. package/skills/ce-optimize/references/example-text-target-spec.yaml +80 -0
  231. package/skills/ce-optimize/references/experiment-log-schema.yaml +563 -0
  232. package/skills/ce-optimize/references/experiment-prompt-template.md +143 -0
  233. package/skills/ce-optimize/references/judge-prompt-template.md +117 -0
  234. package/skills/ce-optimize/references/loop.md +286 -0
  235. package/skills/ce-optimize/references/measurement.md +168 -0
  236. package/skills/ce-optimize/references/optimize-spec-schema.yaml +570 -0
  237. package/skills/ce-optimize/references/persistence.md +93 -0
  238. package/skills/ce-optimize/references/spec.md +107 -0
  239. package/skills/ce-optimize/references/text-targets.md +51 -0
  240. package/skills/ce-optimize/references/usage-guide.md +147 -0
  241. package/skills/ce-optimize/references/wrap-up.md +54 -0
  242. package/skills/ce-optimize/scripts/decide.mjs +676 -0
  243. package/skills/ce-optimize/scripts/experiment-worktree.sh +330 -0
  244. package/skills/ce-optimize/scripts/measure.sh +140 -0
  245. package/skills/ce-optimize/scripts/parallel-probe.sh +134 -0
  246. package/skills/ce-plan/SKILL.md +60 -0
  247. package/skills/ce-plan/references/agents/agent-native-planning-strategist.md +66 -0
  248. package/skills/ce-plan/references/agents/architecture-strategist.md +46 -0
  249. package/skills/ce-plan/references/agents/best-practices-researcher.md +118 -0
  250. package/skills/ce-plan/references/agents/data-integrity-guardian.md +68 -0
  251. package/skills/ce-plan/references/agents/framework-docs-researcher.md +97 -0
  252. package/skills/ce-plan/references/agents/git-history-analyzer.md +40 -0
  253. package/skills/ce-plan/references/agents/learnings-researcher.md +268 -0
  254. package/skills/ce-plan/references/agents/pattern-recognition-specialist.md +55 -0
  255. package/skills/ce-plan/references/agents/performance-oracle.md +108 -0
  256. package/skills/ce-plan/references/agents/repo-research-analyst.md +262 -0
  257. package/skills/ce-plan/references/agents/security-sentinel.md +91 -0
  258. package/skills/ce-plan/references/agents/slack-researcher.md +131 -0
  259. package/skills/ce-plan/references/agents/spec-flow-analyzer.md +84 -0
  260. package/skills/ce-plan/references/agents/web-researcher.md +125 -0
  261. package/skills/ce-plan/references/approach-altitude.md +55 -0
  262. package/skills/ce-plan/references/bakeoff.md +9 -0
  263. package/skills/ce-plan/references/deepening-workflow.md +263 -0
  264. package/skills/ce-plan/references/final-review.md +134 -0
  265. package/skills/ce-plan/references/html-rendering.md +638 -0
  266. package/skills/ce-plan/references/intake.md +158 -0
  267. package/skills/ce-plan/references/markdown-rendering.md +242 -0
  268. package/skills/ce-plan/references/output-contracts.md +29 -0
  269. package/skills/ce-plan/references/output-mode.md +45 -0
  270. package/skills/ce-plan/references/plan-handoff.md +116 -0
  271. package/skills/ce-plan/references/plan-sections.md +489 -0
  272. package/skills/ce-plan/references/reasoning-elevation.md +124 -0
  273. package/skills/ce-plan/references/research.md +211 -0
  274. package/skills/ce-plan/references/resume.md +61 -0
  275. package/skills/ce-plan/references/settled-decisions.md +45 -0
  276. package/skills/ce-plan/references/structure.md +207 -0
  277. package/skills/ce-plan/references/synthesis-summary.md +260 -0
  278. package/skills/ce-plan/references/universal-planning.md +170 -0
  279. package/skills/ce-plan/scripts/elevation-dispatch.sh +288 -0
  280. package/skills/ce-plan/scripts/packs-resolve.py +737 -0
  281. package/skills/ce-plan/scripts/peer-job-runner.py +2594 -0
  282. package/skills/ce-polish/SKILL.md +22 -0
  283. package/skills/ce-polish/agents/openai.yaml +2 -0
  284. package/skills/ce-polish/references/dev-server-astro.md +58 -0
  285. package/skills/ce-polish/references/dev-server-detection.md +40 -0
  286. package/skills/ce-polish/references/dev-server-next.md +61 -0
  287. package/skills/ce-polish/references/dev-server-nuxt.md +58 -0
  288. package/skills/ce-polish/references/dev-server-procfile.md +59 -0
  289. package/skills/ce-polish/references/dev-server-rails.md +50 -0
  290. package/skills/ce-polish/references/dev-server-remix.md +58 -0
  291. package/skills/ce-polish/references/dev-server-sveltekit.md +58 -0
  292. package/skills/ce-polish/references/dev-server-vite.md +48 -0
  293. package/skills/ce-polish/references/install-riffrec.md +35 -0
  294. package/skills/ce-polish/references/launch-json-schema.md +177 -0
  295. package/skills/ce-polish/references/live-loop.md +98 -0
  296. package/skills/ce-polish/references/live-remote.md +35 -0
  297. package/skills/ce-polish/references/live-start.md +93 -0
  298. package/skills/ce-polish/references/live-stream-contract.md +253 -0
  299. package/skills/ce-polish/references/run.md +67 -0
  300. package/skills/ce-polish/scripts/detect-project-type.sh +277 -0
  301. package/skills/ce-polish/scripts/detect-riffrec.sh +225 -0
  302. package/skills/ce-polish/scripts/live-endpoint.js +2841 -0
  303. package/skills/ce-polish/scripts/read-launch-json.sh +117 -0
  304. package/skills/ce-polish/scripts/resolve-package-manager.sh +95 -0
  305. package/skills/ce-polish/scripts/resolve-port.sh +307 -0
  306. package/skills/ce-pov/SKILL.md +64 -0
  307. package/skills/ce-pov/references/agents/external-evidence-researcher.md +26 -0
  308. package/skills/ce-pov/references/agents/pov-peer.md +43 -0
  309. package/skills/ce-pov/references/agents/precedent-activity-scout.md +21 -0
  310. package/skills/ce-pov/references/agents/project-grounding-scout.md +32 -0
  311. package/skills/ce-pov/references/boundaries.md +36 -0
  312. package/skills/ce-pov/references/cross-model-panel.md +596 -0
  313. package/skills/ce-pov/references/followup.md +9 -0
  314. package/skills/ce-pov/references/grounding.md +47 -0
  315. package/skills/ce-pov/references/intake.md +61 -0
  316. package/skills/ce-pov/references/invocation.md +47 -0
  317. package/skills/ce-pov/references/method.md +68 -0
  318. package/skills/ce-pov/references/pov-schema.json +56 -0
  319. package/skills/ce-pov/references/report.md +7 -0
  320. package/skills/ce-pov/scripts/cross-model-pov.sh +1110 -0
  321. package/skills/ce-pov/scripts/peer-job-runner.py +2594 -0
  322. package/skills/ce-product-pulse/SKILL.md +81 -0
  323. package/skills/ce-product-pulse/agents/openai.yaml +2 -0
  324. package/skills/ce-product-pulse/references/config.md +20 -0
  325. package/skills/ce-product-pulse/references/interview.md +260 -0
  326. package/skills/ce-product-pulse/references/report-template.md +89 -0
  327. package/skills/ce-product-pulse/references/run.md +46 -0
  328. package/skills/ce-product-pulse/references/setup.md +43 -0
  329. package/skills/ce-promote/SKILL.md +90 -0
  330. package/skills/ce-promote/agents/openai.yaml +2 -0
  331. package/skills/ce-promote/references/spiral-cli.md +149 -0
  332. package/skills/ce-proof/SKILL.md +65 -0
  333. package/skills/ce-proof/references/api.md +176 -0
  334. package/skills/ce-proof/references/workflows.md +124 -0
  335. package/skills/ce-prototype/SKILL.md +59 -0
  336. package/skills/ce-prototype/assets/annotate.css +206 -0
  337. package/skills/ce-prototype/assets/annotate.js +837 -0
  338. package/skills/ce-prototype/references/annotation-loop.md +32 -0
  339. package/skills/ce-prototype/references/build.md +39 -0
  340. package/skills/ce-prototype/references/craft-floor.md +43 -0
  341. package/skills/ce-prototype/references/preview.md +118 -0
  342. package/skills/ce-prototype/references/scoping.md +38 -0
  343. package/skills/ce-prototype/references/write-back.md +37 -0
  344. package/skills/ce-prototype/scripts/light-webserver.js +1275 -0
  345. package/skills/ce-resolve-pr-feedback/SKILL.md +60 -0
  346. package/skills/ce-resolve-pr-feedback/references/agents/pr-comment-resolver.md +59 -0
  347. package/skills/ce-resolve-pr-feedback/references/evaluation-rubric.md +141 -0
  348. package/skills/ce-resolve-pr-feedback/references/full-mode.md +336 -0
  349. package/skills/ce-resolve-pr-feedback/references/pipeline-mode.md +23 -0
  350. package/skills/ce-resolve-pr-feedback/references/resume.md +60 -0
  351. package/skills/ce-resolve-pr-feedback/references/return-to-caller.md +111 -0
  352. package/skills/ce-resolve-pr-feedback/references/targeted-mode.md +48 -0
  353. package/skills/ce-resolve-pr-feedback/scripts/get-pr-comments +176 -0
  354. package/skills/ce-resolve-pr-feedback/scripts/get-thread-for-comment +84 -0
  355. package/skills/ce-resolve-pr-feedback/scripts/pending-feedback.py +287 -0
  356. package/skills/ce-resolve-pr-feedback/scripts/reply-to-pr-thread +57 -0
  357. package/skills/ce-resolve-pr-feedback/scripts/resolve-pr-thread +23 -0
  358. package/skills/ce-retune/SKILL.md +42 -0
  359. package/skills/ce-retune/agents/openai.yaml +2 -0
  360. package/skills/ce-retune/references/baseline-mining.md +122 -0
  361. package/skills/ce-retune/references/corpus-audit.md +128 -0
  362. package/skills/ce-retune/references/cut-passes.md +129 -0
  363. package/skills/ce-retune/references/halt-taxonomy.md +123 -0
  364. package/skills/ce-retune/references/noise-floor.md +131 -0
  365. package/skills/ce-retune/references/workflow-shapes.md +73 -0
  366. package/skills/ce-riffrec-feedback-analysis/SKILL.md +33 -0
  367. package/skills/ce-riffrec-feedback-analysis/references/analyzer.md +18 -0
  368. package/skills/ce-riffrec-feedback-analysis/references/compound-engineering-feedback-format.md +116 -0
  369. package/skills/ce-riffrec-feedback-analysis/references/extensive-analysis.md +98 -0
  370. package/skills/ce-riffrec-feedback-analysis/references/install-riffrec.md +27 -0
  371. package/skills/ce-riffrec-feedback-analysis/references/quick-bug-report.md +38 -0
  372. package/skills/ce-riffrec-feedback-analysis/scripts/analyze_riffrec_zip.py +1306 -0
  373. package/skills/ce-setup/SKILL.md +103 -0
  374. package/skills/ce-setup/agents/openai.yaml +2 -0
  375. package/skills/ce-setup/assets/compounding-directive.md +11 -0
  376. package/skills/ce-setup/assets/noslop-directive.md +7 -0
  377. package/skills/ce-setup/assets/pack-rule-template.md +11 -0
  378. package/skills/ce-setup/references/acpx-cache-warm.md +14 -0
  379. package/skills/ce-setup/references/config-template.yaml +210 -0
  380. package/skills/ce-setup/references/legacy-codex-tool-map.md +15 -0
  381. package/skills/ce-setup/references/pack-scaffold.md +45 -0
  382. package/skills/ce-setup/references/repo-fixes.md +121 -0
  383. package/skills/ce-setup/scripts/check-health +929 -0
  384. package/skills/ce-setup/scripts/packs-resolve.py +737 -0
  385. package/skills/ce-simplify-code/SKILL.md +76 -0
  386. package/skills/ce-simplify-code/references/personas/code-quality-reviewer.md +17 -0
  387. package/skills/ce-simplify-code/references/personas/code-reuse-reviewer.md +7 -0
  388. package/skills/ce-simplify-code/references/personas/comment-reviewer.md +24 -0
  389. package/skills/ce-simplify-code/references/personas/efficiency-reviewer.md +11 -0
  390. package/skills/ce-simplify-code/references/personas/test-value-reviewer.md +23 -0
  391. package/skills/ce-simplify-code/references/reviewer-dispatch.md +11 -0
  392. package/skills/ce-simplify-code/references/standalone-report.md +25 -0
  393. package/skills/ce-strategy/SKILL.md +61 -0
  394. package/skills/ce-strategy/references/grounding.md +22 -0
  395. package/skills/ce-strategy/references/interview.md +179 -0
  396. package/skills/ce-strategy/references/strategy-template.md +94 -0
  397. package/skills/ce-strategy/references/update-run.md +33 -0
  398. package/skills/ce-sweep/SKILL.md +93 -0
  399. package/skills/ce-sweep/agents/openai.yaml +2 -0
  400. package/skills/ce-sweep/references/agents/media-analyzer.md +54 -0
  401. package/skills/ce-sweep/references/interview.md +208 -0
  402. package/skills/ce-sweep/references/model-tiers.md +13 -0
  403. package/skills/ce-sweep/references/plan-template.md +62 -0
  404. package/skills/ce-sweep/references/run.md +126 -0
  405. package/skills/ce-sweep/references/sources/email.md +57 -0
  406. package/skills/ce-sweep/references/sources/github-issues.md +59 -0
  407. package/skills/ce-sweep/references/sources/slack.md +61 -0
  408. package/skills/ce-sweep/references/state-schema.md +157 -0
  409. package/skills/ce-sweep/references/subagent-template.md +60 -0
  410. package/skills/ce-sweep/scripts/analyze_riffrec_zip.py +1306 -0
  411. package/skills/ce-sweep/scripts/sweep-state.py +793 -0
  412. package/skills/ce-test-browser/SKILL.md +50 -0
  413. package/skills/ce-test-browser/references/agent-browser-driver.md +47 -0
  414. package/skills/ce-test-browser/references/pipeline-orchestration.md +45 -0
  415. package/skills/ce-test-browser/references/route-and-report.md +129 -0
  416. package/skills/ce-test-browser/scripts/resolve-port.sh +41 -0
  417. package/skills/ce-test-xcode/SKILL.md +26 -0
  418. package/skills/ce-test-xcode/agents/openai.yaml +2 -0
  419. package/skills/ce-test-xcode/references/setup-and-build.md +32 -0
  420. package/skills/ce-test-xcode/references/test-and-report.md +64 -0
  421. package/skills/ce-work/SKILL.md +62 -0
  422. package/skills/ce-work/references/agents/figma-design-sync.md +27 -0
  423. package/skills/ce-work/references/agents/implementation-worker.md +17 -0
  424. package/skills/ce-work/references/cross-model-execution.md +191 -0
  425. package/skills/ce-work/references/execution-engines.md +64 -0
  426. package/skills/ce-work/references/execution-strategy.md +73 -0
  427. package/skills/ce-work/references/implementation-loop.md +107 -0
  428. package/skills/ce-work/references/implementation-result-schema.json +52 -0
  429. package/skills/ce-work/references/input-triage.md +50 -0
  430. package/skills/ce-work/references/non-code-execution.md +23 -0
  431. package/skills/ce-work/references/return-to-caller.md +33 -0
  432. package/skills/ce-work/references/review-findings-followup.md +82 -0
  433. package/skills/ce-work/references/shipping-workflow.md +89 -0
  434. package/skills/ce-work/references/tracker-defer.md +150 -0
  435. package/skills/ce-work/references/work-intake.md +51 -0
  436. package/skills/ce-work/references/workspace-setup.md +27 -0
  437. package/skills/ce-work/scripts/__pycache__/unit_workspace_jobs.cpython-314.pyc +0 -0
  438. package/skills/ce-work/scripts/__pycache__/unit_workspace_state.cpython-314.pyc +0 -0
  439. package/skills/ce-work/scripts/cross-model-work.sh +1385 -0
  440. package/skills/ce-work/scripts/peer-job-runner.py +2594 -0
  441. package/skills/ce-work/scripts/unit-workspace.py +215 -0
  442. package/skills/ce-work/scripts/unit_workspace_ignored.py +93 -0
  443. package/skills/ce-work/scripts/unit_workspace_integration.py +677 -0
  444. package/skills/ce-work/scripts/unit_workspace_jobs.py +1216 -0
  445. package/skills/ce-work/scripts/unit_workspace_lifecycle.py +981 -0
  446. package/skills/ce-work/scripts/unit_workspace_state.py +1379 -0
  447. package/skills/ce-work/scripts/unit_workspace_transaction.py +612 -0
  448. package/skills/ce-worktree/SKILL.md +54 -0
  449. package/skills/lfg/SKILL.md +59 -0
  450. package/skills/lfg/references/debug-return.md +25 -0
  451. package/skills/lfg/references/intake.md +30 -0
  452. package/skills/lfg/references/next-work-handoff.md +96 -0
  453. package/skills/lfg/references/plan-brief.md +36 -0
  454. package/skills/lfg/references/review-followup.md +78 -0
  455. package/skills/lfg/references/shipping.md +65 -0
  456. package/skills/lfg/references/stage-routing.md +49 -0
  457. package/skills/lfg/references/task-visibility.md +11 -0
  458. package/skills/lfg/references/tracker-defer.md +150 -0
  459. package/skills/lfg/references/work-return.md +27 -0
  460. package/skills/wtf/SKILL.md +33 -0
  461. package/skills/wtf/agents/openai.yaml +2 -0
@@ -0,0 +1,981 @@
1
+ """Resume, fallback, reap, and finalized-artifact lifecycle operations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import re
7
+ import shutil
8
+ import subprocess
9
+ import sys
10
+ from types import SimpleNamespace
11
+
12
+ from unit_workspace_state import *
13
+ from unit_workspace_jobs import *
14
+ from unit_workspace_integration import *
15
+
16
+
17
+ def cmd_status(args) -> tuple[str, dict]:
18
+ with locked_manifest(args.run_id) as doc:
19
+ validate_repo(doc)
20
+ source = doc.get("source") or {"kind": "plan", **doc.get("plan", {})}
21
+ if args.unit_id:
22
+ unit = doc["units"].get(args.unit_id)
23
+ if not unit:
24
+ raise Operational("REFUSED", "unknown unit")
25
+ body = {"run_id": args.run_id, "revision": doc["revision"], "source": source, "unit": unit, "integration_lock": doc.get("integration_lock"), "verifications": doc.get("verifications", []), "blockers": doc.get("blockers", [])}
26
+ else:
27
+ body = {"run_id": args.run_id, "revision": doc["revision"], "source": source, "units": doc["units"], "integration_lock": doc.get("integration_lock"), "verifications": doc.get("verifications", []), "blockers": doc.get("blockers", []), "recovery_path": run_dir(args.run_id)}
28
+ return "STATUS", body
29
+
30
+
31
+ def unfinished_run(doc: dict, canonical_head: str) -> bool:
32
+ units = doc.get("units")
33
+ if not isinstance(units, dict):
34
+ raise TrustFailure("manifest units are malformed")
35
+ if not units:
36
+ return True
37
+ states: list[str] = []
38
+ for uid, unit in units.items():
39
+ if not isinstance(uid, str) or not SAFE_ID.fullmatch(uid) or not isinstance(unit, dict):
40
+ raise TrustFailure("manifest unit identity or record is malformed")
41
+ state = unit.get("state")
42
+ if state not in UNIT_STATES:
43
+ raise TrustFailure(f"manifest unit state is invalid: {uid}")
44
+ states.append(state)
45
+ terminal_states = {"cleaned", "native-completed"}
46
+ if any(state not in terminal_states for state in states):
47
+ return True
48
+ for uid, unit in doc["units"].items():
49
+ if unit.get("state") != "native-completed":
50
+ continue
51
+ attempt = find_attempt(unit)
52
+ fallback = attempt.get("fallback", {})
53
+ claim = fallback.get("claimed") if isinstance(fallback, dict) else None
54
+ completion = fallback.get("completed") if isinstance(fallback, dict) else None
55
+ claim_valid = isinstance(claim, dict) and claim.get("mode") in {"prefer", "require"}
56
+ if not (
57
+ claim_valid
58
+ and isinstance(completion, dict)
59
+ and completion.get("claim") == claim
60
+ and isinstance(completion.get("at"), str)
61
+ and completion.get("at")
62
+ and isinstance(completion.get("summary"), str)
63
+ and completion.get("summary")
64
+ and isinstance(completion.get("evidence_digest"), str)
65
+ and re.fullmatch(r"[0-9a-f]{64}", completion["evidence_digest"])
66
+ and isinstance(completion.get("accepted_head"), str)
67
+ and re.fullmatch(r"[0-9a-f]{40}|[0-9a-f]{64}", completion["accepted_head"])
68
+ and completion.get("base") == unit.get("workspace", {}).get("base")
69
+ and isinstance(completion.get("snapshot"), dict)
70
+ and completion["snapshot"].get("head") == completion["accepted_head"]
71
+ and completion["snapshot"].get("branch_ref") == doc.get("branch", {}).get("ref")
72
+ and completion["snapshot"].get("status_empty") is True
73
+ and completion["snapshot"].get("worktree_index_empty") is True
74
+ and completion["snapshot"].get("head_tree") == completion["snapshot"].get("index_tree")
75
+ and completion["snapshot"].get("status_sha256") == digest_bytes(b"")
76
+ ):
77
+ raise TrustFailure(f"native fallback completion receipt is malformed: {uid}")
78
+ receipts = doc.get("verifications", [])
79
+ if not isinstance(receipts, list) or any(not isinstance(receipt, dict) for receipt in receipts):
80
+ raise TrustFailure("manifest verification receipts are malformed")
81
+ accepted_units = accepted_unit_commit_snapshot(units)
82
+ if accepted_units is None:
83
+ return True
84
+ return doc.get("integration_lock") is not None or not any(
85
+ receipt.get("verification_exit") == 0
86
+ and receipt.get("accepted_units") == accepted_units
87
+ and receipt.get("canonical_head") == canonical_head
88
+ and canonical_head in accepted_units.values()
89
+ for receipt in receipts
90
+ )
91
+
92
+
93
+ def discover_resume_run(repo: str, plan_digest: str) -> tuple[str, list[dict]]:
94
+ if not re.fullmatch(r"[0-9a-f]{64}", plan_digest):
95
+ raise Operational("REFUSED", "plan digest must be a lowercase SHA-256 hex value")
96
+ ensure_root()
97
+ info = repo_info(repo)
98
+ candidates: list[dict] = []
99
+ # A run recorded under the other candidate root (sandboxed vs unsandboxed
100
+ # session) must still be discoverable; scan every candidate that exists.
101
+ # Read-only: repairing a root this session cannot write (a leftover /tmp
102
+ # tree under the sandbox) would abort discovery before the writable one.
103
+ entries = []
104
+ for root in candidate_runs_roots():
105
+ if not os.path.isdir(root) or os.path.islink(root):
106
+ continue
107
+ entries.extend(os.scandir(root))
108
+ for entry in sorted(entries, key=lambda row: row.path):
109
+ if entry.name == ".locks":
110
+ continue
111
+ if not entry.is_dir(follow_symlinks=False):
112
+ raise TrustFailure(f"unexpected non-directory entry in run root: {entry.path}")
113
+ if not SAFE_ID.fullmatch(entry.name) or not entry.name.strip("."):
114
+ raise TrustFailure(f"unsafe run entry name: {entry.path}")
115
+ validate_private_dir(entry.path)
116
+ doc = read_private_json(os.path.join(entry.path, "manifest.json"))
117
+ if doc.get("schema_version") != SCHEMA_VERSION or doc.get("run_id") != entry.name:
118
+ raise TrustFailure(f"manifest schema or run identity mismatch: {entry.path}")
119
+ repository = doc.get("repository")
120
+ branch = doc.get("branch")
121
+ plan = doc.get("plan")
122
+ source = doc.get("source")
123
+ if not isinstance(repository, dict) or not isinstance(branch, dict) or not isinstance(plan, dict):
124
+ raise TrustFailure(f"manifest repository, branch, or plan record is malformed: {entry.path}")
125
+ if (
126
+ repository.get("identity_digest") != info["identity_digest"]
127
+ or repository.get("toplevel") != info["toplevel"]
128
+ or repository.get("git_dir") != info["git_dir"]
129
+ or branch.get("ref") != info["branch_ref"]
130
+ ):
131
+ continue
132
+ if source is not None and not isinstance(source, dict):
133
+ raise TrustFailure(f"manifest source record is malformed: {entry.path}")
134
+ source_kind = source.get("kind") if isinstance(source, dict) else plan.get("kind", "plan")
135
+ source_digest = source.get("digest") if isinstance(source, dict) else plan.get("digest")
136
+ if source_kind != "plan" or source_digest != plan_digest:
137
+ continue
138
+ validate_source(doc)
139
+ if unfinished_run(doc, info["head"]):
140
+ candidates.append({
141
+ "run_id": entry.name,
142
+ "updated_at": doc.get("updated_at"),
143
+ "recovery_path": entry.path,
144
+ "unit_states": {uid: unit.get("state") for uid, unit in doc["units"].items()},
145
+ })
146
+ if not candidates:
147
+ raise Operational("NOT_FOUND", "no unfinished run matches repository, branch, and plan digest", {"candidates": []})
148
+ if len(candidates) > 1:
149
+ raise Operational("AMBIGUOUS", "multiple unfinished runs match; pass --run-id", {"candidates": candidates})
150
+ return candidates[0]["run_id"], candidates
151
+
152
+
153
+ def resolve_resume_run(args) -> str:
154
+ if args.run_id:
155
+ if args.repo or args.plan_digest:
156
+ raise Operational("REFUSED", "resume accepts --run-id alone or both --repo and --plan-digest")
157
+ return safe_id(args.run_id, "run id")
158
+ if not args.repo or not args.plan_digest:
159
+ raise Operational("REFUSED", "resume requires --run-id or both --repo and --plan-digest")
160
+ run_id, _ = discover_resume_run(args.repo, args.plan_digest)
161
+ return run_id
162
+
163
+
164
+ def retained_worker_blocker(run_id: str, unit_id: str, error: Operational) -> dict | None:
165
+ if error.word != "BLOCKED" or str(error) != "worker returned a host-resolvable blocker":
166
+ return None
167
+ with locked_manifest(run_id) as doc:
168
+ unit = doc["units"].get(unit_id)
169
+ if not unit or unit.get("state") != "authored":
170
+ return None
171
+ attempt = find_attempt(unit)
172
+ receipt = attempt.get("terminal_receipt")
173
+ if (
174
+ attempt.get("process_state") != "done"
175
+ or attempt.get("terminal_validation_failure") is not None
176
+ or not isinstance(receipt, dict)
177
+ or receipt.get("terminal_status") != "blocked"
178
+ ):
179
+ return None
180
+ blocker = {
181
+ "unit_id": unit_id,
182
+ "terminal_status": "blocked",
183
+ "summary": receipt.get("summary", ""),
184
+ "terminal_receipt": receipt,
185
+ "recovery_path": os.path.join(run_dir(run_id), "units", unit_id),
186
+ }
187
+ return blocker if error.detail == blocker else None
188
+
189
+
190
+ def resume_terminalize(run_id: str, unit_id: str) -> list[dict]:
191
+ try:
192
+ transport = terminalize(run_id, unit_id)
193
+ except Operational as exc:
194
+ blocker = retained_worker_blocker(run_id, unit_id, exc)
195
+ if blocker is None:
196
+ raise
197
+ return [{
198
+ "unit_id": unit_id,
199
+ "action": "worker-blocker-retained",
200
+ "terminal_status": blocker["terminal_status"],
201
+ "summary": blocker["summary"],
202
+ "recovery_path": blocker["recovery_path"],
203
+ }]
204
+ return [{"unit_id": unit_id, "action": "terminalized", "transport": transport["commit"]}]
205
+
206
+
207
+ def resume_monitor(run_id: str, unit_id: str) -> list[dict]:
208
+ evidence = sync_job(run_id, unit_id)
209
+ actions = [{"unit_id": unit_id, "action": "monitored", "process_state": evidence["process_state"]}]
210
+ if evidence["process_state"] == "done":
211
+ actions.extend(resume_terminalize(run_id, unit_id))
212
+ return actions
213
+
214
+
215
+ def resolve_unit_recovery_blockers(run_id: str, unit_id: str, reason: str | None = None) -> None:
216
+ with locked_manifest(run_id, write=True) as doc:
217
+ resolved = 0
218
+ for blocker in doc.get("blockers", []):
219
+ if (
220
+ blocker.get("unit_id") == unit_id
221
+ and blocker.get("retain_integration_lock") is True
222
+ and (reason is None or blocker.get("reason") == reason)
223
+ and not blocker.get("resolved_at")
224
+ ):
225
+ blocker["resolved_at"] = now_iso()
226
+ blocker["resolved_by"] = "resume"
227
+ resolved += 1
228
+ if resolved:
229
+ event(doc, "recovery-blockers-resolved", unit_id, {"count": resolved})
230
+
231
+
232
+ def plan_wide_verification_attempts(doc: dict) -> list[dict]:
233
+ attempts = doc.get("verification_attempts", [])
234
+ if not isinstance(attempts, list) or any(not isinstance(attempt, dict) for attempt in attempts):
235
+ raise TrustFailure("manifest plan-wide verification attempts are malformed")
236
+ for attempt in attempts:
237
+ if (
238
+ not isinstance(attempt.get("attempt_id"), str)
239
+ or not re.fullmatch(r"[0-9a-f]{32}", attempt["attempt_id"])
240
+ or attempt.get("status") not in {"pending", "receipt-recorded"}
241
+ or not isinstance(attempt.get("integration_lock_nonce"), str)
242
+ or not re.fullmatch(r"[0-9a-f]{48}", attempt["integration_lock_nonce"])
243
+ or not isinstance(attempt.get("lock_unit_id"), str)
244
+ or not SAFE_ID.fullmatch(attempt["lock_unit_id"])
245
+ ):
246
+ raise TrustFailure("manifest plan-wide verification attempt identity or state is malformed")
247
+ return attempts
248
+
249
+
250
+ def pending_plan_wide_verification(doc: dict, lock: dict) -> dict | None:
251
+ attempts = plan_wide_verification_attempts(doc)
252
+ pending = [
253
+ attempt for attempt in attempts
254
+ if attempt.get("status") == "pending"
255
+ and attempt.get("integration_lock_nonce") == lock.get("nonce")
256
+ and attempt.get("lock_unit_id") == lock.get("unit_id")
257
+ ]
258
+ if len(pending) > 1:
259
+ raise TrustFailure("multiple pending plan-wide verification attempts share one integration lock")
260
+ return pending[0] if pending else None
261
+
262
+
263
+ def receipted_plan_wide_verification(doc: dict, lock: dict) -> dict | None:
264
+ attempts = plan_wide_verification_attempts(doc)
265
+ recorded = [
266
+ attempt for attempt in attempts
267
+ if attempt.get("status") == "receipt-recorded"
268
+ and attempt.get("integration_lock_nonce") == lock.get("nonce")
269
+ and attempt.get("lock_unit_id") == lock.get("unit_id")
270
+ ]
271
+ if len(recorded) > 1:
272
+ raise TrustFailure("multiple receipted plan-wide verification attempts share one integration lock")
273
+ if not recorded:
274
+ return None
275
+ evidence_digest = recorded[0].get("evidence_digest")
276
+ if not isinstance(evidence_digest, str) or not re.fullmatch(r"[0-9a-f]{64}", evidence_digest):
277
+ raise TrustFailure("plan-wide verification attempt receipt digest is malformed")
278
+ verifications = doc.get("verifications", [])
279
+ if not isinstance(verifications, list) or any(not isinstance(receipt, dict) for receipt in verifications):
280
+ raise TrustFailure("manifest verification receipts are malformed")
281
+ receipts = [
282
+ receipt for receipt in verifications
283
+ if receipt.get("evidence_digest") == evidence_digest
284
+ ]
285
+ if len(receipts) != 1:
286
+ raise TrustFailure("plan-wide verification receipt is missing or duplicated")
287
+ return recorded[0]
288
+
289
+
290
+ def plan_wide_blocker_retains_lock(doc: dict, lock: dict) -> bool:
291
+ return any(
292
+ blocker.get("unit_id") is None
293
+ and blocker.get("retain_integration_lock") is True
294
+ and blocker.get("integration_lock_nonce") == lock.get("nonce")
295
+ and not blocker.get("resolved_at")
296
+ for blocker in doc.get("blockers", [])
297
+ )
298
+
299
+
300
+ def resume_finalize_committed(run_id: str, unit_id: str) -> list[dict]:
301
+ with locked_manifest(run_id) as doc:
302
+ unit = doc["units"][unit_id]
303
+ state = unit["state"]
304
+ lock = doc.get("integration_lock")
305
+ pending_plan_verification = pending_plan_wide_verification(doc, lock) if lock else None
306
+ receipted_plan_verification = receipted_plan_wide_verification(doc, lock) if lock else None
307
+ retained_plan_lock = bool(lock and plan_wide_blocker_retains_lock(doc, lock))
308
+ wave_id = unit.get("wave", {}).get("id")
309
+ cleanup = unit.get("cleanup") or {}
310
+ artifact_cleanup_complete = cleanup.get("artifact_cleanup", {}).get("complete") is True
311
+ if state in {"cleaned", "native-completed"}:
312
+ actions: list[dict] = []
313
+ if (state == "cleaned" or cleanup) and not artifact_cleanup_complete:
314
+ cmd_cleanup(SimpleNamespace(
315
+ run_id=run_id,
316
+ unit_id=unit_id,
317
+ abandon=False,
318
+ expect_transport=None,
319
+ expect_job=None,
320
+ ))
321
+ actions.append({"unit_id": unit_id, "action": "artifact-cleanup-reconciled"})
322
+ if lock and lock.get("unit_id") == unit_id:
323
+ if pending_plan_verification:
324
+ raise Operational(
325
+ "BLOCKED",
326
+ "pending plan-wide verification retains the canonical integration lock",
327
+ {
328
+ "unit_id": unit_id,
329
+ "verification_attempt_id": pending_plan_verification.get("attempt_id"),
330
+ "retain_integration_lock": True,
331
+ },
332
+ )
333
+ if retained_plan_lock:
334
+ raise Operational(
335
+ "BLOCKED",
336
+ "plan-wide verification blocker retains the canonical integration lock",
337
+ {"unit_id": unit_id, "retain_integration_lock": True},
338
+ )
339
+ if state == "native-completed" and not receipted_plan_verification:
340
+ raise Operational(
341
+ "BLOCKED",
342
+ "native-completed unit retains the canonical integration lock without a plan-wide verification receipt",
343
+ {"unit_id": unit_id, "retain_integration_lock": True},
344
+ )
345
+ cmd_integration_release(SimpleNamespace(run_id=run_id, unit_id=unit_id, lock_token=lock["nonce"]))
346
+ actions.append({"unit_id": unit_id, "action": "integration-release-reconciled"})
347
+ return actions
348
+ canonical_record = unit.get("integration", {}).get("canonical_commit")
349
+ canonical = canonical_record.get("commit") if isinstance(canonical_record, dict) else None
350
+ if state != "committed" or not canonical:
351
+ raise Operational("BLOCKED", "committed-unit recovery lacks an accepted canonical commit")
352
+ if lock is None:
353
+ lock_token = cmd_integration_acquire(SimpleNamespace(run_id=run_id, unit_id=unit_id, resume=False))[1]["lock_token"]
354
+ elif lock.get("unit_id") == unit_id:
355
+ lock_token = lock["nonce"]
356
+ with locked_manifest(run_id) as doc:
357
+ validate_lock(doc, unit_id, lock_token)
358
+ else:
359
+ raise Operational("BLOCKED", "another unit holds the canonical integration lock")
360
+ actions: list[dict] = []
361
+ if wave_id:
362
+ cmd_wave_advance(SimpleNamespace(
363
+ run_id=run_id,
364
+ unit_id=unit_id,
365
+ lock_token=lock_token,
366
+ canonical_commit=canonical,
367
+ ))
368
+ actions.append({"unit_id": unit_id, "action": "wave-advance-reconciled", "commit": canonical})
369
+ cmd_cleanup(SimpleNamespace(
370
+ run_id=run_id,
371
+ unit_id=unit_id,
372
+ abandon=False,
373
+ expect_transport=None,
374
+ expect_job=None,
375
+ ))
376
+ cmd_integration_release(SimpleNamespace(run_id=run_id, unit_id=unit_id, lock_token=lock_token))
377
+ resolve_unit_recovery_blockers(run_id, unit_id)
378
+ actions.append({"unit_id": unit_id, "action": "committed-unit-finalized", "commit": canonical})
379
+ return actions
380
+
381
+
382
+ def cmd_resume(args) -> tuple[str, dict]:
383
+ run_id = resolve_resume_run(args)
384
+ actions: list[dict] = []
385
+ with locked_manifest(run_id) as doc:
386
+ validate_repo(doc)
387
+ unit_ids = list(doc["units"])
388
+ claim = doc.get("integration_lock")
389
+ releasing = dict(claim) if isinstance(claim, dict) and claim.get("phase") == "releasing" else None
390
+ orphan_unit = None
391
+ orphan_path = integration_lock_path(doc)
392
+ if claim is None and os.path.lexists(orphan_path):
393
+ orphan = read_integration_lock(orphan_path)
394
+ candidate = orphan.get("unit_id")
395
+ if orphan.get("run_id") != run_id or not isinstance(candidate, str) or candidate not in doc["units"]:
396
+ raise Operational(
397
+ "BLOCKED",
398
+ "external integration lock does not belong to this run/unit",
399
+ {"owner_run": orphan.get("run_id"), "owner_unit": candidate},
400
+ )
401
+ validated_lock_nonce(doc, candidate, orphan)
402
+ orphan_unit = candidate
403
+ if releasing:
404
+ integration_release(run_id, releasing["unit_id"], releasing["nonce"])
405
+ actions.append({"unit_id": releasing["unit_id"], "action": "integration-release-reconciled"})
406
+ if orphan_unit:
407
+ cmd_integration_acquire(SimpleNamespace(
408
+ run_id=run_id,
409
+ unit_id=orphan_unit,
410
+ resume=True,
411
+ recover_only=True,
412
+ ))
413
+ actions.append({"unit_id": orphan_unit, "action": "integration-lock-adopted"})
414
+ for uid in unit_ids:
415
+ with locked_manifest(run_id) as doc:
416
+ unit = doc["units"][uid]
417
+ state = unit["state"]
418
+ attempt = find_attempt(unit)
419
+ lock = doc.get("integration_lock")
420
+ if state == "queued" and not attempt.get("job_id"):
421
+ matches = matching_runner_jobs(run_id, unit)
422
+ if len(matches) > 1:
423
+ raise Operational("AMBIGUOUS", f"multiple runner jobs match queued unit {uid}")
424
+ if len(matches) == 1:
425
+ with locked_manifest(run_id, write=True) as current:
426
+ current_unit = current["units"][uid]
427
+ current_attempt = find_attempt(current_unit)
428
+ if current_attempt.get("job_id") not in (None, matches[0]):
429
+ raise Operational("AMBIGUOUS", "attempt was concurrently bound")
430
+ current_attempt["job_id"] = matches[0]
431
+ current_unit["state"] = "authoring"
432
+ event(current, "job-adopted", uid, {"job_id": matches[0]})
433
+ actions.append({"unit_id": uid, "action": "job-adopted", "job_id": matches[0]})
434
+ actions.extend(resume_monitor(run_id, uid))
435
+ elif state == "authoring" and attempt.get("job_id"):
436
+ actions.extend(resume_monitor(run_id, uid))
437
+ elif state == "authored":
438
+ actions.extend(resume_terminalize(run_id, uid))
439
+ elif state == "restoring" and lock and lock.get("unit_id") == uid:
440
+ exact = restore(run_id, uid, lock["nonce"])
441
+ if not exact:
442
+ raise Operational("BLOCKED", "exact pre-fold preservation could not be proven")
443
+ integration_release(run_id, uid, lock["nonce"])
444
+ resolve_unit_recovery_blockers(
445
+ run_id,
446
+ uid,
447
+ reason="integration failed and exact restoration could not be proven",
448
+ )
449
+ actions.append({
450
+ "unit_id": uid,
451
+ "action": "restored",
452
+ "canonical_preserved": True,
453
+ "integration_lock_released": True,
454
+ })
455
+ elif state == "preserved" and lock and lock.get("unit_id") == uid:
456
+ validate_lock(doc, uid, lock["nonce"])
457
+ restore_evidence = unit.get("integration", {}).get("restore")
458
+ pre_fold = unit.get("integration", {}).get("pre_fold")
459
+ if (
460
+ not isinstance(restore_evidence, dict)
461
+ or restore_evidence.get("exact") is not True
462
+ or not isinstance(pre_fold, dict)
463
+ or restore_evidence.get("snapshot") != pre_fold
464
+ ):
465
+ raise Operational("BLOCKED", "preserved-unit recovery lacks exact restoration evidence")
466
+ if semantic_snapshot(doc["repository"]["toplevel"]) != pre_fold:
467
+ raise Operational("BLOCKED", "canonical checkout no longer matches the exact restored snapshot")
468
+ integration_release(run_id, uid, lock["nonce"])
469
+ resolve_unit_recovery_blockers(
470
+ run_id,
471
+ uid,
472
+ reason="integration failed after exact restoration but lock release failed",
473
+ )
474
+ actions.append({"unit_id": uid, "action": "integration-release-reconciled"})
475
+ elif state == "integration-pending" and not unit["integration"].get("pre_fold") and lock and lock.get("unit_id") == uid:
476
+ validate_lock(doc, uid, lock["nonce"])
477
+ integration_release(run_id, uid, lock["nonce"])
478
+ actions.append({"unit_id": uid, "action": "preflight-lock-released"})
479
+ elif state == "integration-pending" and unit["integration"].get("pre_fold") and lock and lock.get("unit_id") == uid:
480
+ validate_lock(doc, uid, lock["nonce"])
481
+ repo = doc["repository"]["toplevel"]
482
+ snap = semantic_snapshot(repo)
483
+ if snap == unit["integration"]["pre_fold"]:
484
+ exact = restore(run_id, uid, lock["nonce"])
485
+ if not exact:
486
+ raise Operational("BLOCKED", "exact pre-fold preservation could not be proven")
487
+ integration_release(run_id, uid, lock["nonce"])
488
+ actions.append({
489
+ "unit_id": uid,
490
+ "action": "preflight-exact-state-recovered",
491
+ "canonical_preserved": True,
492
+ "integration_lock_released": True,
493
+ })
494
+ else:
495
+ if not matches_expected_apply(repo, unit, snap):
496
+ raise Operational("BLOCKED", "canonical dirt does not match the expected in-flight transport; preserved for recovery")
497
+ with locked_manifest(run_id, write=True) as current:
498
+ current_unit = current["units"][uid]
499
+ current_unit["state"] = "integrated"
500
+ current_unit["integration"]["applied"] = {
501
+ "at": now_iso(),
502
+ "post_index_tree": snap["index_tree"],
503
+ "status_sha256": snap["status_sha256"],
504
+ "reconciled": True,
505
+ }
506
+ event(current, "transport-apply-reconciled", uid, {"post_index_tree": snap["index_tree"]})
507
+ actions.append({"unit_id": uid, "action": "apply-reconciled"})
508
+ elif state in {"integrated", "verified"} and lock and lock.get("unit_id") == uid:
509
+ validate_lock(doc, uid, lock["nonce"])
510
+ commit = None
511
+ if state == "verified":
512
+ with locked_manifest(run_id) as current:
513
+ commit = reconcile_commit(current, current["units"][uid])
514
+ if commit:
515
+ with locked_manifest(run_id, write=True) as current:
516
+ current["units"][uid]["integration"]["canonical_commit"] = commit
517
+ current["units"][uid]["state"] = "committed"
518
+ event(current, "canonical-commit-reconciled", uid, {"commit": commit["commit"]})
519
+ actions.append({"unit_id": uid, "action": "commit-reconciled", "commit": commit["commit"]})
520
+ actions.extend(resume_finalize_committed(run_id, uid))
521
+ else:
522
+ exact = restore(run_id, uid, lock["nonce"])
523
+ if not exact:
524
+ raise Operational("BLOCKED", "exact pre-fold preservation could not be proven")
525
+ integration_release(run_id, uid, lock["nonce"])
526
+ actions.append({
527
+ "unit_id": uid,
528
+ "action": "pre-commit-integration-restored",
529
+ "interrupted_state": state,
530
+ "canonical_preserved": True,
531
+ "integration_lock_released": True,
532
+ })
533
+ elif state in {"committed", "cleaned", "native-completed"}:
534
+ actions.extend(resume_finalize_committed(run_id, uid))
535
+ return "RESUMED", {"run_id": run_id, "actions": actions, "redispatched": False, "applied": False}
536
+
537
+
538
+ def fallback_basis(doc: dict, unit: dict) -> tuple[str, dict]:
539
+ if unit.get("state") == "integration-pending" and unit.get("transport", {}).get("commit"):
540
+ raise Operational("REFUSED", "pinned worker transport must be reconciled rather than bypassed by fallback")
541
+ attempt = find_attempt(unit)
542
+ process_state = attempt.get("process_state")
543
+ if process_state == "done" and attempt.get("terminal_validation_failure"):
544
+ validate_terminal_validation_failure(doc["run_id"], unit, attempt)
545
+ snap = semantic_snapshot(doc["repository"]["toplevel"])
546
+ allowed_heads = set(unit.get("wave", {}).get("allowed_heads", []))
547
+ if (
548
+ snap["head"] not in allowed_heads
549
+ and not dependency_advanced_head(doc, unit, snap["head"])
550
+ ) or not snap["status_empty"] or snap["index_tree"] != snap["head_tree"]:
551
+ raise Operational("BLOCKED", "canonical checkout diverged or is dirty; native fallback is not safe")
552
+ return "terminal-validation-failure", attempt
553
+ if process_state in TERMINAL_PROCESS - {"done"} or (process_state == "never-started" and attempt.get("job_id")):
554
+ snap = semantic_snapshot(doc["repository"]["toplevel"])
555
+ allowed_heads = set(unit.get("wave", {}).get("allowed_heads", []))
556
+ if (
557
+ snap["head"] not in allowed_heads
558
+ and not dependency_advanced_head(doc, unit, snap["head"])
559
+ ) or not snap["status_empty"] or snap["index_tree"] != snap["head_tree"]:
560
+ raise Operational("BLOCKED", "canonical checkout diverged or is dirty; native fallback is not safe")
561
+ recorded = attempt.get("terminal_receipt")
562
+ if process_state == "failed" and isinstance(recorded, dict) and recorded.get("terminal_status") in {"unavailable", "failed"}:
563
+ reader = (
564
+ unavailable_terminal_receipt
565
+ if recorded["terminal_status"] == "unavailable"
566
+ else launched_failure_terminal_receipt
567
+ )
568
+ observed = reader(doc["run_id"], unit, attempt)
569
+ if observed != recorded:
570
+ raise Operational("BLOCKED", "recorded failed receipt evidence changed")
571
+ return observed["failure_reason"], attempt
572
+ return str(attempt.get("fallback", {}).get("reason") or process_state), attempt
573
+ restore_evidence = unit.get("integration", {}).get("restore")
574
+ if unit.get("state") == "preserved" and restore_evidence and restore_evidence.get("exact") is True:
575
+ if doc.get("integration_lock"):
576
+ raise Operational("REFUSED", "release the integration lock after exact restoration before fallback")
577
+ actual = semantic_snapshot(doc["repository"]["toplevel"])
578
+ expected = unit["integration"].get("pre_fold")
579
+ if actual != expected:
580
+ raise Operational("BLOCKED", "canonical checkout no longer matches the exact restored snapshot")
581
+ return "canonical-attempt-preserved", attempt
582
+ if process_state == "running":
583
+ raise Operational("REFUSED", "a live attempt still owns implementation; fallback is not authorized")
584
+ if process_state == "done":
585
+ raise Operational("REFUSED", "successful worker output must be reconciled rather than bypassed by fallback")
586
+ raise Operational("REFUSED", "no authoritative terminal or exactly restored attempt authorizes fallback")
587
+
588
+
589
+ def cmd_claim_fallback(args) -> tuple[str, dict]:
590
+ # Refresh runner evidence first. A stale manifest cannot authorize native
591
+ # work while a detached attempt may still be live.
592
+ with locked_manifest(args.run_id) as doc:
593
+ validate_repo(doc)
594
+ unit = doc["units"].get(args.unit_id)
595
+ if not unit:
596
+ raise Operational("REFUSED", "unknown unit")
597
+ attempt = find_attempt(unit)
598
+ should_sync = bool(attempt.get("job_id")) and unit.get("state") == "authoring"
599
+ if should_sync:
600
+ sync_job(args.run_id, args.unit_id)
601
+
602
+ with locked_manifest(args.run_id, write=True) as doc:
603
+ validate_repo(doc)
604
+ unit = doc["units"].get(args.unit_id)
605
+ if not unit:
606
+ raise Operational("REFUSED", "unknown unit")
607
+ attempt = find_attempt(unit)
608
+ fallback = attempt.setdefault("fallback", {})
609
+ fallback.setdefault("completed", None)
610
+ claimed = fallback.get("claimed")
611
+ if claimed:
612
+ return "FALLBACK_ALREADY_AUTHORIZED", {
613
+ "unit_id": args.unit_id,
614
+ "start_native": False,
615
+ "reason": claimed["reason"],
616
+ "claim": claimed,
617
+ }
618
+ validate_dependencies_ready(doc, unit)
619
+ reason, attempt = fallback_basis(doc, unit)
620
+ claim_snapshot = semantic_snapshot(doc["repository"]["toplevel"])
621
+ wave = unit.get("wave", {})
622
+ if wave.get("id"):
623
+ validate_wave_order(doc, unit)
624
+ allowed_heads = wave.get("allowed_heads", [])
625
+ if not allowed_heads or (
626
+ claim_snapshot["head"] != allowed_heads[-1]
627
+ and not dependency_advanced_head(doc, unit, claim_snapshot["head"])
628
+ ):
629
+ raise Operational("BLOCKED", "native fallback must start from the latest recorded wave head")
630
+ mode = doc.get("binding", {}).get("mode")
631
+ if mode not in {"prefer", "require"}:
632
+ raise Operational("REFUSED", f"binding mode {mode!r} does not authorize native fallback")
633
+ claim = {
634
+ "at": now_iso(),
635
+ "reason": reason,
636
+ "caller_mode": args.caller_mode,
637
+ "mode": mode,
638
+ "canonical_head": claim_snapshot["head"],
639
+ }
640
+ fallback.update({"eligible": False, "reason": reason, "claimed": claim})
641
+ event(doc, "native-fallback-authorized", args.unit_id, {"reason": reason, "mode": mode, "caller_mode": args.caller_mode})
642
+ return "FALLBACK_AUTHORIZED", {"unit_id": args.unit_id, "start_native": True, "reason": reason, "claim": claim}
643
+
644
+
645
+ def validate_fallback_ancestry(doc: dict, unit: dict, accepted_head: str) -> None:
646
+ required: list[dict] = []
647
+ dependency_ids = set(unit.get("dependencies", []))
648
+ for dependency_id in unit.get("dependencies", []):
649
+ dependency = doc.get("units", {}).get(dependency_id)
650
+ accepted_commit = unit_accepted_commit(dependency) if isinstance(dependency, dict) else None
651
+ if accepted_commit is None:
652
+ raise Operational(
653
+ "BLOCKED",
654
+ "unit dependency completion evidence changed before native fallback completion",
655
+ {"unit_id": unit["unit_id"], "dependency_id": dependency_id},
656
+ )
657
+ required.append({"kind": "dependency", "unit_id": dependency_id, "commit": accepted_commit})
658
+
659
+ wave = unit.get("wave", {})
660
+ if wave.get("id"):
661
+ wave_members(doc, unit)
662
+ base = wave.get("base")
663
+ for head in wave.get("allowed_heads", []):
664
+ if head != base:
665
+ required.append({"kind": "wave-head", "commit": head})
666
+
667
+ represented_commits = {item["commit"] for item in required}
668
+ for accepted_unit_id in sorted(doc.get("units", {})):
669
+ if accepted_unit_id == unit["unit_id"] or accepted_unit_id in dependency_ids:
670
+ continue
671
+ accepted_unit = doc["units"][accepted_unit_id]
672
+ accepted_commit = unit_accepted_commit(accepted_unit)
673
+ if accepted_commit is None or accepted_commit in represented_commits:
674
+ continue
675
+ required.append({"kind": "accepted-unit", "unit_id": accepted_unit_id, "commit": accepted_commit})
676
+ represented_commits.add(accepted_commit)
677
+
678
+ missing = [
679
+ item for item in required
680
+ if git_text(
681
+ doc["repository"]["toplevel"], "merge-base", item["commit"], accepted_head, check=False,
682
+ ) != item["commit"]
683
+ ]
684
+ if missing:
685
+ raise Operational(
686
+ "BLOCKED",
687
+ "accepted native fallback head does not contain every controller-accepted prerequisite",
688
+ {"unit_id": unit["unit_id"], "accepted_head": accepted_head, "missing_ancestry": missing},
689
+ )
690
+
691
+
692
+ def cmd_complete_fallback(args) -> tuple[str, dict]:
693
+ if not re.fullmatch(r"[0-9a-f]{64}", args.evidence_digest):
694
+ raise Operational("REFUSED", "native fallback evidence digest must be lowercase SHA-256 hex")
695
+ summary = args.summary.strip()
696
+ if not summary or "\0" in summary or len(summary.encode()) > 1024:
697
+ raise Operational("REFUSED", "native fallback summary must be non-empty and at most 1024 bytes")
698
+ if not re.fullmatch(r"[0-9a-f]{40}|[0-9a-f]{64}", args.accepted_head):
699
+ raise Operational("REFUSED", "native fallback accepted head must be a Git object id")
700
+
701
+ with locked_manifest(args.run_id, write=True) as doc:
702
+ validate_repo(doc)
703
+ unit = doc["units"].get(args.unit_id)
704
+ if not unit:
705
+ raise Operational("REFUSED", "unknown unit")
706
+ attempt = find_attempt(unit)
707
+ fallback = attempt.get("fallback")
708
+ claim = fallback.get("claimed") if isinstance(fallback, dict) else None
709
+ if not isinstance(claim, dict):
710
+ raise Operational("REFUSED", "native fallback completion requires an existing claim")
711
+ if fallback.get("completed") is not None or unit.get("state") == "native-completed":
712
+ raise Operational("REFUSED", "native fallback completion was already recorded")
713
+ claim_mode = claim.get("mode")
714
+ if claim_mode not in {"prefer", "require"}:
715
+ raise Operational("REFUSED", "native fallback completion requires an authorized prefer or require claim")
716
+ if doc.get("integration_lock") is not None:
717
+ raise Operational("REFUSED", "release the integration lock before completing native fallback")
718
+
719
+ repo = doc["repository"]["toplevel"]
720
+ snapshot = semantic_snapshot(repo)
721
+ if snapshot.get("branch_ref") != doc["branch"]["ref"]:
722
+ raise Operational("BLOCKED", "canonical branch changed before native fallback completion")
723
+ if snapshot.get("status_empty") is not True:
724
+ raise Operational("BLOCKED", "commit or restore canonical changes before completing native fallback")
725
+ accepted_commit = git_text(repo, "rev-parse", "--verify", f"{args.accepted_head}^{{commit}}", check=False)
726
+ if accepted_commit != args.accepted_head or snapshot.get("head") != args.accepted_head:
727
+ raise Operational("BLOCKED", "accepted native fallback head does not match canonical HEAD")
728
+ base = unit.get("workspace", {}).get("base")
729
+ if not isinstance(base, str) or git_text(repo, "merge-base", base, args.accepted_head, check=False) != base:
730
+ raise Operational("BLOCKED", "accepted native fallback head does not descend from the recorded unit base")
731
+ validate_fallback_ancestry(doc, unit, args.accepted_head)
732
+
733
+ wave = unit.get("wave", {})
734
+ changed_paths: list[str] = []
735
+ advanced: list[str] = []
736
+ if wave.get("id"):
737
+ validate_wave_order(doc, unit)
738
+ claim_head = claim.get("canonical_head")
739
+ allowed_heads = wave.get("allowed_heads", [])
740
+ if (
741
+ not isinstance(claim_head, str)
742
+ or not allowed_heads
743
+ or claim_head != allowed_heads[-1]
744
+ or git_text(repo, "merge-base", claim_head, args.accepted_head, check=False) != claim_head
745
+ ):
746
+ raise Operational("BLOCKED", "native fallback completion does not extend the latest recorded wave head")
747
+ raw = git(repo, "diff-tree", "-r", "-M", "--name-status", "-z", claim_head, args.accepted_head)
748
+ changed_paths = parse_diff_paths(raw)
749
+ validate_wave_collisions(
750
+ doc,
751
+ unit,
752
+ overrides={unit["unit_id"]: set(changed_paths)},
753
+ require_complete=False,
754
+ )
755
+ members = wave_members(doc, unit)
756
+ validate_wave_advancement(members, unit, claim_head, args.accepted_head)
757
+
758
+ receipt = {
759
+ "at": now_iso(),
760
+ "base": base,
761
+ "accepted_head": args.accepted_head,
762
+ "evidence_digest": args.evidence_digest,
763
+ "summary": summary,
764
+ "snapshot": snapshot,
765
+ "claim": dict(claim),
766
+ "changed_paths": changed_paths,
767
+ }
768
+ fallback["completed"] = receipt
769
+ unit["state"] = "native-completed"
770
+ if wave.get("id"):
771
+ advanced = advance_wave_allowed_heads(members, wave["position"], args.accepted_head)
772
+ event(doc, "wave-advanced", args.unit_id, {
773
+ "canonical_commit": args.accepted_head,
774
+ "eligible_siblings": advanced,
775
+ })
776
+ event(doc, "native-fallback-completed", args.unit_id, {
777
+ "accepted_head": args.accepted_head,
778
+ "evidence_digest": args.evidence_digest,
779
+ })
780
+ return "FALLBACK_COMPLETED", {
781
+ "unit_id": args.unit_id,
782
+ "completion": receipt,
783
+ "eligible_siblings": advanced,
784
+ }
785
+
786
+
787
+ def cmd_reap(args) -> tuple[str, dict]:
788
+ with locked_manifest(args.run_id) as doc:
789
+ validate_repo(doc)
790
+ unit = doc["units"].get(args.unit_id)
791
+ if not unit:
792
+ raise Operational("REFUSED", "unknown unit")
793
+ attempt = find_attempt(unit)
794
+ if not attempt.get("job_id"):
795
+ return "REAPED", {"unit_id": args.unit_id, "process_state": "never-started"}
796
+ job_dir = runner_job_dir(args.run_id, attempt["job_id"])
797
+ runner = os.path.join(os.path.dirname(__file__), "peer-job-runner.py")
798
+ proc = subprocess.run([sys.executable, runner, "reap", job_dir], capture_output=True, check=False)
799
+ if proc.returncode not in (0,):
800
+ raise Operational("BLOCKED", f"runner reap failed: {proc.stderr.decode('utf-8', 'replace').strip()}")
801
+ evidence = sync_job(args.run_id, args.unit_id)
802
+ return "REAPED", {"unit_id": args.unit_id, **evidence, "recovery_path": os.path.join(run_dir(args.run_id), "units", args.unit_id)}
803
+
804
+
805
+ def remove_finalized_artifacts(run_id: str, unit_id: str) -> None:
806
+ """Prune bulky controller-owned artifacts only after a unit is finalized."""
807
+ with locked_manifest(run_id) as doc:
808
+ unit = doc["units"].get(unit_id)
809
+ cleanup = unit.get("cleanup") if unit else None
810
+ if (
811
+ not unit
812
+ or unit.get("state") not in {"cleaned", "native-completed"}
813
+ or not isinstance(cleanup, dict)
814
+ ):
815
+ raise Operational("REFUSED", "artifact pruning requires a finalized unit with recorded cleanup")
816
+ attempt_job_ids = [attempt.get("job_id") for attempt in unit.get("attempts", []) if attempt.get("job_id")]
817
+ authorization_paths = [attempt.get("authorization_path") for attempt in unit.get("attempts", []) if attempt.get("authorization_path")]
818
+ packet_path = unit.get("packet", {}).get("path")
819
+ result_dir = os.path.join(os.path.dirname(unit["workspace"]["path"]), "result")
820
+ root = run_dir(run_id)
821
+ paths = [(packet_path, "file"), (result_dir, "dir")]
822
+ paths.extend((authorization_path, "file") for authorization_path in authorization_paths)
823
+ paths.extend((runner_job_dir(run_id, job_id), "dir") for job_id in attempt_job_ids)
824
+ for candidate, kind in paths:
825
+ if not candidate or not os.path.lexists(candidate):
826
+ continue
827
+ absolute = os.path.abspath(candidate)
828
+ if os.path.commonpath([root, absolute]) != root or absolute == root:
829
+ raise Operational("BLOCKED", "finalized artifact path escaped the owned run")
830
+ if kind == "file":
831
+ read_private(absolute, MAX_PACKET_BYTES)
832
+ os.unlink(absolute)
833
+ else:
834
+ validate_private_dir(absolute)
835
+ shutil.rmtree(absolute)
836
+ with locked_manifest(run_id, write=True) as doc:
837
+ unit = doc["units"][unit_id]
838
+ unit["packet"]["retained"] = False
839
+ for attempt in unit.get("attempts", []):
840
+ attempt["bulky_artifacts_retained"] = False
841
+ attempt["authorization_retained"] = False
842
+ unit["cleanup"]["artifact_cleanup"] = {"at": now_iso(), "complete": True}
843
+ event(doc, "finalized-artifacts-pruned", unit_id, {"job_count": len(attempt_job_ids)})
844
+
845
+
846
+ def retained_blocked_abandonment_receipt(run_id: str, unit: dict, attempt: dict) -> dict:
847
+ recorded = attempt.get("terminal_receipt")
848
+ if (
849
+ unit.get("state") != "authored"
850
+ or attempt.get("process_state") != "done"
851
+ or attempt.get("terminal_validation_failure") is not None
852
+ or not isinstance(recorded, dict)
853
+ or recorded.get("terminal_status") != "blocked"
854
+ ):
855
+ raise Operational("REFUSED", "done output is not an exactly retained worker blocker")
856
+ observed_process = process_evidence(runner_job_dir(run_id, attempt["job_id"]))["process_state"]
857
+ if observed_process != "done":
858
+ raise Operational("BLOCKED", "retained worker-blocker job evidence changed")
859
+ observed_receipt = terminal_receipt(unit, attempt)
860
+ if observed_receipt != recorded:
861
+ raise Operational("BLOCKED", "retained worker-blocker receipt evidence changed")
862
+ return {
863
+ "kind": "retained-worker-blocker",
864
+ "value": attempt["job_id"],
865
+ "process_state": observed_process,
866
+ "terminal_status": recorded["terminal_status"],
867
+ "result_sha256": recorded["result_sha256"],
868
+ "raw_log_sha256": recorded["raw_log_sha256"],
869
+ }
870
+
871
+
872
+ def owned_workspace_path(run_id: str, unit_id: str, recorded_workspace: str) -> str:
873
+ unit_root = os.path.join(run_dir(run_id), "units", unit_id)
874
+ expected_workspace = os.path.join(unit_root, "workspace")
875
+ if os.path.abspath(recorded_workspace) != expected_workspace:
876
+ raise TrustFailure("manifest workspace path does not match the controller-owned unit workspace")
877
+ validate_private_dir(unit_root)
878
+ return expected_workspace
879
+
880
+
881
+ def remove_unregistered_owned_workspace(run_id: str, unit_id: str, recorded_workspace: str) -> None:
882
+ expected_workspace = owned_workspace_path(run_id, unit_id, recorded_workspace)
883
+ if not os.path.lexists(expected_workspace):
884
+ return
885
+ entry = os.lstat(expected_workspace)
886
+ uid_getter = getattr(os, "geteuid", None) or getattr(os, "getuid", None)
887
+ effective_uid = uid_getter() if uid_getter is not None else None
888
+ if not stat.S_ISDIR(entry.st_mode) or stat.S_ISLNK(entry.st_mode):
889
+ raise Operational("BLOCKED", "unregistered workspace path is not a real directory")
890
+ if effective_uid is not None and entry.st_uid != effective_uid:
891
+ raise Operational("BLOCKED", "unregistered workspace is not owned by the current user")
892
+ shutil.rmtree(expected_workspace)
893
+ if os.path.lexists(expected_workspace):
894
+ raise Operational("BLOCKED", "unregistered workspace remained after cleanup")
895
+
896
+
897
+ def cmd_cleanup(args) -> tuple[str, dict]:
898
+ with locked_manifest(args.run_id) as doc:
899
+ validate_repo(doc)
900
+ unit = doc["units"].get(args.unit_id)
901
+ if not unit:
902
+ raise Operational("REFUSED", "unknown unit")
903
+ cleanup_recorded = isinstance(unit.get("cleanup"), dict)
904
+ if unit["state"] == "cleaned" or (unit["state"] == "native-completed" and cleanup_recorded):
905
+ if not unit.get("cleanup", {}).get("artifact_cleanup", {}).get("complete"):
906
+ pass
907
+ else:
908
+ return "CLEANED", {"unit_id": args.unit_id, "resumed": True}
909
+ if unit["state"] == "cleaned" or (unit["state"] == "native-completed" and cleanup_recorded):
910
+ remove_finalized_artifacts(args.run_id, args.unit_id)
911
+ return "CLEANED", {"unit_id": args.unit_id, "resumed": True}
912
+ with locked_manifest(args.run_id) as doc:
913
+ unit = doc["units"][args.unit_id]
914
+ attempt = find_attempt(unit)
915
+ if attempt.get("process_state") == "running":
916
+ raise Operational("REFUSED", "cannot cleanup a live worker")
917
+ commit = unit["transport"].get("commit")
918
+ abandonment_receipt = None
919
+ if args.abandon:
920
+ if commit:
921
+ if args.expect_transport != commit:
922
+ raise Operational("REFUSED", "abandon cleanup requires exact transport SHA")
923
+ abandonment_receipt = {"kind": "transport", "value": commit}
924
+ else:
925
+ terminal_failures = TERMINAL_PROCESS - {"done"}
926
+ validation_failure = attempt.get("process_state") == "done" and attempt.get("terminal_validation_failure")
927
+ if not attempt.get("job_id"):
928
+ raise Operational("REFUSED", "transport-free cleanup requires an authoritative failed or reaped job")
929
+ if args.expect_job != attempt["job_id"]:
930
+ raise Operational("REFUSED", "transport-free cleanup requires the exact terminal job id")
931
+ if validation_failure:
932
+ validate_terminal_validation_failure(args.run_id, unit, attempt)
933
+ abandonment_receipt = {"kind": "terminal-validation-failure", "value": attempt["job_id"], "process_state": "done"}
934
+ elif attempt.get("process_state") == "done":
935
+ abandonment_receipt = retained_blocked_abandonment_receipt(args.run_id, unit, attempt)
936
+ else:
937
+ if attempt.get("process_state") not in terminal_failures:
938
+ raise Operational("REFUSED", "transport-free cleanup requires an authoritative failed or reaped job")
939
+ observed = process_evidence(runner_job_dir(args.run_id, attempt["job_id"]))["process_state"]
940
+ if observed != attempt["process_state"] or observed not in terminal_failures:
941
+ raise Operational("BLOCKED", "terminal job evidence changed; refusing cleanup")
942
+ abandonment_receipt = {"kind": "terminal-job", "value": attempt["job_id"], "process_state": observed}
943
+ elif unit["state"] != "committed":
944
+ raise Operational("REFUSED", "uncommitted output is retained unless explicitly abandoned")
945
+ workspace = unit["workspace"]["path"]
946
+ ref = unit["transport"].get("ref")
947
+ repo = doc["repository"]["toplevel"]
948
+ common = doc["repository"]["common_dir"]
949
+ workspace = owned_workspace_path(args.run_id, args.unit_id, workspace)
950
+ with locked_manifest(args.run_id, write=True) as doc:
951
+ event(doc, "cleanup-intent", args.unit_id, {"workspace": workspace, "ref": ref, "abandonment_receipt": abandonment_receipt})
952
+ with admin_lock(common):
953
+ present = [r for r in worktree_rows(repo) if os.path.realpath(str(r.get("worktree", ""))) == os.path.realpath(workspace)]
954
+ if present:
955
+ git(repo, "worktree", "remove", "--force", workspace)
956
+ test_fault("cleanup-after-worktree-remove")
957
+ if any(os.path.realpath(str(r.get("worktree", ""))) == os.path.realpath(workspace) for r in worktree_rows(repo)):
958
+ raise Operational("BLOCKED", "worktree remained registered after cleanup")
959
+ remove_unregistered_owned_workspace(args.run_id, args.unit_id, workspace)
960
+ if ref and commit:
961
+ current = git_text(repo, "rev-parse", "-q", "--verify", ref, check=False)
962
+ if current and current != commit:
963
+ raise Operational("BLOCKED", "transport ref changed; refusing cleanup")
964
+ if current:
965
+ git(repo, "update-ref", "-d", ref, commit)
966
+ with locked_manifest(args.run_id, write=True) as doc:
967
+ unit = doc["units"][args.unit_id]
968
+ finalized_state = "native-completed" if unit["state"] == "native-completed" else "cleaned"
969
+ unit["cleanup"] = {
970
+ "at": now_iso(),
971
+ "workspace_removed": True,
972
+ "ref_removed": True,
973
+ "abandoned": bool(args.abandon),
974
+ "abandonment_receipt": abandonment_receipt,
975
+ "artifact_cleanup": {"at": None, "complete": False},
976
+ }
977
+ unit["state"] = finalized_state
978
+ event(doc, "unit-cleaned", args.unit_id)
979
+ test_fault("cleanup-before-artifact-prune")
980
+ remove_finalized_artifacts(args.run_id, args.unit_id)
981
+ return "CLEANED", {"unit_id": args.unit_id, "resumed": False}