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,961 +0,0 @@
1
- package state
2
-
3
- import (
4
- "errors"
5
- "io/fs"
6
- "os"
7
- "path/filepath"
8
- "slices"
9
- "strings"
10
- "testing"
11
- )
12
-
13
- func TestWorkspaceObservationInventoryCanonicalArtifactsOnce(t *testing.T) {
14
- root, slug := newObservationWorkspace(t)
15
- wantPaths := []ArtifactPath{
16
- "state.md",
17
- "brief.md",
18
- "spec.md",
19
- "decisions.md",
20
- "assumptions.md",
21
- "questions.md",
22
- "decision-coverage.md",
23
- "architecture.md",
24
- "plan.md",
25
- "tasks.md",
26
- "traceability.md",
27
- "eng-review.md",
28
- "test-plan.md",
29
- "gates.md",
30
- "evidence.md",
31
- "touched-files.md",
32
- "review.md",
33
- "seal.md",
34
- "strategy.md",
35
- "design-brief.md",
36
- "ai-spec.md",
37
- ".devrites/principles.md",
38
- }
39
- for _, path := range wantPaths {
40
- body := []byte("# Artifact\n\nsubstantive content\n")
41
- switch path {
42
- case LedgerFile:
43
- body = []byte("- Phase: build\n")
44
- case ".devrites/principles.md":
45
- body = []byte("root principles\n")
46
- }
47
- writeObservationArtifact(t, root, slug, path, body)
48
- }
49
- writeFile(t, filepath.Join(root, "work", slug, "principles.md"), []byte("workspace principles decoy\n"))
50
- writeFile(t, filepath.Join(root, "work", slug, ".devrites", "principles.md"), []byte("workspace .devrites principles decoy\n"))
51
- physicalRoot, err := filepath.EvalSymlinks(root)
52
- if err != nil {
53
- t.Fatal(err)
54
- }
55
- t.Setenv("DEVRITES_WORKSPACE", filepath.Join(physicalRoot, "work", slug))
56
-
57
- opens := make(map[ArtifactPath]int)
58
- reads := make(map[ArtifactPath]int)
59
- observation, err := observeWorkspace(physicalRoot, slug, func(stage observationStage, path ArtifactPath) error {
60
- switch stage {
61
- case observationBeforeOpen:
62
- opens[path]++
63
- case observationBeforeRead:
64
- reads[path]++
65
- }
66
- return nil
67
- })
68
- if err != nil {
69
- t.Fatal(err)
70
- }
71
- if observation.Slug() != slug {
72
- t.Fatalf("Slug() = %q, want %q", observation.Slug(), slug)
73
- }
74
- facts := observation.Facts()
75
- gotPaths := make([]ArtifactPath, len(facts))
76
- for i, fact := range facts {
77
- gotPaths[i] = fact.Path()
78
- }
79
- if !slices.Equal(gotPaths, wantPaths) {
80
- t.Fatalf("Facts paths = %v, want %v", gotPaths, wantPaths)
81
- }
82
- for _, path := range wantPaths {
83
- if opens[path] != 1 || reads[path] != 1 {
84
- t.Errorf("%s opened/read = %d/%d, want 1/1", path, opens[path], reads[path])
85
- }
86
- }
87
- principles, ok := observation.Fact(".devrites/principles.md")
88
- if !ok || string(principles.Bytes()) != "root principles\n" {
89
- t.Fatalf("root principles fact = (%q, %v), want selected-root principles", principles.Bytes(), ok)
90
- }
91
- }
92
-
93
- func TestWorkspaceObservationPathAcceptsCanonicalRelativeOverride(t *testing.T) {
94
- root, slug := newObservationWorkspace(t)
95
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
96
- physicalRoot, err := filepath.EvalSymlinks(root)
97
- if err != nil {
98
- t.Fatal(err)
99
- }
100
- t.Setenv("DEVRITES_WORKSPACE", filepath.Join(filepath.Base(physicalRoot), "work", slug))
101
-
102
- observation, err := ObserveWorkspace(physicalRoot, slug)
103
- if err != nil {
104
- t.Fatal(err)
105
- }
106
- if observation.Slug() != slug {
107
- t.Fatalf("Slug() = %q, want %q", observation.Slug(), slug)
108
- }
109
- }
110
-
111
- func TestWorkspaceObservationPathRejectsWorkspaceOverrideWhitespace(t *testing.T) {
112
- root, slug := newObservationWorkspace(t)
113
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
114
- physicalRoot, err := filepath.EvalSymlinks(root)
115
- if err != nil {
116
- t.Fatal(err)
117
- }
118
- canonical := filepath.Join(physicalRoot, "work", slug)
119
- tests := []struct {
120
- name string
121
- override string
122
- }{
123
- {name: "leading", override: " " + canonical},
124
- {name: "trailing", override: canonical + " "},
125
- }
126
-
127
- for _, test := range tests {
128
- t.Run(test.name, func(t *testing.T) {
129
- t.Setenv("DEVRITES_WORKSPACE", test.override)
130
- observation, err := ObserveWorkspace(physicalRoot, slug)
131
- if observation != nil {
132
- t.Fatalf("observation = %+v, want nil", observation)
133
- }
134
- assertObservationFailure(t, err, ObservationWorkspaceInvalid, "workspace observation: workspace_invalid: workspace is unavailable; verify the selected logical workspace and canonical workspace override, then retry")
135
- })
136
- }
137
- }
138
-
139
- func TestWorkspaceObservationPathRejectsLeadingParentRelativeOverride(t *testing.T) {
140
- root, slug := newObservationWorkspace(t)
141
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
142
- physicalRoot, err := filepath.EvalSymlinks(root)
143
- if err != nil {
144
- t.Fatal(err)
145
- }
146
- rootParent := filepath.Dir(physicalRoot)
147
- override := filepath.Join("..", filepath.Base(rootParent), filepath.Base(physicalRoot), "work", slug)
148
- if filepath.IsAbs(override) || !strings.HasPrefix(override, ".."+string(filepath.Separator)) {
149
- t.Fatalf("override = %q, want leading-parent relative path", override)
150
- }
151
- if filepath.Clean(override) != override {
152
- t.Fatalf("filepath.Clean(%q) changed fixture", override)
153
- }
154
- if filepath.IsLocal(override) {
155
- t.Fatalf("filepath.IsLocal(%q) = true, want false", override)
156
- }
157
- want := filepath.Join(physicalRoot, "work", slug)
158
- if resolved := filepath.Join(rootParent, override); resolved != want {
159
- t.Fatalf("filepath.Join(%q, %q) = %q, want %q", rootParent, override, resolved, want)
160
- }
161
- t.Setenv("DEVRITES_WORKSPACE", override)
162
-
163
- observation, err := ObserveWorkspace(physicalRoot, slug)
164
- if observation != nil {
165
- t.Fatalf("observation = %+v, want nil", observation)
166
- }
167
- assertObservationFailure(t, err, ObservationWorkspaceInvalid, "workspace observation: workspace_invalid: workspace is unavailable; verify the selected logical workspace and canonical workspace override, then retry")
168
- }
169
-
170
- func TestWorkspaceObservationPathRejectsWorkspaceOverrideAliases(t *testing.T) {
171
- aliases := []struct {
172
- name string
173
- path func(root string) string
174
- }{
175
- {
176
- name: "in-root symlink alias",
177
- path: func(root string) string {
178
- return filepath.Join(root, "work", "alias")
179
- },
180
- },
181
- {
182
- name: "outside-root symlink alias",
183
- path: func(string) string {
184
- return filepath.Join(t.TempDir(), "alias")
185
- },
186
- },
187
- }
188
- overrides := []struct {
189
- name string
190
- path func(t *testing.T, root, slug, alias string) string
191
- }{
192
- {
193
- name: "direct absolute",
194
- path: func(_ *testing.T, _, _, alias string) string {
195
- return alias
196
- },
197
- },
198
- {
199
- name: "wrapped relative",
200
- path: func(t *testing.T, root, slug, alias string) string {
201
- aliasFromRootParent, err := filepath.Rel(filepath.Dir(root), alias)
202
- if err != nil {
203
- t.Fatal(err)
204
- }
205
- targetFromAliasParent, err := filepath.Rel(filepath.Dir(alias), filepath.Join(root, "work", slug))
206
- if err != nil {
207
- t.Fatal(err)
208
- }
209
- separator := string(filepath.Separator)
210
- return aliasFromRootParent + separator + ".." + separator + targetFromAliasParent
211
- },
212
- },
213
- {
214
- name: "wrapped absolute",
215
- path: func(t *testing.T, root, slug, alias string) string {
216
- targetFromAliasParent, err := filepath.Rel(filepath.Dir(alias), filepath.Join(root, "work", slug))
217
- if err != nil {
218
- t.Fatal(err)
219
- }
220
- separator := string(filepath.Separator)
221
- return alias + separator + ".." + separator + targetFromAliasParent
222
- },
223
- },
224
- }
225
-
226
- for _, aliasCase := range aliases {
227
- for _, overrideCase := range overrides {
228
- t.Run(aliasCase.name+"/"+overrideCase.name, func(t *testing.T) {
229
- root, slug := newObservationWorkspace(t)
230
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
231
- physicalRoot, err := filepath.EvalSymlinks(root)
232
- if err != nil {
233
- t.Fatal(err)
234
- }
235
- alias := aliasCase.path(physicalRoot)
236
- if err := os.Symlink(filepath.Join(physicalRoot, "work", slug), alias); err != nil {
237
- t.Fatal(err)
238
- }
239
- aliasInfo, err := os.Lstat(alias)
240
- if err != nil {
241
- t.Fatal(err)
242
- }
243
- if aliasInfo.Mode()&os.ModeSymlink == 0 {
244
- t.Fatalf("alias mode = %v, want symlink", aliasInfo.Mode())
245
- }
246
- t.Setenv("DEVRITES_WORKSPACE", overrideCase.path(t, physicalRoot, slug, alias))
247
-
248
- observation, err := ObserveWorkspace(physicalRoot, slug)
249
- if observation != nil {
250
- t.Fatalf("observation = %+v, want nil", observation)
251
- }
252
- assertObservationFailure(t, err, ObservationWorkspaceInvalid, "workspace observation: workspace_invalid: workspace is unavailable; verify the selected logical workspace and canonical workspace override, then retry")
253
- })
254
- }
255
- }
256
- }
257
-
258
- func TestWorkspaceObservationSymlinkClassifiesRootPrinciplesFinalLink(t *testing.T) {
259
- root, slug := newObservationWorkspace(t)
260
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
261
- target := filepath.Join(t.TempDir(), "principles.md")
262
- writeFile(t, target, []byte("outside principles\n"))
263
- if err := os.Symlink(target, filepath.Join(root, "principles.md")); err != nil {
264
- t.Fatal(err)
265
- }
266
-
267
- observation, err := ObserveWorkspace(root, slug)
268
- if err != nil {
269
- t.Fatal(err)
270
- }
271
- assertArtifactFact(t, observation, ".devrites/principles.md", ArtifactUnsafe, DiagnosticFinalSymlink, nil)
272
- }
273
-
274
- func TestWorkspaceObservationStateClassifiesCodesAndRetention(t *testing.T) {
275
- root, slug := newObservationWorkspace(t)
276
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
277
- writeObservationArtifact(t, root, slug, "spec.md", []byte("# Empty\n\n"))
278
- malformed := []byte("hostile-secret\xff\n")
279
- writeObservationArtifact(t, root, slug, "decisions.md", malformed)
280
-
281
- target := filepath.Join(t.TempDir(), "outside.md")
282
- if err := os.WriteFile(target, []byte("outside\n"), 0o644); err != nil {
283
- t.Fatal(err)
284
- }
285
- if err := os.Symlink(target, observationArtifactPath(root, slug, "assumptions.md")); err != nil {
286
- t.Fatal(err)
287
- }
288
- if err := os.Mkdir(observationArtifactPath(root, slug, "questions.md"), 0o755); err != nil {
289
- t.Fatal(err)
290
- }
291
- writeObservationArtifact(t, root, slug, "decision-coverage.md", sizedMarkdown("coverage\n", (1<<20)+1))
292
- writeObservationArtifact(t, root, slug, "architecture.md", []byte("architecture\n"))
293
- writeObservationArtifact(t, root, slug, "plan.md", []byte("plan\n"))
294
- writeObservationArtifact(t, root, slug, "traceability.md", []byte{})
295
- present := []byte("# Tasks\n\n- [ ] retained\n")
296
- writeObservationArtifact(t, root, slug, "tasks.md", present)
297
-
298
- observation, err := observeWorkspace(root, slug, func(stage observationStage, path ArtifactPath) error {
299
- if stage == observationBeforeOpen && path == "architecture.md" {
300
- return fs.ErrPermission
301
- }
302
- if stage == observationBeforeRead && path == "plan.md" {
303
- return errors.New("hostile read failure at /physical/path")
304
- }
305
- return nil
306
- })
307
- if err != nil {
308
- t.Fatal(err)
309
- }
310
-
311
- assertArtifactFact(t, observation, "brief.md", ArtifactAbsent, "", nil)
312
- assertArtifactFact(t, observation, "spec.md", ArtifactEmpty, "", []byte("# Empty\n\n"))
313
- assertArtifactFact(t, observation, "decisions.md", ArtifactMalformed, DiagnosticMalformedMarkdown, malformed)
314
- assertArtifactFact(t, observation, "assumptions.md", ArtifactUnsafe, DiagnosticFinalSymlink, nil)
315
- assertArtifactFact(t, observation, "questions.md", ArtifactUnsafe, DiagnosticNonRegular, nil)
316
- assertArtifactFact(t, observation, "decision-coverage.md", ArtifactUnsafe, DiagnosticFileTooLarge, nil)
317
- assertArtifactFact(t, observation, "architecture.md", ArtifactUnreadable, DiagnosticPermissionDenied, nil)
318
- assertArtifactFact(t, observation, "plan.md", ArtifactUnreadable, DiagnosticReadFailure, nil)
319
- assertArtifactFact(t, observation, "tasks.md", ArtifactPresent, "", present)
320
- assertArtifactFact(t, observation, "traceability.md", ArtifactEmpty, "", []byte{})
321
- zeroByteFact, _ := observation.Fact("traceability.md")
322
- if zeroByteFact.Bytes() == nil {
323
- t.Fatal("zero-byte empty artifact did not retain a copied empty byte slice")
324
- }
325
- }
326
-
327
- func TestWorkspaceObservationSymlinkClassifiesParent(t *testing.T) {
328
- base := t.TempDir()
329
- target := t.TempDir()
330
- if err := os.WriteFile(filepath.Join(target, "spec.md"), []byte("content\n"), 0o644); err != nil {
331
- t.Fatal(err)
332
- }
333
- if err := os.Symlink(target, filepath.Join(base, "nested")); err != nil {
334
- t.Fatal(err)
335
- }
336
- root, err := os.OpenRoot(base)
337
- if err != nil {
338
- t.Fatal(err)
339
- }
340
- defer func() { _ = root.Close() }()
341
-
342
- fact, _, err := observeArtifact(artifactLocation{
343
- path: ArtifactPath("spec.md"),
344
- root: root,
345
- name: "nested/spec.md",
346
- }, nil)
347
- if err != nil {
348
- t.Fatal(err)
349
- }
350
- if fact.State() != ArtifactUnsafe {
351
- t.Fatalf("State() = %q, want %q", fact.State(), ArtifactUnsafe)
352
- }
353
- diagnostic, ok := fact.Diagnostic()
354
- if !ok || diagnostic.Code != DiagnosticParentSymlink {
355
- t.Fatalf("Diagnostic() = (%+v, %v), want parent symlink", diagnostic, ok)
356
- }
357
- if fact.Bytes() != nil {
358
- t.Fatalf("Bytes() = %q, want nil", fact.Bytes())
359
- }
360
- }
361
-
362
- func TestWorkspaceObservationDefensiveCopies(t *testing.T) {
363
- root, slug := newObservationWorkspace(t)
364
- body := []byte("- Phase: build\n")
365
- writeObservationArtifact(t, root, slug, LedgerFile, body)
366
- observation, err := ObserveWorkspace(root, slug)
367
- if err != nil {
368
- t.Fatal(err)
369
- }
370
-
371
- facts := observation.Facts()
372
- facts[0].path = "mutated.md"
373
- facts[0].state = ArtifactUnsafe
374
- facts[0].bytes[0] = 'X'
375
- facts[0] = ArtifactFact{}
376
-
377
- fact, ok := observation.Fact(LedgerFile)
378
- if !ok {
379
- t.Fatal("Fact(state.md) returned ok=false")
380
- }
381
- returned := fact.Bytes()
382
- returned[0] = 'Y'
383
- fresh, ok := observation.Fact(LedgerFile)
384
- if !ok || fresh.Path() != LedgerFile || fresh.State() != ArtifactPresent || !slices.Equal(fresh.Bytes(), body) {
385
- t.Fatalf("fresh fact = (%q, %q, %q, %v), want retained state fact", fresh.Path(), fresh.State(), fresh.Bytes(), ok)
386
- }
387
- }
388
-
389
- func TestWorkspaceObservationUnknownLookupHasNoSideEffects(t *testing.T) {
390
- root, slug := newObservationWorkspace(t)
391
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
392
- callbacks := 0
393
- observation, err := observeWorkspace(root, slug, func(observationStage, ArtifactPath) error {
394
- callbacks++
395
- return nil
396
- })
397
- if err != nil {
398
- t.Fatal(err)
399
- }
400
- beforeCallbacks := callbacks
401
- beforeFacts := observation.Facts()
402
-
403
- fact, ok := observation.Fact("not-in-inventory.md")
404
- if ok || fact.path != "" || fact.state != "" || fact.code != "" || fact.bytes != nil {
405
- t.Fatalf("Fact(uninventoried) = (%+v, %v), want zero/false", fact, ok)
406
- }
407
- if fact.Bytes() != nil {
408
- t.Fatalf("zero fact Bytes() = %q, want nil", fact.Bytes())
409
- }
410
- if diagnostic, diagnosticOK := fact.Diagnostic(); diagnosticOK || diagnostic != (ArtifactDiagnostic{}) {
411
- t.Fatalf("zero fact Diagnostic() = (%+v, %v), want zero/false", diagnostic, diagnosticOK)
412
- }
413
- if callbacks != beforeCallbacks || !slices.EqualFunc(observation.Facts(), beforeFacts, equalArtifactFact) {
414
- t.Fatal("uninventoried lookup performed I/O or mutated the observation")
415
- }
416
- }
417
-
418
- func TestWorkspaceObservationStateMissingPreservesCallerOrderAndSelectedDiagnostics(t *testing.T) {
419
- root, slug := newObservationWorkspace(t)
420
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
421
- writeObservationArtifact(t, root, slug, "brief.md", []byte("# Heading\n"))
422
- writeObservationArtifact(t, root, slug, "spec.md", []byte("bad\x00markdown"))
423
- writeObservationArtifact(t, root, slug, "plan.md", []byte("real\n"))
424
- observation, err := ObserveWorkspace(root, slug)
425
- if err != nil {
426
- t.Fatal(err)
427
- }
428
-
429
- required := []ArtifactPath{"plan.md", "spec.md", "questions.md", "brief.md"}
430
- missing, diagnostics := observation.Missing(required)
431
- wantMissing := []ArtifactPath{"spec.md", "questions.md", "brief.md"}
432
- if !slices.Equal(missing, wantMissing) {
433
- t.Fatalf("Missing() paths = %v, want %v", missing, wantMissing)
434
- }
435
- wantDiagnostics := []ArtifactDiagnostic{{Path: "spec.md", State: ArtifactMalformed, Code: DiagnosticMalformedMarkdown}}
436
- if !slices.Equal(diagnostics, wantDiagnostics) {
437
- t.Fatalf("Missing() diagnostics = %+v, want %+v", diagnostics, wantDiagnostics)
438
- }
439
- }
440
-
441
- func TestWorkspaceObservationDisclosureRejectsInvalidWorkspace(t *testing.T) {
442
- root := filepath.Join(t.TempDir(), "hostile-root-secret", ".devrites")
443
- observation, err := ObserveWorkspace(root, "missing")
444
- if observation != nil {
445
- t.Fatalf("observation = %+v, want nil", observation)
446
- }
447
- assertObservationFailure(t, err, ObservationWorkspaceInvalid, "workspace observation: workspace_invalid: workspace is unavailable; verify the selected logical workspace and canonical workspace override, then retry")
448
- if strings.Contains(err.Error(), root) || strings.Contains(err.Error(), "hostile-root-secret") {
449
- t.Fatalf("error disclosed physical input: %v", err)
450
- }
451
- }
452
-
453
- func TestWorkspaceObservationRejectsCanonicalWorkspaceSymlinkWithoutDisclosure(t *testing.T) {
454
- for _, test := range []struct {
455
- name string
456
- target func(t *testing.T, root string) string
457
- }{
458
- {
459
- name: "inside root",
460
- target: func(t *testing.T, root string) string {
461
- t.Helper()
462
- return filepath.Join(root, "retained-target-secret")
463
- },
464
- },
465
- {
466
- name: "outside root",
467
- target: func(t *testing.T, _ string) string {
468
- t.Helper()
469
- return filepath.Join(t.TempDir(), "retained-target-secret")
470
- },
471
- },
472
- } {
473
- t.Run(test.name, func(t *testing.T) {
474
- root := filepath.Join(t.TempDir(), ".devrites")
475
- slug := "linked"
476
- target := test.target(t, root)
477
- writeFile(t, filepath.Join(target, LedgerFile), []byte("- Phase: build\ntarget-content-secret\n"))
478
- if err := os.MkdirAll(filepath.Join(root, "work"), 0o755); err != nil {
479
- t.Fatal(err)
480
- }
481
- workspace := filepath.Join(root, "work", slug)
482
- if err := os.Symlink(target, workspace); err != nil {
483
- t.Fatal(err)
484
- }
485
- t.Setenv("DEVRITES_WORKSPACE", "")
486
-
487
- observation, err := ObserveWorkspace(root, slug)
488
- if observation != nil {
489
- t.Fatalf("observation = %+v, want nil", observation)
490
- }
491
- assertObservationFailure(t, err, ObservationWorkspaceInvalid, "workspace observation: workspace_invalid: workspace is unavailable; verify the selected logical workspace and canonical workspace override, then retry")
492
- if strings.Contains(err.Error(), target) || strings.Contains(err.Error(), "retained-target-secret") || strings.Contains(err.Error(), "target-content-secret") {
493
- t.Fatalf("error disclosed target path or content: %v", err)
494
- }
495
- })
496
- }
497
- }
498
-
499
- func TestWorkspaceObservationRootRejectsIdentityChanges(t *testing.T) {
500
- for _, tc := range []struct {
501
- name string
502
- mutate func(t *testing.T, root, slug string)
503
- }{
504
- {
505
- name: "root replaced",
506
- mutate: func(t *testing.T, root, slug string) {
507
- t.Helper()
508
- if err := os.Rename(root, root+"-moved"); err != nil {
509
- t.Fatal(err)
510
- }
511
- // Replace with a regular file so OpenRoot fails closed on every
512
- // platform, including Windows directory file-ID reuse across
513
- // rename/recreate of an empty directory at the same path.
514
- if err := os.WriteFile(root, []byte("replaced-root\n"), 0o644); err != nil {
515
- t.Fatal(err)
516
- }
517
- },
518
- },
519
- {
520
- name: "workspace replaced",
521
- mutate: func(t *testing.T, root, slug string) {
522
- t.Helper()
523
- workspace := filepath.Join(root, "work", slug)
524
- if err := os.Rename(workspace, workspace+"-moved"); err != nil {
525
- t.Fatal(err)
526
- }
527
- if err := os.WriteFile(workspace, []byte("replaced-workspace\n"), 0o644); err != nil {
528
- t.Fatal(err)
529
- }
530
- },
531
- },
532
- } {
533
- t.Run(tc.name, func(t *testing.T) {
534
- root, slug := newObservationWorkspace(t)
535
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
536
- calls := 0
537
- observation, err := observeWorkspace(root, slug, func(stage observationStage, _ ArtifactPath) error {
538
- if stage == observationAfterResolve {
539
- calls++
540
- tc.mutate(t, root, slug)
541
- }
542
- return nil
543
- })
544
- if calls != 1 {
545
- t.Fatalf("after-resolve calls = %d, want 1", calls)
546
- }
547
- if observation != nil {
548
- t.Fatalf("observation = %+v, want nil", observation)
549
- }
550
- assertObservationFailure(t, err, ObservationWorkspaceInvalid, "workspace observation: workspace_invalid: workspace is unavailable; verify the selected logical workspace and canonical workspace override, then retry")
551
- })
552
- }
553
- }
554
-
555
- func TestWorkspaceObservationLimitsPerFile(t *testing.T) {
556
- for _, tc := range []struct {
557
- name string
558
- size int
559
- wantState ArtifactState
560
- wantCode DiagnosticCode
561
- wantBytes int
562
- }{
563
- {name: "exactly one MiB", size: 1 << 20, wantState: ArtifactPresent, wantBytes: 1 << 20},
564
- {name: "one MiB plus one", size: (1 << 20) + 1, wantState: ArtifactUnsafe, wantCode: DiagnosticFileTooLarge},
565
- } {
566
- t.Run(tc.name, func(t *testing.T) {
567
- root, slug := newObservationWorkspace(t)
568
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
569
- writeObservationArtifact(t, root, slug, "ai-spec.md", sizedMarkdown("optional input\n", tc.size))
570
- observation, err := ObserveWorkspace(root, slug)
571
- if err != nil {
572
- t.Fatal(err)
573
- }
574
- fact, ok := observation.Fact("ai-spec.md")
575
- if !ok || fact.State() != tc.wantState || len(fact.Bytes()) != tc.wantBytes {
576
- t.Fatalf("ai-spec fact = (%q, %d bytes, %v), want (%q, %d bytes)", fact.State(), len(fact.Bytes()), ok, tc.wantState, tc.wantBytes)
577
- }
578
- diagnostic, diagnosticOK := fact.Diagnostic()
579
- if tc.wantCode == "" {
580
- if diagnosticOK {
581
- t.Fatalf("Diagnostic() = %+v, want none", diagnostic)
582
- }
583
- } else if !diagnosticOK || diagnostic.Code != tc.wantCode {
584
- t.Fatalf("Diagnostic() = (%+v, %v), want %q", diagnostic, diagnosticOK, tc.wantCode)
585
- }
586
- })
587
- }
588
- }
589
-
590
- func TestWorkspaceObservationLimitsAggregateIncludingLaterOptionalFacts(t *testing.T) {
591
- for _, tc := range []struct {
592
- name string
593
- overflow bool
594
- }{
595
- {name: "exactly eight MiB"},
596
- {name: "eight MiB plus one in later optional fact", overflow: true},
597
- } {
598
- t.Run(tc.name, func(t *testing.T) {
599
- root, slug := newObservationWorkspace(t)
600
- paths := []ArtifactPath{LedgerFile, "brief.md", "spec.md", "decisions.md", "assumptions.md", "questions.md", "decision-coverage.md", "strategy.md"}
601
- for _, path := range paths {
602
- prefix := "retained content\n"
603
- if path == LedgerFile {
604
- prefix = "- Phase: build\n"
605
- }
606
- writeObservationArtifact(t, root, slug, path, sizedMarkdown(prefix, 1<<20))
607
- }
608
- if tc.overflow {
609
- writeObservationArtifact(t, root, slug, "ai-spec.md", []byte("x"))
610
- }
611
-
612
- observation, err := ObserveWorkspace(root, slug)
613
- if !tc.overflow {
614
- if err != nil || observation == nil {
615
- t.Fatalf("ObserveWorkspace() = (%+v, %v), want observation", observation, err)
616
- }
617
- return
618
- }
619
- if observation != nil {
620
- t.Fatalf("observation = %+v, want nil", observation)
621
- }
622
- assertObservationFailure(t, err, ObservationAggregateTooLarge, "workspace observation: aggregate_too_large: retained content exceeds the 8 MiB aggregate limit; reduce retained Markdown below 8 MiB, then retry")
623
- })
624
- }
625
- }
626
-
627
- func TestWorkspaceObservationLimitsCountEmptyAndMalformedBytes(t *testing.T) {
628
- root, slug := newObservationWorkspace(t)
629
- presentPaths := []ArtifactPath{LedgerFile, "brief.md", "decisions.md", "assumptions.md", "questions.md", "decision-coverage.md", "strategy.md"}
630
- for _, path := range presentPaths {
631
- prefix := "retained content\n"
632
- if path == LedgerFile {
633
- prefix = "- Phase: build\n"
634
- }
635
- writeObservationArtifact(t, root, slug, path, sizedMarkdown(prefix, 1<<20))
636
- }
637
- writeObservationArtifact(t, root, slug, "design-brief.md", bytesOf(' ', 1<<20))
638
- writeObservationArtifact(t, root, slug, "ai-spec.md", []byte{0xff})
639
-
640
- observation, err := ObserveWorkspace(root, slug)
641
- if observation != nil {
642
- t.Fatalf("observation = %+v, want nil", observation)
643
- }
644
- assertObservationFailure(t, err, ObservationAggregateTooLarge, "workspace observation: aggregate_too_large: retained content exceeds the 8 MiB aggregate limit; reduce retained Markdown below 8 MiB, then retry")
645
- }
646
-
647
- func TestWorkspaceObservationConcurrentChangeOutranksCallbackErrorsAfterDetectedMutation(t *testing.T) {
648
- sentinel := errors.New("sentinel callback failure")
649
- for _, stage := range []observationStage{
650
- observationAfterInspect,
651
- observationBeforeOpen,
652
- observationBeforeRead,
653
- observationAfterRead,
654
- } {
655
- t.Run(observationStageName(stage), func(t *testing.T) {
656
- root, slug := newObservationWorkspace(t)
657
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
658
- writeObservationArtifact(t, root, slug, "brief.md", []byte("before\n"))
659
- artifactPath := observationArtifactPath(root, slug, "brief.md")
660
- calls := make(map[observationStage]int)
661
-
662
- observation, err := observeWorkspace(root, slug, func(current observationStage, artifact ArtifactPath) error {
663
- if artifact != "brief.md" {
664
- return nil
665
- }
666
- calls[current]++
667
- if current != stage {
668
- return nil
669
- }
670
- writeFile(t, artifactPath, []byte("detectably larger content\n"))
671
- return sentinel
672
- })
673
- if observation != nil {
674
- t.Fatalf("observation = %+v, want nil", observation)
675
- }
676
- assertObservationFailure(t, err, ObservationConcurrentChange, "workspace observation: concurrent_change: workspace changed during acquisition; retry")
677
- assertSingleObservationAttempt(t, calls, stage)
678
- })
679
- }
680
- }
681
-
682
- func TestWorkspaceObservationConcurrentChangeRejectsDetectedArtifactChangesWithoutRetry(t *testing.T) {
683
- for _, tc := range []struct {
684
- name string
685
- stage observationStage
686
- setup func(t *testing.T, path string)
687
- mutate func(t *testing.T, path string)
688
- }{
689
- {
690
- name: "appearance",
691
- stage: observationAfterInspect,
692
- setup: func(*testing.T, string) {},
693
- mutate: func(t *testing.T, path string) { writeFile(t, path, []byte("appeared\n")) },
694
- },
695
- {
696
- name: "disappearance",
697
- stage: observationBeforeOpen,
698
- setup: func(t *testing.T, path string) { writeFile(t, path, []byte("before\n")) },
699
- mutate: func(t *testing.T, path string) {
700
- if err := os.Remove(path); err != nil {
701
- t.Fatal(err)
702
- }
703
- },
704
- },
705
- {
706
- name: "identity replacement",
707
- stage: observationBeforeOpen,
708
- setup: func(t *testing.T, path string) { writeFile(t, path, []byte("before\n")) },
709
- mutate: func(t *testing.T, path string) {
710
- if err := os.Rename(path, path+".old"); err != nil {
711
- t.Fatal(err)
712
- }
713
- writeFile(t, path, []byte("after!\n"))
714
- },
715
- },
716
- {
717
- name: "type change",
718
- stage: observationBeforeOpen,
719
- setup: func(t *testing.T, path string) { writeFile(t, path, []byte("before\n")) },
720
- mutate: func(t *testing.T, path string) {
721
- if err := os.Remove(path); err != nil {
722
- t.Fatal(err)
723
- }
724
- if err := os.Mkdir(path, 0o755); err != nil {
725
- t.Fatal(err)
726
- }
727
- },
728
- },
729
- {
730
- name: "size change",
731
- stage: observationBeforeOpen,
732
- setup: func(t *testing.T, path string) { writeFile(t, path, []byte("before\n")) },
733
- mutate: func(t *testing.T, path string) { writeFile(t, path, []byte("larger content\n")) },
734
- },
735
- {
736
- name: "replacement after read",
737
- stage: observationAfterRead,
738
- setup: func(t *testing.T, path string) { writeFile(t, path, []byte("before\n")) },
739
- mutate: func(t *testing.T, path string) {
740
- if err := os.Rename(path, path+".old"); err != nil {
741
- t.Fatal(err)
742
- }
743
- writeFile(t, path, []byte("after!\n"))
744
- },
745
- },
746
- } {
747
- t.Run(tc.name, func(t *testing.T) {
748
- root, slug := newObservationWorkspace(t)
749
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
750
- artifactPath := observationArtifactPath(root, slug, "brief.md")
751
- tc.setup(t, artifactPath)
752
- stageCalls := make(map[observationStage]int)
753
- mutated := false
754
- observation, err := observeWorkspace(root, slug, func(stage observationStage, path ArtifactPath) error {
755
- if path != "brief.md" {
756
- return nil
757
- }
758
- stageCalls[stage]++
759
- if !mutated && stage == tc.stage {
760
- mutated = true
761
- tc.mutate(t, artifactPath)
762
- }
763
- return nil
764
- })
765
- if !mutated {
766
- t.Fatal("target artifact was not mutated")
767
- }
768
- assertSingleObservationAttempt(t, stageCalls, tc.stage)
769
- if observation != nil {
770
- t.Fatalf("observation = %+v, want nil", observation)
771
- }
772
- assertObservationFailure(t, err, ObservationConcurrentChange, "workspace observation: concurrent_change: workspace changed during acquisition; retry")
773
- })
774
- }
775
- }
776
-
777
- func TestWorkspaceObservationConcurrentChangeDoesNotClaimSameSizeOrTransientDetection(t *testing.T) {
778
- t.Run("same identity and size", func(t *testing.T) {
779
- root, slug := newObservationWorkspace(t)
780
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
781
- before := []byte("before\n")
782
- after := []byte("after!\n")
783
- writeObservationArtifact(t, root, slug, "brief.md", before)
784
- artifactPath := observationArtifactPath(root, slug, "brief.md")
785
- observation, err := observeWorkspace(root, slug, func(stage observationStage, artifact ArtifactPath) error {
786
- if stage == observationAfterRead && artifact == "brief.md" {
787
- writeFile(t, artifactPath, after)
788
- }
789
- return nil
790
- })
791
- if err != nil {
792
- if observation != nil {
793
- t.Fatalf("observation = %+v with error %v, want nil", observation, err)
794
- }
795
- assertObservationFailure(t, err, ObservationConcurrentChange, "workspace observation: concurrent_change: workspace changed during acquisition; retry")
796
- return
797
- }
798
- fact, ok := observation.Fact("brief.md")
799
- if !ok || fact.State() != ArtifactPresent || (!slices.Equal(fact.Bytes(), before) && !slices.Equal(fact.Bytes(), after)) {
800
- t.Fatalf("successful same-size acquisition returned incoherent fact: state=%q bytes=%q ok=%v", fact.State(), fact.Bytes(), ok)
801
- }
802
- })
803
-
804
- t.Run("transient appearance between probes", func(t *testing.T) {
805
- root, slug := newObservationWorkspace(t)
806
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
807
- artifactPath := observationArtifactPath(root, slug, "brief.md")
808
- observation, err := observeWorkspace(root, slug, func(stage observationStage, artifact ArtifactPath) error {
809
- if stage == observationAfterInspect && artifact == "brief.md" {
810
- writeFile(t, artifactPath, []byte("transient\n"))
811
- if removeErr := os.Remove(artifactPath); removeErr != nil {
812
- t.Fatal(removeErr)
813
- }
814
- }
815
- return nil
816
- })
817
- if err != nil {
818
- if observation != nil {
819
- t.Fatalf("observation = %+v with error %v, want nil", observation, err)
820
- }
821
- assertObservationFailure(t, err, ObservationConcurrentChange, "workspace observation: concurrent_change: workspace changed during acquisition; retry")
822
- return
823
- }
824
- fact, ok := observation.Fact("brief.md")
825
- if !ok || fact.State() != ArtifactAbsent || fact.Bytes() != nil {
826
- t.Fatalf("successful transient acquisition returned incoherent fact: state=%q bytes=%q ok=%v", fact.State(), fact.Bytes(), ok)
827
- }
828
- })
829
- }
830
-
831
- func TestWorkspaceObservationConcurrentChangeDoesNotApplyAfterReturn(t *testing.T) {
832
- root, slug := newObservationWorkspace(t)
833
- writeObservationArtifact(t, root, slug, LedgerFile, []byte("- Phase: build\n"))
834
- before := []byte("retained before return\n")
835
- writeObservationArtifact(t, root, slug, "brief.md", before)
836
-
837
- observation, err := ObserveWorkspace(root, slug)
838
- if err != nil {
839
- t.Fatal(err)
840
- }
841
- writeObservationArtifact(t, root, slug, "brief.md", []byte("changed after return\n"))
842
-
843
- fact, ok := observation.Fact("brief.md")
844
- if !ok || fact.State() != ArtifactPresent || !slices.Equal(fact.Bytes(), before) {
845
- t.Fatalf("post-return mutation changed retained fact: state=%q bytes=%q ok=%v", fact.State(), fact.Bytes(), ok)
846
- }
847
- }
848
-
849
- func assertSingleObservationAttempt(t *testing.T, calls map[observationStage]int, trigger observationStage) {
850
- t.Helper()
851
- if calls[trigger] != 1 {
852
- t.Fatalf("triggering stage %s calls = %d, want 1", observationStageName(trigger), calls[trigger])
853
- }
854
- for stage, count := range calls {
855
- if count > 1 {
856
- t.Fatalf("stage %s calls = %d, want at most 1", observationStageName(stage), count)
857
- }
858
- }
859
- }
860
-
861
- func observationStageName(stage observationStage) string {
862
- switch stage {
863
- case observationAfterResolve:
864
- return "after_resolve"
865
- case observationAfterInspect:
866
- return "after_inspect"
867
- case observationBeforeOpen:
868
- return "before_open"
869
- case observationBeforeRead:
870
- return "before_read"
871
- case observationAfterRead:
872
- return "after_read"
873
- case observationBeforeFinalSweep:
874
- return "before_final_sweep"
875
- default:
876
- return "unknown"
877
- }
878
- }
879
-
880
- func assertArtifactFact(t *testing.T, observation *WorkspaceObservation, path ArtifactPath, state ArtifactState, code DiagnosticCode, wantBytes []byte) {
881
- t.Helper()
882
- fact, ok := observation.Fact(path)
883
- if !ok {
884
- t.Fatalf("Fact(%q) returned ok=false", path)
885
- }
886
- if fact.Path() != path || fact.State() != state || !slices.Equal(fact.Bytes(), wantBytes) {
887
- t.Fatalf("Fact(%q) = (path %q, state %q, bytes %q), want (%q, %q, %q)", path, fact.Path(), fact.State(), fact.Bytes(), path, state, wantBytes)
888
- }
889
- diagnostic, diagnosticOK := fact.Diagnostic()
890
- if code == "" {
891
- if diagnosticOK || diagnostic != (ArtifactDiagnostic{}) {
892
- t.Fatalf("Fact(%q).Diagnostic() = (%+v, %v), want zero/false", path, diagnostic, diagnosticOK)
893
- }
894
- return
895
- }
896
- wantDiagnostic := ArtifactDiagnostic{Path: path, State: state, Code: code}
897
- if !diagnosticOK || diagnostic != wantDiagnostic {
898
- t.Fatalf("Fact(%q).Diagnostic() = (%+v, %v), want (%+v, true)", path, diagnostic, diagnosticOK, wantDiagnostic)
899
- }
900
- }
901
-
902
- func assertObservationFailure(t *testing.T, err error, want ObservationFailure, wantMessage string) {
903
- t.Helper()
904
- if err == nil || err.Error() != wantMessage {
905
- t.Fatalf("error = %v, want %q", err, wantMessage)
906
- }
907
- var failure ObservationFailure
908
- if !errors.As(err, &failure) || failure != want {
909
- t.Fatalf("errors.As(%v) = %q, want %q", err, failure, want)
910
- }
911
- }
912
-
913
- func equalArtifactFact(left, right ArtifactFact) bool {
914
- return left.path == right.path && left.state == right.state && left.code == right.code && slices.Equal(left.bytes, right.bytes)
915
- }
916
-
917
- func newObservationWorkspace(t *testing.T) (string, string) {
918
- t.Helper()
919
- root := filepath.Join(t.TempDir(), ".devrites")
920
- slug := "observed"
921
- if err := os.MkdirAll(filepath.Join(root, "work", slug), 0o755); err != nil {
922
- t.Fatal(err)
923
- }
924
- return root, slug
925
- }
926
-
927
- func writeObservationArtifact(t *testing.T, root, slug string, path ArtifactPath, body []byte) {
928
- t.Helper()
929
- writeFile(t, observationArtifactPath(root, slug, path), body)
930
- }
931
-
932
- func observationArtifactPath(root, slug string, path ArtifactPath) string {
933
- if path == ".devrites/principles.md" {
934
- return filepath.Join(root, "principles.md")
935
- }
936
- return filepath.Join(root, "work", slug, filepath.FromSlash(string(path)))
937
- }
938
-
939
- func writeFile(t *testing.T, path string, body []byte) {
940
- t.Helper()
941
- if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
942
- t.Fatal(err)
943
- }
944
- if err := os.WriteFile(path, body, 0o644); err != nil {
945
- t.Fatal(err)
946
- }
947
- }
948
-
949
- func sizedMarkdown(prefix string, size int) []byte {
950
- body := bytesOf('x', size)
951
- copy(body, prefix)
952
- return body
953
- }
954
-
955
- func bytesOf(value byte, size int) []byte {
956
- body := make([]byte, size)
957
- for i := range body {
958
- body[i] = value
959
- }
960
- return body
961
- }