devrites 5.14.4 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (637) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/NOTICE.md +6 -4
  3. package/README.md +77 -16
  4. package/SECURITY.md +25 -11
  5. package/bin/devrites.mjs +49 -15
  6. package/docs/adr/0001-go-engine-as-control-plane.md +6 -3
  7. package/docs/adr/0029-v5-workspace-schema-and-native-migration.md +9 -0
  8. package/docs/adr/README.md +3 -2
  9. package/docs/agents/issue-tracker.md +1 -1
  10. package/docs/architecture.md +6 -3
  11. package/docs/cli.md +32 -9
  12. package/docs/command-map.md +5 -3
  13. package/docs/engine/state-schema.md +1 -1
  14. package/docs/flow.md +1 -1
  15. package/docs/harness-compliance.md +2 -2
  16. package/docs/release.md +15 -11
  17. package/docs/usage.md +1 -1
  18. package/engine/commands.go +1 -1
  19. package/engine/go.mod +1 -1
  20. package/engine/help.go +41 -15
  21. package/engine/help_test.go +134 -0
  22. package/engine/internal/acceptance/acceptance_test.go +298 -7
  23. package/engine/internal/acceptance/approve.go +7 -2
  24. package/engine/internal/acceptance/cli.go +3 -0
  25. package/engine/internal/acceptance/evidence.go +69 -5
  26. package/engine/internal/acceptance/lint.go +1 -1
  27. package/engine/internal/acceptance/run.go +5 -3
  28. package/engine/internal/acceptance/scaffold.go +5 -16
  29. package/engine/internal/devritespaths/paths.go +7 -6
  30. package/engine/internal/devritespaths/paths_test.go +18 -0
  31. package/engine/internal/fsutil/copy.go +83 -49
  32. package/engine/internal/fsutil/copy_test.go +70 -109
  33. package/engine/internal/gate/gate.go +89 -16
  34. package/engine/internal/gate/gate_test.go +101 -0
  35. package/engine/internal/hostpack/hostpack.go +52 -2
  36. package/engine/internal/hostpack/hostpack_test.go +83 -2
  37. package/engine/internal/install/apply.go +59 -16
  38. package/engine/internal/install/binary.go +10 -1
  39. package/engine/internal/install/install_test.go +428 -0
  40. package/engine/internal/install/merge.go +69 -38
  41. package/engine/internal/install/preflight.go +7 -0
  42. package/engine/internal/install/uninstall.go +43 -4
  43. package/engine/internal/lib/claims.go +25 -4
  44. package/engine/internal/lib/claims_test.go +57 -0
  45. package/engine/internal/lib/closeout.go +41 -3
  46. package/engine/internal/lib/closeout_test.go +144 -0
  47. package/engine/internal/lib/context.go +8 -4
  48. package/engine/internal/lib/context_next_test.go +100 -0
  49. package/engine/internal/lib/detect.go +1 -1
  50. package/engine/internal/lib/detect_test.go +13 -0
  51. package/engine/internal/lib/diffscope.go +19 -9
  52. package/engine/internal/lib/dispatch.go +7 -0
  53. package/engine/internal/lib/dup.go +40 -37
  54. package/engine/internal/lib/dup_test.go +178 -0
  55. package/engine/internal/lib/manifest_union.go +4 -1
  56. package/engine/internal/lib/manifest_union_test.go +37 -0
  57. package/engine/internal/lib/metrics.go +4 -0
  58. package/engine/internal/lib/metrics_test.go +28 -0
  59. package/engine/internal/lib/migrate_test.go +59 -0
  60. package/engine/internal/lib/observe_budgets.go +25 -9
  61. package/engine/internal/lib/observe_budgets_test.go +254 -0
  62. package/engine/internal/lib/observe_summary.go +23 -2
  63. package/engine/internal/lib/open_visual.go +4 -2
  64. package/engine/internal/lib/open_visual_test.go +11 -0
  65. package/engine/internal/lib/regression.go +62 -23
  66. package/engine/internal/lib/regression_test.go +103 -0
  67. package/engine/internal/lib/resolve.go +36 -17
  68. package/engine/internal/lib/resolve_remediation_test.go +132 -0
  69. package/engine/internal/lib/skilltrust.go +0 -11
  70. package/engine/internal/lib/slicecheck.go +7 -5
  71. package/engine/internal/lib/slicecheck_test.go +18 -0
  72. package/engine/internal/lib/triggers.go +9 -3
  73. package/engine/internal/lib/triggers_test.go +23 -0
  74. package/engine/internal/lib/util.go +17 -3
  75. package/engine/internal/lib/util_test.go +104 -0
  76. package/engine/internal/lib/visual_outline.go +7 -3
  77. package/engine/internal/lib/visual_outline_test.go +28 -0
  78. package/engine/internal/lib/windows.go +13 -9
  79. package/engine/internal/lib/windows_test.go +98 -0
  80. package/engine/internal/lib/workspace_read.go +2 -11
  81. package/engine/internal/lib/workspace_read_test.go +102 -0
  82. package/engine/internal/markdowntext/markdowntext.go +194 -11
  83. package/engine/internal/markdowntext/testdata/structural.json +250 -0
  84. package/engine/internal/notes/cli.go +30 -12
  85. package/engine/internal/notes/notes.go +242 -39
  86. package/engine/internal/notes/notes_test.go +372 -0
  87. package/engine/internal/overhaul/admit/packet.go +89 -0
  88. package/engine/internal/overhaul/admit/packet_test.go +223 -0
  89. package/engine/internal/overhaul/admit/run.go +4 -0
  90. package/engine/internal/overhaul/bench/run.go +6 -0
  91. package/engine/internal/overhaul/bench/run_test.go +46 -0
  92. package/engine/internal/overhaul/overhaul.go +6 -1
  93. package/engine/internal/overhaul/ovio/ovio.go +10 -3
  94. package/engine/internal/overhaul/ovio/ovio_test.go +75 -0
  95. package/engine/internal/overhaul/packet/packet.go +208 -0
  96. package/engine/internal/overhaul/packet/packet_test.go +263 -0
  97. package/engine/internal/overhaul/records/check.go +6 -0
  98. package/engine/internal/overhaul/records/init.go +16 -5
  99. package/engine/internal/overhaul/records/records_test.go +4 -0
  100. package/engine/internal/overhaul/records/run.go +66 -0
  101. package/engine/internal/overhaul/records/run_test.go +77 -0
  102. package/engine/internal/overhaul/render/run.go +15 -11
  103. package/engine/internal/overhaul/render/run_test.go +463 -1
  104. package/engine/internal/overhaul/render/visual.go +95 -33
  105. package/engine/internal/overhaul/score/run.go +20 -0
  106. package/engine/internal/overhaul/score/run_test.go +156 -1
  107. package/engine/internal/overhaul/snapshot/run.go +78 -21
  108. package/engine/internal/overhaul/snapshot/run_test.go +344 -8
  109. package/engine/internal/parallel/cli.go +33 -20
  110. package/engine/internal/parallel/cli_test.go +59 -0
  111. package/engine/internal/parallel/git.go +39 -1
  112. package/engine/internal/parallel/ops.go +101 -11
  113. package/engine/internal/parallel/ops_test.go +552 -69
  114. package/engine/internal/parallel/parallel_test.go +31 -1
  115. package/engine/internal/parallel/pathdisjoint.go +19 -1
  116. package/engine/internal/parallel/pathdisjoint_test.go +72 -0
  117. package/engine/internal/parallel/select.go +6 -2
  118. package/engine/internal/release/release.go +13 -3
  119. package/engine/internal/release/release_test.go +208 -3
  120. package/engine/internal/rootfacts/facts.go +9 -0
  121. package/engine/internal/rootfacts/facts_test.go +38 -0
  122. package/engine/internal/state/acceptance.go +7 -1
  123. package/engine/internal/state/budgets.go +11 -10
  124. package/engine/internal/state/budgets_test.go +93 -0
  125. package/engine/internal/state/cursor.go +19 -8
  126. package/engine/internal/state/cursor_test.go +120 -0
  127. package/engine/internal/state/lock_unix.go +7 -1
  128. package/engine/internal/state/lock_windows.go +7 -1
  129. package/engine/internal/state/state_test.go +49 -18
  130. package/engine/internal/state/taskgraph.go +18 -4
  131. package/engine/internal/state/taskgraph_test.go +43 -0
  132. package/engine/internal/state/workspaceschema.go +16 -2
  133. package/engine/internal/state/workspaceschema_test.go +34 -0
  134. package/engine/internal/state/write.go +67 -6
  135. package/engine/internal/state/write_test.go +136 -0
  136. package/engine/internal/version/version_test.go +2 -0
  137. package/engine/main.go +8 -1
  138. package/engine/observation_contract_test.go +1 -1
  139. package/engine/root_routing_test.go +23 -1
  140. package/install.sh +132 -12
  141. package/pack/.claude/agents/devrites-spec-reviewer.md +2 -2
  142. package/pack/.claude/skills/devrites-browser-proof/SKILL.md +2 -2
  143. package/pack/.claude/skills/devrites-frontend-craft/reference/design-references.md +18 -18
  144. package/pack/.claude/skills/devrites-frontend-craft/reference/quality-standards.md +6 -4
  145. package/pack/.claude/skills/devrites-interview/SKILL.md +4 -4
  146. package/pack/.claude/skills/devrites-lib/reference/parallel-dispatch.md +1 -1
  147. package/pack/.claude/skills/devrites-lib/reference/standards/afk-hitl.md +9 -1
  148. package/pack/.claude/skills/devrites-lib/reference/standards/agents.md +3 -2
  149. package/pack/.claude/skills/devrites-lib/reference/standards/gates.md +6 -5
  150. package/pack/.claude/skills/devrites-lib/reference/standards/spec-grammar.md +1 -1
  151. package/pack/.claude/skills/devrites-lib/reference/standards/verification-methods.md +3 -3
  152. package/pack/.claude/skills/devrites-lib/reference/standards/windows.md +3 -3
  153. package/pack/.claude/skills/devrites-lib/reference/standards/workflow-artifacts.md +2 -2
  154. package/pack/.claude/skills/devrites-lib/reference/visual-playbooks/outline-template.md +1 -1
  155. package/pack/.claude/skills/devrites-lib/reference/workspace-artifact-schema.md +4 -4
  156. package/pack/.claude/skills/devrites-ux-shape/SKILL.md +11 -12
  157. package/pack/.claude/skills/devrites-ux-shape/reference/visual-direction-probe.md +3 -1
  158. package/pack/.claude/skills/overhaul/SKILL.md +1 -1
  159. package/pack/.claude/skills/overhaul/references/orchestration.md +5 -3
  160. package/pack/.claude/skills/overhaul/references/records.md +39 -0
  161. package/pack/.claude/skills/overhaul/references/scoring.md +14 -4
  162. package/pack/.claude/skills/rite/reference/menu.md +1 -1
  163. package/pack/.claude/skills/rite-adopt/SKILL.md +8 -2
  164. package/pack/.claude/skills/rite-autocomplete/SKILL.md +11 -6
  165. package/pack/.claude/skills/rite-autocomplete/reference/decision-policy.md +3 -2
  166. package/pack/.claude/skills/rite-autocomplete/reference/loop.md +1 -1
  167. package/pack/.claude/skills/rite-autocomplete/reference/stop-conditions.md +6 -3
  168. package/pack/.claude/skills/rite-build/SKILL.md +2 -1
  169. package/pack/.claude/skills/rite-build/reference/afk-discipline.md +1 -1
  170. package/pack/.claude/skills/rite-build/reference/checkpoint-protocol.md +1 -1
  171. package/pack/.claude/skills/rite-build/reference/checkpoint.md +5 -0
  172. package/pack/.claude/skills/rite-build/reference/parallel-batch.md +2 -2
  173. package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +3 -2
  174. package/pack/.claude/skills/rite-clarify/SKILL.md +5 -4
  175. package/pack/.claude/skills/rite-clarify/reference/anti-patterns.md +2 -2
  176. package/pack/.claude/skills/rite-clarify/reference/decision-coverage.md +3 -2
  177. package/pack/.claude/skills/rite-converge/SKILL.md +2 -0
  178. package/pack/.claude/skills/rite-customize/SKILL.md +6 -4
  179. package/pack/.claude/skills/rite-define/SKILL.md +2 -0
  180. package/pack/.claude/skills/rite-define/reference/gates.md +8 -7
  181. package/pack/.claude/skills/rite-explain/SKILL.md +1 -1
  182. package/pack/.claude/skills/rite-explain/reference/intake.md +1 -1
  183. package/pack/.claude/skills/rite-fast/SKILL.md +1 -1
  184. package/pack/.claude/skills/rite-plan/SKILL.md +4 -3
  185. package/pack/.claude/skills/rite-plan/reference/replan-and-repair.md +4 -4
  186. package/pack/.claude/skills/rite-polish/reference/anti-ai-slop.md +1 -1
  187. package/pack/.claude/skills/rite-prove/reference/browser-proof.md +5 -5
  188. package/pack/.claude/skills/rite-resolve/SKILL.md +3 -3
  189. package/pack/.claude/skills/rite-seal/SKILL.md +4 -3
  190. package/pack/.claude/skills/rite-seal/reference/phase-contract.md +3 -2
  191. package/pack/.claude/skills/rite-seal/reference/seal-template.md +2 -0
  192. package/pack/.claude/skills/rite-ship/SKILL.md +4 -2
  193. package/pack/.claude/skills/rite-ship/reference/git-ship.md +8 -2
  194. package/pack/.claude/skills/rite-ship/reference/ship-template.md +2 -1
  195. package/pack/.claude/skills/rite-spec/SKILL.md +2 -2
  196. package/pack/.claude/skills/rite-spec/reference/spec-checklists.md +1 -1
  197. package/pack/.claude/skills/rite-spec/reference/spec-template.md +7 -3
  198. package/pack/.claude/skills/rite-spec/reference/state-workspace.md +2 -0
  199. package/pack/.claude/skills/rite-temper/SKILL.md +12 -9
  200. package/pack/.claude/skills/rite-temper/reference/scope-modes.md +1 -1
  201. package/pack/.claude/skills/rite-temper/reference/significance.md +10 -3
  202. package/pack/.claude/skills/rite-temper/reference/strategy-template.md +13 -2
  203. package/pack/.claude/skills/rite-vet/SKILL.md +4 -3
  204. package/pack/.claude/skills/rite-vet/reference/artifacts.md +1 -1
  205. package/pack/.claude/workflows/devrites-readonly-review.js +5 -4
  206. package/pack/generated/claude/agents/devrites-spec-reviewer.md +2 -2
  207. package/pack/generated/claude/skills/devrites-browser-proof/SKILL.md +2 -2
  208. package/pack/generated/claude/skills/devrites-frontend-craft/reference/design-references.md +18 -18
  209. package/pack/generated/claude/skills/devrites-frontend-craft/reference/quality-standards.md +6 -4
  210. package/pack/generated/claude/skills/devrites-interview/SKILL.md +4 -4
  211. package/pack/generated/claude/skills/devrites-lib/reference/parallel-dispatch.md +1 -1
  212. package/pack/generated/claude/skills/devrites-lib/reference/standards/afk-hitl.md +9 -1
  213. package/pack/generated/claude/skills/devrites-lib/reference/standards/agents.md +3 -2
  214. package/pack/generated/claude/skills/devrites-lib/reference/standards/gates.md +6 -5
  215. package/pack/generated/claude/skills/devrites-lib/reference/standards/spec-grammar.md +1 -1
  216. package/pack/generated/claude/skills/devrites-lib/reference/standards/verification-methods.md +3 -3
  217. package/pack/generated/claude/skills/devrites-lib/reference/standards/windows.md +3 -3
  218. package/pack/generated/claude/skills/devrites-lib/reference/standards/workflow-artifacts.md +2 -2
  219. package/pack/generated/claude/skills/devrites-lib/reference/visual-playbooks/outline-template.md +1 -1
  220. package/pack/generated/claude/skills/devrites-lib/reference/workspace-artifact-schema.md +4 -4
  221. package/pack/generated/claude/skills/devrites-ux-shape/SKILL.md +11 -12
  222. package/pack/generated/claude/skills/devrites-ux-shape/reference/visual-direction-probe.md +3 -1
  223. package/pack/generated/claude/skills/overhaul/SKILL.md +1 -1
  224. package/pack/generated/claude/skills/overhaul/references/orchestration.md +5 -3
  225. package/pack/generated/claude/skills/overhaul/references/records.md +39 -0
  226. package/pack/generated/claude/skills/overhaul/references/scoring.md +14 -4
  227. package/pack/generated/claude/skills/rite/reference/menu.md +1 -1
  228. package/pack/generated/claude/skills/rite-adopt/SKILL.md +8 -2
  229. package/pack/generated/claude/skills/rite-autocomplete/SKILL.md +11 -6
  230. package/pack/generated/claude/skills/rite-autocomplete/reference/decision-policy.md +3 -2
  231. package/pack/generated/claude/skills/rite-autocomplete/reference/loop.md +1 -1
  232. package/pack/generated/claude/skills/rite-autocomplete/reference/stop-conditions.md +6 -3
  233. package/pack/generated/claude/skills/rite-build/SKILL.md +2 -1
  234. package/pack/generated/claude/skills/rite-build/reference/afk-discipline.md +1 -1
  235. package/pack/generated/claude/skills/rite-build/reference/checkpoint-protocol.md +1 -1
  236. package/pack/generated/claude/skills/rite-build/reference/checkpoint.md +5 -0
  237. package/pack/generated/claude/skills/rite-build/reference/parallel-batch.md +2 -2
  238. package/pack/generated/claude/skills/rite-build/reference/wright-dispatch.md +3 -2
  239. package/pack/generated/claude/skills/rite-clarify/SKILL.md +5 -4
  240. package/pack/generated/claude/skills/rite-clarify/reference/anti-patterns.md +2 -2
  241. package/pack/generated/claude/skills/rite-clarify/reference/decision-coverage.md +3 -2
  242. package/pack/generated/claude/skills/rite-converge/SKILL.md +2 -0
  243. package/pack/generated/claude/skills/rite-customize/SKILL.md +6 -4
  244. package/pack/generated/claude/skills/rite-define/SKILL.md +2 -0
  245. package/pack/generated/claude/skills/rite-define/reference/gates.md +8 -7
  246. package/pack/generated/claude/skills/rite-explain/SKILL.md +1 -1
  247. package/pack/generated/claude/skills/rite-explain/reference/intake.md +1 -1
  248. package/pack/generated/claude/skills/rite-fast/SKILL.md +1 -1
  249. package/pack/generated/claude/skills/rite-plan/SKILL.md +4 -3
  250. package/pack/generated/claude/skills/rite-plan/reference/replan-and-repair.md +4 -4
  251. package/pack/generated/claude/skills/rite-polish/reference/anti-ai-slop.md +1 -1
  252. package/pack/generated/claude/skills/rite-prove/reference/browser-proof.md +5 -5
  253. package/pack/generated/claude/skills/rite-resolve/SKILL.md +3 -3
  254. package/pack/generated/claude/skills/rite-seal/SKILL.md +4 -3
  255. package/pack/generated/claude/skills/rite-seal/reference/phase-contract.md +3 -2
  256. package/pack/generated/claude/skills/rite-seal/reference/seal-template.md +2 -0
  257. package/pack/generated/claude/skills/rite-ship/SKILL.md +4 -2
  258. package/pack/generated/claude/skills/rite-ship/reference/git-ship.md +8 -2
  259. package/pack/generated/claude/skills/rite-ship/reference/ship-template.md +2 -1
  260. package/pack/generated/claude/skills/rite-spec/SKILL.md +2 -2
  261. package/pack/generated/claude/skills/rite-spec/reference/spec-checklists.md +1 -1
  262. package/pack/generated/claude/skills/rite-spec/reference/spec-template.md +7 -3
  263. package/pack/generated/claude/skills/rite-spec/reference/state-workspace.md +2 -0
  264. package/pack/generated/claude/skills/rite-temper/SKILL.md +12 -9
  265. package/pack/generated/claude/skills/rite-temper/reference/scope-modes.md +1 -1
  266. package/pack/generated/claude/skills/rite-temper/reference/significance.md +10 -3
  267. package/pack/generated/claude/skills/rite-temper/reference/strategy-template.md +13 -2
  268. package/pack/generated/claude/skills/rite-vet/SKILL.md +4 -3
  269. package/pack/generated/claude/skills/rite-vet/reference/artifacts.md +1 -1
  270. package/pack/generated/claude/workflows/devrites-readonly-review.js +5 -4
  271. package/pack/generated/codex/AGENTS.md +1 -1
  272. package/pack/generated/codex/agents/devrites-spec-reviewer.toml +2 -2
  273. package/pack/generated/codex/skills/devrites-browser-proof/SKILL.md +2 -2
  274. package/pack/generated/codex/skills/devrites-frontend-craft/reference/design-references.md +18 -18
  275. package/pack/generated/codex/skills/devrites-frontend-craft/reference/quality-standards.md +6 -4
  276. package/pack/generated/codex/skills/devrites-interview/SKILL.md +4 -4
  277. package/pack/generated/codex/skills/devrites-lib/reference/parallel-dispatch.md +1 -1
  278. package/pack/generated/codex/skills/devrites-lib/reference/standards/afk-hitl.md +9 -1
  279. package/pack/generated/codex/skills/devrites-lib/reference/standards/agents.md +3 -2
  280. package/pack/generated/codex/skills/devrites-lib/reference/standards/gates.md +6 -5
  281. package/pack/generated/codex/skills/devrites-lib/reference/standards/spec-grammar.md +1 -1
  282. package/pack/generated/codex/skills/devrites-lib/reference/standards/verification-methods.md +3 -3
  283. package/pack/generated/codex/skills/devrites-lib/reference/standards/windows.md +3 -3
  284. package/pack/generated/codex/skills/devrites-lib/reference/standards/workflow-artifacts.md +2 -2
  285. package/pack/generated/codex/skills/devrites-lib/reference/visual-playbooks/outline-template.md +1 -1
  286. package/pack/generated/codex/skills/devrites-lib/reference/workspace-artifact-schema.md +4 -4
  287. package/pack/generated/codex/skills/devrites-ux-shape/SKILL.md +11 -12
  288. package/pack/generated/codex/skills/devrites-ux-shape/reference/visual-direction-probe.md +3 -1
  289. package/pack/generated/codex/skills/overhaul/SKILL.md +1 -1
  290. package/pack/generated/codex/skills/overhaul/references/orchestration.md +5 -3
  291. package/pack/generated/codex/skills/overhaul/references/records.md +39 -0
  292. package/pack/generated/codex/skills/overhaul/references/scoring.md +14 -4
  293. package/pack/generated/codex/skills/rite/reference/menu.md +1 -1
  294. package/pack/generated/codex/skills/rite-adopt/SKILL.md +8 -2
  295. package/pack/generated/codex/skills/rite-autocomplete/SKILL.md +11 -6
  296. package/pack/generated/codex/skills/rite-autocomplete/reference/decision-policy.md +3 -2
  297. package/pack/generated/codex/skills/rite-autocomplete/reference/loop.md +1 -1
  298. package/pack/generated/codex/skills/rite-autocomplete/reference/stop-conditions.md +6 -3
  299. package/pack/generated/codex/skills/rite-build/SKILL.md +2 -1
  300. package/pack/generated/codex/skills/rite-build/reference/afk-discipline.md +1 -1
  301. package/pack/generated/codex/skills/rite-build/reference/checkpoint-protocol.md +1 -1
  302. package/pack/generated/codex/skills/rite-build/reference/checkpoint.md +5 -0
  303. package/pack/generated/codex/skills/rite-build/reference/parallel-batch.md +2 -2
  304. package/pack/generated/codex/skills/rite-build/reference/wright-dispatch.md +3 -2
  305. package/pack/generated/codex/skills/rite-clarify/SKILL.md +5 -4
  306. package/pack/generated/codex/skills/rite-clarify/reference/anti-patterns.md +2 -2
  307. package/pack/generated/codex/skills/rite-clarify/reference/decision-coverage.md +3 -2
  308. package/pack/generated/codex/skills/rite-converge/SKILL.md +2 -0
  309. package/pack/generated/codex/skills/rite-customize/SKILL.md +6 -4
  310. package/pack/generated/codex/skills/rite-define/SKILL.md +2 -0
  311. package/pack/generated/codex/skills/rite-define/reference/gates.md +8 -7
  312. package/pack/generated/codex/skills/rite-explain/SKILL.md +1 -1
  313. package/pack/generated/codex/skills/rite-explain/reference/intake.md +1 -1
  314. package/pack/generated/codex/skills/rite-fast/SKILL.md +1 -1
  315. package/pack/generated/codex/skills/rite-plan/SKILL.md +4 -3
  316. package/pack/generated/codex/skills/rite-plan/reference/replan-and-repair.md +4 -4
  317. package/pack/generated/codex/skills/rite-polish/reference/anti-ai-slop.md +1 -1
  318. package/pack/generated/codex/skills/rite-prove/reference/browser-proof.md +5 -5
  319. package/pack/generated/codex/skills/rite-resolve/SKILL.md +3 -3
  320. package/pack/generated/codex/skills/rite-seal/SKILL.md +4 -3
  321. package/pack/generated/codex/skills/rite-seal/reference/phase-contract.md +3 -2
  322. package/pack/generated/codex/skills/rite-seal/reference/seal-template.md +2 -0
  323. package/pack/generated/codex/skills/rite-ship/SKILL.md +4 -2
  324. package/pack/generated/codex/skills/rite-ship/reference/git-ship.md +8 -2
  325. package/pack/generated/codex/skills/rite-ship/reference/ship-template.md +2 -1
  326. package/pack/generated/codex/skills/rite-spec/SKILL.md +2 -2
  327. package/pack/generated/codex/skills/rite-spec/reference/spec-checklists.md +1 -1
  328. package/pack/generated/codex/skills/rite-spec/reference/spec-template.md +7 -3
  329. package/pack/generated/codex/skills/rite-spec/reference/state-workspace.md +2 -0
  330. package/pack/generated/codex/skills/rite-temper/SKILL.md +12 -9
  331. package/pack/generated/codex/skills/rite-temper/reference/scope-modes.md +1 -1
  332. package/pack/generated/codex/skills/rite-temper/reference/significance.md +10 -3
  333. package/pack/generated/codex/skills/rite-temper/reference/strategy-template.md +13 -2
  334. package/pack/generated/codex/skills/rite-vet/SKILL.md +4 -3
  335. package/pack/generated/codex/skills/rite-vet/reference/artifacts.md +1 -1
  336. package/pack/generated/devin/AGENTS.md +1 -1
  337. package/pack/generated/devin/agents/devrites-spec-reviewer.md +2 -2
  338. package/pack/generated/devin/skills/devrites-browser-proof/SKILL.md +2 -2
  339. package/pack/generated/devin/skills/devrites-frontend-craft/reference/design-references.md +18 -18
  340. package/pack/generated/devin/skills/devrites-frontend-craft/reference/quality-standards.md +6 -4
  341. package/pack/generated/devin/skills/devrites-interview/SKILL.md +4 -4
  342. package/pack/generated/devin/skills/devrites-lib/reference/parallel-dispatch.md +1 -1
  343. package/pack/generated/devin/skills/devrites-lib/reference/standards/afk-hitl.md +9 -1
  344. package/pack/generated/devin/skills/devrites-lib/reference/standards/agents.md +3 -2
  345. package/pack/generated/devin/skills/devrites-lib/reference/standards/gates.md +6 -5
  346. package/pack/generated/devin/skills/devrites-lib/reference/standards/spec-grammar.md +1 -1
  347. package/pack/generated/devin/skills/devrites-lib/reference/standards/verification-methods.md +3 -3
  348. package/pack/generated/devin/skills/devrites-lib/reference/standards/windows.md +3 -3
  349. package/pack/generated/devin/skills/devrites-lib/reference/standards/workflow-artifacts.md +2 -2
  350. package/pack/generated/devin/skills/devrites-lib/reference/visual-playbooks/outline-template.md +1 -1
  351. package/pack/generated/devin/skills/devrites-lib/reference/workspace-artifact-schema.md +4 -4
  352. package/pack/generated/devin/skills/devrites-ux-shape/SKILL.md +11 -12
  353. package/pack/generated/devin/skills/devrites-ux-shape/reference/visual-direction-probe.md +3 -1
  354. package/pack/generated/devin/skills/overhaul/SKILL.md +1 -1
  355. package/pack/generated/devin/skills/overhaul/references/orchestration.md +5 -3
  356. package/pack/generated/devin/skills/overhaul/references/records.md +39 -0
  357. package/pack/generated/devin/skills/overhaul/references/scoring.md +14 -4
  358. package/pack/generated/devin/skills/rite/reference/menu.md +1 -1
  359. package/pack/generated/devin/skills/rite-adopt/SKILL.md +8 -2
  360. package/pack/generated/devin/skills/rite-autocomplete/SKILL.md +11 -6
  361. package/pack/generated/devin/skills/rite-autocomplete/reference/decision-policy.md +3 -2
  362. package/pack/generated/devin/skills/rite-autocomplete/reference/loop.md +1 -1
  363. package/pack/generated/devin/skills/rite-autocomplete/reference/stop-conditions.md +6 -3
  364. package/pack/generated/devin/skills/rite-build/SKILL.md +2 -1
  365. package/pack/generated/devin/skills/rite-build/reference/afk-discipline.md +1 -1
  366. package/pack/generated/devin/skills/rite-build/reference/checkpoint-protocol.md +1 -1
  367. package/pack/generated/devin/skills/rite-build/reference/checkpoint.md +5 -0
  368. package/pack/generated/devin/skills/rite-build/reference/parallel-batch.md +2 -2
  369. package/pack/generated/devin/skills/rite-build/reference/wright-dispatch.md +3 -2
  370. package/pack/generated/devin/skills/rite-clarify/SKILL.md +5 -4
  371. package/pack/generated/devin/skills/rite-clarify/reference/anti-patterns.md +2 -2
  372. package/pack/generated/devin/skills/rite-clarify/reference/decision-coverage.md +3 -2
  373. package/pack/generated/devin/skills/rite-converge/SKILL.md +2 -0
  374. package/pack/generated/devin/skills/rite-customize/SKILL.md +6 -4
  375. package/pack/generated/devin/skills/rite-define/SKILL.md +2 -0
  376. package/pack/generated/devin/skills/rite-define/reference/gates.md +8 -7
  377. package/pack/generated/devin/skills/rite-explain/SKILL.md +1 -1
  378. package/pack/generated/devin/skills/rite-explain/reference/intake.md +1 -1
  379. package/pack/generated/devin/skills/rite-fast/SKILL.md +1 -1
  380. package/pack/generated/devin/skills/rite-plan/SKILL.md +4 -3
  381. package/pack/generated/devin/skills/rite-plan/reference/replan-and-repair.md +4 -4
  382. package/pack/generated/devin/skills/rite-polish/reference/anti-ai-slop.md +1 -1
  383. package/pack/generated/devin/skills/rite-prove/reference/browser-proof.md +5 -5
  384. package/pack/generated/devin/skills/rite-resolve/SKILL.md +3 -3
  385. package/pack/generated/devin/skills/rite-seal/SKILL.md +4 -3
  386. package/pack/generated/devin/skills/rite-seal/reference/phase-contract.md +3 -2
  387. package/pack/generated/devin/skills/rite-seal/reference/seal-template.md +2 -0
  388. package/pack/generated/devin/skills/rite-ship/SKILL.md +4 -2
  389. package/pack/generated/devin/skills/rite-ship/reference/git-ship.md +8 -2
  390. package/pack/generated/devin/skills/rite-ship/reference/ship-template.md +2 -1
  391. package/pack/generated/devin/skills/rite-spec/SKILL.md +2 -2
  392. package/pack/generated/devin/skills/rite-spec/reference/spec-checklists.md +1 -1
  393. package/pack/generated/devin/skills/rite-spec/reference/spec-template.md +7 -3
  394. package/pack/generated/devin/skills/rite-spec/reference/state-workspace.md +2 -0
  395. package/pack/generated/devin/skills/rite-temper/SKILL.md +12 -9
  396. package/pack/generated/devin/skills/rite-temper/reference/scope-modes.md +1 -1
  397. package/pack/generated/devin/skills/rite-temper/reference/significance.md +10 -3
  398. package/pack/generated/devin/skills/rite-temper/reference/strategy-template.md +13 -2
  399. package/pack/generated/devin/skills/rite-vet/SKILL.md +4 -3
  400. package/pack/generated/devin/skills/rite-vet/reference/artifacts.md +1 -1
  401. package/pack/generated/omp/agents/devrites-spec-reviewer.md +2 -2
  402. package/pack/generated/omp/commands/rite-define.md +1 -1
  403. package/pack/generated/omp/commands/rite-handoff.md +1 -1
  404. package/pack/generated/omp/commands/rite-plan.md +1 -1
  405. package/pack/generated/omp/commands/rite-pressure-test.md +1 -1
  406. package/pack/generated/omp/commands/rite-quick.md +1 -1
  407. package/pack/generated/omp/commands/rite-status.md +1 -1
  408. package/pack/generated/omp/commands/rite-temper.md +1 -1
  409. package/pack/generated/omp/commands/rite-zoom-out.md +1 -1
  410. package/pack/generated/omp/skills/devrites-browser-proof/SKILL.md +2 -2
  411. package/pack/generated/omp/skills/devrites-frontend-craft/reference/design-references.md +18 -18
  412. package/pack/generated/omp/skills/devrites-frontend-craft/reference/quality-standards.md +6 -4
  413. package/pack/generated/omp/skills/devrites-interview/SKILL.md +4 -4
  414. package/pack/generated/omp/skills/devrites-lib/reference/parallel-dispatch.md +1 -1
  415. package/pack/generated/omp/skills/devrites-lib/reference/standards/afk-hitl.md +9 -1
  416. package/pack/generated/omp/skills/devrites-lib/reference/standards/agents.md +3 -2
  417. package/pack/generated/omp/skills/devrites-lib/reference/standards/gates.md +6 -5
  418. package/pack/generated/omp/skills/devrites-lib/reference/standards/spec-grammar.md +1 -1
  419. package/pack/generated/omp/skills/devrites-lib/reference/standards/verification-methods.md +3 -3
  420. package/pack/generated/omp/skills/devrites-lib/reference/standards/windows.md +3 -3
  421. package/pack/generated/omp/skills/devrites-lib/reference/standards/workflow-artifacts.md +2 -2
  422. package/pack/generated/omp/skills/devrites-lib/reference/visual-playbooks/outline-template.md +1 -1
  423. package/pack/generated/omp/skills/devrites-lib/reference/workspace-artifact-schema.md +4 -4
  424. package/pack/generated/omp/skills/devrites-ux-shape/SKILL.md +11 -12
  425. package/pack/generated/omp/skills/devrites-ux-shape/reference/visual-direction-probe.md +3 -1
  426. package/pack/generated/omp/skills/overhaul/SKILL.md +1 -1
  427. package/pack/generated/omp/skills/overhaul/references/orchestration.md +5 -3
  428. package/pack/generated/omp/skills/overhaul/references/records.md +39 -0
  429. package/pack/generated/omp/skills/overhaul/references/scoring.md +14 -4
  430. package/pack/generated/omp/skills/rite/reference/menu.md +1 -1
  431. package/pack/generated/omp/skills/rite-adopt/SKILL.md +8 -2
  432. package/pack/generated/omp/skills/rite-autocomplete/SKILL.md +11 -6
  433. package/pack/generated/omp/skills/rite-autocomplete/reference/decision-policy.md +3 -2
  434. package/pack/generated/omp/skills/rite-autocomplete/reference/loop.md +1 -1
  435. package/pack/generated/omp/skills/rite-autocomplete/reference/stop-conditions.md +6 -3
  436. package/pack/generated/omp/skills/rite-build/SKILL.md +2 -1
  437. package/pack/generated/omp/skills/rite-build/reference/afk-discipline.md +1 -1
  438. package/pack/generated/omp/skills/rite-build/reference/checkpoint-protocol.md +1 -1
  439. package/pack/generated/omp/skills/rite-build/reference/checkpoint.md +5 -0
  440. package/pack/generated/omp/skills/rite-build/reference/parallel-batch.md +2 -2
  441. package/pack/generated/omp/skills/rite-build/reference/wright-dispatch.md +3 -2
  442. package/pack/generated/omp/skills/rite-clarify/SKILL.md +5 -4
  443. package/pack/generated/omp/skills/rite-clarify/reference/anti-patterns.md +2 -2
  444. package/pack/generated/omp/skills/rite-clarify/reference/decision-coverage.md +3 -2
  445. package/pack/generated/omp/skills/rite-converge/SKILL.md +2 -0
  446. package/pack/generated/omp/skills/rite-customize/SKILL.md +6 -4
  447. package/pack/generated/omp/skills/rite-define/SKILL.md +2 -0
  448. package/pack/generated/omp/skills/rite-define/reference/gates.md +8 -7
  449. package/pack/generated/omp/skills/rite-explain/SKILL.md +1 -1
  450. package/pack/generated/omp/skills/rite-explain/reference/intake.md +1 -1
  451. package/pack/generated/omp/skills/rite-fast/SKILL.md +1 -1
  452. package/pack/generated/omp/skills/rite-plan/SKILL.md +4 -3
  453. package/pack/generated/omp/skills/rite-plan/reference/replan-and-repair.md +4 -4
  454. package/pack/generated/omp/skills/rite-polish/reference/anti-ai-slop.md +1 -1
  455. package/pack/generated/omp/skills/rite-prove/reference/browser-proof.md +5 -5
  456. package/pack/generated/omp/skills/rite-resolve/SKILL.md +3 -3
  457. package/pack/generated/omp/skills/rite-seal/SKILL.md +4 -3
  458. package/pack/generated/omp/skills/rite-seal/reference/phase-contract.md +3 -2
  459. package/pack/generated/omp/skills/rite-seal/reference/seal-template.md +2 -0
  460. package/pack/generated/omp/skills/rite-ship/SKILL.md +4 -2
  461. package/pack/generated/omp/skills/rite-ship/reference/git-ship.md +8 -2
  462. package/pack/generated/omp/skills/rite-ship/reference/ship-template.md +2 -1
  463. package/pack/generated/omp/skills/rite-spec/SKILL.md +2 -2
  464. package/pack/generated/omp/skills/rite-spec/reference/spec-checklists.md +1 -1
  465. package/pack/generated/omp/skills/rite-spec/reference/spec-template.md +7 -3
  466. package/pack/generated/omp/skills/rite-spec/reference/state-workspace.md +2 -0
  467. package/pack/generated/omp/skills/rite-temper/SKILL.md +12 -9
  468. package/pack/generated/omp/skills/rite-temper/reference/scope-modes.md +1 -1
  469. package/pack/generated/omp/skills/rite-temper/reference/significance.md +10 -3
  470. package/pack/generated/omp/skills/rite-temper/reference/strategy-template.md +13 -2
  471. package/pack/generated/omp/skills/rite-vet/SKILL.md +4 -3
  472. package/pack/generated/omp/skills/rite-vet/reference/artifacts.md +1 -1
  473. package/pack/generated/pi/AGENTS.md +1 -1
  474. package/pack/generated/pi/agents/devrites-spec-reviewer.md +2 -2
  475. package/pack/generated/pi/prompts/rite-define.md +1 -1
  476. package/pack/generated/pi/prompts/rite-handoff.md +1 -1
  477. package/pack/generated/pi/prompts/rite-plan.md +1 -1
  478. package/pack/generated/pi/prompts/rite-pressure-test.md +1 -1
  479. package/pack/generated/pi/prompts/rite-quick.md +1 -1
  480. package/pack/generated/pi/prompts/rite-status.md +1 -1
  481. package/pack/generated/pi/prompts/rite-temper.md +1 -1
  482. package/pack/generated/pi/prompts/rite-zoom-out.md +1 -1
  483. package/pack/generated/pi/skills/devrites-browser-proof/SKILL.md +2 -2
  484. package/pack/generated/pi/skills/devrites-frontend-craft/reference/design-references.md +18 -18
  485. package/pack/generated/pi/skills/devrites-frontend-craft/reference/quality-standards.md +6 -4
  486. package/pack/generated/pi/skills/devrites-interview/SKILL.md +4 -4
  487. package/pack/generated/pi/skills/devrites-lib/reference/parallel-dispatch.md +1 -1
  488. package/pack/generated/pi/skills/devrites-lib/reference/standards/afk-hitl.md +9 -1
  489. package/pack/generated/pi/skills/devrites-lib/reference/standards/agents.md +3 -2
  490. package/pack/generated/pi/skills/devrites-lib/reference/standards/gates.md +6 -5
  491. package/pack/generated/pi/skills/devrites-lib/reference/standards/spec-grammar.md +1 -1
  492. package/pack/generated/pi/skills/devrites-lib/reference/standards/verification-methods.md +3 -3
  493. package/pack/generated/pi/skills/devrites-lib/reference/standards/windows.md +3 -3
  494. package/pack/generated/pi/skills/devrites-lib/reference/standards/workflow-artifacts.md +2 -2
  495. package/pack/generated/pi/skills/devrites-lib/reference/visual-playbooks/outline-template.md +1 -1
  496. package/pack/generated/pi/skills/devrites-lib/reference/workspace-artifact-schema.md +4 -4
  497. package/pack/generated/pi/skills/devrites-ux-shape/SKILL.md +11 -12
  498. package/pack/generated/pi/skills/devrites-ux-shape/reference/visual-direction-probe.md +3 -1
  499. package/pack/generated/pi/skills/overhaul/SKILL.md +1 -1
  500. package/pack/generated/pi/skills/overhaul/references/orchestration.md +5 -3
  501. package/pack/generated/pi/skills/overhaul/references/records.md +39 -0
  502. package/pack/generated/pi/skills/overhaul/references/scoring.md +14 -4
  503. package/pack/generated/pi/skills/rite/reference/menu.md +1 -1
  504. package/pack/generated/pi/skills/rite-adopt/SKILL.md +8 -2
  505. package/pack/generated/pi/skills/rite-autocomplete/SKILL.md +11 -6
  506. package/pack/generated/pi/skills/rite-autocomplete/reference/decision-policy.md +3 -2
  507. package/pack/generated/pi/skills/rite-autocomplete/reference/loop.md +1 -1
  508. package/pack/generated/pi/skills/rite-autocomplete/reference/stop-conditions.md +6 -3
  509. package/pack/generated/pi/skills/rite-build/SKILL.md +2 -1
  510. package/pack/generated/pi/skills/rite-build/reference/afk-discipline.md +1 -1
  511. package/pack/generated/pi/skills/rite-build/reference/checkpoint-protocol.md +1 -1
  512. package/pack/generated/pi/skills/rite-build/reference/checkpoint.md +5 -0
  513. package/pack/generated/pi/skills/rite-build/reference/parallel-batch.md +2 -2
  514. package/pack/generated/pi/skills/rite-build/reference/wright-dispatch.md +3 -2
  515. package/pack/generated/pi/skills/rite-clarify/SKILL.md +5 -4
  516. package/pack/generated/pi/skills/rite-clarify/reference/anti-patterns.md +2 -2
  517. package/pack/generated/pi/skills/rite-clarify/reference/decision-coverage.md +3 -2
  518. package/pack/generated/pi/skills/rite-converge/SKILL.md +2 -0
  519. package/pack/generated/pi/skills/rite-customize/SKILL.md +6 -4
  520. package/pack/generated/pi/skills/rite-define/SKILL.md +2 -0
  521. package/pack/generated/pi/skills/rite-define/reference/gates.md +8 -7
  522. package/pack/generated/pi/skills/rite-explain/SKILL.md +1 -1
  523. package/pack/generated/pi/skills/rite-explain/reference/intake.md +1 -1
  524. package/pack/generated/pi/skills/rite-fast/SKILL.md +1 -1
  525. package/pack/generated/pi/skills/rite-plan/SKILL.md +4 -3
  526. package/pack/generated/pi/skills/rite-plan/reference/replan-and-repair.md +4 -4
  527. package/pack/generated/pi/skills/rite-polish/reference/anti-ai-slop.md +1 -1
  528. package/pack/generated/pi/skills/rite-prove/reference/browser-proof.md +5 -5
  529. package/pack/generated/pi/skills/rite-resolve/SKILL.md +3 -3
  530. package/pack/generated/pi/skills/rite-seal/SKILL.md +4 -3
  531. package/pack/generated/pi/skills/rite-seal/reference/phase-contract.md +3 -2
  532. package/pack/generated/pi/skills/rite-seal/reference/seal-template.md +2 -0
  533. package/pack/generated/pi/skills/rite-ship/SKILL.md +4 -2
  534. package/pack/generated/pi/skills/rite-ship/reference/git-ship.md +8 -2
  535. package/pack/generated/pi/skills/rite-ship/reference/ship-template.md +2 -1
  536. package/pack/generated/pi/skills/rite-spec/SKILL.md +2 -2
  537. package/pack/generated/pi/skills/rite-spec/reference/spec-checklists.md +1 -1
  538. package/pack/generated/pi/skills/rite-spec/reference/spec-template.md +7 -3
  539. package/pack/generated/pi/skills/rite-spec/reference/state-workspace.md +2 -0
  540. package/pack/generated/pi/skills/rite-temper/SKILL.md +12 -9
  541. package/pack/generated/pi/skills/rite-temper/reference/scope-modes.md +1 -1
  542. package/pack/generated/pi/skills/rite-temper/reference/significance.md +10 -3
  543. package/pack/generated/pi/skills/rite-temper/reference/strategy-template.md +13 -2
  544. package/pack/generated/pi/skills/rite-vet/SKILL.md +4 -3
  545. package/pack/generated/pi/skills/rite-vet/reference/artifacts.md +1 -1
  546. package/package.json +5 -4
  547. package/scripts/build-host-artifacts.sh +15 -0
  548. package/scripts/codex-generate.sh +1 -1
  549. package/scripts/devin-generate.sh +1 -1
  550. package/scripts/expand-includes.py +46 -0
  551. package/scripts/install-lib.sh +42 -7
  552. package/scripts/omp-generate.sh +11 -0
  553. package/scripts/pi-generate.sh +12 -1
  554. package/update.sh +1 -2
  555. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/README.md +0 -7
  556. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/architecture.md +0 -3
  557. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/assumptions.md +0 -3
  558. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/brief.md +0 -3
  559. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/decision-coverage.md +0 -3
  560. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/decisions.md +0 -4
  561. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/eng-review.md +0 -3
  562. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/gates.md +0 -4
  563. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/plan.md +0 -5
  564. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/questions.md +0 -3
  565. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/spec.md +0 -6
  566. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/state.md +0 -8
  567. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/tasks.md +0 -1
  568. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/test-plan.md +0 -3
  569. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/traceability.md +0 -3
  570. package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/README.md +0 -7
  571. package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/assumptions.md +0 -3
  572. package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/brief.md +0 -3
  573. package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/decisions.md +0 -3
  574. package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/questions.md +0 -3
  575. package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/spec.md +0 -6
  576. package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/state.md +0 -3
  577. package/engine/testdata/golden/TestParityCloseOut/active_pointed_elsewhere.golden +0 -2
  578. package/engine/testdata/golden/TestParityCloseOut/active_slug_cleared.golden +0 -2
  579. package/engine/testdata/golden/TestParityCloseOut/archive_clobber.golden +0 -1
  580. package/engine/testdata/golden/TestParityCloseOut/missing_slug.golden +0 -1
  581. package/engine/testdata/golden/TestParityCloseOut/missing_workspace.golden +0 -1
  582. package/engine/testdata/golden/TestParityLearnings/add.golden +0 -2
  583. package/engine/testdata/golden/TestParityLearnings/list.golden +0 -5
  584. package/engine/testdata/golden/TestParityLearnings/mine-no-archive.golden +0 -2
  585. package/engine/testdata/golden/TestParityLearnings/mine.golden +0 -5
  586. package/engine/testdata/golden/TestParityLearnings/nudge.golden +0 -2
  587. package/engine/testdata/golden/TestParityLearnings/unknown.golden +0 -1
  588. package/engine/testdata/golden/TestParityPackageExistence/ghost-workspace.golden +0 -1
  589. package/engine/testdata/golden/TestParityPackageExistence/no-manifest.golden +0 -1
  590. package/engine/testdata/golden/TestParityPackageExistence/not-git.golden +0 -1
  591. package/engine/testdata/golden/TestParityPackageExistence/undeclared.golden +0 -1
  592. package/engine/testdata/golden/TestParityPreamble/afk/a.golden +0 -14
  593. package/engine/testdata/golden/TestParityPreamble/hitl/active.golden +0 -18
  594. package/engine/testdata/golden/TestParityPreamble/hitl/bare.golden +0 -10
  595. package/engine/testdata/golden/TestParityPreamble/hitl/full.golden +0 -18
  596. package/engine/testdata/golden/TestParityPreamble/hitl/ghost.golden +0 -2
  597. package/engine/testdata/golden/TestParityPreamble/hitl/nonl.golden +0 -11
  598. package/engine/testdata/golden/TestParityPreamble/hitl/openend.golden +0 -13
  599. package/engine/testdata/golden/TestParityProgress/arg=allbuilt.golden +0 -4
  600. package/engine/testdata/golden/TestParityProgress/arg=done.golden +0 -3
  601. package/engine/testdata/golden/TestParityProgress/arg=ghost.golden +0 -1
  602. package/engine/testdata/golden/TestParityProgress/arg=mid.golden +0 -4
  603. package/engine/testdata/golden/TestParityProgress/arg=nophase.golden +0 -3
  604. package/engine/testdata/golden/TestParityProgress/arg=noslice.golden +0 -3
  605. package/engine/testdata/golden/TestParityProgress/arg=plan.golden +0 -4
  606. package/engine/testdata/golden/TestParityProgress/arg=seal.golden +0 -3
  607. package/engine/testdata/golden/TestParityResolve/answer/questions.md.golden +0 -9
  608. package/engine/testdata/golden/TestParityResolve/answer/state.md.golden +0 -7
  609. package/engine/testdata/golden/TestParityResolve/answer.golden +0 -4
  610. package/engine/testdata/golden/TestParityResolve/batch/questions.md.golden +0 -9
  611. package/engine/testdata/golden/TestParityResolve/batch-unterminated/questions.md.golden +0 -9
  612. package/engine/testdata/golden/TestParityResolve/batch-unterminated.golden +0 -2
  613. package/engine/testdata/golden/TestParityResolve/batch.golden +0 -3
  614. package/engine/testdata/golden/TestParityResolve/drop/questions.md.golden +0 -9
  615. package/engine/testdata/golden/TestParityResolve/drop/state.md.golden +0 -9
  616. package/engine/testdata/golden/TestParityResolve/drop.golden +0 -4
  617. package/engine/testdata/golden/TestParityResolve/missing-answer.golden +0 -1
  618. package/engine/testdata/golden/TestParityResolve/no-workspace.golden +0 -1
  619. package/engine/testdata/golden/TestParityResolve/not-found.golden +0 -1
  620. package/engine/testdata/golden/TestParityResolve/not-open.golden +0 -1
  621. package/engine/testdata/golden/TestStatusLiveWorkspace.golden +0 -10
  622. package/engine/testdata/golden/status/auth-tokens.txt +0 -9
  623. package/engine/testdata/golden/status/search-ranking.txt +0 -9
  624. package/engine/testdata/visual/open-visual-smoke.html +0 -675
  625. package/engine/testdata/visual/open-visual-smoke.outline.md +0 -54
  626. package/engine/tests/adr_0003_gate_exit_code_test.go +0 -32
  627. package/engine/tests/adr_0004_required_by_phase_test.go +0 -54
  628. package/engine/tests/adr_0011_define_plan_test.go +0 -32
  629. package/engine/tests/adr_0027_readiness_binding_test.go +0 -107
  630. package/engine/tests/cli_test.go +0 -126
  631. package/engine/tests/gate_test.go +0 -669
  632. package/engine/tests/meta_test.go +0 -37
  633. package/engine/tests/parity_closeout_test.go +0 -105
  634. package/engine/tests/parity_githelpers_test.go +0 -41
  635. package/engine/tests/parity_resolve_test.go +0 -136
  636. package/engine/tests/parity_test.go +0 -86
  637. package/engine/tests/workspace_observation_migration_test.go +0 -1069
