devrites 5.14.4 → 6.0.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 (637) hide show
  1. package/CHANGELOG.md +23 -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 +5 -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 +6 -3
  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 +5 -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 +6 -3
  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 +5 -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 +6 -3
  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 +5 -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 +6 -3
  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 +5 -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 +6 -3
  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 +5 -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 +6 -3
  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
@@ -0,0 +1,263 @@
1
+ package packet
2
+
3
+ import (
4
+ "bytes"
5
+ "encoding/json"
6
+ "os"
7
+ "path/filepath"
8
+ "strings"
9
+ "testing"
10
+ )
11
+
12
+ func jsonString(s string) string {
13
+ b, _ := json.Marshal(s)
14
+ return string(b)
15
+ }
16
+
17
+ func runArea(t *testing.T) string {
18
+ t.Helper()
19
+ return filepath.Join(t.TempDir(), "full-1")
20
+ }
21
+
22
+ func writeArgs(run string, extra ...string) []string {
23
+ base := []string{"write", run, "TASK-1", "a1", "implementer",
24
+ "--phase", "REMEDIATING", "--lane", "backend", "--snapshot", "abc",
25
+ "--authorized-by", "APPROVAL-1", "--brief", "packets/BRIEF.md"}
26
+ return append(base, extra...)
27
+ }
28
+
29
+ func mustMkdir(t *testing.T, dir string) {
30
+ t.Helper()
31
+ if err := os.MkdirAll(dir, 0o700); err != nil {
32
+ t.Fatal(err)
33
+ }
34
+ }
35
+
36
+ func TestWriteThenLoadRoundTrip(t *testing.T) {
37
+ run := runArea(t)
38
+ mustMkdir(t, run)
39
+ var out, errb bytes.Buffer
40
+ if code := Run(writeArgs(run, "--write-path", "a.go", "--write-path", "b.go"), &out, &errb); code != 0 {
41
+ t.Fatalf("exit %d: %s", code, errb.String())
42
+ }
43
+ path := filepath.Join(run, "packets", "full-1__TASK-1__a1__implementer.json")
44
+ if got := strings.TrimSpace(out.String()); got != path {
45
+ t.Fatalf("printed %q, want %q", got, path)
46
+ }
47
+ p, err := Load(path)
48
+ if err != nil {
49
+ t.Fatal(err)
50
+ }
51
+ if p["receipt_path"] != filepath.Join(run, "receipts", "full-1__TASK-1__a1__implementer.json") {
52
+ t.Errorf("receipt_path = %v", p["receipt_path"])
53
+ }
54
+ if wp, _ := p["write_paths"].([]any); len(wp) != 2 || wp[0] != "a.go" || wp[1] != "b.go" {
55
+ t.Errorf("write_paths = %v", p["write_paths"])
56
+ }
57
+ if p["run_id"] != "full-1" || p["lane"] != "backend" || p["authorized_by"] != "APPROVAL-1" {
58
+ t.Errorf("fields not carried: %v", p)
59
+ }
60
+ }
61
+
62
+ func TestWriteRefusesToOverwrite(t *testing.T) {
63
+ run := runArea(t)
64
+ mustMkdir(t, run)
65
+ if code := Run(writeArgs(run), &bytes.Buffer{}, &bytes.Buffer{}); code != 0 {
66
+ t.Fatalf("first write exit %d", code)
67
+ }
68
+ path := filepath.Join(run, "packets", "full-1__TASK-1__a1__implementer.json")
69
+ before, _ := os.ReadFile(path)
70
+ var errb bytes.Buffer
71
+ if code := Run(writeArgs(run, "--lane", "frontend"), &bytes.Buffer{}, &errb); code != 1 {
72
+ t.Fatalf("second write exit %d, want 1", code)
73
+ }
74
+ if !strings.Contains(errb.String(), "already exists") {
75
+ t.Errorf("stderr = %q", errb.String())
76
+ }
77
+ if after, _ := os.ReadFile(path); !bytes.Equal(before, after) {
78
+ t.Error("existing packet was modified")
79
+ }
80
+ if ents, _ := os.ReadDir(filepath.Dir(path)); len(ents) != 1 {
81
+ t.Errorf("packets dir has %d entries, want 1", len(ents))
82
+ }
83
+ }
84
+
85
+ func TestWriteRejectsBadIDs(t *testing.T) {
86
+ for _, bad := range []string{"../x", "a/b", `a\b`, "..", "a__b"} {
87
+ run := runArea(t)
88
+ mustMkdir(t, run)
89
+ args := writeArgs(run)
90
+ args[2] = bad
91
+ var errb bytes.Buffer
92
+ if code := Run(args, &bytes.Buffer{}, &errb); code != 1 {
93
+ t.Errorf("task %q: exit %d, want 1", bad, code)
94
+ }
95
+ if _, err := os.Stat(filepath.Join(run, "packets")); err == nil {
96
+ t.Errorf("task %q: packets dir created", bad)
97
+ }
98
+ }
99
+ }
100
+
101
+ func TestWriteRejectsMissingFieldAndMissingRun(t *testing.T) {
102
+ run := runArea(t)
103
+ mustMkdir(t, run)
104
+ args := []string{"write", run, "TASK-1", "a1", "implementer", "--phase", "P"}
105
+ var errb bytes.Buffer
106
+ if code := Run(args, &bytes.Buffer{}, &errb); code != 1 || !strings.Contains(errb.String(), "missing or empty lane") {
107
+ t.Errorf("exit/stderr = %q", errb.String())
108
+ }
109
+ if code := Run(writeArgs(filepath.Join(t.TempDir(), "nope")), &bytes.Buffer{}, &bytes.Buffer{}); code != 2 {
110
+ t.Errorf("missing run area exit %d, want 2", code)
111
+ }
112
+ }
113
+
114
+ func TestFromFileSuppliesPlanAndFlagsOverride(t *testing.T) {
115
+ run := runArea(t)
116
+ mustMkdir(t, run)
117
+ from := filepath.Join(t.TempDir(), "extra.json")
118
+ if err := os.WriteFile(from, []byte(`{"lane":"other","plan":{"file":"revisions/plan-r1.json","rev":1},"write_paths":["x.go"]}`), 0o600); err != nil {
119
+ t.Fatal(err)
120
+ }
121
+ if code := Run(writeArgs(run, "--from", from), &bytes.Buffer{}, &bytes.Buffer{}); code != 0 {
122
+ t.Fatalf("exit %d", code)
123
+ }
124
+ p, err := Load(filepath.Join(run, "packets", "full-1__TASK-1__a1__implementer.json"))
125
+ if err != nil {
126
+ t.Fatal(err)
127
+ }
128
+ if p["lane"] != "backend" {
129
+ t.Errorf("lane = %v, flag should override file", p["lane"])
130
+ }
131
+ if wp, _ := p["write_paths"].([]any); len(wp) != 1 || wp[0] != "x.go" {
132
+ t.Errorf("write_paths = %v, want file value kept", p["write_paths"])
133
+ }
134
+ if p["plan"] == nil {
135
+ t.Error("plan from file lost")
136
+ }
137
+ }
138
+
139
+ func TestLoadRejectsMismatchedNameAndBadPlan(t *testing.T) {
140
+ run := runArea(t)
141
+ mustMkdir(t, run)
142
+ Run(writeArgs(run), &bytes.Buffer{}, &bytes.Buffer{})
143
+ src := filepath.Join(run, "packets", "full-1__TASK-1__a1__implementer.json")
144
+ b, _ := os.ReadFile(src)
145
+ moved := filepath.Join(run, "packets", "full-1__TASK-2__a1__implementer.json")
146
+ if err := os.WriteFile(moved, b, 0o600); err != nil {
147
+ t.Fatal(err)
148
+ }
149
+ if _, err := Load(moved); err == nil || !strings.Contains(err.Error(), "file name does not match") {
150
+ t.Errorf("Load of renamed packet: %v", err)
151
+ }
152
+ p := map[string]any{"plan": map[string]any{}}
153
+ if why := Validate("", p); !strings.Contains(strings.Join(why, ";"), "plan must be an object with a file") {
154
+ t.Errorf("Validate plan: %v", why)
155
+ }
156
+ }
157
+
158
+ func TestUsage(t *testing.T) {
159
+ var errb bytes.Buffer
160
+ if code := Run([]string{"write", "run"}, &bytes.Buffer{}, &errb); code != 2 || !strings.Contains(errb.String(), "usage:") {
161
+ t.Errorf("exit/stderr = %q", errb.String())
162
+ }
163
+ }
164
+
165
+ func TestWriteRejectsReceiptPathOutsideRunArea(t *testing.T) {
166
+ for i, bad := range []string{"/etc/evil.json", "../../outside/evil.json", "receipts/other.json", ""} {
167
+ run := runArea(t)
168
+ mustMkdir(t, run)
169
+ from := filepath.Join(t.TempDir(), "extra.json")
170
+ body := `{"receipt_path":"` + bad + `"}`
171
+ if err := os.WriteFile(from, []byte(body), 0o600); err != nil {
172
+ t.Fatal(err)
173
+ }
174
+ var errb bytes.Buffer
175
+ code := Run(writeArgs(run, "--from", from), &bytes.Buffer{}, &errb)
176
+ if bad == "" {
177
+ // An empty receipt_path falls back to the derived default.
178
+ if code != 0 {
179
+ t.Errorf("case %d: exit %d, want 0", i, code)
180
+ }
181
+ continue
182
+ }
183
+ if code != 1 || !strings.Contains(errb.String(), "receipt_path") {
184
+ t.Errorf("receipt_path %q: exit %d stderr %q, want 1 naming receipt_path", bad, code, errb.String())
185
+ }
186
+ if _, err := os.Stat(filepath.Join(run, "packets")); err == nil {
187
+ t.Errorf("receipt_path %q: packet written", bad)
188
+ }
189
+ }
190
+ }
191
+
192
+ func TestLoadRejectsReceiptPathOutsideRunArea(t *testing.T) {
193
+ run := runArea(t)
194
+ mustMkdir(t, run)
195
+ if code := Run(writeArgs(run), &bytes.Buffer{}, &bytes.Buffer{}); code != 0 {
196
+ t.Fatalf("exit %d", code)
197
+ }
198
+ path := filepath.Join(run, "packets", "full-1__TASK-1__a1__implementer.json")
199
+ if _, err := Load(path); err != nil {
200
+ t.Fatalf("derived receipt_path rejected: %v", err)
201
+ }
202
+ b, _ := os.ReadFile(path)
203
+ good := filepath.Join(run, "receipts", "full-1__TASK-1__a1__implementer.json")
204
+ for _, bad := range []string{"/etc/evil.json", "../../outside/evil.json", filepath.Join(run, "receipts", "..", "x.json")} {
205
+ // The packet is JSON, so match the encoded form (Windows paths carry escaped separators).
206
+ edited := strings.Replace(string(b), jsonString(good), jsonString(bad), 1)
207
+ if edited == string(b) {
208
+ t.Fatal("receipt_path not found in packet")
209
+ }
210
+ if err := os.WriteFile(path, []byte(edited), 0o600); err != nil {
211
+ t.Fatal(err)
212
+ }
213
+ if _, err := Load(path); err == nil || !strings.Contains(err.Error(), "receipt_path") {
214
+ t.Errorf("Load accepted receipt_path %q: %v", bad, err)
215
+ }
216
+ }
217
+ }
218
+
219
+ func TestWriteRefusesSymlinkedRunOrPacketsDir(t *testing.T) {
220
+ outside := t.TempDir()
221
+ base := t.TempDir()
222
+
223
+ linkedRun := filepath.Join(base, "full-1")
224
+ if err := os.Symlink(outside, linkedRun); err != nil {
225
+ t.Skip("symlinks unavailable:", err)
226
+ }
227
+ if code := Run(writeArgs(linkedRun), &bytes.Buffer{}, &bytes.Buffer{}); code != 2 {
228
+ t.Errorf("symlinked run dir: exit %d, want 2", code)
229
+ }
230
+ if ents, _ := os.ReadDir(outside); len(ents) != 0 {
231
+ t.Errorf("symlinked run dir: wrote %d entries outside", len(ents))
232
+ }
233
+
234
+ run := filepath.Join(base, "full-2")
235
+ mustMkdir(t, run)
236
+ if err := os.Symlink(outside, filepath.Join(run, "packets")); err != nil {
237
+ t.Fatal(err)
238
+ }
239
+ if code := Run(writeArgs(run), &bytes.Buffer{}, &bytes.Buffer{}); code != 2 {
240
+ t.Errorf("symlinked packets dir: exit %d, want 2", code)
241
+ }
242
+ if ents, _ := os.ReadDir(outside); len(ents) != 0 {
243
+ t.Errorf("symlinked packets dir: wrote %d entries outside", len(ents))
244
+ }
245
+ }
246
+
247
+ func TestWriteRejectsExtraPositionals(t *testing.T) {
248
+ for _, tc := range [][]string{
249
+ append(writeArgs("RUN"), "stray"),
250
+ append([]string{"write", "RUN", "TASK-1", "a1", "implementer", "stray"}, writeArgs("RUN")[5:]...),
251
+ } {
252
+ run := runArea(t)
253
+ mustMkdir(t, run)
254
+ tc[1] = run
255
+ var errb bytes.Buffer
256
+ if code := Run(tc, &bytes.Buffer{}, &errb); code != 2 || !strings.Contains(errb.String(), "unexpected argument") {
257
+ t.Errorf("%v: exit %d stderr %q, want 2 unexpected argument", tc[5:], code, errb.String())
258
+ }
259
+ if _, err := os.Stat(filepath.Join(run, "packets")); err == nil {
260
+ t.Errorf("%v: packet written", tc[5:])
261
+ }
262
+ }
263
+ }
@@ -8,6 +8,7 @@ import (
8
8
  "path"
9
9
  "path/filepath"
10
10
  "reflect"
11
+ "regexp"
11
12
  "sort"
12
13
  "strings"
13
14
 
@@ -15,6 +16,8 @@ import (
15
16
  "github.com/devrites/devrites/internal/overhaul/snapshot"
16
17
  )
17
18
 
19
+ var taskID = regexp.MustCompile(`^[A-Z][A-Z0-9]*-[A-Za-z0-9._-]+$`)
20
+
18
21
  func set(vals ...string) map[string]bool {
19
22
  m := map[string]bool{}
20
23
  for _, v := range vals {
@@ -528,6 +531,9 @@ func Check(run, genDir, prevDir string) ([]string, error) {
528
531
  }
529
532
  for _, tid := range order {
530
533
  t, ts := tasks[Repr(tid)], PyStr(tid)
534
+ if !taskID.MatchString(ts) {
535
+ add("task %s: id must match %s", Repr(tid), taskID)
536
+ }
531
537
  for _, d := range ovio.List(t["deps"]) {
532
538
  if _, ok := tasks[Repr(d)]; !ok {
533
539
  add("task %s: unknown dependency %s", ts, PyStr(d))
@@ -1,6 +1,7 @@
1
1
  package records
2
2
 
3
3
  import (
4
+ "context"
4
5
  "encoding/json"
5
6
  "errors"
6
7
  "fmt"
@@ -10,11 +11,17 @@ import (
10
11
  "path/filepath"
11
12
  "regexp"
12
13
  "strings"
14
+ "time"
13
15
 
14
16
  "github.com/devrites/devrites/internal/gitenv"
15
17
  "github.com/devrites/devrites/internal/overhaul/snapshot"
16
18
  )
17
19
 
20
+ const (
21
+ gitTimeout = 60 * time.Second
22
+ gitWaitDelay = 5 * time.Second
23
+ )
24
+
18
25
  var runIDPattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$`)
19
26
 
20
27
  // excludeLine is what init adds to the local .git/info/exclude when git does
@@ -104,8 +111,9 @@ func addExclude(top string) error {
104
111
 
105
112
  // gitIgnores reports whether git's ignore rules match rel (tracked or not).
106
113
  func gitIgnores(top, rel string) (bool, error) {
107
- cmd := gitCmd(top, "check-ignore", "-q", "--no-index", rel)
108
- err := cmd.Run()
114
+ ctx, cancel := context.WithTimeout(context.Background(), gitTimeout)
115
+ defer cancel()
116
+ err := gitCmd(ctx, top, "check-ignore", "-q", "--no-index", rel).Run()
109
117
  var ee *exec.ExitError
110
118
  switch {
111
119
  case err == nil:
@@ -118,15 +126,18 @@ func gitIgnores(top, rel string) (bool, error) {
118
126
  }
119
127
 
120
128
  func gitText(dir string, args ...string) (string, error) {
121
- out, err := gitCmd(dir, args...).Output()
129
+ ctx, cancel := context.WithTimeout(context.Background(), gitTimeout)
130
+ defer cancel()
131
+ out, err := gitCmd(ctx, dir, args...).Output()
122
132
  if err != nil {
123
133
  return "", err
124
134
  }
125
135
  return strings.TrimSpace(string(out)), nil
126
136
  }
127
137
 
128
- func gitCmd(dir string, args ...string) *exec.Cmd {
129
- cmd := exec.Command("git", append([]string{"-C", dir}, args...)...) // #nosec G204 -- fixed git binary; arguments passed as argv, no shell
138
+ func gitCmd(ctx context.Context, dir string, args ...string) *exec.Cmd {
139
+ cmd := exec.CommandContext(ctx, "git", append([]string{"-C", dir}, args...)...) // #nosec G204 -- fixed git binary; arguments passed as argv, no shell
130
140
  cmd.Env = append(gitenv.Sanitize(os.Environ()), "GIT_OPTIONAL_LOCKS=0", "GIT_TERMINAL_PROMPT=0")
141
+ cmd.WaitDelay = gitWaitDelay
131
142
  return cmd
132
143
  }
@@ -265,6 +265,10 @@ func TestSingleGenerationRules(t *testing.T) {
265
265
  approval(r)["plan_digest"] = digest(f.t, filepath.Join(f.run, "revisions/plan-r1.json"))
266
266
  approval(r)["tasks"] = L{"T-1", "T-2"}
267
267
  }, "task dependencies contain a cycle"},
268
+ {"task id breaks the approval fence", func(f *fixture, r map[string]J) {
269
+ f.writePlan(L{task("T-1", L{}, "src/a.py"), task("T-2\n```\n<img src=x>", L{"T-1"}, "src/b.py")})
270
+ approval(r)["plan_digest"] = digest(f.t, filepath.Join(f.run, "revisions/plan-r1.json"))
271
+ }, "id must match"},
268
272
  {"bracket path accepted", func(f *fixture, r map[string]J) {
269
273
  f.writePlan(L{task("T-1", L{}, "src/a.py"), task("T-2", L{"T-1"}, "app/blog/[slug]/page.tsx")})
270
274
  approval(r)["plan_digest"] = digest(f.t, filepath.Join(f.run, "revisions/plan-r1.json"))
@@ -6,6 +6,7 @@
6
6
  // stage RUN copy current generation to RUN/g<N+1>.tmp (prints path)
7
7
  // publish RUN validate staged generation, write manifest, swap CURRENT last
8
8
  // validate RUN verify CURRENT generation integrity + cross-record rules
9
+ // prune RUN [--keep K] delete generations older than the newest K (default 2, minimum 2)
9
10
  //
10
11
  // Exit: 0 ok, 1 rule violations (listed), 2 usage/IO error.
11
12
  package records
@@ -31,6 +32,7 @@ const usage = `usage: overhaul records <command> ...
31
32
  stage RUN copy current generation to RUN/g<N+1>.tmp (prints path)
32
33
  publish RUN validate staged generation, write manifest, swap CURRENT last
33
34
  validate RUN verify CURRENT generation integrity + cross-record rules
35
+ prune RUN [--keep K] delete generations older than the newest K (default 2, minimum 2)
34
36
  Exit: 0 ok, 1 rule violations (listed), 2 usage/IO error.
35
37
  `
36
38
 
@@ -60,6 +62,8 @@ func Run(args []string, stdout, stderr io.Writer) int {
60
62
  code, err = publish(args[1], stdout, stderr)
61
63
  case "validate":
62
64
  code, err = validate(args[1], stdout)
65
+ case "prune":
66
+ code, err = prune(args[1:], stdout, stderr)
63
67
  default:
64
68
  fmt.Fprint(stderr, usage)
65
69
  return 2
@@ -398,3 +402,65 @@ func validate(run string, stdout io.Writer) (int, error) {
398
402
  fmt.Fprintln(stdout, "valid "+gen)
399
403
  return 0, nil
400
404
  }
405
+
406
+ var generationName = regexp.MustCompile(`^g[0-9]{4}$`)
407
+
408
+ // prune deletes published generations outside the newest keep, never touching
409
+ // CURRENT, its manifest.previous, newer or staged generations.
410
+ func prune(args []string, stdout, stderr io.Writer) (int, error) {
411
+ run, keep := args[0], 2
412
+ if len(args) == 3 && args[1] == "--keep" {
413
+ k, err := strconv.Atoi(args[2])
414
+ if err != nil || k < 2 {
415
+ fmt.Fprint(stderr, "--keep must be an integer of at least 2\n")
416
+ return 2, nil
417
+ }
418
+ keep = k
419
+ } else if len(args) != 1 {
420
+ fmt.Fprint(stderr, usage)
421
+ return 2, nil
422
+ }
423
+ cur, has, err := current(run)
424
+ if err != nil {
425
+ return 0, err
426
+ }
427
+ if !has {
428
+ return 0, fmt.Errorf("no CURRENT in %s", run)
429
+ }
430
+ n, err := genNumber(cur)
431
+ if err != nil {
432
+ return 0, err
433
+ }
434
+ m, err := ovio.LoadObject(join(run, cur, "manifest.json"))
435
+ if err != nil {
436
+ return 0, err
437
+ }
438
+ prev := ""
439
+ if p := m["previous"]; ovio.Truthy(p) {
440
+ prev = PyStr(p)
441
+ }
442
+ entries, err := os.ReadDir(run)
443
+ if err != nil {
444
+ return 0, err
445
+ }
446
+ var removed []string
447
+ for _, e := range entries {
448
+ name := e.Name()
449
+ if !generationName.MatchString(name) || name == cur || name == prev {
450
+ continue
451
+ }
452
+ g, err := genNumber(name)
453
+ if err != nil {
454
+ return 0, err
455
+ }
456
+ if g > n-keep {
457
+ continue
458
+ }
459
+ if err := os.RemoveAll(join(run, name)); err != nil {
460
+ return 0, err
461
+ }
462
+ removed = append(removed, name)
463
+ }
464
+ fmt.Fprintf(stdout, "pruned %d: %s\n", len(removed), strings.Join(removed, " "))
465
+ return 0, nil
466
+ }
@@ -0,0 +1,77 @@
1
+ package records
2
+
3
+ import (
4
+ "os"
5
+ "path/filepath"
6
+ "strings"
7
+ "testing"
8
+ )
9
+
10
+ func generations(t *testing.T, run string) []string {
11
+ t.Helper()
12
+ m, err := filepath.Glob(filepath.Join(run, "g[0-9][0-9][0-9][0-9]"))
13
+ if err != nil {
14
+ t.Fatal(err)
15
+ }
16
+ for i := range m {
17
+ m[i] = filepath.Base(m[i])
18
+ }
19
+ return m
20
+ }
21
+
22
+ func TestPruneKeepsCurrentAndPrevious(t *testing.T) {
23
+ f := newFixture(t)
24
+ for i := 0; i < 5; i++ {
25
+ f.mustPublish(f.records())
26
+ }
27
+ if got := generations(t, f.run); len(got) != 5 {
28
+ t.Fatalf("publish must not prune on its own: %v", got)
29
+ }
30
+ if code, out, errs := f.cmd("prune", f.run, "--keep", "2"); code != 0 {
31
+ t.Fatalf("prune: %d %s %s", code, out, errs)
32
+ }
33
+ if got := strings.Join(generations(t, f.run), " "); got != "g0004 g0005" {
34
+ t.Fatalf("generations after prune = %q", got)
35
+ }
36
+ if code, out, _ := f.cmd("validate", f.run); code != 0 || strings.TrimSpace(out) != "valid g0005" {
37
+ t.Fatalf("validate: %d %s", code, out)
38
+ }
39
+ f.mustPublish(f.records())
40
+ if got := strings.Join(generations(t, f.run), " "); got != "g0004 g0005 g0006" {
41
+ t.Fatalf("generations after publish = %q", got)
42
+ }
43
+ }
44
+
45
+ func TestPruneKeepWindowAndGuards(t *testing.T) {
46
+ f := newFixture(t)
47
+ for i := 0; i < 5; i++ {
48
+ f.mustPublish(f.records())
49
+ }
50
+ if code, _, _ := f.cmd("prune", f.run, "--keep", "1"); code != 2 {
51
+ t.Fatalf("keep below 2 must be a usage error, got %d", code)
52
+ }
53
+ if code, _, _ := f.cmd("prune", f.run, "--keep", "x"); code != 2 {
54
+ t.Fatalf("non-numeric keep must be a usage error, got %d", code)
55
+ }
56
+ if got := generations(t, f.run); len(got) != 5 {
57
+ t.Fatalf("rejected prune removed generations: %v", got)
58
+ }
59
+ if code, _, errs := f.cmd("prune", f.run, "--keep", "3"); code != 0 {
60
+ t.Fatalf("prune: %d %s", code, errs)
61
+ }
62
+ if got := strings.Join(generations(t, f.run), " "); got != "g0003 g0004 g0005" {
63
+ t.Fatalf("generations after prune = %q", got)
64
+ }
65
+ if err := os.MkdirAll(filepath.Join(f.run, "g0006.tmp"), 0o700); err != nil {
66
+ t.Fatal(err)
67
+ }
68
+ if code, _, errs := f.cmd("prune", f.run); code != 0 {
69
+ t.Fatalf("default prune: %d %s", code, errs)
70
+ }
71
+ if got := strings.Join(generations(t, f.run), " "); got != "g0004 g0005" {
72
+ t.Fatalf("generations after default prune = %q", got)
73
+ }
74
+ if _, err := os.Stat(filepath.Join(f.run, "g0006.tmp")); err != nil {
75
+ t.Fatalf("staged generation must survive prune: %v", err)
76
+ }
77
+ }
@@ -38,7 +38,7 @@ html{scroll-padding-top:4.5rem;-webkit-text-size-adjust:100%}
38
38
  @media (prefers-reduced-motion:no-preference){html{scroll-behavior:smooth}}
39
39
  body{margin:0;background:var(--bg);color:var(--fg);font:15px/1.5 var(--sans)}
40
40
  h1,h2,h3,h4{font-weight:600;line-height:1.25;margin:0;text-wrap:balance}
41
- h2{font-size:1.25rem;margin:0 0 .25rem}h4{font-size:.8125rem;color:var(--muted);margin:0 0 .25rem}
41
+ h2{font-size:1.25rem;margin:0 0 .25rem}.blk>h3{font-size:.8125rem;color:var(--muted);margin:0 0 .25rem}
42
42
  p{margin:0 0 1rem}a{color:var(--accent);text-underline-offset:2px}
43
43
  code,pre,textarea,.m{font-family:var(--mono);font-size:.8125rem}code{overflow-wrap:anywhere}
44
44
  :focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@@ -53,7 +53,7 @@ code,pre,textarea,.m{font-family:var(--mono);font-size:.8125rem}code{overflow-wr
53
53
  .toc a{display:block;white-space:nowrap;padding:.25rem .75rem;border:1px solid var(--line);border-radius:999px;text-decoration:none;color:var(--fg);font-size:.875rem}
54
54
  .toc a:hover{background:var(--raised)}
55
55
  @media (min-width:64rem){.shell{display:grid;grid-template-columns:12rem minmax(0,1fr);gap:2.5rem}.toc{position:sticky;top:4.5rem;align-self:start}.toc ul{flex-direction:column;gap:0;overflow:visible;margin:0}.toc a{white-space:normal;border:0;border-radius:8px;padding:.3rem .5rem}}
56
- main>section,.records>section{margin:0 0 1.5rem;padding:1.5rem;background:var(--surface);border:1px solid var(--line);border-radius:12px}
56
+ main>section,.rec>section{margin:0 0 1.5rem;padding:1.5rem;background:var(--surface);border:1px solid var(--line);border-radius:12px}
57
57
  .hero{margin:0 0 1.5rem;padding:1.5rem;background:var(--surface);border:1px solid var(--line);border-radius:12px}
58
58
  .hero>p[role=status]{font-size:.8125rem;color:var(--muted);margin:0 0 1rem}.hero>p[role=status] strong{font-weight:500}
59
59
  .answer{display:grid;gap:2rem;grid-template-columns:minmax(0,1fr)}
@@ -63,7 +63,7 @@ main>section,.records>section{margin:0 0 1.5rem;padding:1.5rem;background:var(--
63
63
  .hero .score>.bar{height:18px;margin:.5rem 0 1.25rem}
64
64
  svg.bar{display:block;width:100%;height:12px;overflow:visible}
65
65
  .trk{fill:var(--track)}.tgt{fill:var(--fg)}.was{fill:var(--muted)}
66
- .g0,.c-pass,.c-part{fill:var(--pass)}.g4{fill:var(--sev4)}.g3{fill:var(--sev3)}.g2{fill:var(--sev2)}.g1{fill:var(--sev1)}.c-fail{fill:var(--fail)}.c-unk{fill:var(--unk)}
66
+ .g0,.c-pass,.c-part{fill:var(--pass)}.g4{fill:var(--sev4)}.g3{fill:var(--sev3)}.g2{fill:var(--sev2)}.g1{fill:var(--sev1)}.c-fail{fill:var(--fail)}.c-unk,.gx{fill:var(--unk)}
67
67
  .s-critical{fill:var(--sev1)}.s-high{fill:var(--sev2)}.s-medium{fill:var(--sev3)}.s-low{fill:var(--sev4)}.s-informational,.s-none{fill:var(--info)}
68
68
  .rows{list-style:none;margin:0;padding:0;display:grid;gap:.75rem}
69
69
  .rows li{display:grid;grid-template-columns:minmax(0,1fr) auto;grid-template-areas:"l v" "b b";gap:.25rem .75rem;align-items:center}
@@ -74,7 +74,7 @@ svg.bar{display:block;width:100%;height:12px;overflow:visible}
74
74
  .legend{list-style:none;display:flex;flex-wrap:wrap;gap:.25rem 1.25rem;margin:1rem 0 0;padding:0;font-size:.8125rem;color:var(--muted)}
75
75
  .legend li{display:flex;align-items:center;gap:.4rem}.legend strong{color:var(--fg)}
76
76
  .key{display:inline-block;width:.7rem;height:.7rem;border-radius:2px;background:var(--c,var(--muted));flex:none}
77
- .key.g0,.key.c-pass,.key.c-part{--c:var(--pass)}.key.g4,.key.s-low{--c:var(--sev4)}.key.g3,.key.s-medium{--c:var(--sev3)}.key.g2,.key.s-high{--c:var(--sev2)}.key.g1,.key.s-critical{--c:var(--sev1)}.key.c-fail{--c:var(--fail)}.key.c-unk{--c:var(--unk)}.key.s-informational,.key.s-none{--c:var(--info)}.key.was{--c:var(--muted);width:3px}.key.tgt{--c:var(--fg);width:2px;height:.9rem;border-radius:0}
77
+ .key.g0,.key.c-pass,.key.c-part{--c:var(--pass)}.key.g4,.key.s-low{--c:var(--sev4)}.key.g3,.key.s-medium{--c:var(--sev3)}.key.g2,.key.s-high{--c:var(--sev2)}.key.g1,.key.s-critical{--c:var(--sev1)}.key.c-fail{--c:var(--fail)}.key.c-unk{--c:var(--unk)}.key.gx{--c:var(--track);box-shadow:inset 0 0 0 1px var(--muted)}.key.s-informational,.key.s-none{--c:var(--info)}.key.was{--c:var(--muted);width:3px}.key.tgt{--c:var(--fg);width:2px;height:.9rem;border-radius:0}
78
78
  .blockers h2{font-size:1rem;margin:0 0 .75rem}
79
79
  .gates{list-style:none;margin:0 0 .75rem;padding:0;display:grid;gap:.6rem}
80
80
  .gates li{display:flex;gap:.6rem;align-items:flex-start}.gates code{color:var(--muted);font-size:.75rem}
@@ -94,15 +94,19 @@ svg.bar{display:block;width:100%;height:12px;overflow:visible}
94
94
  .filter input:checked+label{background:var(--fg);color:var(--bg);border-color:var(--fg)}.filter input:checked+label .count{color:inherit}
95
95
  .filter input:focus-visible+label{outline:2px solid var(--accent);outline-offset:2px}
96
96
  @supports not selector(:has(a)){.filter{display:none}}
97
- #findings:has(#sev-critical:checked) .finding:not(.s-critical),#findings:has(#sev-high:checked) .finding:not(.s-high),#findings:has(#sev-medium:checked) .finding:not(.s-medium),#findings:has(#sev-low:checked) .finding:not(.s-low),#findings:has(#sev-informational:checked) .finding:not(.s-informational){display:none}
97
+ @media screen{#findings:has(#sev-critical:checked) .finding:not(.s-critical):not(:target),#findings:has(#sev-high:checked) .finding:not(.s-high):not(:target),#findings:has(#sev-medium:checked) .finding:not(.s-medium):not(:target),#findings:has(#sev-low:checked) .finding:not(.s-low):not(:target),#findings:has(#sev-informational:checked) .finding:not(.s-informational):not(:target){display:none}}
98
98
  .cards{border:1px solid var(--line);border-radius:10px;overflow:hidden}
99
99
  .finding,.task{border-bottom:1px solid var(--line-2)}.finding:last-child,.task:last-child{border-bottom:0}.sub{font-size:1rem;margin:1.5rem 0 .5rem}
100
100
  .finding>summary,.task>summary{list-style:none;cursor:pointer;display:grid;grid-template-columns:5.5rem 4.5rem minmax(0,1fr);gap:.25rem .75rem;align-items:baseline;padding:.6rem .9rem}.task>summary{grid-template-columns:4.5rem 6.5rem minmax(0,1fr) auto}.task>summary>.pill:nth-child(2){justify-self:start}
101
101
  .finding>summary::-webkit-details-marker,.task>summary::-webkit-details-marker{display:none}.finding>summary:hover,.task>summary:hover{background:var(--raised)}
102
102
  .finding .where{grid-column:3;color:var(--muted);font-size:.75rem}
103
103
  @media (min-width:60rem){.finding>summary{grid-template-columns:5.5rem 4.5rem minmax(0,1fr) minmax(0,16rem)}.finding .where{grid-column:auto;text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}}
104
+ @media (max-width:40rem){.finding>summary,.task>summary{grid-template-columns:auto auto minmax(0,1fr)}.ftitle,.finding .where{grid-column:1/-1}}
105
+ @media (forced-colors:active){.filter input:checked+label{forced-color-adjust:none;background:Highlight;color:HighlightText;border-color:Highlight}.key{forced-color-adjust:none}}
104
106
  .sev{display:inline-flex;align-items:center;gap:.4rem;font-size:.8125rem;font-weight:600}
105
107
  .fid{font-weight:600}.ftitle{overflow-wrap:anywhere}
108
+ .finding>summary .fid::before,.task>summary .fid::before,.records>summary::before{content:"\25B8\00A0"/"";color:var(--muted)}
109
+ .finding[open]>summary .fid::before,.task[open]>summary .fid::before,.records[open]>summary::before{content:"\25BE\00A0"/""}
106
110
  .finding[open]>summary,.task[open]>summary{background:var(--raised)}.fbody{padding:.75rem .9rem 1rem;display:grid;gap:.9rem}
107
111
  .kv{display:grid;grid-template-columns:minmax(0,9rem) minmax(0,1fr);gap:.25rem 1rem;margin:0}
108
112
  .kv dt{color:var(--muted);font-size:.8125rem}.kv dd{margin:0;overflow-wrap:anywhere}
@@ -122,17 +126,17 @@ tr:target,.finding:target,.task:target{outline:2px solid var(--accent);outline-o
122
126
  #decide label{display:block;font-weight:600;margin:0 0 .5rem}
123
127
  textarea{display:block;width:100%;min-height:7rem;padding:.75rem;border:1px solid var(--line);border-radius:8px;background:var(--bg);color:var(--fg);resize:vertical}
124
128
  @media print{.top,.toc,.skip,.filter{display:none}.shell{display:block;padding:0}.scroll{max-height:none;overflow:visible}thead th{position:static}.scroll:has(th:nth-child(6)) table{min-width:0}.finding,tr,.rows li{break-inside:avoid}body{font-size:10pt}}
125
- @media print{details::details-content{content-visibility:visible}}`
129
+ @media print{details::details-content{content-visibility:visible}details.records:not([open])::details-content{content-visibility:hidden}}`
126
130
 
127
131
  var (
128
132
  rowID = regexp.MustCompile(`^[A-Z][A-Z0-9]*-[A-Za-z0-9._-]+$`)
129
133
  unsafeID = regexp.MustCompile(`[^A-Za-z0-9_-]`)
130
134
  flags = set("PASS", "FAIL", "UNKNOWN", "NOT_READY", "MEETS_TARGETS", "NOT_ASSESSABLE", "BLOCKED")
131
135
  leads = set("candidate", "needs-validation")
132
- reviewed = set("semantically-reviewed", "cross-boundary-reviewed", "verified")
136
+ reviewed = set("semantically-reviewed", "cross-boundary-reviewed", "verified", "excluded")
133
137
  // esc matches Python html.escape(quote=True) byte for byte.
134
138
  esc = strings.NewReplacer("&", "&amp;", "<", "&lt;", ">", "&gt;", `"`, "&quot;", "'", "&#x27;").Replace
135
- mdEsc = strings.NewReplacer(`\`, `\\`, "|", `\|`, "\n", " ", "<", "&lt;").Replace
139
+ mdEsc = strings.NewReplacer(`\`, `\\`, "|", `\|`, "\r\n", " ", "\r", " ", "\n", " ", "<", "&lt;").Replace
136
140
 
137
141
  // HTML-only presentation: severity scale, status order, typed table cells.
138
142
  sevOrder = []string{"critical", "high", "medium", "low", "informational"}
@@ -941,11 +945,11 @@ func (v view) page(b *built, kind, title, summary, csp string, decide bool) []st
941
945
  rest++
942
946
  }
943
947
  }
944
- out = append(out, fmt.Sprintf(`<details id="records" class="records"><summary>All records <span class="count">%d tables</span></summary>`+
948
+ out = append(out, fmt.Sprintf(`<details id="records" class="records"><summary>All records <span class="count">%d sections</span></summary>`+
945
949
  `<p class="muted">Every canonical record behind the charts above, as tables.</p>`, rest))
946
950
  for _, s := range b.secs {
947
951
  if !shown[s.anchor] {
948
- out = append(out, v.section(b, s))
952
+ out = append(out, `<details class="rec"><summary>`+esc(s.heading)+`</summary>`+v.section(b, s)+`</details>`)
949
953
  }
950
954
  }
951
955
  return append(out, "</details></main></div></body></html>")
@@ -1204,7 +1208,7 @@ func (v view) details(summary, body string) string {
1204
1208
  if body == "" {
1205
1209
  return ""
1206
1210
  }
1207
- return `<div class="blk"><h4>` + esc(summary) + `</h4>` + body + `</div>`
1211
+ return `<div class="blk"><h3>` + esc(summary) + `</h3>` + body + `</div>`
1208
1212
  }
1209
1213
 
1210
1214
  // threshold returns one scorecard threshold row: value, minimum and result.