devrites 5.4.0 → 5.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (490) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +8 -6
  3. package/docs/command-map.md +2 -2
  4. package/docs/engine/state-schema.md +12 -0
  5. package/docs/flow.md +4 -0
  6. package/docs/orchestration.md +5 -2
  7. package/engine/commands.go +2 -2
  8. package/engine/internal/devritespaths/paths.go +18 -0
  9. package/engine/internal/gate/gate.go +78 -0
  10. package/engine/internal/gate/gate_test.go +118 -0
  11. package/engine/internal/hostpack/hostpack.go +45 -6
  12. package/engine/internal/hostpack/hostpack_test.go +29 -13
  13. package/engine/internal/install/apply.go +14 -5
  14. package/engine/internal/install/install.go +8 -2
  15. package/engine/internal/install/install_test.go +12 -5
  16. package/engine/internal/install/merge.go +5 -0
  17. package/engine/internal/install/preflight.go +20 -2
  18. package/engine/internal/install/uninstall.go +5 -0
  19. package/engine/internal/install/update.go +1 -1
  20. package/engine/internal/lib/candidate.go +7 -3
  21. package/engine/internal/lib/manifest_union.go +326 -0
  22. package/engine/internal/lib/manifest_union_test.go +214 -0
  23. package/engine/internal/lib/observe_budgets.go +73 -0
  24. package/engine/internal/lib/observe_budgets_test.go +142 -0
  25. package/engine/internal/lib/observe_summary.go +74 -13
  26. package/engine/internal/lib/workspace_read.go +11 -6
  27. package/engine/internal/state/budgets.go +163 -0
  28. package/engine/internal/state/budgets_test.go +42 -0
  29. package/engine/internal/state/cursor.go +16 -10
  30. package/engine/internal/state/observation.go +50 -4
  31. package/engine/internal/state/status.go +38 -26
  32. package/engine/internal/state/taskgraph.go +23 -0
  33. package/engine/main.go +32 -13
  34. package/engine/root_routing_test.go +3 -1
  35. package/install.sh +4 -1
  36. package/pack/.claude/agents/devrites-code-reviewer.md +9 -6
  37. package/pack/.claude/agents/devrites-doubt-reviewer.md +6 -0
  38. package/pack/.claude/agents/devrites-plan-reviewer.md +7 -1
  39. package/pack/.claude/agents/devrites-slice-wright.md +42 -46
  40. package/pack/.claude/agents/devrites-test-analyst.md +9 -4
  41. package/pack/.claude/agents/devrites-upgrade-planner.md +9 -1
  42. package/pack/.claude/settings.json +17 -0
  43. package/pack/.claude/skills/devrites-api-interface/SKILL.md +2 -2
  44. package/pack/.claude/skills/devrites-doubt/SKILL.md +9 -17
  45. package/pack/.claude/skills/devrites-lib/reference/candidate-integrity.md +34 -35
  46. package/pack/.claude/skills/devrites-lib/reference/parallel-dispatch.md +11 -12
  47. package/pack/.claude/skills/devrites-lib/reference/standards/afk-hitl.md +104 -51
  48. package/pack/.claude/skills/devrites-lib/reference/standards/agents.md +1 -0
  49. package/pack/.claude/skills/devrites-lib/reference/standards/context-hygiene.md +45 -25
  50. package/pack/.claude/skills/devrites-lib/reference/standards/core.md +1 -1
  51. package/pack/.claude/skills/devrites-lib/reference/workspace-artifact-schema.md +80 -41
  52. package/pack/.claude/skills/rite-autocomplete/SKILL.md +19 -8
  53. package/pack/.claude/skills/rite-autocomplete/reference/loop.md +33 -1
  54. package/pack/.claude/skills/rite-build/SKILL.md +26 -19
  55. package/pack/.claude/skills/rite-build/reference/afk-discipline.md +1 -1
  56. package/pack/.claude/skills/rite-build/reference/parallel-batch.md +90 -40
  57. package/pack/.claude/skills/rite-build/reference/phase-contract.md +79 -59
  58. package/pack/.claude/skills/rite-build/reference/spec-drift-guard.md +14 -15
  59. package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +8 -8
  60. package/pack/.claude/skills/rite-define/SKILL.md +4 -1
  61. package/pack/.claude/skills/rite-plan/SKILL.md +4 -1
  62. package/pack/.claude/skills/rite-plan/reference/replan-and-repair.md +21 -0
  63. package/pack/.claude/skills/rite-plan/reference/slicing.md +117 -15
  64. package/pack/.claude/skills/rite-prove/SKILL.md +20 -22
  65. package/pack/.claude/skills/rite-review/SKILL.md +23 -16
  66. package/pack/.claude/skills/rite-seal/SKILL.md +8 -8
  67. package/pack/.claude/skills/rite-seal/reference/final-evidence.md +6 -5
  68. package/pack/.claude/skills/rite-seal/reference/phase-contract.md +13 -13
  69. package/pack/.claude/skills/rite-ship/SKILL.md +3 -0
  70. package/pack/.claude/skills/rite-ship/reference/close-out.md +16 -2
  71. package/pack/.claude/skills/rite-ship/reference/git-ship.md +14 -5
  72. package/pack/.claude/skills/rite-spec/SKILL.md +6 -0
  73. package/pack/.claude/skills/rite-spec/reference/state-workspace.md +6 -0
  74. package/pack/.claude/skills/rite-status/SKILL.md +4 -1
  75. package/pack/.claude/skills/rite-temper/SKILL.md +14 -11
  76. package/pack/.claude/skills/rite-temper/reference/anti-patterns.md +14 -13
  77. package/pack/.claude/skills/rite-temper/reference/review-dimensions.md +3 -4
  78. package/pack/.claude/skills/rite-upgrade/SKILL.md +11 -2
  79. package/pack/.claude/skills/rite-vet/SKILL.md +22 -15
  80. package/pack/.claude/skills/rite-vet/reference/anti-patterns.md +11 -9
  81. package/pack/.claude/skills/rite-vet/reference/depth.md +6 -7
  82. package/pack/.claude/skills/rite-vet/reference/review-axes.md +39 -14
  83. package/pack/generated/README.md +5 -1
  84. package/pack/generated/claude/agents/devrites-code-reviewer.md +9 -6
  85. package/pack/generated/claude/agents/devrites-doubt-reviewer.md +6 -0
  86. package/pack/generated/claude/agents/devrites-plan-reviewer.md +7 -1
  87. package/pack/generated/claude/agents/devrites-slice-wright.md +42 -46
  88. package/pack/generated/claude/agents/devrites-test-analyst.md +9 -4
  89. package/pack/generated/claude/agents/devrites-upgrade-planner.md +9 -1
  90. package/pack/generated/claude/settings.json +17 -0
  91. package/pack/generated/claude/skills/devrites-api-interface/SKILL.md +2 -2
  92. package/pack/generated/claude/skills/devrites-doubt/SKILL.md +9 -17
  93. package/pack/generated/claude/skills/devrites-lib/reference/candidate-integrity.md +34 -35
  94. package/pack/generated/claude/skills/devrites-lib/reference/parallel-dispatch.md +11 -12
  95. package/pack/generated/claude/skills/devrites-lib/reference/standards/afk-hitl.md +104 -51
  96. package/pack/generated/claude/skills/devrites-lib/reference/standards/agents.md +1 -0
  97. package/pack/generated/claude/skills/devrites-lib/reference/standards/context-hygiene.md +45 -25
  98. package/pack/generated/claude/skills/devrites-lib/reference/standards/core.md +1 -1
  99. package/pack/generated/claude/skills/devrites-lib/reference/workspace-artifact-schema.md +80 -41
  100. package/pack/generated/claude/skills/rite-autocomplete/SKILL.md +19 -8
  101. package/pack/generated/claude/skills/rite-autocomplete/reference/loop.md +33 -1
  102. package/pack/generated/claude/skills/rite-build/SKILL.md +26 -19
  103. package/pack/generated/claude/skills/rite-build/reference/afk-discipline.md +1 -1
  104. package/pack/generated/claude/skills/rite-build/reference/parallel-batch.md +90 -40
  105. package/pack/generated/claude/skills/rite-build/reference/phase-contract.md +79 -59
  106. package/pack/generated/claude/skills/rite-build/reference/spec-drift-guard.md +14 -15
  107. package/pack/generated/claude/skills/rite-build/reference/wright-dispatch.md +8 -8
  108. package/pack/generated/claude/skills/rite-define/SKILL.md +4 -1
  109. package/pack/generated/claude/skills/rite-plan/SKILL.md +4 -1
  110. package/pack/generated/claude/skills/rite-plan/reference/replan-and-repair.md +21 -0
  111. package/pack/generated/claude/skills/rite-plan/reference/slicing.md +117 -15
  112. package/pack/generated/claude/skills/rite-prove/SKILL.md +20 -22
  113. package/pack/generated/claude/skills/rite-review/SKILL.md +23 -16
  114. package/pack/generated/claude/skills/rite-seal/SKILL.md +8 -8
  115. package/pack/generated/claude/skills/rite-seal/reference/final-evidence.md +6 -5
  116. package/pack/generated/claude/skills/rite-seal/reference/phase-contract.md +13 -13
  117. package/pack/generated/claude/skills/rite-ship/SKILL.md +3 -0
  118. package/pack/generated/claude/skills/rite-ship/reference/close-out.md +16 -2
  119. package/pack/generated/claude/skills/rite-ship/reference/git-ship.md +14 -5
  120. package/pack/generated/claude/skills/rite-spec/SKILL.md +6 -0
  121. package/pack/generated/claude/skills/rite-spec/reference/state-workspace.md +6 -0
  122. package/pack/generated/claude/skills/rite-status/SKILL.md +4 -1
  123. package/pack/generated/claude/skills/rite-temper/SKILL.md +14 -11
  124. package/pack/generated/claude/skills/rite-temper/reference/anti-patterns.md +14 -13
  125. package/pack/generated/claude/skills/rite-temper/reference/review-dimensions.md +3 -4
  126. package/pack/generated/claude/skills/rite-upgrade/SKILL.md +11 -2
  127. package/pack/generated/claude/skills/rite-vet/SKILL.md +22 -15
  128. package/pack/generated/claude/skills/rite-vet/reference/anti-patterns.md +11 -9
  129. package/pack/generated/claude/skills/rite-vet/reference/depth.md +6 -7
  130. package/pack/generated/claude/skills/rite-vet/reference/review-axes.md +39 -14
  131. package/pack/generated/codex/agents/devrites-code-reviewer.toml +9 -6
  132. package/pack/generated/codex/agents/devrites-doubt-reviewer.toml +6 -0
  133. package/pack/generated/codex/agents/devrites-plan-reviewer.toml +7 -1
  134. package/pack/generated/codex/agents/devrites-slice-wright.toml +42 -46
  135. package/pack/generated/codex/agents/devrites-test-analyst.toml +9 -4
  136. package/pack/generated/codex/agents/devrites-upgrade-planner.toml +9 -1
  137. package/pack/generated/codex/skills/devrites-api-interface/SKILL.md +2 -2
  138. package/pack/generated/codex/skills/devrites-doubt/SKILL.md +9 -17
  139. package/pack/generated/codex/skills/devrites-lib/reference/candidate-integrity.md +34 -35
  140. package/pack/generated/codex/skills/devrites-lib/reference/parallel-dispatch.md +11 -12
  141. package/pack/generated/codex/skills/devrites-lib/reference/standards/afk-hitl.md +104 -51
  142. package/pack/generated/codex/skills/devrites-lib/reference/standards/agents.md +1 -0
  143. package/pack/generated/codex/skills/devrites-lib/reference/standards/context-hygiene.md +45 -25
  144. package/pack/generated/codex/skills/devrites-lib/reference/standards/core.md +1 -1
  145. package/pack/generated/codex/skills/devrites-lib/reference/workspace-artifact-schema.md +80 -41
  146. package/pack/generated/codex/skills/rite-autocomplete/SKILL.md +19 -8
  147. package/pack/generated/codex/skills/rite-autocomplete/reference/loop.md +33 -1
  148. package/pack/generated/codex/skills/rite-build/SKILL.md +26 -19
  149. package/pack/generated/codex/skills/rite-build/reference/afk-discipline.md +1 -1
  150. package/pack/generated/codex/skills/rite-build/reference/parallel-batch.md +90 -40
  151. package/pack/generated/codex/skills/rite-build/reference/phase-contract.md +79 -59
  152. package/pack/generated/codex/skills/rite-build/reference/spec-drift-guard.md +14 -15
  153. package/pack/generated/codex/skills/rite-build/reference/wright-dispatch.md +8 -8
  154. package/pack/generated/codex/skills/rite-define/SKILL.md +4 -1
  155. package/pack/generated/codex/skills/rite-plan/SKILL.md +4 -1
  156. package/pack/generated/codex/skills/rite-plan/reference/replan-and-repair.md +21 -0
  157. package/pack/generated/codex/skills/rite-plan/reference/slicing.md +117 -15
  158. package/pack/generated/codex/skills/rite-prove/SKILL.md +20 -22
  159. package/pack/generated/codex/skills/rite-review/SKILL.md +23 -16
  160. package/pack/generated/codex/skills/rite-seal/SKILL.md +8 -8
  161. package/pack/generated/codex/skills/rite-seal/reference/final-evidence.md +6 -5
  162. package/pack/generated/codex/skills/rite-seal/reference/phase-contract.md +13 -13
  163. package/pack/generated/codex/skills/rite-ship/SKILL.md +3 -0
  164. package/pack/generated/codex/skills/rite-ship/reference/close-out.md +16 -2
  165. package/pack/generated/codex/skills/rite-ship/reference/git-ship.md +14 -5
  166. package/pack/generated/codex/skills/rite-spec/SKILL.md +6 -0
  167. package/pack/generated/codex/skills/rite-spec/reference/state-workspace.md +6 -0
  168. package/pack/generated/codex/skills/rite-status/SKILL.md +4 -1
  169. package/pack/generated/codex/skills/rite-temper/SKILL.md +14 -11
  170. package/pack/generated/codex/skills/rite-temper/reference/anti-patterns.md +14 -13
  171. package/pack/generated/codex/skills/rite-temper/reference/review-dimensions.md +3 -4
  172. package/pack/generated/codex/skills/rite-upgrade/SKILL.md +11 -2
  173. package/pack/generated/codex/skills/rite-vet/SKILL.md +22 -15
  174. package/pack/generated/codex/skills/rite-vet/reference/anti-patterns.md +11 -9
  175. package/pack/generated/codex/skills/rite-vet/reference/depth.md +6 -7
  176. package/pack/generated/codex/skills/rite-vet/reference/review-axes.md +39 -14
  177. package/pack/generated/omp/agents/devrites-code-reviewer.md +9 -6
  178. package/pack/generated/omp/agents/devrites-doubt-reviewer.md +6 -0
  179. package/pack/generated/omp/agents/devrites-plan-reviewer.md +7 -1
  180. package/pack/generated/omp/agents/devrites-slice-wright.md +42 -46
  181. package/pack/generated/omp/agents/devrites-test-analyst.md +9 -4
  182. package/pack/generated/omp/agents/devrites-upgrade-planner.md +9 -1
  183. package/pack/generated/omp/skills/devrites-api-interface/SKILL.md +2 -2
  184. package/pack/generated/omp/skills/devrites-doubt/SKILL.md +9 -17
  185. package/pack/generated/omp/skills/devrites-lib/reference/candidate-integrity.md +34 -35
  186. package/pack/generated/omp/skills/devrites-lib/reference/parallel-dispatch.md +11 -12
  187. package/pack/generated/omp/skills/devrites-lib/reference/standards/afk-hitl.md +104 -51
  188. package/pack/generated/omp/skills/devrites-lib/reference/standards/agents.md +1 -0
  189. package/pack/generated/omp/skills/devrites-lib/reference/standards/context-hygiene.md +45 -25
  190. package/pack/generated/omp/skills/devrites-lib/reference/standards/core.md +1 -1
  191. package/pack/generated/omp/skills/devrites-lib/reference/workspace-artifact-schema.md +80 -41
  192. package/pack/generated/omp/skills/rite-autocomplete/SKILL.md +19 -8
  193. package/pack/generated/omp/skills/rite-autocomplete/reference/loop.md +33 -1
  194. package/pack/generated/omp/skills/rite-build/SKILL.md +26 -19
  195. package/pack/generated/omp/skills/rite-build/reference/afk-discipline.md +1 -1
  196. package/pack/generated/omp/skills/rite-build/reference/parallel-batch.md +90 -40
  197. package/pack/generated/omp/skills/rite-build/reference/phase-contract.md +79 -59
  198. package/pack/generated/omp/skills/rite-build/reference/spec-drift-guard.md +14 -15
  199. package/pack/generated/omp/skills/rite-build/reference/wright-dispatch.md +8 -8
  200. package/pack/generated/omp/skills/rite-define/SKILL.md +4 -1
  201. package/pack/generated/omp/skills/rite-plan/SKILL.md +4 -1
  202. package/pack/generated/omp/skills/rite-plan/reference/replan-and-repair.md +21 -0
  203. package/pack/generated/omp/skills/rite-plan/reference/slicing.md +117 -15
  204. package/pack/generated/omp/skills/rite-prove/SKILL.md +20 -22
  205. package/pack/generated/omp/skills/rite-review/SKILL.md +23 -16
  206. package/pack/generated/omp/skills/rite-seal/SKILL.md +8 -8
  207. package/pack/generated/omp/skills/rite-seal/reference/final-evidence.md +6 -5
  208. package/pack/generated/omp/skills/rite-seal/reference/phase-contract.md +13 -13
  209. package/pack/generated/omp/skills/rite-ship/SKILL.md +3 -0
  210. package/pack/generated/omp/skills/rite-ship/reference/close-out.md +16 -2
  211. package/pack/generated/omp/skills/rite-ship/reference/git-ship.md +14 -5
  212. package/pack/generated/omp/skills/rite-spec/SKILL.md +6 -0
  213. package/pack/generated/omp/skills/rite-spec/reference/state-workspace.md +6 -0
  214. package/pack/generated/omp/skills/rite-status/SKILL.md +4 -1
  215. package/pack/generated/omp/skills/rite-temper/SKILL.md +14 -11
  216. package/pack/generated/omp/skills/rite-temper/reference/anti-patterns.md +14 -13
  217. package/pack/generated/omp/skills/rite-temper/reference/review-dimensions.md +3 -4
  218. package/pack/generated/omp/skills/rite-upgrade/SKILL.md +11 -2
  219. package/pack/generated/omp/skills/rite-vet/SKILL.md +22 -15
  220. package/pack/generated/omp/skills/rite-vet/reference/anti-patterns.md +11 -9
  221. package/pack/generated/omp/skills/rite-vet/reference/depth.md +6 -7
  222. package/pack/generated/omp/skills/rite-vet/reference/review-axes.md +39 -14
  223. package/pack/generated/pi/AGENTS.md +22 -0
  224. package/pack/generated/pi/agents/devrites-code-reviewer.md +142 -0
  225. package/pack/generated/pi/agents/devrites-devex-reviewer.md +124 -0
  226. package/pack/generated/pi/agents/devrites-doubt-reviewer.md +88 -0
  227. package/pack/generated/pi/agents/devrites-evidence-scout.md +72 -0
  228. package/pack/generated/pi/agents/devrites-frontend-reviewer.md +116 -0
  229. package/pack/generated/pi/agents/devrites-performance-reviewer.md +115 -0
  230. package/pack/generated/pi/agents/devrites-plan-drafter.md +99 -0
  231. package/pack/generated/pi/agents/devrites-plan-reviewer.md +142 -0
  232. package/pack/generated/pi/agents/devrites-proof-runner.md +74 -0
  233. package/pack/generated/pi/agents/devrites-retrospector.md +61 -0
  234. package/pack/generated/pi/agents/devrites-security-auditor.md +109 -0
  235. package/pack/generated/pi/agents/devrites-simplifier-reviewer.md +94 -0
  236. package/pack/generated/pi/agents/devrites-slice-wright.md +204 -0
  237. package/pack/generated/pi/agents/devrites-spec-reviewer.md +96 -0
  238. package/pack/generated/pi/agents/devrites-strategy-reviewer.md +100 -0
  239. package/pack/generated/pi/agents/devrites-test-analyst.md +94 -0
  240. package/pack/generated/pi/agents/devrites-upgrade-planner.md +89 -0
  241. package/pack/generated/pi/prompts/rite-adopt.md +5 -0
  242. package/pack/generated/pi/prompts/rite-autocomplete.md +5 -0
  243. package/pack/generated/pi/prompts/rite-build.md +5 -0
  244. package/pack/generated/pi/prompts/rite-clarify.md +5 -0
  245. package/pack/generated/pi/prompts/rite-converge.md +5 -0
  246. package/pack/generated/pi/prompts/rite-customize.md +5 -0
  247. package/pack/generated/pi/prompts/rite-define.md +5 -0
  248. package/pack/generated/pi/prompts/rite-doctor.md +5 -0
  249. package/pack/generated/pi/prompts/rite-dogfood.md +5 -0
  250. package/pack/generated/pi/prompts/rite-explain.md +5 -0
  251. package/pack/generated/pi/prompts/rite-frame.md +5 -0
  252. package/pack/generated/pi/prompts/rite-handoff.md +5 -0
  253. package/pack/generated/pi/prompts/rite-learn.md +5 -0
  254. package/pack/generated/pi/prompts/rite-plan.md +5 -0
  255. package/pack/generated/pi/prompts/rite-polish.md +5 -0
  256. package/pack/generated/pi/prompts/rite-pov.md +5 -0
  257. package/pack/generated/pi/prompts/rite-pr-feedback.md +5 -0
  258. package/pack/generated/pi/prompts/rite-pressure-test.md +5 -0
  259. package/pack/generated/pi/prompts/rite-prototype.md +5 -0
  260. package/pack/generated/pi/prompts/rite-prove.md +5 -0
  261. package/pack/generated/pi/prompts/rite-quick.md +5 -0
  262. package/pack/generated/pi/prompts/rite-resolve.md +5 -0
  263. package/pack/generated/pi/prompts/rite-review.md +5 -0
  264. package/pack/generated/pi/prompts/rite-seal.md +5 -0
  265. package/pack/generated/pi/prompts/rite-ship.md +5 -0
  266. package/pack/generated/pi/prompts/rite-spec.md +5 -0
  267. package/pack/generated/pi/prompts/rite-status.md +5 -0
  268. package/pack/generated/pi/prompts/rite-temper.md +5 -0
  269. package/pack/generated/pi/prompts/rite-upgrade.md +5 -0
  270. package/pack/generated/pi/prompts/rite-vet.md +5 -0
  271. package/pack/generated/pi/prompts/rite-watch-pr.md +5 -0
  272. package/pack/generated/pi/prompts/rite-zoom-out.md +5 -0
  273. package/pack/generated/pi/prompts/rite.md +5 -0
  274. package/pack/generated/pi/skills/devrites-api-interface/SKILL.md +63 -0
  275. package/pack/generated/pi/skills/devrites-audit/SKILL.md +50 -0
  276. package/pack/generated/pi/skills/devrites-browser-proof/SKILL.md +76 -0
  277. package/pack/generated/pi/skills/devrites-browser-proof/reference/browser-performance.md +15 -0
  278. package/pack/generated/pi/skills/devrites-browser-proof/reference/visual-verdict.md +34 -0
  279. package/pack/generated/pi/skills/devrites-debug-recovery/SKILL.md +96 -0
  280. package/pack/generated/pi/skills/devrites-debug-recovery/reference/build-the-loop.md +58 -0
  281. package/pack/generated/pi/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +34 -0
  282. package/pack/generated/pi/skills/devrites-debug-recovery/reference/hypotheses.md +17 -0
  283. package/pack/generated/pi/skills/devrites-debug-recovery/reference/instrumentation.md +21 -0
  284. package/pack/generated/pi/skills/devrites-debug-recovery/reference/regression-test.md +30 -0
  285. package/pack/generated/pi/skills/devrites-debug-recovery/reference/trace.md +25 -0
  286. package/pack/generated/pi/skills/devrites-doubt/SKILL.md +79 -0
  287. package/pack/generated/pi/skills/devrites-frontend-craft/SKILL.md +86 -0
  288. package/pack/generated/pi/skills/devrites-frontend-craft/reference/craft.md +63 -0
  289. package/pack/generated/pi/skills/devrites-frontend-craft/reference/design-references.md +116 -0
  290. package/pack/generated/pi/skills/devrites-frontend-craft/reference/fullstack.md +46 -0
  291. package/pack/generated/pi/skills/devrites-frontend-craft/reference/quality-standards.md +294 -0
  292. package/pack/generated/pi/skills/devrites-frontend-craft/reference/reuse-first.md +53 -0
  293. package/pack/generated/pi/skills/devrites-frontend-craft/reference/shape.md +56 -0
  294. package/pack/generated/pi/skills/devrites-interview/SKILL.md +102 -0
  295. package/pack/generated/pi/skills/devrites-lib/SKILL.md +58 -0
  296. package/pack/generated/pi/skills/devrites-lib/reference/candidate-integrity.md +42 -0
  297. package/pack/generated/pi/skills/devrites-lib/reference/intent-map.md +64 -0
  298. package/pack/generated/pi/skills/devrites-lib/reference/orchestration-profiles.md +27 -0
  299. package/pack/generated/pi/skills/devrites-lib/reference/parallel-dispatch.md +73 -0
  300. package/pack/generated/pi/skills/devrites-lib/reference/reply-contract.md +88 -0
  301. package/pack/generated/pi/skills/devrites-lib/reference/standards/README.md +60 -0
  302. package/pack/generated/pi/skills/devrites-lib/reference/standards/acceptance-preserving-reslice.md +30 -0
  303. package/pack/generated/pi/skills/devrites-lib/reference/standards/afk-hitl.md +398 -0
  304. package/pack/generated/pi/skills/devrites-lib/reference/standards/agents.md +99 -0
  305. package/pack/generated/pi/skills/devrites-lib/reference/standards/anti-patterns.md +48 -0
  306. package/pack/generated/pi/skills/devrites-lib/reference/standards/browser-proof-checklist.md +24 -0
  307. package/pack/generated/pi/skills/devrites-lib/reference/standards/ci-cd.md +50 -0
  308. package/pack/generated/pi/skills/devrites-lib/reference/standards/code-navigation.md +43 -0
  309. package/pack/generated/pi/skills/devrites-lib/reference/standards/code-review.md +108 -0
  310. package/pack/generated/pi/skills/devrites-lib/reference/standards/coding-style.md +48 -0
  311. package/pack/generated/pi/skills/devrites-lib/reference/standards/context-hygiene.md +109 -0
  312. package/pack/generated/pi/skills/devrites-lib/reference/standards/core.md +167 -0
  313. package/pack/generated/pi/skills/devrites-lib/reference/standards/data-integrity.md +118 -0
  314. package/pack/generated/pi/skills/devrites-lib/reference/standards/debug-recovery.md +28 -0
  315. package/pack/generated/pi/skills/devrites-lib/reference/standards/definition-of-done.md +19 -0
  316. package/pack/generated/pi/skills/devrites-lib/reference/standards/deprecation.md +31 -0
  317. package/pack/generated/pi/skills/devrites-lib/reference/standards/developer-experience.md +119 -0
  318. package/pack/generated/pi/skills/devrites-lib/reference/standards/development-workflow.md +29 -0
  319. package/pack/generated/pi/skills/devrites-lib/reference/standards/documentation.md +43 -0
  320. package/pack/generated/pi/skills/devrites-lib/reference/standards/edge-case-trace.md +92 -0
  321. package/pack/generated/pi/skills/devrites-lib/reference/standards/elicitation.md +85 -0
  322. package/pack/generated/pi/skills/devrites-lib/reference/standards/error-handling.md +47 -0
  323. package/pack/generated/pi/skills/devrites-lib/reference/standards/git-workflow.md +49 -0
  324. package/pack/generated/pi/skills/devrites-lib/reference/standards/hooks.md +25 -0
  325. package/pack/generated/pi/skills/devrites-lib/reference/standards/integration-reliability.md +102 -0
  326. package/pack/generated/pi/skills/devrites-lib/reference/standards/loop-operations.md +85 -0
  327. package/pack/generated/pi/skills/devrites-lib/reference/standards/observability.md +88 -0
  328. package/pack/generated/pi/skills/devrites-lib/reference/standards/one-shot-actions.md +97 -0
  329. package/pack/generated/pi/skills/devrites-lib/reference/standards/patterns.md +68 -0
  330. package/pack/generated/pi/skills/devrites-lib/reference/standards/performance.md +51 -0
  331. package/pack/generated/pi/skills/devrites-lib/reference/standards/principles.md +42 -0
  332. package/pack/generated/pi/skills/devrites-lib/reference/standards/prose-style.md +123 -0
  333. package/pack/generated/pi/skills/devrites-lib/reference/standards/release/ship-checklist.md +8 -0
  334. package/pack/generated/pi/skills/devrites-lib/reference/standards/repository-topology.md +80 -0
  335. package/pack/generated/pi/skills/devrites-lib/reference/standards/review-checklist.md +12 -0
  336. package/pack/generated/pi/skills/devrites-lib/reference/standards/security-checklist.md +25 -0
  337. package/pack/generated/pi/skills/devrites-lib/reference/standards/security.md +202 -0
  338. package/pack/generated/pi/skills/devrites-lib/reference/standards/skill-authoring.md +209 -0
  339. package/pack/generated/pi/skills/devrites-lib/reference/standards/spec-grammar.md +197 -0
  340. package/pack/generated/pi/skills/devrites-lib/reference/standards/test-proof-checklist.md +13 -0
  341. package/pack/generated/pi/skills/devrites-lib/reference/standards/testing.md +212 -0
  342. package/pack/generated/pi/skills/devrites-lib/reference/standards/tooling.md +92 -0
  343. package/pack/generated/pi/skills/devrites-lib/reference/standards/workflow-artifacts.md +427 -0
  344. package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/code.md +44 -0
  345. package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/comparison.md +42 -0
  346. package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/diagram.md +51 -0
  347. package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/index.md +66 -0
  348. package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/input.md +46 -0
  349. package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/outline-template.md +106 -0
  350. package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/plan.md +48 -0
  351. package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/slides.md +40 -0
  352. package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/table.md +42 -0
  353. package/pack/generated/pi/skills/devrites-lib/reference/workspace-artifact-schema.md +267 -0
  354. package/pack/generated/pi/skills/devrites-prose-craft/SKILL.md +73 -0
  355. package/pack/generated/pi/skills/devrites-prose-craft/reference/banned-phrases.md +132 -0
  356. package/pack/generated/pi/skills/devrites-prose-craft/reference/examples.md +131 -0
  357. package/pack/generated/pi/skills/devrites-prose-craft/reference/structures.md +196 -0
  358. package/pack/generated/pi/skills/devrites-source-driven/SKILL.md +52 -0
  359. package/pack/generated/pi/skills/devrites-ux-shape/SKILL.md +134 -0
  360. package/pack/generated/pi/skills/devrites-ux-shape/reference/brief-template.md +108 -0
  361. package/pack/generated/pi/skills/devrites-ux-shape/reference/visual-direction-probe.md +48 -0
  362. package/pack/generated/pi/skills/rite/SKILL.md +148 -0
  363. package/pack/generated/pi/skills/rite/reference/menu.md +48 -0
  364. package/pack/generated/pi/skills/rite-adopt/SKILL.md +52 -0
  365. package/pack/generated/pi/skills/rite-adopt/reference/adoption.md +19 -0
  366. package/pack/generated/pi/skills/rite-adopt/reference/anti-patterns.md +19 -0
  367. package/pack/generated/pi/skills/rite-autocomplete/SKILL.md +132 -0
  368. package/pack/generated/pi/skills/rite-autocomplete/reference/decision-policy.md +41 -0
  369. package/pack/generated/pi/skills/rite-autocomplete/reference/loop.md +148 -0
  370. package/pack/generated/pi/skills/rite-autocomplete/reference/stop-conditions.md +92 -0
  371. package/pack/generated/pi/skills/rite-build/SKILL.md +96 -0
  372. package/pack/generated/pi/skills/rite-build/reference/afk-discipline.md +145 -0
  373. package/pack/generated/pi/skills/rite-build/reference/anti-patterns.md +23 -0
  374. package/pack/generated/pi/skills/rite-build/reference/checkpoint-protocol.md +120 -0
  375. package/pack/generated/pi/skills/rite-build/reference/checkpoint.md +44 -0
  376. package/pack/generated/pi/skills/rite-build/reference/frontend-trigger.md +39 -0
  377. package/pack/generated/pi/skills/rite-build/reference/one-slice-cycle.md +50 -0
  378. package/pack/generated/pi/skills/rite-build/reference/output.md +33 -0
  379. package/pack/generated/pi/skills/rite-build/reference/parallel-batch.md +205 -0
  380. package/pack/generated/pi/skills/rite-build/reference/phase-contract.md +87 -0
  381. package/pack/generated/pi/skills/rite-build/reference/spec-drift-guard.md +84 -0
  382. package/pack/generated/pi/skills/rite-build/reference/tdd.md +27 -0
  383. package/pack/generated/pi/skills/rite-build/reference/wright-dispatch.md +89 -0
  384. package/pack/generated/pi/skills/rite-clarify/SKILL.md +99 -0
  385. package/pack/generated/pi/skills/rite-clarify/reference/anti-patterns.md +24 -0
  386. package/pack/generated/pi/skills/rite-clarify/reference/decision-coverage.md +55 -0
  387. package/pack/generated/pi/skills/rite-converge/SKILL.md +145 -0
  388. package/pack/generated/pi/skills/rite-converge/reference/anti-patterns.md +35 -0
  389. package/pack/generated/pi/skills/rite-converge/reference/convergence-assessment.md +65 -0
  390. package/pack/generated/pi/skills/rite-customize/SKILL.md +60 -0
  391. package/pack/generated/pi/skills/rite-define/SKILL.md +169 -0
  392. package/pack/generated/pi/skills/rite-define/reference/anti-patterns.md +26 -0
  393. package/pack/generated/pi/skills/rite-define/reference/gates.md +154 -0
  394. package/pack/generated/pi/skills/rite-define/reference/plan-template.md +149 -0
  395. package/pack/generated/pi/skills/rite-doctor/SKILL.md +69 -0
  396. package/pack/generated/pi/skills/rite-dogfood/SKILL.md +55 -0
  397. package/pack/generated/pi/skills/rite-explain/SKILL.md +152 -0
  398. package/pack/generated/pi/skills/rite-explain/reference/intake.md +89 -0
  399. package/pack/generated/pi/skills/rite-frame/SKILL.md +115 -0
  400. package/pack/generated/pi/skills/rite-frame/reference/failure-modes.md +66 -0
  401. package/pack/generated/pi/skills/rite-handoff/SKILL.md +97 -0
  402. package/pack/generated/pi/skills/rite-handoff/reference/handoff-template.md +44 -0
  403. package/pack/generated/pi/skills/rite-learn/SKILL.md +72 -0
  404. package/pack/generated/pi/skills/rite-plan/SKILL.md +186 -0
  405. package/pack/generated/pi/skills/rite-plan/reference/anti-patterns.md +34 -0
  406. package/pack/generated/pi/skills/rite-plan/reference/dependency-graph.md +48 -0
  407. package/pack/generated/pi/skills/rite-plan/reference/replan-and-repair.md +105 -0
  408. package/pack/generated/pi/skills/rite-plan/reference/slicing.md +167 -0
  409. package/pack/generated/pi/skills/rite-plan/reference/task-breakdown.md +42 -0
  410. package/pack/generated/pi/skills/rite-polish/SKILL.md +104 -0
  411. package/pack/generated/pi/skills/rite-polish/reference/adr-promotion.md +11 -0
  412. package/pack/generated/pi/skills/rite-polish/reference/anti-ai-slop.md +187 -0
  413. package/pack/generated/pi/skills/rite-polish/reference/anti-patterns.md +30 -0
  414. package/pack/generated/pi/skills/rite-polish/reference/backend-polish.md +80 -0
  415. package/pack/generated/pi/skills/rite-polish/reference/browser-polish-evidence.md +33 -0
  416. package/pack/generated/pi/skills/rite-polish/reference/code.md +82 -0
  417. package/pack/generated/pi/skills/rite-polish/reference/design-memory.md +117 -0
  418. package/pack/generated/pi/skills/rite-polish/reference/design-system-discovery.md +8 -0
  419. package/pack/generated/pi/skills/rite-polish/reference/harden-checklist.md +109 -0
  420. package/pack/generated/pi/skills/rite-polish/reference/ledger.md +65 -0
  421. package/pack/generated/pi/skills/rite-polish/reference/ui.md +137 -0
  422. package/pack/generated/pi/skills/rite-pov/SKILL.md +58 -0
  423. package/pack/generated/pi/skills/rite-pr-feedback/SKILL.md +54 -0
  424. package/pack/generated/pi/skills/rite-pressure-test/SKILL.md +67 -0
  425. package/pack/generated/pi/skills/rite-prototype/SKILL.md +104 -0
  426. package/pack/generated/pi/skills/rite-prove/SKILL.md +120 -0
  427. package/pack/generated/pi/skills/rite-prove/reference/acceptance-proof.md +88 -0
  428. package/pack/generated/pi/skills/rite-prove/reference/anti-patterns.md +25 -0
  429. package/pack/generated/pi/skills/rite-prove/reference/browser-proof.md +51 -0
  430. package/pack/generated/pi/skills/rite-prove/reference/failure-triage.md +43 -0
  431. package/pack/generated/pi/skills/rite-prove/reference/proof-ladder.md +28 -0
  432. package/pack/generated/pi/skills/rite-prove/reference/test-command-discovery.md +30 -0
  433. package/pack/generated/pi/skills/rite-quick/SKILL.md +82 -0
  434. package/pack/generated/pi/skills/rite-resolve/SKILL.md +95 -0
  435. package/pack/generated/pi/skills/rite-resolve/reference/answer-protocol.md +118 -0
  436. package/pack/generated/pi/skills/rite-review/SKILL.md +170 -0
  437. package/pack/generated/pi/skills/rite-review/reference/anti-patterns.md +32 -0
  438. package/pack/generated/pi/skills/rite-review/reference/cognitive-load.md +90 -0
  439. package/pack/generated/pi/skills/rite-review/reference/feature-scoped-review.md +26 -0
  440. package/pack/generated/pi/skills/rite-review/reference/five-axis-review.md +66 -0
  441. package/pack/generated/pi/skills/rite-review/reference/nielsen-heuristics.md +126 -0
  442. package/pack/generated/pi/skills/rite-review/reference/performance-checklist.md +80 -0
  443. package/pack/generated/pi/skills/rite-review/reference/performance-review.md +14 -0
  444. package/pack/generated/pi/skills/rite-review/reference/security-review.md +42 -0
  445. package/pack/generated/pi/skills/rite-seal/SKILL.md +75 -0
  446. package/pack/generated/pi/skills/rite-seal/reference/anti-patterns.md +29 -0
  447. package/pack/generated/pi/skills/rite-seal/reference/final-evidence.md +41 -0
  448. package/pack/generated/pi/skills/rite-seal/reference/go-no-go.md +29 -0
  449. package/pack/generated/pi/skills/rite-seal/reference/output.md +5 -0
  450. package/pack/generated/pi/skills/rite-seal/reference/phase-contract.md +47 -0
  451. package/pack/generated/pi/skills/rite-seal/reference/risk-and-rollback.md +56 -0
  452. package/pack/generated/pi/skills/rite-seal/reference/seal-template.md +27 -0
  453. package/pack/generated/pi/skills/rite-ship/SKILL.md +88 -0
  454. package/pack/generated/pi/skills/rite-ship/reference/anti-patterns.md +28 -0
  455. package/pack/generated/pi/skills/rite-ship/reference/close-out.md +68 -0
  456. package/pack/generated/pi/skills/rite-ship/reference/git-ship.md +120 -0
  457. package/pack/generated/pi/skills/rite-ship/reference/rollout.md +62 -0
  458. package/pack/generated/pi/skills/rite-ship/reference/ship-template.md +39 -0
  459. package/pack/generated/pi/skills/rite-spec/SKILL.md +150 -0
  460. package/pack/generated/pi/skills/rite-spec/reference/acceptance-criteria.md +31 -0
  461. package/pack/generated/pi/skills/rite-spec/reference/ai-spec-template.md +40 -0
  462. package/pack/generated/pi/skills/rite-spec/reference/anti-patterns.md +27 -0
  463. package/pack/generated/pi/skills/rite-spec/reference/interview-patterns.md +56 -0
  464. package/pack/generated/pi/skills/rite-spec/reference/investigation.md +83 -0
  465. package/pack/generated/pi/skills/rite-spec/reference/question-protocol.md +36 -0
  466. package/pack/generated/pi/skills/rite-spec/reference/references-intake.md +62 -0
  467. package/pack/generated/pi/skills/rite-spec/reference/spec-checklists.md +89 -0
  468. package/pack/generated/pi/skills/rite-spec/reference/spec-template.md +154 -0
  469. package/pack/generated/pi/skills/rite-spec/reference/state-workspace.md +227 -0
  470. package/pack/generated/pi/skills/rite-status/SKILL.md +57 -0
  471. package/pack/generated/pi/skills/rite-temper/SKILL.md +130 -0
  472. package/pack/generated/pi/skills/rite-temper/reference/anti-patterns.md +30 -0
  473. package/pack/generated/pi/skills/rite-temper/reference/review-dimensions.md +66 -0
  474. package/pack/generated/pi/skills/rite-temper/reference/scope-modes.md +53 -0
  475. package/pack/generated/pi/skills/rite-temper/reference/significance.md +46 -0
  476. package/pack/generated/pi/skills/rite-temper/reference/strategy-template.md +90 -0
  477. package/pack/generated/pi/skills/rite-upgrade/SKILL.md +121 -0
  478. package/pack/generated/pi/skills/rite-vet/SKILL.md +193 -0
  479. package/pack/generated/pi/skills/rite-vet/reference/anti-patterns.md +43 -0
  480. package/pack/generated/pi/skills/rite-vet/reference/artifacts.md +202 -0
  481. package/pack/generated/pi/skills/rite-vet/reference/cross-model.md +19 -0
  482. package/pack/generated/pi/skills/rite-vet/reference/depth.md +59 -0
  483. package/pack/generated/pi/skills/rite-vet/reference/eng-lenses.md +48 -0
  484. package/pack/generated/pi/skills/rite-vet/reference/review-axes.md +201 -0
  485. package/pack/generated/pi/skills/rite-watch-pr/SKILL.md +85 -0
  486. package/pack/generated/pi/skills/rite-zoom-out/SKILL.md +69 -0
  487. package/package.json +3 -2
  488. package/scripts/build-host-artifacts.sh +54 -4
  489. package/scripts/codex-generate.sh +6 -0
  490. package/scripts/pi-generate.sh +198 -0