@@ -231,10 +231,10 @@ func TestReduceCountsAndIds(t *testing.T) {
231
231
  if len(red.UnapprIDs) != 2 {
232
232
  t.Fatalf("unapproved ids=%v", red.UnapprIDs)
233
233
  }
234
- // A nil approved surface (unreadable plan) reports no unapproved diagnostic.
234
+ // A nil approval surface approves nothing: every unmet runnable gate is unapproved.
235
235
  red = doc.Reduce(nil)
236
- if len(red.UnapprIDs) != 0 {
237
- t.Fatalf("nil approved must not flag: %v", red.UnapprIDs)
236
+ if len(red.UnapprIDs) != 2 {
237
+ t.Fatalf("nil approved must flag every unmet runnable gate: %v", red.UnapprIDs)
238
238
  }
239
239
  }
240
240
 
@@ -293,8 +293,9 @@ func TestApprovedCommandsNoSection(t *testing.T) {
293
293
  if approved := ApprovedCommands([]byte("# Plan\n\nno table\n")); len(approved) != 0 {
294
294
  t.Fatalf("approved=%+v", approved)
295
295
  }
296
- if approved := ApprovedCommands(nil); approved != nil {
297
- t.Fatalf("nil plan must approve nothing: %+v", approved)
296
+ // A nil plan approves nothing and reports it as an empty value, never nil.
297
+ if approved := ApprovedCommands(nil); approved == nil || len(approved) != 0 {
298
+ t.Fatalf("nil plan must approve nothing, and report it as a value: %+v", approved)
298
299
  }
299
300
  }
300
301
 
@@ -553,8 +554,9 @@ func TestLintMostlyManualAndCounts(t *testing.T) {
553
554
  if !mostlyManual {
554
555
  t.Fatalf("findings=%+v", findings)
555
556
  }
557
+ // The one runnable gate (G1) has no approved row, so lint reports an error.
556
558
  errs, warns := LintCounts(findings)
557
- if errs != 0 || warns == 0 {
559
+ if errs != 1 || warns == 0 {
558
560
  t.Fatalf("counts=%d/%d", errs, warns)
559
561
  }
560
562
  }
@@ -567,7 +569,7 @@ func TestScaffoldLedger(t *testing.T) {
567
569
  if len(doc.Errors) != 0 || len(doc.Gates) != 1 || doc.Gates[0].ID != "G1" {
568
570
  t.Fatalf("placeholder scaffold malformed: %v %+v", doc.Errors, doc.Gates)
569
571
  }
570
- spec := []byte("# Spec\n\n- AC-002 first\n- AC-001 second\n- AC-002 repeated\n")
572
+ spec := []byte("# Spec\n\n## Acceptance criteria\n\n- AC-002 first\n- AC-001 second\n- AC-002 repeated\n\n## Non-goals\n\n- AC-003 not required\n")
571
573
  scaffolded := ScaffoldLedger("feat", spec)
572
574
  doc = ParseLedger(scaffolded)
573
575
  if len(doc.Errors) != 0 || len(doc.Gates) != 2 || doc.Gates[0].ID != "AC-002" || doc.Gates[1].ID != "AC-001" {
@@ -653,3 +655,292 @@ func mustRead(t *testing.T, path string) string {
653
655
  }
654
656
  return string(raw)
655
657
  }
658
+
659
+ // An unresolvable approval surface is refused, never executed. Each consumer
660
+ // (run, reduce, lint) is asserted at its own guard, and nil and empty surfaces
661
+ // must behave identically.
662
+
663
+ func TestApprovedCommandsNeverNilSurface(t *testing.T) {
664
+ // ApprovedCommands never returns nil: a consumer must be able to refuse on an
665
+ // empty surface.
666
+ cases := map[string][]byte{
667
+ "absent file (empty input)": nil,
668
+ "invalid utf8": {0xff, 0xfe, 0x00, 'a'},
669
+ "no preflight section": []byte("# Test plan\n\n## Plan\nnothing here\n"),
670
+ "heading only": []byte("## Build-entry preflight\n"),
671
+ "header row only": []byte("## Build-entry preflight\n| command | cwd |\n"),
672
+ }
673
+ for name, in := range cases {
674
+ got := ApprovedCommands(in)
675
+ if got == nil {
676
+ t.Errorf("CASE %s: ApprovedCommands returned nil; nil reads as 'approval not applicable' so every CHECK executes unreviewed. Must return a non-nil (possibly empty) surface.", name)
677
+ continue
678
+ }
679
+ if len(got) != 0 {
680
+ t.Errorf("CASE %s: ApprovedCommands = %v; want non-nil empty (nothing was approved)", name, got)
681
+ }
682
+ }
683
+ }
684
+
685
+ func TestRunGatesRefusesUnresolvableApprovalSurface(t *testing.T) {
686
+ for _, tc := range []struct {
687
+ name string
688
+ approved []ApprovedCommand
689
+ }{
690
+ {"nil surface", nil},
691
+ {"empty non-nil surface", []ApprovedCommand{}},
692
+ } {
693
+ t.Run(tc.name, func(t *testing.T) {
694
+ project := t.TempDir()
695
+ work := filepath.Join(project, ".devrites", "work", "feat")
696
+ if err := os.MkdirAll(work, 0o755); err != nil {
697
+ t.Fatal(err)
698
+ }
699
+ ledgerPath := filepath.Join(work, GatesFile)
700
+ body := "- [ ] G1: unreviewed oracle\n CHECK: echo UNAPPROVED-MUST-NOT-RUN\n EXPECT: UNAPPROVED-MUST-NOT-RUN\n EVIDENCE: pending\n"
701
+ if err := os.WriteFile(ledgerPath, []byte(body), 0o644); err != nil {
702
+ t.Fatal(err)
703
+ }
704
+ doc := ParseLedger(mustRead(t, ledgerPath))
705
+ results := RunGates(context.Background(), project, ledgerPath, doc, tc.approved, false, 10*time.Second)
706
+ if len(results) != 1 {
707
+ t.Fatalf("results=%+v", results)
708
+ }
709
+ r := results[0]
710
+ if r.Ran {
711
+ t.Errorf("DEFECT: gate executed under a %s approval surface (passed=%v detail=%q). An unreviewed CHECK must not execute when approvals cannot be established.", tc.name, r.Passed, r.Detail)
712
+ }
713
+ if r.Passed {
714
+ t.Errorf("DEFECT: gate reported passed under a %s approval surface; certification must not happen.", tc.name)
715
+ }
716
+ if !strings.Contains(r.Detail, "not an approved") {
717
+ t.Errorf("detail=%q; want a refusal naming the unapproved CHECK", r.Detail)
718
+ }
719
+ after := mustRead(t, ledgerPath)
720
+ if strings.Contains(after, EvidenceMarker) {
721
+ t.Errorf("DEFECT: ledger was certified with automatic evidence under a %s approval surface:\n%s", tc.name, after)
722
+ }
723
+ if !strings.Contains(after, "EVIDENCE: pending") {
724
+ t.Errorf("ledger evidence was mutated under a %s approval surface:\n%s", tc.name, after)
725
+ }
726
+ if red := doc.Reduce(tc.approved); red.Unapproved != 1 {
727
+ t.Errorf("reduction under %s surface: Unapproved=%d; want 1 so `gates status` cannot report unapproved: 0", tc.name, red.Unapproved)
728
+ }
729
+ })
730
+ }
731
+ }
732
+
733
+ func TestLintFlagsNilAndEmptyApprovalSurfaceIdentically(t *testing.T) {
734
+ for _, tc := range []struct {
735
+ name string
736
+ approved []ApprovedCommand
737
+ }{
738
+ {"nil surface", nil},
739
+ {"empty surface", []ApprovedCommand{}},
740
+ } {
741
+ doc := &Document{Abandoned: map[string]string{}}
742
+ g := runnableGate("G1", true, "pending")
743
+ g.Check = "echo anything"
744
+ g.Cwd = ""
745
+ doc.Gates = []*Gate{g}
746
+ found := false
747
+ for _, f := range LintLedger(doc, tc.approved) {
748
+ if f.Rule == "unapproved-check" && strings.Contains(f.Message, "echo anything") {
749
+ found = true
750
+ }
751
+ }
752
+ if !found {
753
+ t.Errorf("DEFECT: Lint(%s) reported no unapproved-check finding; `gates lint --strict` reports LINT OK instead of the authorization error.", tc.name)
754
+ }
755
+ }
756
+ }
757
+
758
+ // Refusal applies only where a command would actually execute; manual and
759
+ // already-met gates must not be blocked by an unresolvable approval surface.
760
+ func TestUnresolvableApprovalDoesNotBlockNonExecutingGates(t *testing.T) {
761
+ project := t.TempDir()
762
+
763
+ // Manual gates execute nothing, so there is nothing to authorize.
764
+ manualOnly := ParseLedger("- [x] M1: human judged\n EVIDENCE: a stranger checked the transcript\n")
765
+ if red := manualOnly.Reduce(nil); !red.AllMet() {
766
+ t.Errorf("a manual-only ledger has no CHECK to approve and must still reduce all-met: %+v", red)
767
+ }
768
+ if red := manualOnly.Reduce(nil); red.Unapproved != 0 {
769
+ t.Errorf("manual gates are not executions and must not count as unapproved: %+v", red)
770
+ }
771
+ for _, f := range LintLedger(manualOnly, nil) {
772
+ if f.Rule == "unapproved-check" {
773
+ t.Errorf("manual gates must never be flagged unapproved: %+v", f)
774
+ }
775
+ }
776
+
777
+ // An already-met runnable gate returns before the approval guard, so a
778
+ // workspace whose gates were vetted and met in an earlier run keeps its state.
779
+ met := runnableGate("R1", true, "")
780
+ met.Check = "echo already"
781
+ met.Expect = "already"
782
+ met.Evidence = FormatEvidence(met, OutputDigest("already\n"), 8, "2026-01-01T00:00:00Z")
783
+ if got := GateState(met, &Document{Abandoned: map[string]string{}}); got != StateMet {
784
+ t.Fatalf("fixture must be genuinely met, not %s", got)
785
+ }
786
+ manualUnmet := &Gate{ID: "M2", Title: "human judged", Evidence: "pending"}
787
+ doc := &Document{Abandoned: map[string]string{}, Gates: []*Gate{manualUnmet, met}}
788
+ for _, r := range RunGates(context.Background(), project, filepath.Join(project, "unused.md"), doc, nil, false, 10*time.Second) {
789
+ if strings.Contains(r.Detail, "not an approved") {
790
+ t.Errorf("gate %s was refused for approval although it never executes: %q", r.ID, r.Detail)
791
+ }
792
+ switch r.ID {
793
+ case "M2":
794
+ if !strings.Contains(r.Detail, "manual gate") {
795
+ t.Errorf("M2 detail=%q; want the manual-gate wording, proving the approval guard was never reached", r.Detail)
796
+ }
797
+ case "R1":
798
+ if !strings.Contains(r.Detail, "already met") {
799
+ t.Errorf("R1 detail=%q; want already-met, proving a vetted pass is not re-litigated", r.Detail)
800
+ }
801
+ }
802
+ }
803
+ }
804
+
805
+ // An unreadable test-plan.md leaves every runnable CHECK unapproved: the runner
806
+ // refuses it and the reduction and lint report it, whatever the value's nil-ness.
807
+ func TestLoadTestPlanUnreadableApprovesNothing(t *testing.T) {
808
+ approved := loadTestPlan(filepath.Join(t.TempDir(), "missing", "test-plan.md"))
809
+ if Approved("echo hi", "", approved) {
810
+ t.Fatalf("unreadable plan approved a command: %+v", approved)
811
+ }
812
+ g := runnableGate("G1", true, "pending")
813
+ g.Check = "echo hi"
814
+ doc := &Document{Abandoned: map[string]string{}, Gates: []*Gate{g}}
815
+ if red := doc.Reduce(approved); red.Unapproved != 1 {
816
+ t.Fatalf("Unapproved=%d; want 1", red.Unapproved)
817
+ }
818
+ errs, _ := LintCounts(LintLedger(doc, approved))
819
+ if errs != 1 {
820
+ t.Fatalf("lint errs=%d; want 1 unapproved-check", errs)
821
+ }
822
+ }
823
+
824
+ // `gates attest` refuses a placeholder note at write time, so a manual gate is
825
+ // never left checked on evidence the reader would later reject.
826
+ func TestAttestRefusesPlaceholderNotes(t *testing.T) {
827
+ placeholders := []string{"n/a", "tbd", "-", "ok", "done", "yes", "pending", "PENDING", "verified", "TODO", "N/A", "none", "n/a (see notes)", "done.", "AC-004: outcome seen", "outcome seen", "AC-004 - outcome seen", "**done**"}
828
+ for _, note := range placeholders {
829
+ project := t.TempDir()
830
+ root := filepath.Join(project, ".devrites")
831
+ work := filepath.Join(root, "work", "feat")
832
+ if err := os.MkdirAll(work, 0o755); err != nil {
833
+ t.Fatal(err)
834
+ }
835
+ ledgerPath := filepath.Join(work, GatesFile)
836
+ body := "- [ ] AC-004: outcome seen\n EVIDENCE: pending\n"
837
+ writeLedger(t, ledgerPath, body)
838
+ var stdout, stderr strings.Builder
839
+ if code := Run(root, []string{"attest", "feat", "AC-004", note}, &stdout, &stderr); code == ExitOK {
840
+ t.Errorf("placeholder %q was accepted at write time", note)
841
+ }
842
+ if !strings.Contains(stderr.String(), "placeholder") {
843
+ t.Errorf("placeholder %q: stderr=%q; want a message naming the placeholder", note, stderr.String())
844
+ }
845
+ if got := mustRead(t, ledgerPath); got != body {
846
+ t.Errorf("placeholder %q mutated the ledger:\n%s", note, got)
847
+ }
848
+ }
849
+ }
850
+
851
+ // The refusal must say a trailing parenthetical after a placeholder word is
852
+ // ignored, since the note otherwise appears to already cite who and where.
853
+ func TestAttestRefusalExplainsIgnoredParenthetical(t *testing.T) {
854
+ project := t.TempDir()
855
+ root := filepath.Join(project, ".devrites")
856
+ work := filepath.Join(root, "work", "feat")
857
+ if err := os.MkdirAll(work, 0o755); err != nil {
858
+ t.Fatal(err)
859
+ }
860
+ writeLedger(t, filepath.Join(work, GatesFile), "- [ ] AC-004: outcome seen\n EVIDENCE: pending\n")
861
+ var stdout, stderr strings.Builder
862
+ note := "done (verified on staging by Ann, q-12)"
863
+ if code := Run(root, []string{"attest", "feat", "AC-004", note}, &stdout, &stderr); code == ExitOK {
864
+ t.Fatalf("note %q was accepted", note)
865
+ }
866
+ for _, want := range []string{"placeholder", "trailing (", "is ignored"} {
867
+ if !strings.Contains(stderr.String(), want) {
868
+ t.Errorf("stderr=%q; want it to contain %q", stderr.String(), want)
869
+ }
870
+ }
871
+ }
872
+
873
+ func TestAttestAcceptsSubstantiveNote(t *testing.T) {
874
+ project := t.TempDir()
875
+ root := filepath.Join(project, ".devrites")
876
+ work := filepath.Join(root, "work", "feat")
877
+ if err := os.MkdirAll(work, 0o755); err != nil {
878
+ t.Fatal(err)
879
+ }
880
+ ledgerPath := filepath.Join(work, GatesFile)
881
+ writeLedger(t, ledgerPath, "- [ ] AC-004: outcome seen\n EVIDENCE: pending\n")
882
+ var stdout, stderr strings.Builder
883
+ if code := Run(root, []string{"attest", "feat", "AC-004", "verified on staging by reviewer"}, &stdout, &stderr); code != ExitOK {
884
+ t.Fatalf("substantive note refused: code=%d stderr=%q", code, stderr.String())
885
+ }
886
+ doc := ParseLedger(mustRead(t, ledgerPath))
887
+ if len(doc.Gates) != 1 || GateState(doc.Gates[0], doc) != StateMet {
888
+ t.Fatalf("substantive attestation not met: %+v", doc.Gates)
889
+ }
890
+ }
891
+
892
+ func manualLedger(note string) *Document {
893
+ return ParseLedger("# Gates\n\n- [x] AC-004: outcome seen\n EVIDENCE: " + note + "\n")
894
+ }
895
+
896
+ func TestManualGatePlaceholdersNeverMet(t *testing.T) {
897
+ for _, ev := range []string{"n/a", "tbd", "-", "ok", "done", "yes", "pending", "PENDING", "Pending", "verified", "TODO", "N/A", "TBD", "none", "n/a (see notes)", "done.",
898
+ "AC-004 — outcome seen", "AC-004 - outcome seen", "`done`", "**done**", "\"n/a\"",
899
+ "AC-004: outcome seen", "outcome seen", "AC-004", "AC-004 – outcome seen", "*done*", "_done_", "'done'", "Done!", " yes. ", "N.A.", "—", "✅", "✓ done", "[done]", "> done", "~~tbd~~", "outcome seen (AC-004)", "AC-004 (outcome seen)", "AC004 outcome seen", "ac-004: OUTCOME SEEN.", "pass", "passed", "true", "0", "okay", "none.", "TODO: later", "not applicable", "N/A - not applicable", "AC-004 done", "done - AC-004", "AC004 outcome seen", "AC 004 done", "see above", "(done)", "TBD (see notes)"} {
900
+ d := manualLedger(ev)
901
+ if len(d.Gates) != 1 || d.Gates[0].ID != "AC-004" || d.Gates[0].Evidence == "" {
902
+ t.Logf("PARSE %q: gates=%d errs=%v", ev, len(d.Gates), d.Errors)
903
+ continue
904
+ }
905
+ if got := GateState(d.Gates[0], d); got == StateMet {
906
+ t.Errorf("placeholder %q reached met", ev)
907
+ }
908
+ if d.Reduce(nil).AllMet() {
909
+ t.Errorf("placeholder %q: AllMet", ev)
910
+ }
911
+ }
912
+ }
913
+
914
+ // A title's own trailing parenthetical is part of the title, so a note that
915
+ // repeats only that parenthetical restates the title and stays unmet.
916
+ func TestManualGateTitleParentheticalIsTitleText(t *testing.T) {
917
+ for _, title := range []string{"Refund appears in ledger. (REQ-002)", "Refund appears in ledger (REQ-002)"} {
918
+ for _, note := range []string{"REQ-002", "(REQ-002)", "req 002", "Refund appears in ledger (REQ-002)"} {
919
+ d := ParseLedger("# Gates\n\n- [x] AC-004: " + title + "\n EVIDENCE: " + note + "\n")
920
+ if len(d.Gates) != 1 {
921
+ t.Fatalf("title %q note %q: gates=%d errs=%v", title, note, len(d.Gates), d.Errors)
922
+ }
923
+ if got := GateState(d.Gates[0], d); got == StateMet {
924
+ t.Errorf("title %q: title-only note %q reached met", title, note)
925
+ }
926
+ }
927
+ d := ParseLedger("# Gates\n\n- [x] AC-004: " + title + "\n EVIDENCE: REQ-002 confirmed on staging by Brooke\n")
928
+ if got := GateState(d.Gates[0], d); got != StateMet {
929
+ t.Errorf("title %q: substantive note = %s, want met", title, got)
930
+ }
931
+ }
932
+ }
933
+
934
+ func TestManualGateSubstantiveNotesMet(t *testing.T) {
935
+ for _, ev := range []string{"verified on staging by reviewer", "Verified on staging by reviewer (ticket 42)", "done on prod: 3 orders replayed, outcome seen in dashboard",
936
+ "Done: reviewer confirmed checkout on staging (q-12)", "q-12: Brooke confirmed the outcome seen on staging", "Yes - Brooke saw the banner on iPhone 15 (q-7)",
937
+ "(q-12) Brooke confirmed refund on staging", "outcome seen on staging by Brooke", "AC-004 outcome seen on staging by Brooke, q-3", "(Brooke confirmed refund on staging, q-12)"} {
938
+ d := manualLedger(ev)
939
+ if got := GateState(d.Gates[0], d); got != StateMet {
940
+ t.Errorf("substantive %q = %s, want met", ev, got)
941
+ }
942
+ if !d.Reduce(nil).AllMet() {
943
+ t.Errorf("substantive %q not AllMet", ev)
944
+ }
945
+ }
946
+ }
@@ -21,12 +21,17 @@ type ApprovedCommand struct {
21
21
  // other section approves execution — fenced examples, prose mentions, and
22
22
  // consumptive-action rows are not re-runnable oracles. A test plan without
23
23
  // the section approves nothing, so every runnable gate stays unapproved.
24
+ //
25
+ // The result is never nil: an absent, unreadable, or unparsable plan yields an
26
+ // empty surface rather than an absent one, because "approvals could not be
27
+ // determined" must be a value the caller can refuse on, never a nil that reads
28
+ // as "no approval is applicable".
24
29
  func ApprovedCommands(testPlan []byte) []ApprovedCommand {
30
+ approved := []ApprovedCommand{}
25
31
  structural, err := markdowntext.Structural(testPlan)
26
32
  if err != nil {
27
- return nil
33
+ return approved
28
34
  }
29
- var approved []ApprovedCommand
30
35
  inSection := false
31
36
  commandCol, cwdCol := -1, -1
32
37
  for _, line := range strings.Split(string(structural), "\n") {
@@ -362,6 +362,9 @@ func cmdAttest(root string, args []string, stdout, stderr io.Writer) int {
362
362
  if gate.Check != "" {
363
363
  return fmt.Errorf("gate %s is runnable; evidence comes from `gates run`, not attestation", gateID)
364
364
  }
365
+ if placeholderEvidence(note, gate.ID, gate.Title) {
366
+ return fmt.Errorf("evidence note %q is a placeholder: a note needs a word beyond done/n/a/ok/pending-style words, the gate ID or its title, and a trailing (…) after such words is ignored; say who observed what and where", note)
367
+ }
365
368
  return writeResult(ledgerPath, gate, note, true)
366
369
  })
367
370
  if lockErr != nil {
@@ -6,6 +6,7 @@ import (
6
6
  "fmt"
7
7
  "regexp"
8
8
  "strings"
9
+ "unicode"
9
10
  )
10
11
 
11
12
  // Evidence state vocabulary. A runnable gate is met only when its recorded
@@ -55,9 +56,8 @@ func GateState(gate *Gate, doc *Document) string {
55
56
  return StateAbandoned
56
57
  }
57
58
  if gate.Check == "" {
58
- // Manual gate: met when checked with any non-empty human evidence.
59
- evidence := strings.TrimSpace(gate.Evidence)
60
- if gate.Checked && evidence != "" && evidence != "pending" {
59
+ // Manual gate: met when checked with substantive human evidence.
60
+ if gate.Checked && !placeholderEvidence(gate.Evidence, gate.ID, gate.Title) {
61
61
  return StateMet
62
62
  }
63
63
  return StateUnmet
@@ -73,6 +73,68 @@ func GateState(gate *Gate, doc *Document) string {
73
73
  return StateMet
74
74
  }
75
75
 
76
+ // placeholderWords is the tautological vocabulary a manual attestation may not
77
+ // consist of (gates.md), as normalised words. A note whose every word comes
78
+ // from it, from the gate title, or is the gate ID is a placeholder.
79
+ var placeholderWords = map[string]bool{
80
+ "n": true, "a": true, "na": true, "tbd": true, "todo": true, "later": true,
81
+ "ok": true, "okay": true, "done": true, "yes": true, "pass": true, "passed": true,
82
+ "true": true, "0": true, "pending": true, "none": true, "verified": true,
83
+ "not": true, "applicable": true, "see": true, "above": true,
84
+ }
85
+
86
+ var trailingParenRE = regexp.MustCompile(`\s*\([^()]*\)$`)
87
+
88
+ // splitWords lowercases text and splits on every run of non-alphanumeric
89
+ // characters (markdown marks, quotes, punctuation, dash variants).
90
+ func splitWords(text string) []string {
91
+ return strings.FieldsFunc(strings.ToLower(text), func(r rune) bool { return !unicode.IsLetter(r) && !unicode.IsDigit(r) })
92
+ }
93
+
94
+ // noteWords is splitWords after dropping one trailing parenthetical when text
95
+ // remains before it. Gate titles use splitWords: their parenthetical is title
96
+ // text a note may not merely repeat.
97
+ func noteWords(text string) []string {
98
+ text = strings.TrimSpace(text)
99
+ if stripped := trailingParenRE.ReplaceAllString(text, ""); strings.TrimSpace(stripped) != "" {
100
+ text = stripped
101
+ }
102
+ return splitWords(text)
103
+ }
104
+
105
+ // placeholderEvidence reports whether a manual note is only a placeholder, so
106
+ // `N/A (see notes)`, `**done**`, `TODO: later` and `AC-004 - done` count while
107
+ // real prose does not. The gate ID is recognised in any spacing (`AC004`,
108
+ // `AC 004`, `AC-004`), and restating the gate title is also a placeholder.
109
+ func placeholderEvidence(evidence, id, title string) bool {
110
+ titleWords := map[string]bool{}
111
+ for _, w := range splitWords(title) {
112
+ titleWords[w] = true
113
+ }
114
+ compactID := strings.Join(noteWords(id), "")
115
+ words := noteWords(evidence)
116
+ for i := 0; i < len(words); {
117
+ if compactID != "" {
118
+ skip := 0
119
+ for k, joined := 1, ""; i+k <= len(words) && len(joined) < len(compactID); k++ {
120
+ joined += words[i+k-1]
121
+ if joined == compactID {
122
+ skip = k
123
+ }
124
+ }
125
+ if skip > 0 {
126
+ i += skip
127
+ continue
128
+ }
129
+ }
130
+ if !placeholderWords[words[i]] && !titleWords[words[i]] {
131
+ return false
132
+ }
133
+ i++
134
+ }
135
+ return true
136
+ }
137
+
76
138
  // Reduction is the non-executing ledger verdict shared by `gates status` and
77
139
  // the seal gate. Unmet counts every gate that is neither met nor abandoned;
78
140
  // Stale and Unapproved are diagnostic subsets of it.
@@ -102,7 +164,9 @@ func (r Reduction) HandoffRequired() bool {
102
164
 
103
165
  // Reduce computes the ledger reduction. approved is the vetted (command, cwd)
104
166
  // surface from test-plan.md; a runnable gate whose CHECK is absent also
105
- // records an unapproved diagnostic but always counts as unmet.
167
+ // records an unapproved diagnostic but always counts as unmet. A nil or empty
168
+ // approved surface approves nothing, so every unmet runnable gate is reported
169
+ // unapproved rather than silently counted as approved.
106
170
  func (d *Document) Reduce(approved []ApprovedCommand) Reduction {
107
171
  r := Reduction{Total: len(d.Gates)}
108
172
  for _, gate := range d.Gates {
@@ -122,7 +186,7 @@ func (d *Document) Reduce(approved []ApprovedCommand) Reduction {
122
186
  r.Stale++
123
187
  r.StaleIDs = append(r.StaleIDs, gate.ID)
124
188
  }
125
- if approved != nil && !Approved(gate.Check, gate.Cwd, approved) {
189
+ if !Approved(gate.Check, gate.Cwd, approved) {
126
190
  r.Unapproved++
127
191
  r.UnapprIDs = append(r.UnapprIDs, gate.ID)
128
192
  }
@@ -61,7 +61,7 @@ func LintLedger(doc *Document, approved []ApprovedCommand) []Finding {
61
61
  add("warn", gate.ID, "tautological-check",
62
62
  "CHECK looks like a fixed-output command: %q; use an oracle that observes the named outcome", gate.Check)
63
63
  }
64
- if approved != nil && !Approved(gate.Check, gate.Cwd, approved) {
64
+ if !Approved(gate.Check, gate.Cwd, approved) {
65
65
  add("error", gate.ID, "unapproved-check",
66
66
  "CHECK %q with CWD %q matches no Build-entry preflight row in test-plan.md; the runner refuses it", gate.Check, gate.Cwd)
67
67
  }
@@ -60,8 +60,10 @@ func ReadLedgerFile(ledgerPath string) (string, error) {
60
60
  // RunGates executes the runnable gates of ledgerPath. reverify re-runs every
61
61
  // runnable gate including already-met ones; the normal mode runs only unmet
62
62
  // runnable gates. approved is the vetted command set from test-plan.md; a
63
- // CHECK outside it never executes. Each pass writes definition-bound evidence;
64
- // each failure clears the box and restores EVIDENCE: pending.
63
+ // CHECK outside it never executes, and neither does one outside a surface that
64
+ // could not be determined — an absent preflight is a refusal, not permission.
65
+ // Each pass writes definition-bound evidence; each failure clears the box and
66
+ // restores EVIDENCE: pending.
65
67
  //
66
68
  // The caller holds the feature lock across this call.
67
69
  func RunGates(ctx context.Context, root, ledgerPath string, doc *Document, approved []ApprovedCommand, reverify bool, timeout time.Duration) []GateResult {
@@ -79,7 +81,7 @@ func RunGates(ctx context.Context, root, ledgerPath string, doc *Document, appro
79
81
  results = append(results, GateResult{ID: gate.ID, Passed: true, Detail: "already met"})
80
82
  continue
81
83
  }
82
- if approved != nil && !Approved(gate.Check, gate.Cwd, approved) {
84
+ if !Approved(gate.Check, gate.Cwd, approved) {
83
85
  results = append(results, GateResult{ID: gate.ID, Detail: "CHECK/CWD is not an approved test-plan.md preflight row; not executed"})
84
86
  continue
85
87
  }
@@ -2,8 +2,9 @@ package acceptance
2
2
 
3
3
  import (
4
4
  "fmt"
5
- "regexp"
6
5
  "strings"
6
+
7
+ "github.com/devrites/devrites/internal/state"
7
8
  )
8
9
 
9
10
  // ScaffoldLedger emits a template ledger: one pending gate per canonical
@@ -36,20 +37,8 @@ func ScaffoldLedger(slug string, spec []byte) string {
36
37
  return b.String()
37
38
  }
38
39
 
39
- var scaffoldACRE = regexp.MustCompile(`\bAC-\d{3}\b`)
40
-
41
- // specACIDs returns the unique AC-### ids declared anywhere in the spec; the
42
- // scaffold does not restrict to one section because the gate contract is the
43
- // same set the acceptance map already enforces onto tasks.md/test-plan.md.
40
+ // specACIDs returns the unique AC-### ids in the spec's Acceptance criteria
41
+ // section, the same set the acceptance map enforces onto tasks.md/test-plan.md.
44
42
  func specACIDs(spec []byte) []string {
45
- found := scaffoldACRE.FindAllString(string(spec), -1)
46
- seen := map[string]bool{}
47
- var ids []string
48
- for _, id := range found {
49
- if !seen[id] {
50
- seen[id] = true
51
- ids = append(ids, id)
52
- }
53
- }
54
- return ids
43
+ return state.ParseAcceptanceMap(spec, nil, nil, false, false).SpecIDs
55
44
  }
@@ -77,7 +77,7 @@ func WorkspaceOverrideChecked(root, slug string) (string, error) {
77
77
  })
78
78
  canonicalWorkspace := relErr == nil && len(parts) == 2 &&
79
79
  parts[0] == "work"
80
- if sameRoot || !canonicalWorkspace || !validSlug(filepath.Base(path)) {
80
+ if sameRoot || !canonicalWorkspace || !ValidSlug(filepath.Base(path)) {
81
81
  return "", fmt.Errorf("DRV-WORKSPACE-INVALID: DEVRITES_WORKSPACE %q is not a feature workspace; run `unset DEVRITES_WORKSPACE`", raw)
82
82
  }
83
83
  if slug != "" && filepath.Base(path) != slug {
@@ -99,7 +99,7 @@ func FeatureDir(root, slug string) string {
99
99
  // control-plane commands use this instead of FeatureDir so an attacker cannot
100
100
  // redirect archive/removal operations outside the selected DevRites root.
101
101
  func ExistingFeatureDirChecked(root, slug string) (string, error) {
102
- if !validSlug(slug) {
102
+ if !ValidSlug(slug) {
103
103
  return "", fmt.Errorf("DRV-WORKSPACE-INVALID: %q is not a feature slug", slug)
104
104
  }
105
105
  if ws, err := WorkspaceOverrideChecked(root, slug); err != nil {
@@ -113,7 +113,7 @@ func ExistingFeatureDirChecked(root, slug string) (string, error) {
113
113
  return resolved, nil
114
114
  }
115
115
  if errors.Is(err, os.ErrNotExist) {
116
- return "", os.ErrNotExist
116
+ return "", fmt.Errorf("no workspace for feature %q at %s: %w", slug, candidate, os.ErrNotExist)
117
117
  }
118
118
  return "", err
119
119
  }
@@ -129,7 +129,7 @@ func ArchiveDirChecked(root string) (string, error) {
129
129
  // must already exist. A live workspace never satisfies this lookup; callers
130
130
  // that accept either location try ExistingFeatureDirChecked first.
131
131
  func ExistingArchivedFeatureDirChecked(root, slug string) (string, error) {
132
- if !validSlug(slug) {
132
+ if !ValidSlug(slug) {
133
133
  return "", fmt.Errorf("DRV-WORKSPACE-INVALID: %q is not a feature slug", slug)
134
134
  }
135
135
  candidate := filepath.Join(root, "archive", slug)
@@ -208,13 +208,14 @@ func ActiveSlug(root string) (string, error) {
208
208
  return "", fmt.Errorf("read active feature: %w", err)
209
209
  }
210
210
  slug := strings.TrimSpace(string(raw))
211
- if slug != "" && !validSlug(slug) {
211
+ if slug != "" && !ValidSlug(slug) {
212
212
  return "", fmt.Errorf("DRV-ACTIVE-INVALID: ACTIVE value %q is not a feature slug; run `rm -f %q`", slug, activePath)
213
213
  }
214
214
  return slug, nil
215
215
  }
216
216
 
217
- func validSlug(slug string) bool {
217
+ // ValidSlug reports whether slug is a single, non-empty path element.
218
+ func ValidSlug(slug string) bool {
218
219
  return slug != "" && slug != "." && slug != ".." &&
219
220
  filepath.Base(slug) == slug &&
220
221
  !strings.ContainsAny(slug, `/\`)
@@ -1,6 +1,7 @@
1
1
  package devritespaths
2
2
 
3
3
  import (
4
+ "errors"
4
5
  "os"
5
6
  "path/filepath"
6
7
  "strings"
@@ -108,3 +109,20 @@ func TestActiveSlugRejectsPathTraversal(t *testing.T) {
108
109
  t.Fatalf("ActiveSlug symlink error = %v, want stable pointer diagnostic", err)
109
110
  }
110
111
  }
112
+
113
+ func TestExistingFeatureDirCheckedMissingNamesSlugAndMatchesNotExist(t *testing.T) {
114
+ root := t.TempDir()
115
+ if err := os.MkdirAll(filepath.Join(root, "work"), 0o755); err != nil {
116
+ t.Fatal(err)
117
+ }
118
+ _, err := ExistingFeatureDirChecked(root, "nosuch")
119
+ if err == nil {
120
+ t.Fatal("want error for missing workspace")
121
+ }
122
+ if !errors.Is(err, os.ErrNotExist) {
123
+ t.Fatalf("err = %v, want errors.Is os.ErrNotExist", err)
124
+ }
125
+ if !strings.Contains(err.Error(), "nosuch") {
126
+ t.Fatalf("err = %q, want it to name the slug", err.Error())
127
+ }
128
+ }