devrites 6.0.4 → 6.1.1

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 (800) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +24 -9
  3. package/SECURITY.md +9 -6
  4. package/bin/devrites.mjs +28 -12
  5. package/docs/adr/0035-claude-root-leaves-plan-mode.md +33 -0
  6. package/docs/adr/0036-archive-recall-is-a-read-time-query.md +32 -0
  7. package/docs/adr/README.md +4 -2
  8. package/docs/architecture.md +3 -1
  9. package/docs/cli.md +25 -2
  10. package/docs/command-map.md +10 -8
  11. package/docs/engine/commands.md +6 -3
  12. package/docs/harness-compliance.md +2 -2
  13. package/docs/orchestration.md +5 -4
  14. package/docs/release.md +4 -4
  15. package/docs/skills.md +2 -2
  16. package/engine/commands.go +1 -1
  17. package/engine/help.go +10 -6
  18. package/engine/internal/acceptance/cli.go +4 -1
  19. package/engine/internal/acceptance/exec.go +11 -11
  20. package/engine/internal/devritespaths/paths.go +5 -0
  21. package/engine/internal/hostpack/hostpack.go +48 -3
  22. package/engine/internal/install/apply.go +68 -1
  23. package/engine/internal/install/binary.go +4 -0
  24. package/engine/internal/install/install.go +25 -15
  25. package/engine/internal/install/merge.go +287 -123
  26. package/engine/internal/install/preflight.go +71 -1
  27. package/engine/internal/install/uninstall.go +7 -1
  28. package/engine/internal/install/update.go +7 -3
  29. package/engine/internal/lib/claims.go +30 -14
  30. package/engine/internal/lib/cli_observe.go +6 -0
  31. package/engine/internal/lib/context.go +24 -7
  32. package/engine/internal/lib/diffscope.go +79 -3
  33. package/engine/internal/lib/dispatch.go +34 -7
  34. package/engine/internal/lib/drift.go +9 -2
  35. package/engine/internal/lib/handoff.go +14 -5
  36. package/engine/internal/lib/metrics.go +29 -9
  37. package/engine/internal/lib/migrate.go +30 -12
  38. package/engine/internal/lib/next.go +22 -2
  39. package/engine/internal/lib/open_visual.go +3 -1
  40. package/engine/internal/lib/recall.go +355 -0
  41. package/engine/internal/lib/regression.go +20 -0
  42. package/engine/internal/lib/resolve.go +96 -53
  43. package/engine/internal/lib/secretscan.go +24 -1
  44. package/engine/internal/lib/taskgraph.go +31 -1
  45. package/engine/internal/lib/util.go +18 -7
  46. package/engine/internal/lib/windows.go +68 -15
  47. package/engine/internal/markdowntext/markdowntext.go +45 -6
  48. package/engine/internal/notes/cli.go +5 -3
  49. package/engine/internal/notes/notes.go +8 -3
  50. package/engine/internal/overhaul/admit/run.go +16 -12
  51. package/engine/internal/overhaul/overhaul.go +1 -0
  52. package/engine/internal/overhaul/records/check.go +52 -9
  53. package/engine/internal/overhaul/render/run.go +3 -2
  54. package/engine/internal/overhaul/snapshot/run.go +2 -2
  55. package/engine/internal/parallel/git.go +5 -6
  56. package/engine/internal/parallel/ops.go +3 -0
  57. package/engine/internal/parallel/pathdisjoint.go +9 -4
  58. package/engine/internal/release/release.go +11 -9
  59. package/engine/internal/safepath/safepath.go +17 -1
  60. package/engine/internal/state/budgets.go +8 -4
  61. package/engine/internal/state/feature.go +3 -1
  62. package/engine/internal/state/observation.go +12 -7
  63. package/engine/internal/state/taskgraph.go +67 -12
  64. package/engine/internal/state/write.go +7 -1
  65. package/engine/main.go +5 -1
  66. package/pack/.claude/agents/_shared/composition-overhaul.md +2 -0
  67. package/pack/.claude/agents/devrites-devex-reviewer.md +5 -0
  68. package/pack/.claude/agents/devrites-evidence-scout.md +4 -0
  69. package/pack/.claude/agents/devrites-plan-reviewer.md +4 -1
  70. package/pack/.claude/agents/overhaul-implementer.md +1 -0
  71. package/pack/.claude/settings.json +4 -4
  72. package/pack/.claude/skills/devrites-api-interface/SKILL.md +1 -1
  73. package/pack/.claude/skills/devrites-audit/SKILL.md +1 -1
  74. package/pack/.claude/skills/devrites-browser-proof/SKILL.md +1 -1
  75. package/pack/.claude/skills/devrites-debug-recovery/SKILL.md +8 -6
  76. package/pack/.claude/skills/devrites-doubt/SKILL.md +1 -1
  77. package/pack/.claude/skills/devrites-frontend-craft/SKILL.md +1 -1
  78. package/pack/.claude/skills/devrites-interview/SKILL.md +1 -1
  79. package/pack/.claude/skills/devrites-lib/reference/intent-map.md +3 -3
  80. package/pack/.claude/skills/devrites-lib/reference/parallel-dispatch.md +4 -3
  81. package/pack/.claude/skills/devrites-lib/reference/reply-contract.md +12 -15
  82. package/pack/.claude/skills/devrites-lib/reference/standards/afk-hitl.md +30 -10
  83. package/pack/.claude/skills/devrites-lib/reference/standards/ci-cd.md +2 -1
  84. package/pack/.claude/skills/devrites-lib/reference/standards/code-review.md +1 -1
  85. package/pack/.claude/skills/devrites-lib/reference/standards/core.md +1 -1
  86. package/pack/.claude/skills/devrites-lib/reference/standards/data-integrity.md +4 -0
  87. package/pack/.claude/skills/devrites-lib/reference/standards/developer-experience.md +5 -0
  88. package/pack/.claude/skills/devrites-lib/reference/standards/loop-operations.md +3 -0
  89. package/pack/.claude/skills/devrites-lib/reference/standards/one-shot-actions.md +7 -6
  90. package/pack/.claude/skills/devrites-lib/reference/standards/performance.md +2 -0
  91. package/pack/.claude/skills/devrites-lib/reference/standards/skill-authoring.md +13 -1
  92. package/pack/.claude/skills/devrites-lib/reference/standards/testing.md +13 -0
  93. package/pack/.claude/skills/devrites-lib/reference/workspace-artifact-schema.md +10 -6
  94. package/pack/.claude/skills/devrites-prose-craft/SKILL.md +1 -1
  95. package/pack/.claude/skills/devrites-source-driven/SKILL.md +1 -1
  96. package/pack/.claude/skills/devrites-ux-shape/SKILL.md +1 -1
  97. package/pack/.claude/skills/overhaul/references/orchestration.md +6 -2
  98. package/pack/.claude/skills/overhaul/references/records.md +8 -3
  99. package/pack/.claude/skills/rite/SKILL.md +4 -3
  100. package/pack/.claude/skills/rite/reference/menu.md +6 -5
  101. package/pack/.claude/skills/rite-adopt/SKILL.md +4 -3
  102. package/pack/.claude/skills/rite-autocomplete/SKILL.md +17 -14
  103. package/pack/.claude/skills/rite-autocomplete/reference/loop.md +9 -6
  104. package/pack/.claude/skills/rite-autocomplete/reference/stop-conditions.md +25 -21
  105. package/pack/.claude/skills/rite-build/reference/afk-discipline.md +6 -3
  106. package/pack/.claude/skills/rite-build/reference/parallel-batch.md +5 -5
  107. package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +19 -0
  108. package/pack/.claude/skills/rite-converge/SKILL.md +4 -3
  109. package/pack/.claude/skills/rite-customize/SKILL.md +1 -1
  110. package/pack/.claude/skills/rite-define/SKILL.md +3 -2
  111. package/pack/.claude/skills/rite-doctor/SKILL.md +12 -6
  112. package/pack/.claude/skills/rite-dogfood/SKILL.md +2 -2
  113. package/pack/.claude/skills/rite-explain/SKILL.md +1 -1
  114. package/pack/.claude/skills/rite-fast/SKILL.md +3 -1
  115. package/pack/.claude/skills/rite-handoff/SKILL.md +4 -3
  116. package/pack/.claude/skills/rite-learn/SKILL.md +2 -2
  117. package/pack/.claude/skills/rite-plan/SKILL.md +1 -1
  118. package/pack/.claude/skills/rite-plan/reference/replan-and-repair.md +2 -0
  119. package/pack/.claude/skills/rite-plan/reference/slicing.md +3 -1
  120. package/pack/.claude/skills/rite-pov/SKILL.md +1 -1
  121. package/pack/.claude/skills/rite-pr-feedback/SKILL.md +5 -4
  122. package/pack/.claude/skills/rite-pressure-test/SKILL.md +7 -5
  123. package/pack/.claude/skills/rite-prototype/SKILL.md +1 -1
  124. package/pack/.claude/skills/rite-prove/SKILL.md +4 -2
  125. package/pack/.claude/skills/rite-prove/reference/failure-triage.md +2 -1
  126. package/pack/.claude/skills/rite-quick/SKILL.md +10 -5
  127. package/pack/.claude/skills/rite-resolve/SKILL.md +3 -3
  128. package/pack/.claude/skills/rite-resolve/reference/answer-protocol.md +4 -5
  129. package/pack/.claude/skills/rite-review/SKILL.md +2 -1
  130. package/pack/.claude/skills/rite-seal/SKILL.md +3 -3
  131. package/pack/.claude/skills/rite-seal/reference/go-no-go.md +2 -0
  132. package/pack/.claude/skills/rite-seal/reference/seal-template.md +5 -2
  133. package/pack/.claude/skills/rite-ship/reference/close-out.md +3 -2
  134. package/pack/.claude/skills/rite-spec/SKILL.md +4 -1
  135. package/pack/.claude/skills/rite-spec/reference/state-workspace.md +2 -2
  136. package/pack/.claude/skills/rite-status/SKILL.md +1 -1
  137. package/pack/.claude/skills/rite-temper/reference/significance.md +2 -0
  138. package/pack/.claude/skills/rite-upgrade/SKILL.md +4 -2
  139. package/pack/.claude/skills/rite-vet/SKILL.md +3 -2
  140. package/pack/.claude/skills/rite-vet/reference/artifacts.md +1 -1
  141. package/pack/.claude/skills/rite-watch-pr/SKILL.md +1 -1
  142. package/pack/.claude/skills/rite-zoom-out/SKILL.md +1 -1
  143. package/pack/generated/claude/agents/devrites-devex-reviewer.md +5 -0
  144. package/pack/generated/claude/agents/devrites-evidence-scout.md +4 -0
  145. package/pack/generated/claude/agents/devrites-plan-reviewer.md +4 -1
  146. package/pack/generated/claude/agents/overhaul-backend-engineer.md +2 -0
  147. package/pack/generated/claude/agents/overhaul-boundary.md +2 -0
  148. package/pack/generated/claude/agents/overhaul-craft.md +2 -0
  149. package/pack/generated/claude/agents/overhaul-frontend-engineer.md +2 -0
  150. package/pack/generated/claude/agents/overhaul-implementer.md +3 -0
  151. package/pack/generated/claude/agents/overhaul-recon.md +2 -0
  152. package/pack/generated/claude/agents/overhaul-specialist.md +2 -0
  153. package/pack/generated/claude/agents/overhaul-verifier.md +2 -0
  154. package/pack/generated/claude/settings.json +4 -4
  155. package/pack/generated/claude/skills/devrites-api-interface/SKILL.md +1 -1
  156. package/pack/generated/claude/skills/devrites-audit/SKILL.md +1 -1
  157. package/pack/generated/claude/skills/devrites-browser-proof/SKILL.md +1 -1
  158. package/pack/generated/claude/skills/devrites-debug-recovery/SKILL.md +8 -6
  159. package/pack/generated/claude/skills/devrites-doubt/SKILL.md +1 -1
  160. package/pack/generated/claude/skills/devrites-frontend-craft/SKILL.md +1 -1
  161. package/pack/generated/claude/skills/devrites-interview/SKILL.md +1 -1
  162. package/pack/generated/claude/skills/devrites-lib/reference/intent-map.md +3 -3
  163. package/pack/generated/claude/skills/devrites-lib/reference/parallel-dispatch.md +4 -3
  164. package/pack/generated/claude/skills/devrites-lib/reference/reply-contract.md +12 -15
  165. package/pack/generated/claude/skills/devrites-lib/reference/standards/afk-hitl.md +30 -10
  166. package/pack/generated/claude/skills/devrites-lib/reference/standards/ci-cd.md +2 -1
  167. package/pack/generated/claude/skills/devrites-lib/reference/standards/code-review.md +1 -1
  168. package/pack/generated/claude/skills/devrites-lib/reference/standards/core.md +1 -1
  169. package/pack/generated/claude/skills/devrites-lib/reference/standards/data-integrity.md +4 -0
  170. package/pack/generated/claude/skills/devrites-lib/reference/standards/developer-experience.md +5 -0
  171. package/pack/generated/claude/skills/devrites-lib/reference/standards/loop-operations.md +3 -0
  172. package/pack/generated/claude/skills/devrites-lib/reference/standards/one-shot-actions.md +7 -6
  173. package/pack/generated/claude/skills/devrites-lib/reference/standards/performance.md +2 -0
  174. package/pack/generated/claude/skills/devrites-lib/reference/standards/skill-authoring.md +13 -1
  175. package/pack/generated/claude/skills/devrites-lib/reference/standards/testing.md +13 -0
  176. package/pack/generated/claude/skills/devrites-lib/reference/workspace-artifact-schema.md +10 -6
  177. package/pack/generated/claude/skills/devrites-prose-craft/SKILL.md +1 -1
  178. package/pack/generated/claude/skills/devrites-source-driven/SKILL.md +1 -1
  179. package/pack/generated/claude/skills/devrites-ux-shape/SKILL.md +1 -1
  180. package/pack/generated/claude/skills/overhaul/references/orchestration.md +6 -2
  181. package/pack/generated/claude/skills/overhaul/references/records.md +8 -3
  182. package/pack/generated/claude/skills/rite/SKILL.md +4 -3
  183. package/pack/generated/claude/skills/rite/reference/menu.md +6 -5
  184. package/pack/generated/claude/skills/rite-adopt/SKILL.md +4 -3
  185. package/pack/generated/claude/skills/rite-autocomplete/SKILL.md +17 -14
  186. package/pack/generated/claude/skills/rite-autocomplete/reference/loop.md +9 -6
  187. package/pack/generated/claude/skills/rite-autocomplete/reference/stop-conditions.md +25 -21
  188. package/pack/generated/claude/skills/rite-build/reference/afk-discipline.md +6 -3
  189. package/pack/generated/claude/skills/rite-build/reference/parallel-batch.md +5 -5
  190. package/pack/generated/claude/skills/rite-build/reference/wright-dispatch.md +19 -0
  191. package/pack/generated/claude/skills/rite-converge/SKILL.md +4 -3
  192. package/pack/generated/claude/skills/rite-customize/SKILL.md +1 -1
  193. package/pack/generated/claude/skills/rite-define/SKILL.md +3 -2
  194. package/pack/generated/claude/skills/rite-doctor/SKILL.md +12 -6
  195. package/pack/generated/claude/skills/rite-dogfood/SKILL.md +2 -2
  196. package/pack/generated/claude/skills/rite-explain/SKILL.md +1 -1
  197. package/pack/generated/claude/skills/rite-fast/SKILL.md +3 -1
  198. package/pack/generated/claude/skills/rite-handoff/SKILL.md +4 -3
  199. package/pack/generated/claude/skills/rite-learn/SKILL.md +2 -2
  200. package/pack/generated/claude/skills/rite-plan/SKILL.md +1 -1
  201. package/pack/generated/claude/skills/rite-plan/reference/replan-and-repair.md +2 -0
  202. package/pack/generated/claude/skills/rite-plan/reference/slicing.md +3 -1
  203. package/pack/generated/claude/skills/rite-pov/SKILL.md +1 -1
  204. package/pack/generated/claude/skills/rite-pr-feedback/SKILL.md +5 -4
  205. package/pack/generated/claude/skills/rite-pressure-test/SKILL.md +7 -5
  206. package/pack/generated/claude/skills/rite-prototype/SKILL.md +1 -1
  207. package/pack/generated/claude/skills/rite-prove/SKILL.md +4 -2
  208. package/pack/generated/claude/skills/rite-prove/reference/failure-triage.md +2 -1
  209. package/pack/generated/claude/skills/rite-quick/SKILL.md +10 -5
  210. package/pack/generated/claude/skills/rite-resolve/SKILL.md +3 -3
  211. package/pack/generated/claude/skills/rite-resolve/reference/answer-protocol.md +4 -5
  212. package/pack/generated/claude/skills/rite-review/SKILL.md +2 -1
  213. package/pack/generated/claude/skills/rite-seal/SKILL.md +3 -3
  214. package/pack/generated/claude/skills/rite-seal/reference/go-no-go.md +2 -0
  215. package/pack/generated/claude/skills/rite-seal/reference/seal-template.md +5 -2
  216. package/pack/generated/claude/skills/rite-ship/reference/close-out.md +3 -2
  217. package/pack/generated/claude/skills/rite-spec/SKILL.md +4 -1
  218. package/pack/generated/claude/skills/rite-spec/reference/state-workspace.md +2 -2
  219. package/pack/generated/claude/skills/rite-status/SKILL.md +1 -1
  220. package/pack/generated/claude/skills/rite-temper/reference/significance.md +2 -0
  221. package/pack/generated/claude/skills/rite-upgrade/SKILL.md +4 -2
  222. package/pack/generated/claude/skills/rite-vet/SKILL.md +3 -2
  223. package/pack/generated/claude/skills/rite-vet/reference/artifacts.md +1 -1
  224. package/pack/generated/claude/skills/rite-watch-pr/SKILL.md +1 -1
  225. package/pack/generated/claude/skills/rite-zoom-out/SKILL.md +1 -1
  226. package/pack/generated/codex/agents/devrites-code-reviewer.toml +7 -7
  227. package/pack/generated/codex/agents/devrites-devex-reviewer.toml +6 -1
  228. package/pack/generated/codex/agents/devrites-evidence-scout.toml +4 -0
  229. package/pack/generated/codex/agents/devrites-frontend-reviewer.toml +1 -1
  230. package/pack/generated/codex/agents/devrites-plan-drafter.toml +3 -3
  231. package/pack/generated/codex/agents/devrites-plan-reviewer.toml +5 -2
  232. package/pack/generated/codex/agents/devrites-proof-runner.toml +2 -2
  233. package/pack/generated/codex/agents/devrites-security-auditor.toml +1 -1
  234. package/pack/generated/codex/agents/devrites-simplifier-reviewer.toml +1 -1
  235. package/pack/generated/codex/agents/devrites-slice-wright.toml +5 -5
  236. package/pack/generated/codex/agents/devrites-test-analyst.toml +5 -5
  237. package/pack/generated/codex/agents/devrites-upgrade-planner.toml +1 -1
  238. package/pack/generated/codex/agents/fast-builder.toml +3 -3
  239. package/pack/generated/codex/agents/fast-critic.toml +3 -3
  240. package/pack/generated/codex/agents/overhaul-backend-engineer.toml +2 -0
  241. package/pack/generated/codex/agents/overhaul-boundary.toml +2 -0
  242. package/pack/generated/codex/agents/overhaul-craft.toml +2 -0
  243. package/pack/generated/codex/agents/overhaul-frontend-engineer.toml +2 -0
  244. package/pack/generated/codex/agents/overhaul-implementer.toml +2 -0
  245. package/pack/generated/codex/agents/overhaul-recon.toml +2 -0
  246. package/pack/generated/codex/agents/overhaul-specialist.toml +2 -0
  247. package/pack/generated/codex/agents/overhaul-verifier.toml +2 -0
  248. package/pack/generated/codex/skills/devrites-api-interface/SKILL.md +1 -1
  249. package/pack/generated/codex/skills/devrites-audit/SKILL.md +1 -1
  250. package/pack/generated/codex/skills/devrites-browser-proof/SKILL.md +1 -1
  251. package/pack/generated/codex/skills/devrites-debug-recovery/SKILL.md +8 -6
  252. package/pack/generated/codex/skills/devrites-doubt/SKILL.md +1 -1
  253. package/pack/generated/codex/skills/devrites-frontend-craft/SKILL.md +1 -1
  254. package/pack/generated/codex/skills/devrites-interview/SKILL.md +1 -1
  255. package/pack/generated/codex/skills/devrites-lib/reference/intent-map.md +3 -3
  256. package/pack/generated/codex/skills/devrites-lib/reference/parallel-dispatch.md +6 -5
  257. package/pack/generated/codex/skills/devrites-lib/reference/reply-contract.md +12 -15
  258. package/pack/generated/codex/skills/devrites-lib/reference/standards/afk-hitl.md +30 -10
  259. package/pack/generated/codex/skills/devrites-lib/reference/standards/agents.md +1 -1
  260. package/pack/generated/codex/skills/devrites-lib/reference/standards/ci-cd.md +2 -1
  261. package/pack/generated/codex/skills/devrites-lib/reference/standards/code-review.md +1 -1
  262. package/pack/generated/codex/skills/devrites-lib/reference/standards/core.md +2 -2
  263. package/pack/generated/codex/skills/devrites-lib/reference/standards/data-integrity.md +4 -0
  264. package/pack/generated/codex/skills/devrites-lib/reference/standards/developer-experience.md +5 -0
  265. package/pack/generated/codex/skills/devrites-lib/reference/standards/loop-operations.md +3 -0
  266. package/pack/generated/codex/skills/devrites-lib/reference/standards/one-shot-actions.md +7 -6
  267. package/pack/generated/codex/skills/devrites-lib/reference/standards/performance.md +2 -0
  268. package/pack/generated/codex/skills/devrites-lib/reference/standards/skill-authoring.md +13 -1
  269. package/pack/generated/codex/skills/devrites-lib/reference/standards/testing.md +13 -0
  270. package/pack/generated/codex/skills/devrites-lib/reference/workspace-artifact-schema.md +11 -7
  271. package/pack/generated/codex/skills/devrites-prose-craft/SKILL.md +1 -1
  272. package/pack/generated/codex/skills/devrites-source-driven/SKILL.md +1 -1
  273. package/pack/generated/codex/skills/devrites-ux-shape/SKILL.md +1 -1
  274. package/pack/generated/codex/skills/overhaul/SKILL.md +15 -15
  275. package/pack/generated/codex/skills/overhaul/references/audit-domains.md +2 -2
  276. package/pack/generated/codex/skills/overhaul/references/orchestration.md +11 -7
  277. package/pack/generated/codex/skills/overhaul/references/records.md +8 -3
  278. package/pack/generated/codex/skills/rite/SKILL.md +4 -3
  279. package/pack/generated/codex/skills/rite/reference/menu.md +6 -5
  280. package/pack/generated/codex/skills/rite-adopt/SKILL.md +4 -3
  281. package/pack/generated/codex/skills/rite-autocomplete/SKILL.md +18 -15
  282. package/pack/generated/codex/skills/rite-autocomplete/reference/loop.md +9 -6
  283. package/pack/generated/codex/skills/rite-autocomplete/reference/stop-conditions.md +25 -21
  284. package/pack/generated/codex/skills/rite-build/SKILL.md +2 -2
  285. package/pack/generated/codex/skills/rite-build/reference/afk-discipline.md +6 -3
  286. package/pack/generated/codex/skills/rite-build/reference/parallel-batch.md +6 -6
  287. package/pack/generated/codex/skills/rite-build/reference/wright-dispatch.md +20 -1
  288. package/pack/generated/codex/skills/rite-clarify/SKILL.md +1 -1
  289. package/pack/generated/codex/skills/rite-converge/SKILL.md +5 -4
  290. package/pack/generated/codex/skills/rite-customize/SKILL.md +1 -1
  291. package/pack/generated/codex/skills/rite-define/SKILL.md +4 -3
  292. package/pack/generated/codex/skills/rite-doctor/SKILL.md +12 -6
  293. package/pack/generated/codex/skills/rite-dogfood/SKILL.md +2 -2
  294. package/pack/generated/codex/skills/rite-explain/SKILL.md +1 -1
  295. package/pack/generated/codex/skills/rite-fast/SKILL.md +8 -6
  296. package/pack/generated/codex/skills/rite-frame/SKILL.md +1 -1
  297. package/pack/generated/codex/skills/rite-handoff/SKILL.md +4 -3
  298. package/pack/generated/codex/skills/rite-learn/SKILL.md +2 -2
  299. package/pack/generated/codex/skills/rite-plan/SKILL.md +2 -2
  300. package/pack/generated/codex/skills/rite-plan/reference/replan-and-repair.md +2 -0
  301. package/pack/generated/codex/skills/rite-plan/reference/slicing.md +3 -1
  302. package/pack/generated/codex/skills/rite-polish/SKILL.md +2 -2
  303. package/pack/generated/codex/skills/rite-pov/SKILL.md +1 -1
  304. package/pack/generated/codex/skills/rite-pr-feedback/SKILL.md +5 -4
  305. package/pack/generated/codex/skills/rite-pressure-test/SKILL.md +7 -5
  306. package/pack/generated/codex/skills/rite-prototype/SKILL.md +1 -1
  307. package/pack/generated/codex/skills/rite-prove/SKILL.md +5 -3
  308. package/pack/generated/codex/skills/rite-prove/reference/failure-triage.md +2 -1
  309. package/pack/generated/codex/skills/rite-quick/SKILL.md +11 -6
  310. package/pack/generated/codex/skills/rite-resolve/SKILL.md +3 -3
  311. package/pack/generated/codex/skills/rite-resolve/reference/answer-protocol.md +4 -5
  312. package/pack/generated/codex/skills/rite-review/SKILL.md +3 -2
  313. package/pack/generated/codex/skills/rite-seal/SKILL.md +4 -4
  314. package/pack/generated/codex/skills/rite-seal/reference/go-no-go.md +2 -0
  315. package/pack/generated/codex/skills/rite-seal/reference/seal-template.md +5 -2
  316. package/pack/generated/codex/skills/rite-ship/SKILL.md +1 -1
  317. package/pack/generated/codex/skills/rite-ship/reference/close-out.md +3 -2
  318. package/pack/generated/codex/skills/rite-spec/SKILL.md +5 -2
  319. package/pack/generated/codex/skills/rite-spec/reference/state-workspace.md +2 -2
  320. package/pack/generated/codex/skills/rite-status/SKILL.md +1 -1
  321. package/pack/generated/codex/skills/rite-temper/SKILL.md +2 -2
  322. package/pack/generated/codex/skills/rite-temper/reference/significance.md +2 -0
  323. package/pack/generated/codex/skills/rite-upgrade/SKILL.md +4 -2
  324. package/pack/generated/codex/skills/rite-vet/SKILL.md +4 -3
  325. package/pack/generated/codex/skills/rite-vet/reference/artifacts.md +1 -1
  326. package/pack/generated/codex/skills/rite-watch-pr/SKILL.md +1 -1
  327. package/pack/generated/codex/skills/rite-zoom-out/SKILL.md +1 -1
  328. package/pack/generated/devin/AGENTS.md +1 -1
  329. package/pack/generated/devin/agents/devrites-devex-reviewer.md +5 -0
  330. package/pack/generated/devin/agents/devrites-evidence-scout.md +4 -0
  331. package/pack/generated/devin/agents/devrites-plan-reviewer.md +4 -1
  332. package/pack/generated/devin/agents/overhaul-backend-engineer.md +2 -0
  333. package/pack/generated/devin/agents/overhaul-boundary.md +2 -0
  334. package/pack/generated/devin/agents/overhaul-craft.md +2 -0
  335. package/pack/generated/devin/agents/overhaul-frontend-engineer.md +2 -0
  336. package/pack/generated/devin/agents/overhaul-implementer.md +2 -0
  337. package/pack/generated/devin/agents/overhaul-recon.md +2 -0
  338. package/pack/generated/devin/agents/overhaul-specialist.md +2 -0
  339. package/pack/generated/devin/agents/overhaul-verifier.md +2 -0
  340. package/pack/generated/devin/skills/devrites-api-interface/SKILL.md +1 -1
  341. package/pack/generated/devin/skills/devrites-audit/SKILL.md +1 -1
  342. package/pack/generated/devin/skills/devrites-browser-proof/SKILL.md +1 -1
  343. package/pack/generated/devin/skills/devrites-debug-recovery/SKILL.md +8 -6
  344. package/pack/generated/devin/skills/devrites-doubt/SKILL.md +1 -1
  345. package/pack/generated/devin/skills/devrites-frontend-craft/SKILL.md +1 -1
  346. package/pack/generated/devin/skills/devrites-interview/SKILL.md +2 -2
  347. package/pack/generated/devin/skills/devrites-lib/reference/intent-map.md +3 -3
  348. package/pack/generated/devin/skills/devrites-lib/reference/parallel-dispatch.md +6 -5
  349. package/pack/generated/devin/skills/devrites-lib/reference/reply-contract.md +12 -15
  350. package/pack/generated/devin/skills/devrites-lib/reference/standards/afk-hitl.md +33 -13
  351. package/pack/generated/devin/skills/devrites-lib/reference/standards/agents.md +1 -1
  352. package/pack/generated/devin/skills/devrites-lib/reference/standards/ci-cd.md +2 -1
  353. package/pack/generated/devin/skills/devrites-lib/reference/standards/code-review.md +1 -1
  354. package/pack/generated/devin/skills/devrites-lib/reference/standards/core.md +2 -2
  355. package/pack/generated/devin/skills/devrites-lib/reference/standards/data-integrity.md +4 -0
  356. package/pack/generated/devin/skills/devrites-lib/reference/standards/developer-experience.md +5 -0
  357. package/pack/generated/devin/skills/devrites-lib/reference/standards/loop-operations.md +3 -0
  358. package/pack/generated/devin/skills/devrites-lib/reference/standards/one-shot-actions.md +7 -6
  359. package/pack/generated/devin/skills/devrites-lib/reference/standards/performance.md +2 -0
  360. package/pack/generated/devin/skills/devrites-lib/reference/standards/skill-authoring.md +13 -1
  361. package/pack/generated/devin/skills/devrites-lib/reference/standards/testing.md +13 -0
  362. package/pack/generated/devin/skills/devrites-lib/reference/workspace-artifact-schema.md +11 -7
  363. package/pack/generated/devin/skills/devrites-prose-craft/SKILL.md +1 -1
  364. package/pack/generated/devin/skills/devrites-source-driven/SKILL.md +1 -1
  365. package/pack/generated/devin/skills/devrites-ux-shape/SKILL.md +1 -1
  366. package/pack/generated/devin/skills/overhaul/SKILL.md +15 -15
  367. package/pack/generated/devin/skills/overhaul/references/audit-domains.md +2 -2
  368. package/pack/generated/devin/skills/overhaul/references/orchestration.md +11 -7
  369. package/pack/generated/devin/skills/overhaul/references/records.md +8 -3
  370. package/pack/generated/devin/skills/rite/SKILL.md +4 -3
  371. package/pack/generated/devin/skills/rite/reference/menu.md +6 -5
  372. package/pack/generated/devin/skills/rite-adopt/SKILL.md +4 -3
  373. package/pack/generated/devin/skills/rite-autocomplete/SKILL.md +19 -16
  374. package/pack/generated/devin/skills/rite-autocomplete/reference/decision-policy.md +1 -1
  375. package/pack/generated/devin/skills/rite-autocomplete/reference/loop.md +9 -6
  376. package/pack/generated/devin/skills/rite-autocomplete/reference/stop-conditions.md +26 -22
  377. package/pack/generated/devin/skills/rite-build/SKILL.md +2 -2
  378. package/pack/generated/devin/skills/rite-build/reference/afk-discipline.md +6 -3
  379. package/pack/generated/devin/skills/rite-build/reference/checkpoint-protocol.md +2 -2
  380. package/pack/generated/devin/skills/rite-build/reference/parallel-batch.md +6 -6
  381. package/pack/generated/devin/skills/rite-build/reference/wright-dispatch.md +20 -1
  382. package/pack/generated/devin/skills/rite-clarify/SKILL.md +1 -1
  383. package/pack/generated/devin/skills/rite-converge/SKILL.md +5 -4
  384. package/pack/generated/devin/skills/rite-customize/SKILL.md +1 -1
  385. package/pack/generated/devin/skills/rite-define/SKILL.md +4 -3
  386. package/pack/generated/devin/skills/rite-doctor/SKILL.md +12 -6
  387. package/pack/generated/devin/skills/rite-dogfood/SKILL.md +2 -2
  388. package/pack/generated/devin/skills/rite-explain/SKILL.md +3 -3
  389. package/pack/generated/devin/skills/rite-explain/reference/intake.md +1 -1
  390. package/pack/generated/devin/skills/rite-fast/SKILL.md +8 -6
  391. package/pack/generated/devin/skills/rite-frame/SKILL.md +1 -1
  392. package/pack/generated/devin/skills/rite-handoff/SKILL.md +4 -3
  393. package/pack/generated/devin/skills/rite-learn/SKILL.md +2 -2
  394. package/pack/generated/devin/skills/rite-plan/SKILL.md +2 -2
  395. package/pack/generated/devin/skills/rite-plan/reference/replan-and-repair.md +2 -0
  396. package/pack/generated/devin/skills/rite-plan/reference/slicing.md +3 -1
  397. package/pack/generated/devin/skills/rite-polish/SKILL.md +2 -2
  398. package/pack/generated/devin/skills/rite-pov/SKILL.md +1 -1
  399. package/pack/generated/devin/skills/rite-pr-feedback/SKILL.md +5 -4
  400. package/pack/generated/devin/skills/rite-pressure-test/SKILL.md +7 -5
  401. package/pack/generated/devin/skills/rite-prototype/SKILL.md +1 -1
  402. package/pack/generated/devin/skills/rite-prove/SKILL.md +5 -3
  403. package/pack/generated/devin/skills/rite-prove/reference/failure-triage.md +2 -1
  404. package/pack/generated/devin/skills/rite-quick/SKILL.md +11 -6
  405. package/pack/generated/devin/skills/rite-resolve/SKILL.md +4 -4
  406. package/pack/generated/devin/skills/rite-resolve/reference/answer-protocol.md +4 -5
  407. package/pack/generated/devin/skills/rite-review/SKILL.md +3 -2
  408. package/pack/generated/devin/skills/rite-seal/SKILL.md +4 -4
  409. package/pack/generated/devin/skills/rite-seal/reference/go-no-go.md +2 -0
  410. package/pack/generated/devin/skills/rite-seal/reference/seal-template.md +5 -2
  411. package/pack/generated/devin/skills/rite-ship/SKILL.md +1 -1
  412. package/pack/generated/devin/skills/rite-ship/reference/close-out.md +3 -2
  413. package/pack/generated/devin/skills/rite-spec/SKILL.md +5 -2
  414. package/pack/generated/devin/skills/rite-spec/reference/investigation.md +1 -1
  415. package/pack/generated/devin/skills/rite-spec/reference/state-workspace.md +2 -2
  416. package/pack/generated/devin/skills/rite-status/SKILL.md +1 -1
  417. package/pack/generated/devin/skills/rite-temper/SKILL.md +3 -3
  418. package/pack/generated/devin/skills/rite-temper/reference/scope-modes.md +1 -1
  419. package/pack/generated/devin/skills/rite-temper/reference/significance.md +3 -1
  420. package/pack/generated/devin/skills/rite-upgrade/SKILL.md +4 -2
  421. package/pack/generated/devin/skills/rite-vet/SKILL.md +4 -3
  422. package/pack/generated/devin/skills/rite-vet/reference/artifacts.md +1 -1
  423. package/pack/generated/devin/skills/rite-vet/reference/review-axes.md +2 -2
  424. package/pack/generated/devin/skills/rite-watch-pr/SKILL.md +1 -1
  425. package/pack/generated/devin/skills/rite-zoom-out/SKILL.md +1 -1
  426. package/pack/generated/omp/agents/devrites-code-reviewer.md +7 -7
  427. package/pack/generated/omp/agents/devrites-devex-reviewer.md +6 -1
  428. package/pack/generated/omp/agents/devrites-evidence-scout.md +4 -0
  429. package/pack/generated/omp/agents/devrites-frontend-reviewer.md +1 -1
  430. package/pack/generated/omp/agents/devrites-plan-drafter.md +3 -3
  431. package/pack/generated/omp/agents/devrites-plan-reviewer.md +5 -2
  432. package/pack/generated/omp/agents/devrites-proof-runner.md +2 -2
  433. package/pack/generated/omp/agents/devrites-security-auditor.md +1 -1
  434. package/pack/generated/omp/agents/devrites-simplifier-reviewer.md +1 -1
  435. package/pack/generated/omp/agents/devrites-slice-wright.md +5 -5
  436. package/pack/generated/omp/agents/devrites-test-analyst.md +5 -5
  437. package/pack/generated/omp/agents/devrites-upgrade-planner.md +1 -1
  438. package/pack/generated/omp/agents/fast-builder.md +3 -3
  439. package/pack/generated/omp/agents/fast-critic.md +3 -3
  440. package/pack/generated/omp/agents/overhaul-backend-engineer.md +2 -0
  441. package/pack/generated/omp/agents/overhaul-boundary.md +2 -0
  442. package/pack/generated/omp/agents/overhaul-craft.md +2 -0
  443. package/pack/generated/omp/agents/overhaul-frontend-engineer.md +2 -0
  444. package/pack/generated/omp/agents/overhaul-implementer.md +2 -0
  445. package/pack/generated/omp/agents/overhaul-recon.md +2 -0
  446. package/pack/generated/omp/agents/overhaul-specialist.md +2 -0
  447. package/pack/generated/omp/agents/overhaul-verifier.md +2 -0
  448. package/pack/generated/omp/commands/rite-resolve.md +1 -1
  449. package/pack/generated/omp/skills/devrites-api-interface/SKILL.md +4 -4
  450. package/pack/generated/omp/skills/devrites-audit/SKILL.md +5 -5
  451. package/pack/generated/omp/skills/devrites-browser-proof/SKILL.md +5 -5
  452. package/pack/generated/omp/skills/devrites-browser-proof/reference/browser-performance.md +1 -1
  453. package/pack/generated/omp/skills/devrites-browser-proof/reference/visual-verdict.md +1 -1
  454. package/pack/generated/omp/skills/devrites-debug-recovery/SKILL.md +12 -10
  455. package/pack/generated/omp/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +1 -1
  456. package/pack/generated/omp/skills/devrites-doubt/SKILL.md +6 -6
  457. package/pack/generated/omp/skills/devrites-frontend-craft/SKILL.md +3 -3
  458. package/pack/generated/omp/skills/devrites-frontend-craft/reference/craft.md +1 -1
  459. package/pack/generated/omp/skills/devrites-frontend-craft/reference/design-references.md +4 -4
  460. package/pack/generated/omp/skills/devrites-frontend-craft/reference/fullstack.md +1 -1
  461. package/pack/generated/omp/skills/devrites-frontend-craft/reference/quality-standards.md +8 -8
  462. package/pack/generated/omp/skills/devrites-frontend-craft/reference/reuse-first.md +2 -2
  463. package/pack/generated/omp/skills/devrites-frontend-craft/reference/shape.md +2 -2
  464. package/pack/generated/omp/skills/devrites-interview/SKILL.md +3 -3
  465. package/pack/generated/omp/skills/devrites-lib/reference/intent-map.md +4 -4
  466. package/pack/generated/omp/skills/devrites-lib/reference/parallel-dispatch.md +8 -7
  467. package/pack/generated/omp/skills/devrites-lib/reference/reply-contract.md +12 -15
  468. package/pack/generated/omp/skills/devrites-lib/reference/standards/afk-hitl.md +38 -18
  469. package/pack/generated/omp/skills/devrites-lib/reference/standards/agents.md +6 -6
  470. package/pack/generated/omp/skills/devrites-lib/reference/standards/browser-proof-checklist.md +2 -2
  471. package/pack/generated/omp/skills/devrites-lib/reference/standards/ci-cd.md +2 -1
  472. package/pack/generated/omp/skills/devrites-lib/reference/standards/code-review.md +3 -3
  473. package/pack/generated/omp/skills/devrites-lib/reference/standards/coding-style.md +1 -1
  474. package/pack/generated/omp/skills/devrites-lib/reference/standards/context-hygiene.md +2 -2
  475. package/pack/generated/omp/skills/devrites-lib/reference/standards/core.md +4 -4
  476. package/pack/generated/omp/skills/devrites-lib/reference/standards/data-integrity.md +4 -0
  477. package/pack/generated/omp/skills/devrites-lib/reference/standards/debug-recovery.md +1 -1
  478. package/pack/generated/omp/skills/devrites-lib/reference/standards/definition-of-done.md +1 -1
  479. package/pack/generated/omp/skills/devrites-lib/reference/standards/developer-experience.md +8 -3
  480. package/pack/generated/omp/skills/devrites-lib/reference/standards/glossary.md +3 -3
  481. package/pack/generated/omp/skills/devrites-lib/reference/standards/loop-operations.md +3 -0
  482. package/pack/generated/omp/skills/devrites-lib/reference/standards/one-shot-actions.md +7 -6
  483. package/pack/generated/omp/skills/devrites-lib/reference/standards/performance.md +3 -1
  484. package/pack/generated/omp/skills/devrites-lib/reference/standards/prose-style.md +4 -4
  485. package/pack/generated/omp/skills/devrites-lib/reference/standards/release/ship-checklist.md +1 -1
  486. package/pack/generated/omp/skills/devrites-lib/reference/standards/review/README.md +1 -1
  487. package/pack/generated/omp/skills/devrites-lib/reference/standards/review/ci-workflows.md +1 -1
  488. package/pack/generated/omp/skills/devrites-lib/reference/standards/review/react.md +1 -1
  489. package/pack/generated/omp/skills/devrites-lib/reference/standards/review/stack-profile.md +5 -5
  490. package/pack/generated/omp/skills/devrites-lib/reference/standards/skill-authoring.md +15 -3
  491. package/pack/generated/omp/skills/devrites-lib/reference/standards/spec-grammar.md +3 -3
  492. package/pack/generated/omp/skills/devrites-lib/reference/standards/testing.md +14 -1
  493. package/pack/generated/omp/skills/devrites-lib/reference/standards/tooling.md +1 -1
  494. package/pack/generated/omp/skills/devrites-lib/reference/standards/verification-methods.md +1 -1
  495. package/pack/generated/omp/skills/devrites-lib/reference/visual-playbooks/index.md +2 -2
  496. package/pack/generated/omp/skills/devrites-lib/reference/workspace-artifact-schema.md +12 -8
  497. package/pack/generated/omp/skills/devrites-prose-craft/SKILL.md +4 -4
  498. package/pack/generated/omp/skills/devrites-prose-craft/reference/examples.md +1 -1
  499. package/pack/generated/omp/skills/devrites-source-driven/SKILL.md +3 -3
  500. package/pack/generated/omp/skills/devrites-ux-shape/SKILL.md +10 -10
  501. package/pack/generated/omp/skills/devrites-ux-shape/reference/brief-template.md +3 -3
  502. package/pack/generated/omp/skills/devrites-ux-shape/reference/visual-direction-probe.md +1 -1
  503. package/pack/generated/omp/skills/overhaul/references/orchestration.md +6 -2
  504. package/pack/generated/omp/skills/overhaul/references/records.md +8 -3
  505. package/pack/generated/omp/skills/rite/SKILL.md +8 -7
  506. package/pack/generated/omp/skills/rite/reference/menu.md +6 -5
  507. package/pack/generated/omp/skills/rite-adopt/SKILL.md +6 -5
  508. package/pack/generated/omp/skills/rite-adopt/reference/anti-patterns.md +1 -1
  509. package/pack/generated/omp/skills/rite-autocomplete/SKILL.md +22 -19
  510. package/pack/generated/omp/skills/rite-autocomplete/reference/decision-policy.md +1 -1
  511. package/pack/generated/omp/skills/rite-autocomplete/reference/loop.md +11 -8
  512. package/pack/generated/omp/skills/rite-autocomplete/reference/stop-conditions.md +25 -21
  513. package/pack/generated/omp/skills/rite-build/SKILL.md +7 -7
  514. package/pack/generated/omp/skills/rite-build/reference/afk-discipline.md +7 -4
  515. package/pack/generated/omp/skills/rite-build/reference/anti-patterns.md +1 -1
  516. package/pack/generated/omp/skills/rite-build/reference/checkpoint-protocol.md +2 -2
  517. package/pack/generated/omp/skills/rite-build/reference/checkpoint.md +2 -2
  518. package/pack/generated/omp/skills/rite-build/reference/frontend-trigger.md +1 -1
  519. package/pack/generated/omp/skills/rite-build/reference/parallel-batch.md +9 -9
  520. package/pack/generated/omp/skills/rite-build/reference/phase-contract.md +6 -6
  521. package/pack/generated/omp/skills/rite-build/reference/tdd.md +1 -1
  522. package/pack/generated/omp/skills/rite-build/reference/wright-dispatch.md +27 -8
  523. package/pack/generated/omp/skills/rite-clarify/SKILL.md +4 -4
  524. package/pack/generated/omp/skills/rite-clarify/reference/anti-patterns.md +1 -1
  525. package/pack/generated/omp/skills/rite-converge/SKILL.md +16 -15
  526. package/pack/generated/omp/skills/rite-converge/reference/convergence-assessment.md +4 -4
  527. package/pack/generated/omp/skills/rite-customize/SKILL.md +2 -2
  528. package/pack/generated/omp/skills/rite-define/SKILL.md +25 -24
  529. package/pack/generated/omp/skills/rite-define/reference/anti-patterns.md +2 -2
  530. package/pack/generated/omp/skills/rite-define/reference/gates.md +2 -2
  531. package/pack/generated/omp/skills/rite-doctor/SKILL.md +12 -6
  532. package/pack/generated/omp/skills/rite-dogfood/SKILL.md +5 -5
  533. package/pack/generated/omp/skills/rite-explain/SKILL.md +7 -7
  534. package/pack/generated/omp/skills/rite-explain/reference/intake.md +1 -1
  535. package/pack/generated/omp/skills/rite-fast/SKILL.md +12 -10
  536. package/pack/generated/omp/skills/rite-fast/reference/artifacts.md +1 -1
  537. package/pack/generated/omp/skills/rite-frame/SKILL.md +6 -6
  538. package/pack/generated/omp/skills/rite-frame/reference/failure-modes.md +4 -4
  539. package/pack/generated/omp/skills/rite-handoff/SKILL.md +7 -6
  540. package/pack/generated/omp/skills/rite-learn/SKILL.md +6 -6
  541. package/pack/generated/omp/skills/rite-plan/SKILL.md +9 -9
  542. package/pack/generated/omp/skills/rite-plan/reference/anti-patterns.md +1 -1
  543. package/pack/generated/omp/skills/rite-plan/reference/replan-and-repair.md +3 -1
  544. package/pack/generated/omp/skills/rite-plan/reference/slicing.md +6 -4
  545. package/pack/generated/omp/skills/rite-plan/reference/task-breakdown.md +1 -1
  546. package/pack/generated/omp/skills/rite-polish/SKILL.md +6 -6
  547. package/pack/generated/omp/skills/rite-polish/reference/anti-ai-slop.md +9 -9
  548. package/pack/generated/omp/skills/rite-polish/reference/anti-patterns.md +1 -1
  549. package/pack/generated/omp/skills/rite-polish/reference/backend-polish.md +2 -2
  550. package/pack/generated/omp/skills/rite-polish/reference/browser-polish-evidence.md +1 -1
  551. package/pack/generated/omp/skills/rite-polish/reference/code.md +8 -8
  552. package/pack/generated/omp/skills/rite-polish/reference/design-memory.md +3 -3
  553. package/pack/generated/omp/skills/rite-polish/reference/design-system-discovery.md +1 -1
  554. package/pack/generated/omp/skills/rite-polish/reference/harden-checklist.md +1 -1
  555. package/pack/generated/omp/skills/rite-polish/reference/ledger.md +3 -3
  556. package/pack/generated/omp/skills/rite-polish/reference/ui.md +1 -1
  557. package/pack/generated/omp/skills/rite-pov/SKILL.md +2 -2
  558. package/pack/generated/omp/skills/rite-pr-feedback/SKILL.md +6 -5
  559. package/pack/generated/omp/skills/rite-pressure-test/SKILL.md +9 -7
  560. package/pack/generated/omp/skills/rite-prototype/SKILL.md +1 -1
  561. package/pack/generated/omp/skills/rite-prove/SKILL.md +17 -15
  562. package/pack/generated/omp/skills/rite-prove/reference/acceptance-proof.md +7 -7
  563. package/pack/generated/omp/skills/rite-prove/reference/anti-patterns.md +1 -1
  564. package/pack/generated/omp/skills/rite-prove/reference/browser-proof.md +3 -3
  565. package/pack/generated/omp/skills/rite-prove/reference/failure-triage.md +4 -3
  566. package/pack/generated/omp/skills/rite-quick/SKILL.md +19 -14
  567. package/pack/generated/omp/skills/rite-resolve/SKILL.md +6 -6
  568. package/pack/generated/omp/skills/rite-resolve/reference/answer-protocol.md +4 -5
  569. package/pack/generated/omp/skills/rite-review/SKILL.md +23 -22
  570. package/pack/generated/omp/skills/rite-review/reference/anti-patterns.md +1 -1
  571. package/pack/generated/omp/skills/rite-review/reference/cognitive-load.md +2 -2
  572. package/pack/generated/omp/skills/rite-review/reference/nielsen-heuristics.md +1 -1
  573. package/pack/generated/omp/skills/rite-review/reference/performance-checklist.md +1 -1
  574. package/pack/generated/omp/skills/rite-review/reference/performance-review.md +1 -1
  575. package/pack/generated/omp/skills/rite-review/reference/security-review.md +2 -2
  576. package/pack/generated/omp/skills/rite-seal/SKILL.md +11 -11
  577. package/pack/generated/omp/skills/rite-seal/reference/anti-patterns.md +1 -1
  578. package/pack/generated/omp/skills/rite-seal/reference/final-evidence.md +3 -3
  579. package/pack/generated/omp/skills/rite-seal/reference/go-no-go.md +3 -1
  580. package/pack/generated/omp/skills/rite-seal/reference/output.md +1 -1
  581. package/pack/generated/omp/skills/rite-seal/reference/phase-contract.md +4 -4
  582. package/pack/generated/omp/skills/rite-seal/reference/seal-template.md +5 -2
  583. package/pack/generated/omp/skills/rite-ship/SKILL.md +7 -7
  584. package/pack/generated/omp/skills/rite-ship/reference/anti-patterns.md +1 -1
  585. package/pack/generated/omp/skills/rite-ship/reference/close-out.md +5 -4
  586. package/pack/generated/omp/skills/rite-ship/reference/git-ship.md +2 -2
  587. package/pack/generated/omp/skills/rite-ship/reference/rollout.md +3 -3
  588. package/pack/generated/omp/skills/rite-spec/SKILL.md +17 -14
  589. package/pack/generated/omp/skills/rite-spec/reference/anti-patterns.md +1 -1
  590. package/pack/generated/omp/skills/rite-spec/reference/investigation.md +3 -3
  591. package/pack/generated/omp/skills/rite-spec/reference/question-protocol.md +1 -1
  592. package/pack/generated/omp/skills/rite-spec/reference/spec-template.md +2 -2
  593. package/pack/generated/omp/skills/rite-spec/reference/state-workspace.md +10 -10
  594. package/pack/generated/omp/skills/rite-status/SKILL.md +2 -2
  595. package/pack/generated/omp/skills/rite-temper/SKILL.md +13 -13
  596. package/pack/generated/omp/skills/rite-temper/reference/anti-patterns.md +2 -2
  597. package/pack/generated/omp/skills/rite-temper/reference/review-dimensions.md +3 -3
  598. package/pack/generated/omp/skills/rite-temper/reference/scope-modes.md +3 -3
  599. package/pack/generated/omp/skills/rite-temper/reference/significance.md +4 -2
  600. package/pack/generated/omp/skills/rite-upgrade/SKILL.md +7 -5
  601. package/pack/generated/omp/skills/rite-vet/SKILL.md +14 -13
  602. package/pack/generated/omp/skills/rite-vet/reference/anti-patterns.md +2 -2
  603. package/pack/generated/omp/skills/rite-vet/reference/artifacts.md +3 -3
  604. package/pack/generated/omp/skills/rite-vet/reference/depth.md +3 -3
  605. package/pack/generated/omp/skills/rite-vet/reference/review-axes.md +5 -5
  606. package/pack/generated/omp/skills/rite-watch-pr/SKILL.md +2 -2
  607. package/pack/generated/omp/skills/rite-zoom-out/SKILL.md +1 -1
  608. package/pack/generated/pi/agents/devrites-devex-reviewer.md +5 -0
  609. package/pack/generated/pi/agents/devrites-evidence-scout.md +4 -0
  610. package/pack/generated/pi/agents/devrites-plan-reviewer.md +4 -1
  611. package/pack/generated/pi/agents/overhaul-backend-engineer.md +2 -0
  612. package/pack/generated/pi/agents/overhaul-boundary.md +2 -0
  613. package/pack/generated/pi/agents/overhaul-craft.md +2 -0
  614. package/pack/generated/pi/agents/overhaul-frontend-engineer.md +2 -0
  615. package/pack/generated/pi/agents/overhaul-implementer.md +2 -0
  616. package/pack/generated/pi/agents/overhaul-recon.md +2 -0
  617. package/pack/generated/pi/agents/overhaul-specialist.md +2 -0
  618. package/pack/generated/pi/agents/overhaul-verifier.md +2 -0
  619. package/pack/generated/pi/prompts/rite-resolve.md +1 -1
  620. package/pack/generated/pi/skills/devrites-api-interface/SKILL.md +1 -1
  621. package/pack/generated/pi/skills/devrites-audit/SKILL.md +1 -1
  622. package/pack/generated/pi/skills/devrites-browser-proof/SKILL.md +1 -1
  623. package/pack/generated/pi/skills/devrites-debug-recovery/SKILL.md +8 -6
  624. package/pack/generated/pi/skills/devrites-doubt/SKILL.md +1 -1
  625. package/pack/generated/pi/skills/devrites-frontend-craft/SKILL.md +1 -1
  626. package/pack/generated/pi/skills/devrites-interview/SKILL.md +1 -1
  627. package/pack/generated/pi/skills/devrites-lib/reference/intent-map.md +3 -3
  628. package/pack/generated/pi/skills/devrites-lib/reference/parallel-dispatch.md +6 -5
  629. package/pack/generated/pi/skills/devrites-lib/reference/reply-contract.md +12 -15
  630. package/pack/generated/pi/skills/devrites-lib/reference/standards/afk-hitl.md +30 -10
  631. package/pack/generated/pi/skills/devrites-lib/reference/standards/agents.md +1 -1
  632. package/pack/generated/pi/skills/devrites-lib/reference/standards/ci-cd.md +2 -1
  633. package/pack/generated/pi/skills/devrites-lib/reference/standards/code-review.md +1 -1
  634. package/pack/generated/pi/skills/devrites-lib/reference/standards/core.md +2 -2
  635. package/pack/generated/pi/skills/devrites-lib/reference/standards/data-integrity.md +4 -0
  636. package/pack/generated/pi/skills/devrites-lib/reference/standards/developer-experience.md +5 -0
  637. package/pack/generated/pi/skills/devrites-lib/reference/standards/loop-operations.md +3 -0
  638. package/pack/generated/pi/skills/devrites-lib/reference/standards/one-shot-actions.md +7 -6
  639. package/pack/generated/pi/skills/devrites-lib/reference/standards/performance.md +2 -0
  640. package/pack/generated/pi/skills/devrites-lib/reference/standards/skill-authoring.md +13 -1
  641. package/pack/generated/pi/skills/devrites-lib/reference/standards/testing.md +13 -0
  642. package/pack/generated/pi/skills/devrites-lib/reference/workspace-artifact-schema.md +11 -7
  643. package/pack/generated/pi/skills/devrites-prose-craft/SKILL.md +1 -1
  644. package/pack/generated/pi/skills/devrites-source-driven/SKILL.md +1 -1
  645. package/pack/generated/pi/skills/devrites-ux-shape/SKILL.md +1 -1
  646. package/pack/generated/pi/skills/overhaul/SKILL.md +15 -15
  647. package/pack/generated/pi/skills/overhaul/references/audit-domains.md +2 -2
  648. package/pack/generated/pi/skills/overhaul/references/orchestration.md +11 -7
  649. package/pack/generated/pi/skills/overhaul/references/records.md +8 -3
  650. package/pack/generated/pi/skills/rite/SKILL.md +4 -3
  651. package/pack/generated/pi/skills/rite/reference/menu.md +6 -5
  652. package/pack/generated/pi/skills/rite-adopt/SKILL.md +4 -3
  653. package/pack/generated/pi/skills/rite-autocomplete/SKILL.md +18 -15
  654. package/pack/generated/pi/skills/rite-autocomplete/reference/loop.md +9 -6
  655. package/pack/generated/pi/skills/rite-autocomplete/reference/stop-conditions.md +25 -21
  656. package/pack/generated/pi/skills/rite-build/SKILL.md +2 -2
  657. package/pack/generated/pi/skills/rite-build/reference/afk-discipline.md +6 -3
  658. package/pack/generated/pi/skills/rite-build/reference/parallel-batch.md +6 -6
  659. package/pack/generated/pi/skills/rite-build/reference/wright-dispatch.md +20 -1
  660. package/pack/generated/pi/skills/rite-clarify/SKILL.md +1 -1
  661. package/pack/generated/pi/skills/rite-converge/SKILL.md +5 -4
  662. package/pack/generated/pi/skills/rite-customize/SKILL.md +1 -1
  663. package/pack/generated/pi/skills/rite-define/SKILL.md +4 -3
  664. package/pack/generated/pi/skills/rite-doctor/SKILL.md +12 -6
  665. package/pack/generated/pi/skills/rite-dogfood/SKILL.md +2 -2
  666. package/pack/generated/pi/skills/rite-explain/SKILL.md +1 -1
  667. package/pack/generated/pi/skills/rite-fast/SKILL.md +8 -6
  668. package/pack/generated/pi/skills/rite-frame/SKILL.md +1 -1
  669. package/pack/generated/pi/skills/rite-handoff/SKILL.md +4 -3
  670. package/pack/generated/pi/skills/rite-learn/SKILL.md +2 -2
  671. package/pack/generated/pi/skills/rite-plan/SKILL.md +2 -2
  672. package/pack/generated/pi/skills/rite-plan/reference/replan-and-repair.md +2 -0
  673. package/pack/generated/pi/skills/rite-plan/reference/slicing.md +3 -1
  674. package/pack/generated/pi/skills/rite-polish/SKILL.md +2 -2
  675. package/pack/generated/pi/skills/rite-pov/SKILL.md +1 -1
  676. package/pack/generated/pi/skills/rite-pr-feedback/SKILL.md +5 -4
  677. package/pack/generated/pi/skills/rite-pressure-test/SKILL.md +7 -5
  678. package/pack/generated/pi/skills/rite-prototype/SKILL.md +1 -1
  679. package/pack/generated/pi/skills/rite-prove/SKILL.md +5 -3
  680. package/pack/generated/pi/skills/rite-prove/reference/failure-triage.md +2 -1
  681. package/pack/generated/pi/skills/rite-quick/SKILL.md +11 -6
  682. package/pack/generated/pi/skills/rite-resolve/SKILL.md +3 -3
  683. package/pack/generated/pi/skills/rite-resolve/reference/answer-protocol.md +4 -5
  684. package/pack/generated/pi/skills/rite-review/SKILL.md +3 -2
  685. package/pack/generated/pi/skills/rite-seal/SKILL.md +4 -4
  686. package/pack/generated/pi/skills/rite-seal/reference/go-no-go.md +2 -0
  687. package/pack/generated/pi/skills/rite-seal/reference/seal-template.md +5 -2
  688. package/pack/generated/pi/skills/rite-ship/SKILL.md +1 -1
  689. package/pack/generated/pi/skills/rite-ship/reference/close-out.md +3 -2
  690. package/pack/generated/pi/skills/rite-spec/SKILL.md +5 -2
  691. package/pack/generated/pi/skills/rite-spec/reference/state-workspace.md +2 -2
  692. package/pack/generated/pi/skills/rite-status/SKILL.md +1 -1
  693. package/pack/generated/pi/skills/rite-temper/SKILL.md +2 -2
  694. package/pack/generated/pi/skills/rite-temper/reference/significance.md +2 -0
  695. package/pack/generated/pi/skills/rite-upgrade/SKILL.md +4 -2
  696. package/pack/generated/pi/skills/rite-vet/SKILL.md +4 -3
  697. package/pack/generated/pi/skills/rite-vet/reference/artifacts.md +1 -1
  698. package/pack/generated/pi/skills/rite-watch-pr/SKILL.md +1 -1
  699. package/pack/generated/pi/skills/rite-zoom-out/SKILL.md +1 -1
  700. package/package.json +3 -2
  701. package/scripts/build-host-artifacts.sh +13 -0
  702. package/scripts/codex-generate.sh +5 -1
  703. package/scripts/devin-generate.sh +4 -3
  704. package/scripts/install-lib.sh +5 -0
  705. package/scripts/omp-generate.sh +23 -1
  706. package/scripts/pi-generate.sh +2 -2
  707. package/engine/cmd/releasepack/main_test.go +0 -239
  708. package/engine/harnessmatrix_test.go +0 -46
  709. package/engine/help_test.go +0 -241
  710. package/engine/internal/acceptance/acceptance_test.go +0 -946
  711. package/engine/internal/devritespaths/paths_test.go +0 -128
  712. package/engine/internal/fsutil/copy_test.go +0 -154
  713. package/engine/internal/gate/gate_test.go +0 -865
  714. package/engine/internal/gate/readiness_binding_test.go +0 -443
  715. package/engine/internal/gitenv/env_test.go +0 -48
  716. package/engine/internal/hostpack/hostpack_test.go +0 -269
  717. package/engine/internal/install/install_test.go +0 -1741
  718. package/engine/internal/install/workspace_advisory_test.go +0 -54
  719. package/engine/internal/lib/candidate_test.go +0 -506
  720. package/engine/internal/lib/claims_test.go +0 -267
  721. package/engine/internal/lib/closeout_test.go +0 -266
  722. package/engine/internal/lib/context_next_test.go +0 -912
  723. package/engine/internal/lib/cursor_compat_test.go +0 -65
  724. package/engine/internal/lib/detect_test.go +0 -118
  725. package/engine/internal/lib/drift_test.go +0 -135
  726. package/engine/internal/lib/dup_test.go +0 -666
  727. package/engine/internal/lib/environment_report_test.go +0 -54
  728. package/engine/internal/lib/evidencefresh_test.go +0 -120
  729. package/engine/internal/lib/handoff_test.go +0 -83
  730. package/engine/internal/lib/manifest_union_test.go +0 -251
  731. package/engine/internal/lib/metrics_test.go +0 -28
  732. package/engine/internal/lib/migrate_test.go +0 -213
  733. package/engine/internal/lib/observe_budgets_test.go +0 -428
  734. package/engine/internal/lib/open_visual_test.go +0 -291
  735. package/engine/internal/lib/regression_test.go +0 -282
  736. package/engine/internal/lib/resolve_remediation_test.go +0 -192
  737. package/engine/internal/lib/secretscan_test.go +0 -556
  738. package/engine/internal/lib/slicecheck_test.go +0 -170
  739. package/engine/internal/lib/taskgraph_test.go +0 -353
  740. package/engine/internal/lib/triggers_test.go +0 -23
  741. package/engine/internal/lib/util_test.go +0 -148
  742. package/engine/internal/lib/visual_outline_test.go +0 -189
  743. package/engine/internal/lib/windows_test.go +0 -420
  744. package/engine/internal/lib/workspace_read_test.go +0 -102
  745. package/engine/internal/markdowntext/markdowntext_fuzz_test.go +0 -36
  746. package/engine/internal/markdowntext/markdowntext_test.go +0 -58
  747. package/engine/internal/markdowntext/testdata/structural.json +0 -277
  748. package/engine/internal/notes/notes_test.go +0 -545
  749. package/engine/internal/overhaul/admit/admit_test.go +0 -204
  750. package/engine/internal/overhaul/admit/packet_test.go +0 -223
  751. package/engine/internal/overhaul/bench/run_test.go +0 -316
  752. package/engine/internal/overhaul/ovio/ovio_test.go +0 -75
  753. package/engine/internal/overhaul/packet/packet_test.go +0 -263
  754. package/engine/internal/overhaul/records/init_test.go +0 -96
  755. package/engine/internal/overhaul/records/records_test.go +0 -696
  756. package/engine/internal/overhaul/records/run_test.go +0 -77
  757. package/engine/internal/overhaul/render/run_test.go +0 -928
  758. package/engine/internal/overhaul/score/run_test.go +0 -636
  759. package/engine/internal/overhaul/snapshot/run_test.go +0 -718
  760. package/engine/internal/parallel/cli_test.go +0 -91
  761. package/engine/internal/parallel/ops_test.go +0 -939
  762. package/engine/internal/parallel/parallel_test.go +0 -645
  763. package/engine/internal/parallel/pathdisjoint_fuzz_test.go +0 -43
  764. package/engine/internal/parallel/pathdisjoint_test.go +0 -193
  765. package/engine/internal/parallel/select_test.go +0 -95
  766. package/engine/internal/parallel/testdata/fuzz/FuzzPathDisjoint/a449b81b4711b7b4 +0 -3
  767. package/engine/internal/reason/reason_test.go +0 -37
  768. package/engine/internal/release/release_test.go +0 -181
  769. package/engine/internal/rootfacts/facts_test.go +0 -364
  770. package/engine/internal/safepath/safepath_fuzz_test.go +0 -21
  771. package/engine/internal/safepath/safepath_test.go +0 -69
  772. package/engine/internal/safepath/safepath_windows_test.go +0 -26
  773. package/engine/internal/state/acceptance_test.go +0 -57
  774. package/engine/internal/state/budgets_test.go +0 -135
  775. package/engine/internal/state/cmd/workflowmanifest/main_test.go +0 -96
  776. package/engine/internal/state/concurrency_test.go +0 -184
  777. package/engine/internal/state/cursor_fuzz_test.go +0 -80
  778. package/engine/internal/state/cursor_test.go +0 -276
  779. package/engine/internal/state/observation_test.go +0 -961
  780. package/engine/internal/state/observation_unix_test.go +0 -68
  781. package/engine/internal/state/state_test.go +0 -986
  782. package/engine/internal/state/taskgraph_fuzz_test.go +0 -38
  783. package/engine/internal/state/taskgraph_test.go +0 -43
  784. package/engine/internal/state/testdata/fuzz/FuzzCursorRoundTrip/114b28f68c1fa4db +0 -4
  785. package/engine/internal/state/testdata/fuzz/FuzzCursorRoundTrip/378a0f2218e812ea +0 -4
  786. package/engine/internal/state/testdata/fuzz/FuzzCursorRoundTrip/39eaa26fcb481e3c +0 -4
  787. package/engine/internal/state/testdata/fuzz/FuzzCursorRoundTrip/776ca1dc0143acf0 +0 -4
  788. package/engine/internal/state/testdata/fuzz/FuzzCursorRoundTrip/9295930c1ebb81df +0 -4
  789. package/engine/internal/state/testdata/fuzz/FuzzCursorRoundTrip/a60de309dc33be0d +0 -4
  790. package/engine/internal/state/testdata/fuzz/FuzzCursorRoundTrip/f04dc7b06ef7c99f +0 -4
  791. package/engine/internal/state/testdata/fuzz/FuzzCursorRoundTrip/f3000ac510878bd6 +0 -4
  792. package/engine/internal/state/testdata/fuzz/FuzzWorkspaceSchemaRow/a75aabb9f2a847d5 +0 -2
  793. package/engine/internal/state/workspaceschema_fuzz_test.go +0 -27
  794. package/engine/internal/state/workspaceschema_test.go +0 -101
  795. package/engine/internal/state/write_test.go +0 -136
  796. package/engine/internal/version/version_test.go +0 -29
  797. package/engine/internal/workflow/commands_test.go +0 -18
  798. package/engine/note_routing_test.go +0 -95
  799. package/engine/observation_contract_test.go +0 -175
  800. package/engine/root_routing_test.go +0 -340