@@ -24,6 +24,7 @@ func (r *runner) install() error {
24
24
  fmt.Fprintf(r.opts.Stdout, " agents : %s\n", yesno(r.opts.WithAgents))
25
25
  fmt.Fprintf(r.opts.Stdout, " codex : %s\n", yesno(r.opts.WithCodex))
26
26
  fmt.Fprintf(r.opts.Stdout, " omp : %s\n", yesno(r.opts.WithOmp))
27
+ fmt.Fprintf(r.opts.Stdout, " pi : %s\n", yesno(r.opts.WithPi))
27
28
  fmt.Fprintf(r.opts.Stdout, " aliases: %s\n", r.opts.AliasMode)
28
29
  if r.opts.DryRun {
29
30
  fmt.Fprintln(r.opts.Stdout, " (dry run - no changes will be made)")
@@ -38,7 +39,7 @@ func (r *runner) install() error {
38
39
  return err
39
40
  }
40
41
 
41
- for _, tree := range hostpack.InstallTrees(r.opts.WithSkills, r.opts.WithAgents, r.opts.WithCodex, r.opts.WithOmp) {
42
+ for _, tree := range hostpack.InstallTrees(r.opts.WithSkills, r.opts.WithAgents, r.opts.WithCodex, r.opts.WithOmp, r.opts.WithPi) {
42
43
  if err := r.installTree(tree.PayloadPrefix, tree.TargetPrefix); err != nil {
43
44
  return fmt.Errorf("install tree %s: %w", tree.TargetPrefix, err)
44
45
  }
@@ -49,7 +50,7 @@ func (r *runner) install() error {
49
50
  if err != nil {
50
51
  return fmt.Errorf("render alias skill %s: %w", alias.Name, err)
51
52
  }
52
- for _, rel := range hostpack.AliasTargets(alias, r.opts.WithCodex, r.opts.WithOmp) {
53
+ for _, rel := range hostpack.AliasTargets(alias, r.opts.WithCodex, r.opts.WithOmp, r.opts.WithPi) {
53
54
  if err := r.installData(data, rel); err != nil {
54
55
  return fmt.Errorf("install alias: %w", err)
55
56
  }
@@ -64,6 +65,11 @@ func (r *runner) install() error {
64
65
  return fmt.Errorf("merge %s: %w", hostpack.CodexConfigMerge.TargetRel, err)
65
66
  }
66
67
  }
68
+ if r.opts.WithSkills && r.opts.WithPi {
69
+ if err := r.mergeMarkerFile(hostpack.PiAgentsMerge); err != nil {
70
+ return fmt.Errorf("merge %s: %w", hostpack.PiAgentsMerge.TargetRel, err)
71
+ }
72
+ }
67
73
  if r.opts.WithSkills {
68
74
  if err := r.seedClaudeSettings(); err != nil {
69
75
  return fmt.Errorf("seed claude settings: %w", err)
@@ -93,11 +99,11 @@ func (r *runner) install() error {
93
99
  fmt.Fprintf(r.opts.Stdout, " installed: %d overwritten: %d skipped(conflict): %d pruned: %d\n", r.stats.installed, r.stats.overwrote, r.stats.skipped, r.stats.pruned)
94
100
  if !r.opts.DryRun && r.opts.WithSkills {
95
101
  switch {
96
- case r.opts.WithCodex && r.opts.WithOmp:
97
- fmt.Fprintln(r.opts.Stdout, "Next: reopen the project, then run /rite (Claude) or $rite (Codex) or /skill:rite.")
102
+ case r.opts.WithCodex && (r.opts.WithOmp || r.opts.WithPi):
103
+ fmt.Fprintln(r.opts.Stdout, "Next: reopen the project, then run /rite (Claude) or $rite (Codex) or /skill:rite (omp/pi).")
98
104
  case r.opts.WithCodex:
99
105
  fmt.Fprintln(r.opts.Stdout, "Next: reopen the project, then run /rite (Claude) or $rite (Codex).")
100
- case r.opts.WithOmp:
106
+ case r.opts.WithOmp || r.opts.WithPi:
101
107
  fmt.Fprintln(r.opts.Stdout, "Next: reopen the project, then run /rite or /skill:rite.")
102
108
  default:
103
109
  fmt.Fprintln(r.opts.Stdout, "Next: reopen the project, then run /rite.")
@@ -311,6 +317,9 @@ func (r *runner) flagsString() string {
311
317
  if !r.opts.WithOmp {
312
318
  flags = append(flags, "--no-omp")
313
319
  }
320
+ if !r.opts.WithPi {
321
+ flags = append(flags, "--no-pi")
322
+ }
314
323
  if !r.opts.WithBinary {
315
324
  flags = append(flags, "--no-binary")
316
325
  }
@@ -35,6 +35,7 @@ type Options struct {
35
35
  WithAgents bool
36
36
  WithCodex bool
37
37
  WithOmp bool
38
+ WithPi bool
38
39
  WithBinary bool
39
40
  KeepBinary bool
40
41
  AliasMode string
@@ -84,6 +85,7 @@ func DefaultOptions(mode Mode) Options {
84
85
  WithAgents: true,
85
86
  WithCodex: true,
86
87
  WithOmp: true,
88
+ WithPi: true,
87
89
  WithBinary: true,
88
90
  AliasMode: "safe",
89
91
  Stdout: io.Discard,
@@ -135,6 +137,7 @@ func parseArgs(args []string, opts *Options) error {
135
137
  force := flags.Bool("force", opts.Force, "")
136
138
  noCodex := flags.Bool("no-codex", !opts.WithCodex, "")
137
139
  noOmp := flags.Bool("no-omp", !opts.WithOmp, "")
140
+ noPi := flags.Bool("no-pi", !opts.WithPi, "")
138
141
  noAgents := flags.Bool("no-agents", !opts.WithAgents, "")
139
142
  noSkills := flags.Bool("no-skills", !opts.WithSkills, "")
140
143
  noBinary := flags.Bool("no-binary", !opts.WithBinary, "")
@@ -162,6 +165,7 @@ func parseArgs(args []string, opts *Options) error {
162
165
  opts.Force = *force
163
166
  opts.WithCodex = !*noCodex
164
167
  opts.WithOmp = !*noOmp
168
+ opts.WithPi = !*noPi
165
169
  opts.WithAgents = !*noAgents
166
170
  opts.WithSkills = !*noSkills
167
171
  opts.WithBinary = !*noBinary
@@ -208,7 +212,7 @@ func usage(mode Mode) string {
208
212
  case ModeUpdate:
209
213
  return "usage: devrites-engine update [--target DIR] [--dry-run] [--force] [--check] [install flags] [--source-dir DIR --payload-dir DIR]\n"
210
214
  default:
211
- return "usage: devrites-engine install [--target DIR] [--dry-run] [--force] [--no-codex] [--no-omp] [--no-agents] [--no-skills] [--no-binary] [--short-aliases=all]\n"
215
+ return "usage: devrites-engine install [--target DIR] [--dry-run] [--force] [--no-codex] [--no-omp] [--no-pi] [--no-agents] [--no-skills] [--no-binary] [--short-aliases=all]\n"
212
216
  }
213
217
  }
214
218
 
@@ -333,7 +337,7 @@ func (r *runner) validatePayload() error {
333
337
  if r.payload == "" {
334
338
  return fmt.Errorf("generated install payload not found; pass --payload-dir or run scripts/build-host-artifacts.sh")
335
339
  }
336
- if err := hostpack.ValidatePayload(r.payloadFS, r.opts.WithCodex, r.opts.WithOmp); err != nil {
340
+ if err := hostpack.ValidatePayload(r.payloadFS, r.opts.WithCodex, r.opts.WithOmp, r.opts.WithPi); err != nil {
337
341
  return fmt.Errorf("generated install payload under %s: %w", r.payload, err)
338
342
  }
339
343
  return nil
@@ -349,6 +353,8 @@ func isGlobalTarget(target string) bool {
349
353
  filepath.Join(home, ".codex"),
350
354
  filepath.Join(home, ".omp"),
351
355
  filepath.Join(home, ".omp", "agent"),
356
+ filepath.Join(home, ".pi"),
357
+ filepath.Join(home, ".pi", "agent"),
352
358
  } {
353
359
  if target == global || strings.HasPrefix(target, global+string(os.PathSeparator)) {
354
360
  return true
@@ -53,12 +53,14 @@ func TestInstallPrintsFirstMoveForInstalledHosts(t *testing.T) {
53
53
  name string
54
54
  withCodex bool
55
55
  withOmp bool
56
+ withPi bool
56
57
  want string
57
58
  }{
58
- {name: "Claude, Codex, and OMP", withCodex: true, withOmp: true, want: "Next: reopen the project, then run /rite (Claude) or $rite (Codex) or /skill:rite."},
59
- {name: "Claude and Codex", withCodex: true, withOmp: false, want: "Next: reopen the project, then run /rite (Claude) or $rite (Codex)."},
60
- {name: "Claude and OMP", withCodex: false, withOmp: true, want: "Next: reopen the project, then run /rite or /skill:rite."},
61
- {name: "Claude only", withCodex: false, withOmp: false, want: "Next: reopen the project, then run /rite."},
59
+ {name: "Claude, Codex, and OMP", withCodex: true, withOmp: true, want: "Next: reopen the project, then run /rite (Claude) or $rite (Codex) or /skill:rite (omp/pi)."},
60
+ {name: "Claude and Codex", withCodex: true, withOmp: false, withPi: false, want: "Next: reopen the project, then run /rite (Claude) or $rite (Codex)."},
61
+ {name: "Claude and OMP", withCodex: false, withOmp: true, withPi: false, want: "Next: reopen the project, then run /rite or /skill:rite."},
62
+ {name: "Claude and pi", withCodex: false, withOmp: false, withPi: true, want: "Next: reopen the project, then run /rite or /skill:rite."},
63
+ {name: "Claude only", withCodex: false, withOmp: false, withPi: false, want: "Next: reopen the project, then run /rite."},
62
64
  } {
63
65
  t.Run(tc.name, func(t *testing.T) {
64
66
  var out bytes.Buffer
@@ -67,6 +69,7 @@ func TestInstallPrintsFirstMoveForInstalledHosts(t *testing.T) {
67
69
  opts.PayloadDir = testPayload(t)
68
70
  opts.WithCodex = tc.withCodex
69
71
  opts.WithOmp = tc.withOmp
72
+ opts.WithPi = tc.withPi
70
73
  opts.Stdout = &out
71
74
  opts.Stderr = &bytes.Buffer{}
72
75
 
@@ -758,7 +761,7 @@ func TestLegacyCodexHooksMergeIsCleanupOnly(t *testing.T) {
758
761
  if !ok || merge != legacy {
759
762
  t.Fatalf("legacy marker lookup = %#v, %t", merge, ok)
760
763
  }
761
- if slices.Contains(hostpack.RequiredPayload(true, true), "codex/hooks.json") {
764
+ if slices.Contains(hostpack.RequiredPayload(true, true, true), "codex/hooks.json") {
762
765
  t.Fatal("legacy Codex hooks entered the required payload")
763
766
  }
764
767
  r := runner{opts: DefaultOptions(ModeInstall), payloadFS: os.DirFS(testPayload(t))}
@@ -1247,6 +1250,10 @@ extends = ":workspace"
1247
1250
  testutil.WriteFile(t, filepath.Join(root, "omp", "skills", "rite", "SKILL.md"), "omp rite\n")
1248
1251
  testutil.WriteFile(t, filepath.Join(root, "omp", "agents", "devrites-code-reviewer.md"), "omp agent\n")
1249
1252
  testutil.WriteFile(t, filepath.Join(root, "omp", ".omp-plugin", "plugin.json"), "{}\n")
1253
+ testutil.WriteFile(t, filepath.Join(root, "pi", "skills", "rite", "SKILL.md"), "pi rite\n")
1254
+ testutil.WriteFile(t, filepath.Join(root, "pi", "agents", "devrites-code-reviewer.md"), "pi agent\n")
1255
+ testutil.WriteFile(t, filepath.Join(root, "pi", "prompts", "rite.md"), "pi prompt\n")
1256
+ testutil.WriteFile(t, filepath.Join(root, "pi", "AGENTS.md"), "<!-- BEGIN DEVRITES PI -->\nDevRites\n<!-- END DEVRITES PI -->\n")
1250
1257
  }
1251
1258
 
1252
1259
  func testSource(t *testing.T, version string) string {
@@ -63,6 +63,11 @@ func (r *runner) mergeMarkerFile(merge hostpack.MarkerMerge) error {
63
63
  if err := fsutil.WriteFileAtomic(dest, next, 0o644); err != nil {
64
64
  return fmt.Errorf("cannot write %s: %w", merge.TargetRel, err)
65
65
  }
66
+ // Multiple marker blocks can share one target (AGENTS.md carries both
67
+ // the Codex and pi blocks).
68
+ if err := r.refreshPreflight(merge.TargetRel); err != nil {
69
+ return err
70
+ }
66
71
  }
67
72
  return r.installMarker(merge.MarkerRel, merge.MarkerText)
68
73
  }
@@ -93,7 +93,7 @@ func (r *runner) preflightUninstall(entries []string) error {
93
93
 
94
94
  func (r *runner) desiredInstallPaths() (map[string]bool, error) {
95
95
  out := map[string]bool{".devrites/README.md": true}
96
- for _, tree := range hostpack.InstallTrees(r.opts.WithSkills, r.opts.WithAgents, r.opts.WithCodex, r.opts.WithOmp) {
96
+ for _, tree := range hostpack.InstallTrees(r.opts.WithSkills, r.opts.WithAgents, r.opts.WithCodex, r.opts.WithOmp, r.opts.WithPi) {
97
97
  err := fs.WalkDir(r.payloadFS, tree.PayloadPrefix, func(path string, d fs.DirEntry, err error) error {
98
98
  if err != nil {
99
99
  return err
@@ -114,7 +114,7 @@ func (r *runner) desiredInstallPaths() (map[string]bool, error) {
114
114
  }
115
115
  if r.opts.WithSkills && r.opts.AliasMode == "all" {
116
116
  for _, alias := range hostpack.Aliases {
117
- for _, rel := range hostpack.AliasTargets(alias, r.opts.WithCodex, r.opts.WithOmp) {
117
+ for _, rel := range hostpack.AliasTargets(alias, r.opts.WithCodex, r.opts.WithOmp, r.opts.WithPi) {
118
118
  out[rel] = true
119
119
  }
120
120
  }
@@ -123,6 +123,9 @@ func (r *runner) desiredInstallPaths() (map[string]bool, error) {
123
123
  out[hostpack.CodexAgentsMerge.MarkerRel] = true
124
124
  out[hostpack.CodexConfigMerge.MarkerRel] = true
125
125
  }
126
+ if r.opts.WithSkills && r.opts.WithPi {
127
+ out[hostpack.PiAgentsMerge.MarkerRel] = true
128
+ }
126
129
  if r.opts.WithSkills {
127
130
  out[hostpack.ClaudeSettingsMerge.MarkerRel] = true
128
131
  }
@@ -136,6 +139,9 @@ func (r *runner) installMergeTargets() []string {
136
139
  if r.opts.WithCodex {
137
140
  out = append(out, hostpack.CodexAgentsMerge.TargetRel, hostpack.CodexConfigMerge.TargetRel)
138
141
  }
142
+ if r.opts.WithPi {
143
+ out = append(out, hostpack.PiAgentsMerge.TargetRel)
144
+ }
139
145
  }
140
146
  return out
141
147
  }
@@ -153,6 +159,18 @@ func (r *runner) rememberPath(rel string) (pathSnapshot, error) {
153
159
  return snapshot, nil
154
160
  }
155
161
 
162
+ // refreshPreflight replaces a recorded snapshot after the runner's own
163
+ // verified write (marker merge, strip). Needed when several managed merges
164
+ // share one target such as AGENTS.md.
165
+ func (r *runner) refreshPreflight(rel string) error {
166
+ snap, err := inspectManagedPath(r.target, rel)
167
+ if err != nil {
168
+ return err
169
+ }
170
+ r.preflight[filepath.ToSlash(rel)] = snap
171
+ return nil
172
+ }
173
+
156
174
  func (r *runner) recheckPath(rel string) error {
157
175
  rel = filepath.ToSlash(rel)
158
176
  before, ok := r.preflight[rel]
@@ -58,6 +58,11 @@ func (r *runner) uninstall() error {
58
58
  if err := stripMarkerPath(filepath.Join(r.target, filepath.FromSlash(merge.TargetRel)), merge.Begin, merge.End); err != nil {
59
59
  return fmt.Errorf("strip marker block from %s: %w", merge.TargetRel, err)
60
60
  }
61
+ // The Codex and pi AGENTS.md blocks share one target; record the strip
62
+ // so the next merge's recheckPath sees our own write, not a race.
63
+ if err := r.refreshPreflight(merge.TargetRel); err != nil {
64
+ return err
65
+ }
61
66
  }
62
67
 
63
68
  var dirs []string
@@ -65,7 +65,7 @@ func runUpdate(opts Options) error {
65
65
  if err != nil {
66
66
  return fmt.Errorf("resolve payload %s: %w", opts.PayloadDir, err)
67
67
  }
68
- if err := hostpack.ValidatePayload(os.DirFS(payload), true, true); err != nil {
68
+ if err := hostpack.ValidatePayload(os.DirFS(payload), true, true, true); err != nil {
69
69
  return fmt.Errorf("local update payload under %s is invalid: %w", payload, err)
70
70
  }
71
71
  installFlags := manifestHeader(mf, "devrites-flags")
@@ -33,6 +33,8 @@ const (
33
33
  type candidateRow struct {
34
34
  state string
35
35
  path string
36
+ slice string
37
+ reason string
36
38
  executable bool
37
39
  size int64
38
40
  info os.FileInfo
@@ -203,10 +205,12 @@ func parseCandidateManifest(raw []byte) ([]candidateRow, error) {
203
205
  if err != nil {
204
206
  return nil, fmt.Errorf("row %d File: %w", i+1, err)
205
207
  }
206
- if strings.TrimSpace(cells[3]) == "" {
208
+ sliceCell := strings.TrimSpace(cells[3])
209
+ if sliceCell == "" {
207
210
  return nil, fmt.Errorf("row %d Slice must be nonempty", i+1)
208
211
  }
209
- if strings.TrimSpace(cells[4]) == "" {
212
+ reasonCell := strings.TrimSpace(cells[4])
213
+ if reasonCell == "" {
210
214
  return nil, fmt.Errorf("row %d Reason must be nonempty", i+1)
211
215
  }
212
216
  if _, ok := seen[normalized]; ok {
@@ -221,7 +225,7 @@ func parseCandidateManifest(raw []byte) ([]candidateRow, error) {
221
225
  }
222
226
  seen[normalized] = struct{}{}
223
227
  seenFolded[folded] = normalized
224
- rows = append(rows, candidateRow{state: state, path: normalized})
228
+ rows = append(rows, candidateRow{state: state, path: normalized, slice: sliceCell, reason: reasonCell})
225
229
  if len(rows) > maxCandidateRows {
226
230
  return nil, errors.New("manifest exceeds 4096 rows")
227
231
  }
@@ -0,0 +1,326 @@
1
+ package lib
2
+
3
+ import (
4
+ "errors"
5
+ "fmt"
6
+ "io"
7
+ "os"
8
+ "path/filepath"
9
+ "sort"
10
+ "strings"
11
+
12
+ "github.com/devrites/devrites/internal/devritespaths"
13
+ "github.com/devrites/devrites/internal/state"
14
+ )
15
+
16
+ // maxSequenceChain bounds the sequence_parent walk so a malformed cycle cannot
17
+ // loop forever; real chains are far smaller.
18
+ const maxSequenceChain = 64
19
+
20
+ // RunMergeManifest folds predecessor candidate manifests into the release
21
+ // workspace's `## Candidate manifest` so a release milestone's prove/review/seal
22
+ // binds the union surface instead of only its own slices. On a path collision
23
+ // the later sequence position's row wins (it records the most recent touch).
24
+ // Everything outside the manifest section of the release workspace's
25
+ // touched-files.md is preserved.
26
+ //
27
+ // args is `<slug>` to walk the recorded `sequence_parent` chain, or
28
+ // `<slug> <predecessor> [<predecessor>...]` for an explicit ordered list —
29
+ // required for chains recorded before the sequence cursor fields existed.
30
+ // Exit codes:
31
+ //
32
+ // 0 merged and written
33
+ // 2 usage error
34
+ // 3 blocked: a workspace, manifest, or chain check failed
35
+ // 1 internal/IO error
36
+ func RunMergeManifest(root string, args []string, stdout, stderr io.Writer) int {
37
+ if len(args) < 1 {
38
+ fmt.Fprintln(stderr, "usage: devrites-engine state merge-manifest <slug> [<predecessor>...]")
39
+ return 2
40
+ }
41
+ slug := args[0]
42
+ workspace, err := devritespaths.ExistingFeatureDirChecked(root, slug)
43
+ if err != nil {
44
+ fmt.Fprintf(stderr, "merge-manifest: BLOCKED: workspace for %s: %v\n", slug, err)
45
+ return 3
46
+ }
47
+ if err := state.RequireWorkspaceSchema(root, slug); err != nil {
48
+ fmt.Fprintf(stderr, "merge-manifest: BLOCKED: %v\n", err)
49
+ return 3
50
+ }
51
+ manifestPath := filepath.Join(workspace, "touched-files.md")
52
+ releaseRaw, err := readBoundedRegularFile(manifestPath, maxCandidateManifestBytes)
53
+ if err != nil {
54
+ fmt.Fprintf(stderr, "merge-manifest: BLOCKED: candidate manifest %s: %v\n", manifestPath, err)
55
+ return 3
56
+ }
57
+
58
+ var manifests [][]candidateRow
59
+ if len(args) > 1 {
60
+ manifests, err = explicitManifests(root, slug, args[1:])
61
+ } else {
62
+ // The walked chain is validated inside walkSequenceChain; only its
63
+ // manifests feed the union.
64
+ _, manifests, err = walkSequenceChain(root, slug, workspace)
65
+ }
66
+ if err != nil {
67
+ fmt.Fprintf(stderr, "merge-manifest: BLOCKED: %v\n", err)
68
+ return 3
69
+ }
70
+
71
+ merged := make(map[string]candidateRow)
72
+ collisions := 0
73
+ fold := func(rows []candidateRow) {
74
+ for _, row := range rows {
75
+ if _, dup := merged[row.path]; dup {
76
+ collisions++
77
+ }
78
+ merged[row.path] = row
79
+ }
80
+ }
81
+ for _, rows := range manifests {
82
+ fold(rows)
83
+ }
84
+ releaseRows, err := parseCandidateManifest(releaseRaw)
85
+ if err != nil {
86
+ fmt.Fprintf(stderr, "merge-manifest: BLOCKED: candidate manifest %s: %v\n", manifestPath, err)
87
+ return 3
88
+ }
89
+ fold(releaseRows)
90
+
91
+ paths := make([]string, 0, len(merged))
92
+ for path := range merged {
93
+ paths = append(paths, path)
94
+ }
95
+ sort.Strings(paths)
96
+ body := make([]string, 0, len(paths)+2)
97
+ if len(paths) == 0 {
98
+ body = append(body, "No project files.")
99
+ } else {
100
+ body = append(body, "| State | File | Slice | Reason |", "| --- | --- | --- | --- |")
101
+ for _, path := range paths {
102
+ row := merged[path]
103
+ body = append(body, fmt.Sprintf("| %s | `%s` | %s | %s |", row.state, row.path, row.slice, row.reason))
104
+ }
105
+ }
106
+ updated, err := replaceManifestSectionBody(releaseRaw, body)
107
+ if err != nil {
108
+ fmt.Fprintf(stderr, "merge-manifest: BLOCKED: candidate manifest %s: %v\n", manifestPath, err)
109
+ return 3
110
+ }
111
+ if err := state.AtomicWrite(manifestPath, updated, 0o644); err != nil {
112
+ fmt.Fprintf(stderr, "merge-manifest: cannot write %s: %v\n", manifestPath, err)
113
+ return 1
114
+ }
115
+ fmt.Fprintf(stdout, "merge-manifest: merged %d manifest(s) into %d row(s)", len(manifests)+1, len(paths))
116
+ if collisions > 0 {
117
+ fmt.Fprintf(stdout, " (%d path collision(s), later position kept)", collisions)
118
+ }
119
+ fmt.Fprintln(stdout)
120
+ return 0
121
+ }
122
+
123
+ // explicitManifests parses the caller-ordered predecessor list. When the
124
+ // workspace carries a sequence_parent cursor, the last predecessor must be the
125
+ // recorded parent; a mismatch means the list does not describe this chain.
126
+ func explicitManifests(root, slug string, predecessors []string) ([][]candidateRow, error) {
127
+ seen := make(map[string]struct{}, len(predecessors))
128
+ for _, pred := range predecessors {
129
+ if pred == slug {
130
+ return nil, fmt.Errorf("predecessor %q names the target workspace", pred)
131
+ }
132
+ if _, dup := seen[pred]; dup {
133
+ return nil, fmt.Errorf("duplicate predecessor %q", pred)
134
+ }
135
+ seen[pred] = struct{}{}
136
+ }
137
+ if parent := sequenceParent(root, slug); parent != "" && parent != predecessors[len(predecessors)-1] {
138
+ return nil, fmt.Errorf("%s records sequence_parent %q; pass the full ordered predecessor list ending with it (or no list to walk the recorded chain)", slug, parent)
139
+ }
140
+ manifests := make([][]candidateRow, 0, len(predecessors))
141
+ for _, pred := range predecessors {
142
+ rows, err := predecessorManifestRows(root, pred)
143
+ if err != nil {
144
+ return nil, fmt.Errorf("predecessor %s: %w", pred, err)
145
+ }
146
+ manifests = append(manifests, rows)
147
+ }
148
+ return manifests, nil
149
+ }
150
+
151
+ // walkSequenceChain follows the target workspace's sequence_parent links to the
152
+ // chain head, returning predecessors oldest-first with their manifests. Every
153
+ // link must resolve to a live or archived workspace carrying the cursor field;
154
+ // a broken link refuses the merge rather than producing a partial union.
155
+ func walkSequenceChain(root, slug, workspace string) ([]string, [][]candidateRow, error) {
156
+ visited := map[string]struct{}{slug: {}}
157
+ chain := []string{}
158
+ manifests := [][]candidateRow{}
159
+ dir := workspace
160
+ for len(chain) < maxSequenceChain {
161
+ raw, err := readBoundedRegularFile(filepath.Join(dir, "state.md"), maxCandidateManifestBytes)
162
+ if err != nil {
163
+ return nil, nil, fmt.Errorf("%s state.md: %w", filepath.Base(dir), err)
164
+ }
165
+ parent, _ := state.CursorField(strings.Split(string(raw), "\n"), state.CursorSequenceParent)
166
+ if parent == "" {
167
+ break
168
+ }
169
+ if _, dup := visited[parent]; dup {
170
+ return nil, nil, fmt.Errorf("sequence_parent cycle at %q", parent)
171
+ }
172
+ visited[parent] = struct{}{}
173
+ rows, err := predecessorManifestRows(root, parent)
174
+ if err != nil {
175
+ return nil, nil, fmt.Errorf("sequence_parent %s: %w", parent, err)
176
+ }
177
+ dir, err = devritespaths.ExistingFeatureDirChecked(root, parent)
178
+ if errors.Is(err, os.ErrNotExist) {
179
+ dir, err = devritespaths.ExistingArchivedFeatureDirChecked(root, parent)
180
+ }
181
+ if err != nil {
182
+ return nil, nil, fmt.Errorf("sequence_parent %s: %w", parent, err)
183
+ }
184
+ chain = append(chain, parent)
185
+ manifests = append(manifests, rows)
186
+ }
187
+ if len(chain) == 0 {
188
+ return nil, nil, fmt.Errorf("%s has no sequence_parent; pass an explicit ordered predecessor list", slug)
189
+ }
190
+ for i, j := 0, len(chain)-1; i < j; i, j = i+1, j-1 {
191
+ chain[i], chain[j] = chain[j], chain[i]
192
+ manifests[i], manifests[j] = manifests[j], manifests[i]
193
+ }
194
+ return chain, manifests, nil
195
+ }
196
+
197
+ func sequenceParent(root, slug string) string {
198
+ dir, err := devritespaths.ExistingFeatureDirChecked(root, slug)
199
+ if err != nil {
200
+ return ""
201
+ }
202
+ raw, err := readBoundedRegularFile(filepath.Join(dir, "state.md"), maxCandidateManifestBytes)
203
+ if err != nil {
204
+ return ""
205
+ }
206
+ parent, _ := state.CursorField(strings.Split(string(raw), "\n"), state.CursorSequenceParent)
207
+ return parent
208
+ }
209
+
210
+ // VerifyReleaseUnion enforces the release-milestone contract at the candidate
211
+ // and seal gates: a workspace whose cursor declares `sequence_role: release`
212
+ // must carry a candidate manifest covering every predecessor in its recorded
213
+ // `sequence_parent` chain. Workspaces without the role are unaffected.
214
+ func VerifyReleaseUnion(root, slug string) error {
215
+ dir, err := devritespaths.ExistingFeatureDirChecked(root, slug)
216
+ if err != nil {
217
+ return fmt.Errorf("workspace for %s: %w", slug, err)
218
+ }
219
+ raw, err := readBoundedRegularFile(filepath.Join(dir, "state.md"), maxCandidateManifestBytes)
220
+ if errors.Is(err, os.ErrNotExist) {
221
+ return nil // no state.md: nothing declares the release role
222
+ }
223
+ if err != nil {
224
+ return fmt.Errorf("%s state.md: %w", slug, err)
225
+ }
226
+ role, _ := state.CursorField(strings.Split(string(raw), "\n"), state.CursorSequenceRole)
227
+ if role != "release" {
228
+ return nil
229
+ }
230
+ _, manifests, err := walkSequenceChain(root, slug, dir)
231
+ if err != nil {
232
+ return err
233
+ }
234
+ manifestRaw, err := readBoundedRegularFile(filepath.Join(dir, "touched-files.md"), maxCandidateManifestBytes)
235
+ if err != nil {
236
+ return fmt.Errorf("candidate manifest: %w", err)
237
+ }
238
+ rows, err := parseCandidateManifest(manifestRaw)
239
+ if err != nil {
240
+ return fmt.Errorf("candidate manifest: %w", err)
241
+ }
242
+ declared := make(map[string]struct{}, len(rows))
243
+ for _, row := range rows {
244
+ declared[row.path] = struct{}{}
245
+ }
246
+ var missing []string
247
+ for _, ancestor := range manifests {
248
+ for _, row := range ancestor {
249
+ if _, ok := declared[row.path]; !ok {
250
+ missing = append(missing, row.path)
251
+ }
252
+ }
253
+ }
254
+ if len(missing) > 0 {
255
+ sort.Strings(missing)
256
+ const show = 8
257
+ list := missing
258
+ if len(list) > show {
259
+ list = append(append([]string(nil), missing[:show]...), fmt.Sprintf("…and %d more", len(missing)-show))
260
+ }
261
+ return fmt.Errorf("release manifest does not cover the recorded sequence chain; run `devrites-engine state merge-manifest %s`. Missing: %s", slug, strings.Join(list, ", "))
262
+ }
263
+ return nil
264
+ }
265
+
266
+ // predecessorManifestRows loads the candidate manifest of a sealed or archived
267
+ // predecessor workspace. Live workspaces win over archive entries so an
268
+ // unshipped sequence member is always found first.
269
+ func predecessorManifestRows(root, slug string) ([]candidateRow, error) {
270
+ dir, err := devritespaths.ExistingFeatureDirChecked(root, slug)
271
+ if errors.Is(err, os.ErrNotExist) {
272
+ dir, err = devritespaths.ExistingArchivedFeatureDirChecked(root, slug)
273
+ }
274
+ if err != nil {
275
+ return nil, fmt.Errorf("no live or archived workspace: %w", err)
276
+ }
277
+ raw, err := readBoundedRegularFile(filepath.Join(dir, "touched-files.md"), maxCandidateManifestBytes)
278
+ if err != nil {
279
+ return nil, fmt.Errorf("candidate manifest: %w", err)
280
+ }
281
+ rows, err := parseCandidateManifest(raw)
282
+ if err != nil {
283
+ return nil, fmt.Errorf("candidate manifest: %w", err)
284
+ }
285
+ return rows, nil
286
+ }
287
+
288
+ // replaceManifestSectionBody rewrites the body of the single
289
+ // `## Candidate manifest` section, keeping every other byte of the file —
290
+ // headings, `## Touched files` narrative, and `## Review trail` — intact.
291
+ func replaceManifestSectionBody(raw []byte, body []string) ([]byte, error) {
292
+ text := string(raw)
293
+ crlf := strings.Contains(text, "\r\n")
294
+ lines := strings.Split(text, "\n")
295
+ start, count := -1, 0
296
+ for i, line := range lines {
297
+ if strings.TrimSpace(line) == "## Candidate manifest" {
298
+ start = i + 1
299
+ count++
300
+ }
301
+ }
302
+ if count != 1 {
303
+ return nil, errors.New("requires exactly one ## Candidate manifest section")
304
+ }
305
+ end := len(lines)
306
+ for i := start; i < len(lines); i++ {
307
+ if strings.HasPrefix(strings.TrimSpace(lines[i]), "## ") {
308
+ end = i
309
+ break
310
+ }
311
+ }
312
+ emitted := append([]string(nil), body...)
313
+ if crlf {
314
+ for i := range emitted {
315
+ emitted[i] += "\r"
316
+ }
317
+ }
318
+ if end < len(lines) {
319
+ emitted = append(emitted, "")
320
+ if crlf {
321
+ emitted[len(emitted)-1] = "\r"
322
+ }
323
+ }
324
+ lines = append(lines[:start], append(emitted, lines[end:]...)...)
325
+ return []byte(strings.Join(lines, "\n")), nil
326
+ }