@@ -1,939 +0,0 @@
1
- package parallel
2
-
3
- import (
4
- "errors"
5
- "fmt"
6
- "os"
7
- "path/filepath"
8
- "runtime"
9
- "strings"
10
- "sync"
11
- "testing"
12
- )
13
-
14
- // commitIn makes a one-file green commit inside a worker worktree and returns
15
- // its transfer commit SHA.
16
- func commitIn(t *testing.T, wt, file, marker string) string {
17
- t.Helper()
18
- body := "package main\n\nfunc " + marker + "() {}\n"
19
- if err := os.WriteFile(filepath.Join(wt, file), []byte(body), 0o644); err != nil {
20
- t.Fatal(err)
21
- }
22
- gitOk(t, wt, "add", file)
23
- gitOk(t, wt, "commit", "-m", "WIP(demo-feature): add "+marker+" helper")
24
- return gitOk(t, wt, "rev-parse", "HEAD")
25
- }
26
-
27
- // greenBatch creates a running lease with two recorded-green slices.
28
- func greenBatch(t *testing.T, repo, base, slug, batch string) *Lease {
29
- t.Helper()
30
- lease, err := Create(CreateOpts{
31
- Root: repo,
32
- Slug: slug,
33
- BatchID: batch,
34
- BaseSHA: base,
35
- Slices: []SlicePaths{
36
- {ID: "slice-a", Paths: []string{"src/a.go"}},
37
- {ID: "slice-b", Paths: []string{"src/b.go"}},
38
- },
39
- })
40
- if err != nil {
41
- t.Fatal(err)
42
- }
43
- tcA := commitIn(t, lease.Slices[0].WorktreePath, "src/a.go", "A")
44
- tcB := commitIn(t, lease.Slices[1].WorktreePath, "src/b.go", "B")
45
- if _, err := RecordGreen(repo, slug, "slice-a", tcA); err != nil {
46
- t.Fatal(err)
47
- }
48
- if _, err := RecordGreen(repo, slug, "slice-b", tcB); err != nil {
49
- t.Fatal(err)
50
- }
51
- return lease
52
- }
53
-
54
- type seamRestore struct {
55
- origLease func(string, *Lease) error
56
- origRemove func(string, string) error
57
- origSalvage func(LeaseSlice, string) (string, error)
58
- origWarn func(string, ...any)
59
- }
60
-
61
- func swapSeams(t *testing.T) {
62
- t.Helper()
63
- s := seamRestore{origLease: writeLease, origRemove: removeWorktree, origSalvage: salvage, origWarn: warnf}
64
- t.Cleanup(func() {
65
- writeLease, removeWorktree, salvage, warnf = s.origLease, s.origRemove, s.origSalvage, s.origWarn
66
- })
67
- }
68
-
69
- // TestIntegrateFailedTransitionSurvivesTransientWriteFailure proves the
70
- // integrate-failed lease transition is retried once when the first write
71
- // fails, so the on-disk lease honestly records integrate-failed instead of a
72
- // stale running status.
73
- func TestIntegrateFailedTransitionSurvivesTransientWriteFailure(t *testing.T) {
74
- repo, base := setupRepo(t)
75
- slug, batch := "demo-feature", "batch1"
76
- greenBatch(t, repo, base, slug, batch)
77
- leasePath, err := LeasePath(repo, slug)
78
- if err != nil {
79
- t.Fatal(err)
80
- }
81
-
82
- // Corrupt a transfer commit so Integrate fails mid-flight via fail().
83
- corrupted, err := ReadLease(leasePath)
84
- if err != nil {
85
- t.Fatal(err)
86
- }
87
- corrupted.Slices[0].TransferCommit = strings.Repeat("deadbeef", 5)
88
- if err := WriteLease(leasePath, corrupted); err != nil {
89
- t.Fatal(err)
90
- }
91
-
92
- swapSeams(t)
93
- calls := 0
94
- writeLease = func(path string, l *Lease) error {
95
- calls++
96
- if calls == 1 {
97
- return errors.New("transient lease write failure")
98
- }
99
- // delegates to the real WriteLease captured by swapSeams
100
- return origWriteLease()(path, l)
101
- }
102
-
103
- _, got, err := Integrate(IntegrateOpts{Root: repo, Slug: slug, ApplyToControl: true})
104
- if err == nil {
105
- t.Fatal("expected integrate failure from corrupted transfer commit")
106
- }
107
- if calls != 2 {
108
- t.Fatalf("lease write calls=%d want 2 (initial + one retry)", calls)
109
- }
110
- if got == nil || got.Status != StatusIntegrateFailed {
111
- t.Fatalf("returned lease status=%v want integrate-failed", got)
112
- }
113
- onDisk, err := ReadLease(leasePath)
114
- if err != nil {
115
- t.Fatal(err)
116
- }
117
- if onDisk.Status != StatusIntegrateFailed {
118
- t.Fatalf("on-disk lease status=%s want integrate-failed", onDisk.Status)
119
- }
120
- if head := gitOk(t, repo, "rev-parse", "HEAD"); head != base {
121
- t.Fatalf("control head %s want base %s", head, base)
122
- }
123
- }
124
-
125
- // origWriteLease returns the real WriteLease bypassing any test override.
126
- func origWriteLease() func(string, *Lease) error {
127
- return WriteLease
128
- }
129
-
130
- // TestIntegrateSurfacesStuckStagingWorktree proves a staging-worktree removal
131
- // failure on the integrate success path is propagated (fail closed, status
132
- // integrate-failed, control untouched) instead of silently compounding into
133
- // un-cleanable branch state.
134
- func TestIntegrateSurfacesStuckStagingWorktree(t *testing.T) {
135
- repo, base := setupRepo(t)
136
- slug, batch := "demo-feature", "batch1"
137
- greenBatch(t, repo, base, slug, batch)
138
- leasePath, err := LeasePath(repo, slug)
139
- if err != nil {
140
- t.Fatal(err)
141
- }
142
-
143
- swapSeams(t)
144
- removeWorktree = func(string, string) error {
145
- return errors.New("simulated locked staging worktree")
146
- }
147
-
148
- _, got, err := Integrate(IntegrateOpts{Root: repo, Slug: slug, ApplyToControl: true})
149
- if err == nil {
150
- t.Fatal("expected integrate to surface the stuck staging worktree")
151
- }
152
- if !strings.Contains(err.Error(), "staging worktree") {
153
- t.Fatalf("error should name the staging worktree, got %v", err)
154
- }
155
- if got == nil || got.Status != StatusIntegrateFailed {
156
- t.Fatalf("returned lease status=%v want integrate-failed", got)
157
- }
158
- onDisk, err := ReadLease(leasePath)
159
- if err != nil {
160
- t.Fatal(err)
161
- }
162
- if onDisk.Status != StatusIntegrateFailed {
163
- t.Fatalf("on-disk lease status=%s want integrate-failed", onDisk.Status)
164
- }
165
- if head := gitOk(t, repo, "rev-parse", "HEAD"); head != base {
166
- t.Fatalf("control head %s want base %s (merge must not apply when staging cleanup fails)", head, base)
167
- }
168
- }
169
-
170
- // TestCleanupNeverTouchesForeignWorktreePath proves a lease whose
171
- // worktree_path is not the exact directory Create wrote is never salvaged
172
- // into nor deleted — the lease field is advisory, not a RemoveAll license.
173
- // Two spellings of "not ours" are covered: a path outside the batch scratch
174
- // layout, and the deterministic scratch path itself reached through a symlink.
175
- func TestCleanupNeverTouchesForeignWorktreePath(t *testing.T) {
176
- slug, batch := "demo-feature", "batch1"
177
- slices := []SlicePaths{
178
- {ID: "slice-a", Paths: []string{"src/a.go"}},
179
- {ID: "slice-b", Paths: []string{"src/b.go"}},
180
- }
181
-
182
- t.Run("worktree_path outside the scratch root", func(t *testing.T) {
183
- repo, base := setupRepo(t)
184
- lease, err := Create(CreateOpts{
185
- Root: repo,
186
- Slug: slug,
187
- BatchID: batch,
188
- BaseSHA: base,
189
- Slices: slices,
190
- })
191
- if err != nil {
192
- t.Fatal(err)
193
- }
194
- foreign := filepath.Join(t.TempDir(), "precious")
195
- if err := os.MkdirAll(foreign, 0o755); err != nil {
196
- t.Fatal(err)
197
- }
198
- if err := os.WriteFile(filepath.Join(foreign, "keep.txt"), []byte("x"), 0o644); err != nil {
199
- t.Fatal(err)
200
- }
201
- lease.Slices[0].WorktreePath = foreign
202
- // A forged branch outside the batch namespace must survive too.
203
- gitOk(t, repo, "branch", "user/topic", base)
204
- lease.Slices[0].Branch = "user/topic"
205
- leasePath, err := LeasePath(repo, slug)
206
- if err != nil {
207
- t.Fatal(err)
208
- }
209
- if err := WriteLease(leasePath, lease); err != nil {
210
- t.Fatal(err)
211
- }
212
-
213
- var warnings []string
214
- swapSeams(t)
215
- warnf = func(format string, args ...any) {
216
- warnings = append(warnings, fmt.Sprintf(format, args...))
217
- }
218
- if _, err := Cleanup(repo, slug, true); err != nil {
219
- t.Fatal(err)
220
- }
221
- if _, err := os.Stat(filepath.Join(foreign, "keep.txt")); err != nil {
222
- t.Fatalf("foreign path was touched: %v", err)
223
- }
224
- if tip := gitOk(t, repo, "rev-parse", "user/topic"); tip != base {
225
- t.Fatalf("foreign branch user/topic moved to %s, want %s", tip, base)
226
- }
227
- joined := strings.Join(warnings, "\n")
228
- if !strings.Contains(joined, "outside") {
229
- t.Fatalf("expected warnings naming foreign path and branch, got:\n%s", warnings)
230
- }
231
- })
232
-
233
- // A stale lease still names exactly the path Create wrote; here the batch
234
- // directory was replaced by a symlink, so the directory a forced cleanup
235
- // would delete lives outside the scratch root. filepath.Abs matches both sides
236
- // of the ownership check because neither side resolves symlinks.
237
- t.Run("scratch worktree_path reached through a symlink", func(t *testing.T) {
238
- repo, base := setupRepo(t)
239
- if _, err := Create(CreateOpts{
240
- Root: repo,
241
- Slug: slug,
242
- BatchID: batch,
243
- BaseSHA: base,
244
- Slices: slices,
245
- }); err != nil {
246
- t.Fatal(err)
247
- }
248
-
249
- // An unrelated repository outside the workspace, carrying a committed file
250
- // and a dirty one on the allowlisted path: a salvage would commit inside it
251
- // and a RemoveAll would delete the tree.
252
- outside := t.TempDir()
253
- sliceA := filepath.Join(outside, "slice-a")
254
- if err := os.MkdirAll(filepath.Join(sliceA, "src"), 0o755); err != nil {
255
- t.Fatal(err)
256
- }
257
- gitOk(t, sliceA, "init")
258
- gitOk(t, sliceA, "checkout", "-b", "main")
259
- if err := os.WriteFile(filepath.Join(sliceA, "src", "a.go"), []byte("package main\n"), 0o644); err != nil {
260
- t.Fatal(err)
261
- }
262
- gitOk(t, sliceA, "add", ".")
263
- gitOk(t, sliceA, "commit", "-m", "unrelated base")
264
- unrelatedTip := gitOk(t, sliceA, "rev-parse", "HEAD")
265
- if err := os.WriteFile(filepath.Join(sliceA, "src", "a.go"), []byte("package main\n\nfunc Unrelated() {}\n"), 0o644); err != nil {
266
- t.Fatal(err)
267
- }
268
-
269
- batchDir := filepath.Join(ScratchRoot(repo), batch)
270
- if err := os.RemoveAll(batchDir); err != nil {
271
- t.Fatal(err)
272
- }
273
- if err := os.Symlink(outside, batchDir); err != nil {
274
- t.Fatal(err)
275
- }
276
-
277
- // The lease on disk is what Create wrote; only the filesystem moved.
278
- // Assert the path cleanup will use really does resolve through the symlink,
279
- // so this case cannot pass without traversing it.
280
- leasePath, err := LeasePath(repo, slug)
281
- if err != nil {
282
- t.Fatal(err)
283
- }
284
- lease, err := ReadLease(leasePath)
285
- if err != nil {
286
- t.Fatal(err)
287
- }
288
- claimed := lease.Slices[0].WorktreePath
289
- if want := WorkerWorktreePath(repo, batch, "slice-a"); claimed != want {
290
- t.Fatalf("lease worktree_path %q, want the deterministic %q", claimed, want)
291
- }
292
- resolved, err := filepath.EvalSymlinks(claimed)
293
- if err != nil {
294
- t.Fatalf("claimed worktree_path does not resolve: %v", err)
295
- }
296
- realSliceA, err := filepath.EvalSymlinks(sliceA)
297
- if err != nil {
298
- t.Fatal(err)
299
- }
300
- if resolved != realSliceA {
301
- t.Fatalf("%q resolved to %q, want the symlink target %q", claimed, resolved, realSliceA)
302
- }
303
-
304
- var warnings []string
305
- swapSeams(t)
306
- warnf = func(format string, args ...any) {
307
- warnings = append(warnings, fmt.Sprintf(format, args...))
308
- }
309
- if _, err := Cleanup(repo, slug, true); err != nil {
310
- t.Fatal(err)
311
- }
312
-
313
- if _, err := os.Stat(filepath.Join(sliceA, "src", "a.go")); err != nil {
314
- t.Fatalf("worktree reached through a symlinked batch directory was deleted: %v", err)
315
- }
316
- if tip := gitOk(t, sliceA, "rev-parse", "HEAD"); tip != unrelatedTip {
317
- t.Fatalf("salvage committed inside an unrelated repository: tip %s want %s", tip, unrelatedTip)
318
- }
319
- if joined := strings.Join(warnings, "\n"); !strings.Contains(joined, "worktree_path") {
320
- t.Fatalf("expected a warning naming the refused worktree_path, got:\n%s", warnings)
321
- }
322
- })
323
-
324
- // A symlink that stays inside the scratch root still redirects the delete
325
- // onto a directory the lease does not name.
326
- t.Run("scratch worktree_path reached through a symlink inside the scratch root", func(t *testing.T) {
327
- repo, base := setupRepo(t)
328
- if _, err := Create(CreateOpts{
329
- Root: repo,
330
- Slug: slug,
331
- BatchID: batch,
332
- BaseSHA: base,
333
- Slices: slices,
334
- }); err != nil {
335
- t.Fatal(err)
336
- }
337
- sibling := filepath.Join(ScratchRoot(repo), "sibling-batch")
338
- keep := filepath.Join(sibling, "slice-a", "keep.txt")
339
- if err := os.MkdirAll(filepath.Dir(keep), 0o755); err != nil {
340
- t.Fatal(err)
341
- }
342
- if err := os.WriteFile(keep, []byte("x"), 0o644); err != nil {
343
- t.Fatal(err)
344
- }
345
- batchDir := filepath.Join(ScratchRoot(repo), batch)
346
- if err := os.RemoveAll(batchDir); err != nil {
347
- t.Fatal(err)
348
- }
349
- if err := os.Symlink(sibling, batchDir); err != nil {
350
- t.Fatal(err)
351
- }
352
-
353
- swapSeams(t)
354
- warnf = func(string, ...any) {}
355
- if _, err := Cleanup(repo, slug, true); err != nil {
356
- t.Fatal(err)
357
- }
358
- if _, err := os.Stat(keep); err != nil {
359
- t.Fatalf("directory under an in-scratch symlink was deleted: %v", err)
360
- }
361
- })
362
-
363
- // Ownership is decided by what git registered when Create ran, not by the
364
- // lease. A lease naming a deterministic in-scratch path that Create never
365
- // made (and a stray sibling no lease names) must survive a forced cleanup,
366
- // while the real worktrees are still removed.
367
- t.Run("in-scratch path Create never made", func(t *testing.T) {
368
- repo, base := setupRepo(t)
369
- lease, err := Create(CreateOpts{
370
- Root: repo,
371
- Slug: slug,
372
- BatchID: batch,
373
- BaseSHA: base,
374
- Slices: slices,
375
- })
376
- if err != nil {
377
- t.Fatal(err)
378
- }
379
- forged := WorkerWorktreePath(repo, batch, "slice-x")
380
- stray := filepath.Join(ScratchRoot(repo), batch, "stray")
381
- for _, d := range []string{forged, stray} {
382
- if err := os.MkdirAll(d, 0o755); err != nil {
383
- t.Fatal(err)
384
- }
385
- if err := os.WriteFile(filepath.Join(d, "keep.txt"), []byte("x"), 0o644); err != nil {
386
- t.Fatal(err)
387
- }
388
- }
389
- lease.Slices = append(lease.Slices, LeaseSlice{
390
- ID: "slice-x",
391
- Paths: []string{"src/x.go"},
392
- WorktreePath: forged,
393
- WrightStatus: WrightPending,
394
- })
395
- lease.N = len(lease.Slices)
396
- leasePath, err := LeasePath(repo, slug)
397
- if err != nil {
398
- t.Fatal(err)
399
- }
400
- if err := WriteLease(leasePath, lease); err != nil {
401
- t.Fatal(err)
402
- }
403
-
404
- var warnings []string
405
- swapSeams(t)
406
- warnf = func(format string, args ...any) {
407
- warnings = append(warnings, fmt.Sprintf(format, args...))
408
- }
409
- if _, err := Cleanup(repo, slug, true); err != nil {
410
- t.Fatal(err)
411
- }
412
- for _, d := range []string{forged, stray} {
413
- if _, err := os.Stat(filepath.Join(d, "keep.txt")); err != nil {
414
- t.Fatalf("unregistered scratch directory %s was deleted: %v", d, err)
415
- }
416
- }
417
- for _, id := range []string{"slice-a", "slice-b"} {
418
- if _, err := os.Stat(WorkerWorktreePath(repo, batch, id)); !os.IsNotExist(err) {
419
- t.Fatalf("registered worktree %s was not removed: %v", id, err)
420
- }
421
- }
422
- if joined := strings.Join(warnings, "\n"); !strings.Contains(joined, "not a worktree") {
423
- t.Fatalf("expected a warning naming the refused path, got:\n%s", warnings)
424
- }
425
- })
426
- }
427
-
428
- // TestCleanupFailedSalvageKeepsWorktreeDir proves a salvage error keeps the
429
- // worktree on disk as the only remaining copy — the batch-level scratch
430
- // removal must skip kept slice dirs instead of destroying them.
431
- func TestCleanupFailedSalvageKeepsWorktreeDir(t *testing.T) {
432
- repo, base := setupRepo(t)
433
- slug, batch := "demo-feature", "batch1"
434
- if _, err := Create(CreateOpts{
435
- Root: repo,
436
- Slug: slug,
437
- BatchID: batch,
438
- BaseSHA: base,
439
- Slices: []SlicePaths{
440
- {ID: "slice-a", Paths: []string{"src/a.go"}},
441
- {ID: "slice-b", Paths: []string{"src/b.go"}},
442
- },
443
- }); err != nil {
444
- t.Fatal(err)
445
- }
446
- wtA := WorkerWorktreePath(repo, batch, "slice-a")
447
- wtB := WorkerWorktreePath(repo, batch, "slice-b")
448
-
449
- swapSeams(t)
450
- realSalvage := salvage
451
- salvage = func(sl LeaseSlice, batchID string) (string, error) {
452
- if sl.ID == "slice-a" {
453
- return "", errors.New("injected salvage failure")
454
- }
455
- return realSalvage(sl, batchID)
456
- }
457
- salvaged, err := Cleanup(repo, slug, true)
458
- if err != nil {
459
- t.Fatal(err)
460
- }
461
- if _, err := os.Stat(wtA); err != nil {
462
- t.Fatalf("kept worktree was removed: %v", err)
463
- }
464
- if _, err := os.Stat(wtB); !os.IsNotExist(err) {
465
- t.Fatalf("clean slice-b worktree should be removed, stat err=%v", err)
466
- }
467
- if _, err := git(repo, "rev-parse", "--verify", "devrites/parallel/"+slug+"/"+batch+"/slice-a"); err != nil {
468
- t.Fatalf("slice-a branch should be kept: %v", err)
469
- }
470
- found := false
471
- for _, s := range salvaged {
472
- if s.SliceID == "slice-a" && s.Worktree == wtA {
473
- found = true
474
- }
475
- }
476
- if !found {
477
- t.Fatalf("salvage output should report kept worktree for slice-a, got %+v", salvaged)
478
- }
479
- }
480
-
481
- // TestCleanupNamesDirectoryGitDroppedButNotDeleted proves that when git has
482
- // already dropped a worktree and its directory cannot be deleted, the error
483
- // names the directory and says a rerun will not delete it, and the rerun does
484
- // leave it on disk.
485
- func TestCleanupNamesDirectoryGitDroppedButNotDeleted(t *testing.T) {
486
- if os.Geteuid() == 0 || runtime.GOOS == "windows" {
487
- t.Skip("directory permissions do not bind root or windows")
488
- }
489
- repo, base := setupRepo(t)
490
- slug, batch := "demo-feature", "batch1"
491
- if _, err := Create(CreateOpts{
492
- Root: repo,
493
- Slug: slug,
494
- BatchID: batch,
495
- BaseSHA: base,
496
- Slices: []SlicePaths{
497
- {ID: "slice-a", Paths: []string{"src/a.go"}},
498
- {ID: "slice-b", Paths: []string{"src/b.go"}},
499
- },
500
- }); err != nil {
501
- t.Fatal(err)
502
- }
503
- wt := WorkerWorktreePath(repo, batch, "slice-a")
504
- batchDir := filepath.Dir(wt)
505
-
506
- swapSeams(t)
507
- warnf = func(string, ...any) {}
508
- removeWorktree = func(repo, path string) error {
509
- // Like real git: drop the registration, fail to delete the
510
- // directory, and exit non-zero.
511
- if err := os.RemoveAll(filepath.Join(repo, ".git", "worktrees", filepath.Base(path))); err != nil {
512
- return err
513
- }
514
- if err := os.Chmod(batchDir, 0o500); err != nil {
515
- return err
516
- }
517
- return errors.New("failed to delete '" + path + "': Permission denied")
518
- }
519
- t.Cleanup(func() { _ = os.Chmod(batchDir, 0o700) })
520
-
521
- _, err := Cleanup(repo, slug, true)
522
- if err == nil || !strings.Contains(err.Error(), wt) || !strings.Contains(err.Error(), "remove it by hand") {
523
- t.Fatalf("error must name %s and say it needs manual removal, got %v", wt, err)
524
- }
525
- if err := os.Chmod(batchDir, 0o700); err != nil {
526
- t.Fatal(err)
527
- }
528
- if _, err := Cleanup(repo, slug, true); err != nil {
529
- t.Fatalf("rerun: %v", err)
530
- }
531
- if _, err := os.Stat(wt); err != nil {
532
- t.Fatalf("rerun must leave the unregistered directory in place, stat err=%v", err)
533
- }
534
- }
535
-
536
- // TestCleanupFailedListNamesEachEntryOnce proves a slice whose directory
537
- // removal fails in both the per-slice and the scratch-entry pass is named once,
538
- // in lease order.
539
- func TestCleanupFailedListNamesEachEntryOnce(t *testing.T) {
540
- if os.Geteuid() == 0 || runtime.GOOS == "windows" {
541
- t.Skip("directory permissions do not bind root or windows")
542
- }
543
- repo, base := setupRepo(t)
544
- slug, batch := "demo-feature", "batch1"
545
- if _, err := Create(CreateOpts{
546
- Root: repo,
547
- Slug: slug,
548
- BatchID: batch,
549
- BaseSHA: base,
550
- Slices: []SlicePaths{
551
- {ID: "slice-a", Paths: []string{"src/a.go"}},
552
- {ID: "slice-b", Paths: []string{"src/b.go"}},
553
- },
554
- }); err != nil {
555
- t.Fatal(err)
556
- }
557
- batchDir := filepath.Dir(WorkerWorktreePath(repo, batch, "slice-a"))
558
-
559
- swapSeams(t)
560
- warnf = func(string, ...any) {}
561
- removeWorktree = func(string, string) error {
562
- if err := os.Chmod(batchDir, 0o500); err != nil {
563
- return err
564
- }
565
- return errors.New("simulated stuck worker worktree")
566
- }
567
- t.Cleanup(func() { _ = os.Chmod(batchDir, 0o700) })
568
-
569
- _, err := Cleanup(repo, slug, true)
570
- const want = "cleanup incomplete for slice-a, slice-b; "
571
- if err == nil || !strings.HasPrefix(err.Error(), want) {
572
- t.Fatalf("failed list must name slice-a and slice-b once each, want prefix %q, got %v", want, err)
573
- }
574
- }
575
-
576
- // TestCleanupKeepsRerunGuidanceWhileStillRegistered proves a failed directory
577
- // delete that leaves git's registration intact is retryable: the error asks for
578
- // a rerun and does not tell the operator to remove the directory by hand.
579
- func TestCleanupKeepsRerunGuidanceWhileStillRegistered(t *testing.T) {
580
- if os.Geteuid() == 0 || runtime.GOOS == "windows" {
581
- t.Skip("directory permissions do not bind root or windows")
582
- }
583
- repo, base := setupRepo(t)
584
- slug, batch := "demo-feature", "batch1"
585
- if _, err := Create(CreateOpts{
586
- Root: repo,
587
- Slug: slug,
588
- BatchID: batch,
589
- BaseSHA: base,
590
- Slices: []SlicePaths{
591
- {ID: "slice-a", Paths: []string{"src/a.go"}},
592
- {ID: "slice-b", Paths: []string{"src/b.go"}},
593
- },
594
- }); err != nil {
595
- t.Fatal(err)
596
- }
597
- wt := WorkerWorktreePath(repo, batch, "slice-a")
598
- batchDir := filepath.Dir(wt)
599
-
600
- swapSeams(t)
601
- warnf = func(string, ...any) {}
602
- removeWorktree = func(repo, path string) error {
603
- if err := os.Chmod(batchDir, 0o500); err != nil {
604
- return err
605
- }
606
- return errors.New("failed to delete '" + path + "': Permission denied")
607
- }
608
- t.Cleanup(func() { _ = os.Chmod(batchDir, 0o700) })
609
-
610
- _, err := Cleanup(repo, slug, true)
611
- if err == nil || !strings.Contains(err.Error(), "rerun cleanup") {
612
- t.Fatalf("error must ask for a rerun, got %v", err)
613
- }
614
- if strings.Contains(err.Error(), "remove it by hand") {
615
- t.Fatalf("a still-registered worktree is retryable, got %v", err)
616
- }
617
- leasePath, lerr := LeasePath(repo, slug)
618
- if lerr != nil {
619
- t.Fatal(lerr)
620
- }
621
- if _, rerr := ReadLease(leasePath); rerr != nil {
622
- t.Fatalf("lease must be kept for the rerun: %v", rerr)
623
- }
624
- }
625
-
626
- // TestCleanupDoesNotClaimUnregisteredWhenListUnreadable proves that when git's
627
- // registration cannot be re-read after a failed delete, the error says so
628
- // instead of claiming git dropped the worktree.
629
- func TestCleanupDoesNotClaimUnregisteredWhenListUnreadable(t *testing.T) {
630
- if os.Geteuid() == 0 || runtime.GOOS == "windows" {
631
- t.Skip("directory permissions do not bind root or windows")
632
- }
633
- repo, base := setupRepo(t)
634
- slug, batch := "demo-feature", "batch1"
635
- if _, err := Create(CreateOpts{
636
- Root: repo,
637
- Slug: slug,
638
- BatchID: batch,
639
- BaseSHA: base,
640
- Slices: []SlicePaths{
641
- {ID: "slice-a", Paths: []string{"src/a.go"}},
642
- {ID: "slice-b", Paths: []string{"src/b.go"}},
643
- },
644
- }); err != nil {
645
- t.Fatal(err)
646
- }
647
- wt := WorkerWorktreePath(repo, batch, "slice-a")
648
- batchDir := filepath.Dir(wt)
649
- gitDir := filepath.Join(repo, ".git")
650
-
651
- swapSeams(t)
652
- warnf = func(string, ...any) {}
653
- removeWorktree = func(repo, path string) error {
654
- if err := os.Chmod(batchDir, 0o500); err != nil {
655
- return err
656
- }
657
- if err := os.Chmod(gitDir, 0o000); err != nil {
658
- return err
659
- }
660
- return errors.New("failed to delete '" + path + "': Permission denied")
661
- }
662
- t.Cleanup(func() {
663
- _ = os.Chmod(batchDir, 0o700)
664
- _ = os.Chmod(gitDir, 0o755)
665
- })
666
-
667
- _, err := Cleanup(repo, slug, true)
668
- if err == nil || !strings.Contains(err.Error(), wt) {
669
- t.Fatalf("error must name %s, got %v", wt, err)
670
- }
671
- if strings.Contains(err.Error(), "no longer registers") {
672
- t.Fatalf("registration is unknown, must not be called dropped: %v", err)
673
- }
674
- if !strings.Contains(err.Error(), "could not confirm whether git still registers") {
675
- t.Fatalf("error must say registration could not be confirmed, got %v", err)
676
- }
677
- }
678
-
679
- // TestCleanupStrandedRealGit runs the real git: an undeletable file inside the
680
- // worktree makes `git worktree remove --force` unregister it and still fail,
681
- // so stranding must be decided from git's registration, not the exit code.
682
- func TestCleanupStrandedRealGit(t *testing.T) {
683
- if os.Geteuid() == 0 || runtime.GOOS == "windows" {
684
- t.Skip("directory permissions do not bind root or windows")
685
- }
686
- repo, base := setupRepo(t)
687
- slug, batch := "demo-feature", "batch1"
688
- if _, err := Create(CreateOpts{
689
- Root: repo,
690
- Slug: slug,
691
- BatchID: batch,
692
- BaseSHA: base,
693
- Slices: []SlicePaths{
694
- {ID: "slice-a", Paths: []string{"src/a.go"}},
695
- {ID: "slice-b", Paths: []string{"src/b.go"}},
696
- },
697
- }); err != nil {
698
- t.Fatal(err)
699
- }
700
- wt := WorkerWorktreePath(repo, batch, "slice-a")
701
- locked := filepath.Join(wt, "locked")
702
- if err := os.MkdirAll(locked, 0o755); err != nil {
703
- t.Fatal(err)
704
- }
705
- if err := os.WriteFile(filepath.Join(locked, "f"), []byte("x"), 0o644); err != nil {
706
- t.Fatal(err)
707
- }
708
- if err := os.Chmod(locked, 0o555); err != nil {
709
- t.Fatal(err)
710
- }
711
- t.Cleanup(func() { _ = os.Chmod(locked, 0o755) })
712
-
713
- swapSeams(t)
714
- warnf = func(string, ...any) {}
715
- _, err := Cleanup(repo, slug, true)
716
- if err == nil || !strings.Contains(err.Error(), wt) || !strings.Contains(err.Error(), "remove it by hand") {
717
- t.Fatalf("error must name %s and say it needs manual removal, got %v", wt, err)
718
- }
719
- if err := os.Chmod(locked, 0o755); err != nil {
720
- t.Fatal(err)
721
- }
722
- if _, err := Cleanup(repo, slug, true); err != nil {
723
- t.Fatalf("rerun: %v", err)
724
- }
725
- if _, err := os.Stat(wt); err != nil {
726
- t.Fatalf("rerun must leave the unregistered directory in place, stat err=%v", err)
727
- }
728
- }
729
-
730
- // TestConcurrentRecordGreenKeepsEverySlice proves the feature lock serializes
731
- // concurrent record-green calls so no sibling's transfer commit is lost to a
732
- // read-modify-write race on the lease.
733
- func TestConcurrentRecordGreenKeepsEverySlice(t *testing.T) {
734
- repo, base := setupRepo(t)
735
- slug, batch := "demo-feature", "batch1"
736
- lease, err := Create(CreateOpts{
737
- Root: repo,
738
- Slug: slug,
739
- BatchID: batch,
740
- BaseSHA: base,
741
- Slices: []SlicePaths{
742
- {ID: "slice-a", Paths: []string{"src/a.go"}},
743
- {ID: "slice-b", Paths: []string{"src/b.go"}},
744
- },
745
- })
746
- if err != nil {
747
- t.Fatal(err)
748
- }
749
- tcA := commitIn(t, lease.Slices[0].WorktreePath, "src/a.go", "A")
750
- tcB := commitIn(t, lease.Slices[1].WorktreePath, "src/b.go", "B")
751
-
752
- var wg sync.WaitGroup
753
- errs := make(chan error, 2)
754
- for _, item := range [][2]string{{"slice-a", tcA}, {"slice-b", tcB}} {
755
- wg.Add(1)
756
- go func(sliceID, commit string) {
757
- defer wg.Done()
758
- _, err := RecordGreen(repo, slug, sliceID, commit)
759
- errs <- err
760
- }(item[0], item[1])
761
- }
762
- wg.Wait()
763
- close(errs)
764
- for err := range errs {
765
- if err != nil {
766
- t.Fatal(err)
767
- }
768
- }
769
-
770
- leasePath, err := LeasePath(repo, slug)
771
- if err != nil {
772
- t.Fatal(err)
773
- }
774
- onDisk, err := ReadLease(leasePath)
775
- if err != nil {
776
- t.Fatal(err)
777
- }
778
- got := map[string]string{}
779
- for _, sl := range onDisk.Slices {
780
- got[sl.ID] = sl.TransferCommit
781
- }
782
- if got["slice-a"] != tcA || got["slice-b"] != tcB {
783
- t.Fatalf("lost update: transfer commits %v want a=%s b=%s", got, tcA, tcB)
784
- }
785
- }
786
-
787
- // TestConcurrentCreateSingleWinner proves the feature lock serializes create
788
- // so two racing creates cannot both pass the lease-existence check.
789
- func TestConcurrentCreateSingleWinner(t *testing.T) {
790
- repo, base := setupRepo(t)
791
- opts := CreateOpts{
792
- Root: repo,
793
- Slug: "demo-feature",
794
- BatchID: "batch1",
795
- BaseSHA: base,
796
- Slices: []SlicePaths{
797
- {ID: "slice-a", Paths: []string{"src/a.go"}},
798
- {ID: "slice-b", Paths: []string{"src/b.go"}},
799
- },
800
- }
801
- var wg sync.WaitGroup
802
- errs := make(chan error, 2)
803
- wins := make(chan *Lease, 2)
804
- for i := 0; i < 2; i++ {
805
- wg.Add(1)
806
- go func() {
807
- defer wg.Done()
808
- lease, err := Create(opts)
809
- if err != nil {
810
- errs <- err
811
- return
812
- }
813
- wins <- lease
814
- }()
815
- }
816
- wg.Wait()
817
- close(errs)
818
- close(wins)
819
- succeeded := 0
820
- for range wins {
821
- succeeded++
822
- }
823
- failed := 0
824
- for range errs {
825
- failed++
826
- }
827
- if succeeded != 1 || failed != 1 {
828
- t.Fatalf("concurrent create: %d succeeded, %d failed; want exactly 1/1", succeeded, failed)
829
- }
830
- }
831
-
832
- // stuckBranchBatch creates a two-slice batch and stubs worktree removal so
833
- // cleanup leaves a stale registration behind: Cleanup's own RemoveAll deletes
834
- // the worktree directory while git still lists the branch as checked out, so
835
- // deleteBranch refuses. It returns the repo, slug, the stuck branch and the
836
- // captured warnings.
837
- func stuckBranchBatch(t *testing.T) (repo, slug, branch string, warnings *[]string) {
838
- t.Helper()
839
- repo, base := setupRepo(t)
840
- slug = "demo-feature"
841
- lease, err := Create(CreateOpts{
842
- Root: repo,
843
- Slug: slug,
844
- BatchID: "batch1",
845
- BaseSHA: base,
846
- Slices: []SlicePaths{
847
- {ID: "slice-a", Paths: []string{"src/a.go"}},
848
- {ID: "slice-b", Paths: []string{"src/b.go"}},
849
- },
850
- })
851
- if err != nil {
852
- t.Fatal(err)
853
- }
854
- swapSeams(t)
855
- removeWorktree = func(string, string) error {
856
- return errors.New("simulated stuck worker worktree")
857
- }
858
- warnings = new([]string)
859
- warnf = func(format string, args ...any) {
860
- *warnings = append(*warnings, fmt.Sprintf(format, args...))
861
- }
862
- return repo, slug, lease.Slices[0].Branch, warnings
863
- }
864
-
865
- // TestCleanupWarnsOnFailedBranchCleanup proves Cleanup reports branch cleanup
866
- // failures and keeps the lease so the orphans stay reachable for a rerun.
867
- func TestCleanupWarnsOnFailedBranchCleanup(t *testing.T) {
868
- repo, slug, branchA, warnings := stuckBranchBatch(t)
869
-
870
- if _, err := Cleanup(repo, slug, true); err == nil || !strings.Contains(err.Error(), "slice-a") {
871
- t.Fatalf("cleanup must fail naming slice-a, got %v", err)
872
- }
873
- leasePath, err := LeasePath(repo, slug)
874
- if err != nil {
875
- t.Fatal(err)
876
- }
877
- if _, err := os.Stat(leasePath); err != nil {
878
- t.Fatalf("lease must survive a failed cleanup, got %v", err)
879
- }
880
- // The rerun finds the lease and, with the stale registration pruned by the
881
- // first pass, completes the removal and clears it.
882
- if _, err := Cleanup(repo, slug, true); err != nil {
883
- t.Fatalf("rerun against the kept lease: %v", err)
884
- }
885
- if _, err := os.Stat(leasePath); !os.IsNotExist(err) {
886
- t.Fatalf("rerun should clear the lease, got %v", err)
887
- }
888
- if exists, err := branchExists(repo, branchA); err != nil || exists {
889
- t.Fatalf("rerun should delete %s: exists=%v err=%v", branchA, exists, err)
890
- }
891
- if joined := strings.Join(*warnings, "\n"); !strings.Contains(joined, branchA) {
892
- t.Fatalf("warnings should name the stuck branch %s, got:\n%s", branchA, joined)
893
- }
894
- }
895
-
896
- func TestControlCommitMessage(t *testing.T) {
897
- t.Parallel()
898
- got := controlCommitMessage("admin-report", "WIP(admin-report): SLICE-003 add CSV export")
899
- wantPrefix := "WIP(admin-report): add CSV export\n"
900
- if !strings.HasPrefix(got, wantPrefix) {
901
- t.Fatalf("subject %q want prefix %q", got, wantPrefix)
902
- }
903
- if strings.Contains(got, "SLICE-") || strings.Contains(strings.ToLower(got), "slice-003") {
904
- t.Fatalf("message still names a slice id: %q", got)
905
- }
906
- got = controlCommitMessage("admin-report", "WIP(other): complete slice 3")
907
- if !strings.HasPrefix(got, "WIP(admin-report): complete\n") {
908
- t.Fatalf("foreign WIP prefix / slice N: %q", got)
909
- }
910
- got = controlCommitMessage("admin-report", "add this slice CSV")
911
- if !strings.HasPrefix(got, "WIP(admin-report): add CSV\n") {
912
- t.Fatalf("this slice: %q", got)
913
- }
914
- got = controlCommitMessage("admin-report", "keep array slice helper")
915
- if !strings.HasPrefix(got, "WIP(admin-report): keep array slice helper\n") {
916
- t.Fatalf("ordinary English stripped: %q", got)
917
- }
918
- got = controlCommitMessage("admin-report", "SLICE-001")
919
- if !strings.HasPrefix(got, "WIP(admin-report): land proven work\n") {
920
- t.Fatalf("empty summary after strip: %q", got)
921
- }
922
- }
923
-
924
- func TestCreateRefusesAncestorOverlap(t *testing.T) {
925
- repo, base := setupRepo(t)
926
- _, err := Create(CreateOpts{
927
- Root: repo,
928
- Slug: "demo",
929
- BatchID: "batch1",
930
- BaseSHA: base,
931
- Slices: []SlicePaths{
932
- {ID: "slice-a", Paths: []string{"src"}},
933
- {ID: "slice-b", Paths: []string{"src/a.go"}},
934
- },
935
- })
936
- if err == nil || !strings.Contains(err.Error(), "overlap") {
937
- t.Fatalf("expected overlap refusal, got %v", err)
938
- }
939
- }