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
@@ -0,0 +1,223 @@
1
+ package admit
2
+
3
+ import (
4
+ "os"
5
+ "path/filepath"
6
+ "strings"
7
+ "testing"
8
+ )
9
+
10
+ const packetName = "full-1__T-1__A1__implementer.json"
11
+
12
+ // packetRun builds a run area named full-1 with one dispatched attempt and
13
+ // returns the run path and the path of its valid packet.
14
+ func packetRun(t *testing.T) (string, string) {
15
+ t.Helper()
16
+ dir := filepath.Join(t.TempDir(), "work", "full-1")
17
+ write(t, filepath.Join(dir, "CURRENT"), "g0001\n")
18
+ write(t, filepath.Join(dir, "g0001/run.json"), J{"run_id": "full-1"})
19
+ write(t, filepath.Join(dir, "g0001/dispatch.json"), J{"attempts": L{
20
+ J{"task_id": "T-1", "attempt_id": "A1", "role": "implementer", "snapshot": "s1", "status": "dispatched",
21
+ "receipt": "receipts/full-1__T-1__A1__implementer.json", "packet": "packets/" + packetName},
22
+ J{"task_id": "T-1", "attempt_id": "A0", "role": "implementer", "snapshot": "s1", "status": "admitted"},
23
+ }})
24
+ pk := write(t, filepath.Join(dir, "packets", packetName), validPacket(dir))
25
+ return dir, pk
26
+ }
27
+
28
+ func validPacket(dir string) J {
29
+ return J{"run_id": "full-1", "phase": "REMEDIATING", "task_id": "T-1", "attempt_id": "A1",
30
+ "role": "implementer", "lane": "backend", "snapshot": "s1", "authorized_by": "APPROVAL-1",
31
+ "brief": "packets/BRIEF.md", "write_paths": L{"a.go"},
32
+ "receipt_path": filepath.Join(dir, "receipts", "full-1__T-1__A1__implementer.json")}
33
+ }
34
+
35
+ func TestPacketAdmit(t *testing.T) {
36
+ cases := []struct {
37
+ name string
38
+ mutate func(J)
39
+ code int
40
+ want string
41
+ }{
42
+ {"valid", func(J) {}, 0, `{"verdict": "ADMISSIBLE", "reasons": []}`},
43
+ {"missing snapshot", func(p J) { delete(p, "snapshot") }, 1, "missing or empty snapshot"},
44
+ {"missing attempt_id", func(p J) { delete(p, "attempt_id") }, 1, "missing or empty attempt_id"},
45
+ {"empty role", func(p J) { p["role"] = "" }, 1, "missing or empty role"},
46
+ {"wrong run", func(p J) { p["run_id"] = "full-2" }, 1, "run_id differs from the run"},
47
+ {"receipt elsewhere", func(p J) { p["receipt_path"] = "/elsewhere/r.json" }, 1, "receipt_path must be <run>/receipts/"},
48
+ {"snapshot mismatch", func(p J) { p["snapshot"] = "s2" }, 1, "snapshot differs from the dispatched attempt"},
49
+ {"role mismatch", func(p J) { p["role"] = "reviewer" }, 1, "role differs from the dispatched attempt"},
50
+ {"unknown attempt", func(p J) { p["attempt_id"] = "A9" }, 1, "no such dispatched attempt"},
51
+ {"already admitted", func(p J) { p["attempt_id"] = "A0" }, 3, `{"verdict": "DUPLICATE_OR_LATE", "attempt_status": "admitted"}`},
52
+ }
53
+ for _, c := range cases {
54
+ t.Run(c.name, func(t *testing.T) {
55
+ dir, _ := packetRun(t)
56
+ p := validPacket(dir)
57
+ c.mutate(p)
58
+ // the file keeps its name so only the field under test is wrong
59
+ pk := write(t, filepath.Join(dir, "packets", packetName), p)
60
+ code, out, errs := run("packet", dir, pk)
61
+ if code != c.code || !strings.Contains(out, c.want) {
62
+ t.Fatalf("want %d with %q, got %d:\n%s%s", c.code, c.want, code, out, errs)
63
+ }
64
+ })
65
+ }
66
+ }
67
+
68
+ // The dispatch.json attempt records the receipt location; a packet naming
69
+ // another run-relative receipt is not the packet that was dispatched.
70
+ func TestPacketReceiptDiffersFromAttempt(t *testing.T) {
71
+ dir, pk := packetRun(t)
72
+ write(t, filepath.Join(dir, "g0001/dispatch.json"), J{"attempts": L{
73
+ J{"task_id": "T-1", "attempt_id": "A1", "role": "implementer", "snapshot": "s1", "status": "dispatched",
74
+ "receipt": "receipts/other.json"}}})
75
+ code, out, _ := run("packet", dir, pk)
76
+ if code != 1 || !strings.Contains(out, "receipt_path differs from the dispatched attempt's receipt") {
77
+ t.Fatalf("got %d: %s", code, out)
78
+ }
79
+ }
80
+
81
+ // The attempt also records the packet location; an attempt that recorded one
82
+ // packet cannot admit a different file whose identifiers happen to match.
83
+ func TestPacketPathDiffersFromAttempt(t *testing.T) {
84
+ dir, pk := packetRun(t)
85
+ write(t, filepath.Join(dir, "g0001/dispatch.json"), J{"attempts": L{
86
+ J{"task_id": "T-1", "attempt_id": "A1", "role": "implementer", "snapshot": "s1", "status": "dispatched",
87
+ "packet": "packets/other.json"}}})
88
+ code, out, _ := run("packet", dir, pk)
89
+ if code != 1 || !strings.Contains(out, "packet path differs from the dispatched attempt's packet") {
90
+ t.Fatalf("got %d: %s", code, out)
91
+ }
92
+ }
93
+
94
+ // An attempt that records no packet key predates the field and is judged on
95
+ // the other agreements alone.
96
+ func TestPacketAttemptWithoutPacketKey(t *testing.T) {
97
+ dir, pk := packetRun(t)
98
+ write(t, filepath.Join(dir, "g0001/dispatch.json"), J{"attempts": L{
99
+ J{"task_id": "T-1", "attempt_id": "A1", "role": "implementer", "snapshot": "s1", "status": "dispatched"}}})
100
+ code, out, errs := run("packet", dir, pk)
101
+ if code != 0 || !strings.Contains(out, `"verdict": "ADMISSIBLE"`) {
102
+ t.Fatalf("got %d: %s%s", code, out, errs)
103
+ }
104
+ }
105
+
106
+ // A recorded packet path that names the same file by an unclean spelling is
107
+ // the packet that was dispatched.
108
+ func TestPacketPathUncleanSpelling(t *testing.T) {
109
+ for _, rec := range []string{"packets/./" + packetName, "./packets/../packets/" + packetName} {
110
+ t.Run(rec, func(t *testing.T) {
111
+ dir, pk := packetRun(t)
112
+ write(t, filepath.Join(dir, "g0001/dispatch.json"), J{"attempts": L{
113
+ J{"task_id": "T-1", "attempt_id": "A1", "role": "implementer", "snapshot": "s1", "status": "dispatched",
114
+ "packet": rec}}})
115
+ code, out, errs := run("packet", dir, pk)
116
+ if code != 0 || !strings.Contains(out, `"verdict": "ADMISSIBLE"`) {
117
+ t.Fatalf("got %d: %s%s", code, out, errs)
118
+ }
119
+ })
120
+ }
121
+ }
122
+
123
+ // admit packet accepts exactly the receipt_path spellings packet.Validate
124
+ // accepts: the run's receipts file, absolute or spelled from the working
125
+ // directory, and nothing else.
126
+ func TestPacketReceiptPathSpellings(t *testing.T) {
127
+ dir, pk := packetRun(t)
128
+ name := "full-1__T-1__A1__implementer.json"
129
+ for _, c := range []struct {
130
+ label, path string
131
+ code int
132
+ }{
133
+ {"bare file name", name, 1},
134
+ {"receipts/<name>", filepath.Join("receipts", name), 1},
135
+ {"another run", filepath.Join("work", "full-2", "receipts", name), 1},
136
+ {"relative to the working directory", filepath.Join("full-1", "receipts", name), 0},
137
+ } {
138
+ t.Run(c.label, func(t *testing.T) {
139
+ t.Chdir(filepath.Dir(dir))
140
+ p := validPacket(dir)
141
+ p["receipt_path"] = c.path
142
+ write(t, pk, p)
143
+ code, out, errs := run("packet", dir, pk)
144
+ if code != c.code || (c.code == 1 && !strings.Contains(out, "receipt_path must be")) {
145
+ t.Fatalf("want %d, got %d: %s%s", c.code, code, out, errs)
146
+ }
147
+ })
148
+ }
149
+ }
150
+
151
+ // A valid packet with an absolute receipt_path is admitted from an unrelated
152
+ // working directory with an absolute run path, and from the run's parent
153
+ // directory with a relative run path.
154
+ func TestPacketAdmitFromAnyCwd(t *testing.T) {
155
+ dir, pk := packetRun(t)
156
+ t.Chdir(t.TempDir())
157
+ if code, out, errs := run("packet", dir, pk); code != 0 {
158
+ t.Fatalf("absolute run: %d %s%s", code, out, errs)
159
+ }
160
+ t.Chdir(filepath.Dir(dir))
161
+ if code, out, errs := run("packet", "full-1", filepath.Join("full-1", "packets", packetName)); code != 0 {
162
+ t.Fatalf("relative run: %d %s%s", code, out, errs)
163
+ }
164
+ }
165
+
166
+ func TestPacketUsesWorkingGeneration(t *testing.T) {
167
+ dir, pk := packetRun(t)
168
+ stage := filepath.Join(dir, "g0002.tmp")
169
+ write(t, filepath.Join(stage, ".base"), "g0001")
170
+ write(t, filepath.Join(stage, "run.json"), J{"run_id": "full-1"})
171
+ write(t, filepath.Join(stage, "dispatch.json"), J{"attempts": L{}})
172
+ if code, out, _ := run("packet", dir, pk); code != 1 || !strings.Contains(out, "no such dispatched attempt") {
173
+ t.Fatalf("open stage ignored: %d %s", code, out)
174
+ }
175
+ }
176
+
177
+ func TestPacketSymlinkedPath(t *testing.T) {
178
+ dir, pk := packetRun(t)
179
+ link := filepath.Join(dir, "packets", "link.json")
180
+ if err := os.Symlink(pk, link); err != nil {
181
+ t.Skip(err)
182
+ }
183
+ if code, out, _ := run("packet", dir, link); code != 1 || !strings.Contains(out, "must not be a symlink") {
184
+ t.Fatalf("symlinked file: %d %s", code, out)
185
+ }
186
+ // a symlinked packets directory is not the run's packets directory
187
+ real := filepath.Join(t.TempDir(), "packets")
188
+ if err := os.Rename(filepath.Join(dir, "packets"), real); err != nil {
189
+ t.Fatal(err)
190
+ }
191
+ if err := os.Symlink(real, filepath.Join(dir, "packets")); err != nil {
192
+ t.Skip(err)
193
+ }
194
+ if code, out, _ := run("packet", dir, filepath.Join(dir, "packets", packetName)); code != 1 || !strings.Contains(out, "not under the run's packets directory") {
195
+ t.Fatalf("symlinked packets dir: %d %s", code, out)
196
+ }
197
+ }
198
+
199
+ func TestPacketMisplaced(t *testing.T) {
200
+ dir, pk := packetRun(t)
201
+ moved := filepath.Join(dir, "stray.json")
202
+ if err := os.Rename(pk, moved); err != nil {
203
+ t.Fatal(err)
204
+ }
205
+ code, out, _ := run("packet", dir, moved)
206
+ if code != 1 || !strings.Contains(out, "file name does not match") || !strings.Contains(out, "not under the run's packets directory") {
207
+ t.Fatalf("got %d: %s", code, out)
208
+ }
209
+ }
210
+
211
+ func TestPacketIOAndUsage(t *testing.T) {
212
+ dir, _ := packetRun(t)
213
+ if code, _, errs := run("packet", dir, filepath.Join(dir, "packets", "missing.json")); code != 2 || !strings.HasPrefix(errs, "ERROR: ") {
214
+ t.Fatalf("missing packet: %d %q", code, errs)
215
+ }
216
+ write(t, filepath.Join(dir, "packets", "bad.json"), "{not json")
217
+ if code, _, errs := run("packet", dir, filepath.Join(dir, "packets", "bad.json")); code != 2 || !strings.HasPrefix(errs, "ERROR: ") {
218
+ t.Fatalf("unparsable packet: %d %q", code, errs)
219
+ }
220
+ if code, _, errs := run("packet", dir); code != 2 || !strings.Contains(errs, "packet RUN PACKET") {
221
+ t.Fatalf("usage: %d %q", code, errs)
222
+ }
223
+ }
@@ -2,6 +2,7 @@
2
2
  // checks for worker output.
3
3
  //
4
4
  // receipt RUN RECEIPT [--observed FILE] receipt vs its dispatch packet; writers vs observed paths
5
+ // packet RUN PACKET packet shape and identity vs its dispatch attempt
5
6
  // anchor ROOT PROPOSALS every quoted location matches its file lines (ROOT = snapshot tree or repo)
6
7
  //
7
8
  // Exit: 0 admissible, 1 reject (reasons listed), 2 usage/IO error, 3 duplicate
@@ -30,6 +31,7 @@ import (
30
31
  const usage = `usage: overhaul admit <command> ...
31
32
 
32
33
  receipt RUN RECEIPT [--observed FILE] receipt vs its dispatch packet; writers vs observed paths
34
+ packet RUN PACKET packet shape and identity vs its dispatch attempt
33
35
  anchor ROOT PROPOSALS every quoted location matches its file lines (ROOT = snapshot tree or repo)
34
36
  Exit: 0 admissible, 1 reject (reasons listed), 2 usage/IO error, 3 duplicate or late receipt.
35
37
  `
@@ -57,6 +59,8 @@ func Run(args []string, stdout, stderr io.Writer) int {
57
59
  }
58
60
  }
59
61
  code, err = receipt(args[1], args[2], observed, hasObserved, stdout)
62
+ case len(args) == 3 && args[0] == "packet":
63
+ code, err = packetAdmit(args[1], args[2], stdout)
60
64
  case len(args) >= 3 && args[0] == "anchor":
61
65
  code, err = anchor(args[1], args[2], stdout, stderr)
62
66
  default:
@@ -172,6 +172,9 @@ func compare(d map[string]any) (any, error) {
172
172
  if err != nil {
173
173
  return nil, err
174
174
  }
175
+ if !(floor >= 0) {
176
+ return nil, fmt.Errorf("resolution must be a number >= 0, got %v", floor)
177
+ }
175
178
  rng, err := seeded(d)
176
179
  if err != nil {
177
180
  return nil, err
@@ -207,6 +210,9 @@ func compare(d map[string]any) (any, error) {
207
210
  hiIdx += len(boots)
208
211
  }
209
212
  bootLo, bootHi := boots[int(0.025*float64(len(boots)))], boots[hiIdx]
213
+ if math.IsInf(bootLo, 0) || math.IsInf(bootHi, 0) || math.IsNaN(bootLo) || math.IsNaN(bootHi) {
214
+ return noRatio{"NO_RATIO", "resampled medians reach zero: ratio interval is unbounded", ma, mb, bud, er, notes}, nil
215
+ }
210
216
  lo, hi := bootLo, bootHi
211
217
  target, err := number(d, "target", 1)
212
218
  if err != nil {
@@ -142,6 +142,52 @@ func TestBench(t *testing.T) {
142
142
  })
143
143
  }
144
144
 
145
+ func assertFinite(t *testing.T, v any, path string) {
146
+ t.Helper()
147
+ switch x := v.(type) {
148
+ case float64:
149
+ if math.IsInf(x, 0) || math.IsNaN(x) {
150
+ t.Fatalf("%s is not finite: %v", path, x)
151
+ }
152
+ case []any:
153
+ for i, e := range x {
154
+ assertFinite(t, e, fmt.Sprintf("%s[%d]", path, i))
155
+ }
156
+ case map[string]any:
157
+ for k, e := range x {
158
+ assertFinite(t, e, path+"."+k)
159
+ }
160
+ }
161
+ }
162
+
163
+ func TestBenchNonFiniteInputs(t *testing.T) {
164
+ fast, _ := fixture()
165
+ someZeros := append(make([]float64, 8), gauss(rand.New(rand.NewPCG(3, 0)), 10, 0.4, 12)...)
166
+
167
+ t.Run("zero-valued resamples give a finite verdict", func(t *testing.T) {
168
+ for name, d := range map[string]map[string]any{
169
+ "lower is better": with(fast, "candidate", someZeros),
170
+ "higher is better": with(fast, "direction", "higher_is_better", "baseline", someZeros, "candidate", fast["baseline"]),
171
+ } {
172
+ v, res := verdict(t, d)
173
+ if v != "NO_RATIO" && v != "INCONCLUSIVE" {
174
+ t.Fatalf("%s: got %v", name, res)
175
+ }
176
+ assertFinite(t, res, name)
177
+ }
178
+ })
179
+ t.Run("negative resolution is an error", func(t *testing.T) {
180
+ code, _, stderr := run(t, with(fast, "resolution", -1))
181
+ if code != 2 || !strings.Contains(stderr, "resolution") {
182
+ t.Fatalf("exit %d %q", code, stderr)
183
+ }
184
+ })
185
+ t.Run("every float of a normal result is finite", func(t *testing.T) {
186
+ _, res := verdict(t, fast)
187
+ assertFinite(t, res, "result")
188
+ })
189
+ }
190
+
145
191
  func TestStats(t *testing.T) {
146
192
  if k := tailCount(10, 10, 0.05); k != 24 {
147
193
  t.Fatalf("n=m=10 alpha .05: k=%d, want 24 (Hollander-Wolfe D_(24), D_(77))", k)
@@ -1,6 +1,6 @@
1
1
  // Package overhaul dispatches the deterministic tools behind the standalone
2
2
  // /overhaul skill: run-record generations and validation, worker-output
3
- // admission, baseline snapshots, readiness scoring, benchmark statistics and
3
+ // admission, dispatch packets, baseline snapshots, readiness scoring, benchmark statistics and
4
4
  // escaped offline views. It never calls a model or the network.
5
5
  package overhaul
6
6
 
@@ -10,6 +10,7 @@ import (
10
10
 
11
11
  "github.com/devrites/devrites/internal/overhaul/admit"
12
12
  "github.com/devrites/devrites/internal/overhaul/bench"
13
+ "github.com/devrites/devrites/internal/overhaul/packet"
13
14
  "github.com/devrites/devrites/internal/overhaul/records"
14
15
  "github.com/devrites/devrites/internal/overhaul/render"
15
16
  "github.com/devrites/devrites/internal/overhaul/score"
@@ -25,7 +26,9 @@ const Usage = `usage: devrites-engine overhaul <tool> ...
25
26
  overhaul records publish <run>
26
27
  overhaul records validate <run>
27
28
  overhaul admit receipt <run> <receipt.json> [--observed <paths.txt>]
29
+ overhaul admit packet <run> <packet.json>
28
30
  overhaul admit anchor <tree> <proposals.json>
31
+ overhaul packet write <run> <task> <attempt> <role> [--from <fields.json>] [--phase P] [--wave W] [--lane L] [--snapshot S] [--authorized-by A] [--brief PATH] [--write-path PATH]...
29
32
  overhaul snapshot capture <repo> <out>
30
33
  overhaul snapshot fingerprint <repo>
31
34
  overhaul snapshot verify <repo> <out> [--agent-paths <file>]
@@ -50,6 +53,8 @@ func Run(args []string, stdout, stderr io.Writer) int {
50
53
  return records.Run(rest, stdout, stderr)
51
54
  case "admit":
52
55
  return admit.Run(rest, stdout, stderr)
56
+ case "packet":
57
+ return packet.Run(rest, stdout, stderr)
53
58
  case "snapshot":
54
59
  return snapshot.Run(rest, stdout, stderr)
55
60
  case "score":
@@ -9,6 +9,7 @@ import (
9
9
  "encoding/hex"
10
10
  "encoding/json"
11
11
  "fmt"
12
+ "io"
12
13
  "os"
13
14
  "path/filepath"
14
15
  "strings"
@@ -22,11 +23,16 @@ func SHA256Bytes(b []byte) string {
22
23
 
23
24
  // SHA256File returns the lowercase hex SHA-256 of the file's exact bytes.
24
25
  func SHA256File(path string) (string, error) {
25
- b, err := os.ReadFile(path) // #nosec G304 -- callers pass operator-selected run-area paths
26
+ f, err := os.Open(path) // #nosec G304 -- callers pass operator-selected run-area paths
26
27
  if err != nil {
27
28
  return "", err
28
29
  }
29
- return SHA256Bytes(b), nil
30
+ defer func() { _ = f.Close() }()
31
+ h := sha256.New()
32
+ if _, err := io.Copy(h, f); err != nil {
33
+ return "", err
34
+ }
35
+ return hex.EncodeToString(h.Sum(nil)), nil
30
36
  }
31
37
 
32
38
  // LoadJSON decodes a UTF-8 JSON document. Numbers stay json.Number so digests,
@@ -146,7 +152,8 @@ func Truthy(v any) bool {
146
152
  case string:
147
153
  return x != ""
148
154
  case json.Number:
149
- return x.String() != "0" && x.String() != "0.0"
155
+ f, err := x.Float64()
156
+ return err != nil || f != 0
150
157
  case float64:
151
158
  return x != 0
152
159
  case []any:
@@ -0,0 +1,75 @@
1
+ package ovio
2
+
3
+ import (
4
+ "bytes"
5
+ "encoding/json"
6
+ "os"
7
+ "path/filepath"
8
+ "runtime"
9
+ "testing"
10
+ )
11
+
12
+ func TestTruthyNumberZeroSpellingsAreFalse(t *testing.T) {
13
+ t.Parallel()
14
+ for _, n := range []json.Number{"0", "0.0", "0.00", "0.000", "-0", "-0.0", "0e0", "0e-1"} {
15
+ if Truthy(n) {
16
+ t.Errorf("Truthy(json.Number(%q)) = true, want false", n)
17
+ }
18
+ }
19
+ }
20
+
21
+ func TestTruthyNumberNonZeroValuesAreTrue(t *testing.T) {
22
+ t.Parallel()
23
+ for _, n := range []json.Number{"1", "0.5", "-1", "-0.5", "1e-3", "1e400"} {
24
+ if !Truthy(n) {
25
+ t.Errorf("Truthy(json.Number(%q)) = false, want true", n)
26
+ }
27
+ }
28
+ }
29
+
30
+ func TestTruthyNumberZeroAndNonZeroAreDistinguishable(t *testing.T) {
31
+ t.Parallel()
32
+ zero, one := Truthy(json.Number("0.00")), Truthy(json.Number("1"))
33
+ if zero == one {
34
+ t.Errorf("Truthy(json.Number(\"0.00\")) = Truthy(json.Number(\"1\")) = %v, want false and true", zero)
35
+ }
36
+ }
37
+
38
+ func TestTruthyMissingAndNullKeysAreFalse(t *testing.T) {
39
+ t.Parallel()
40
+ var record map[string]any
41
+ if err := json.Unmarshal([]byte(`{"present": 1, "explicit_null": null}`), &record); err != nil {
42
+ t.Fatal(err)
43
+ }
44
+ for _, key := range []string{"absent", "explicit_null"} {
45
+ if Truthy(Get(record, key)) {
46
+ t.Errorf("Truthy(Get(record, %q)) = true, want false", key)
47
+ }
48
+ }
49
+ }
50
+
51
+ func TestSHA256FileStreamsWithoutBufferingTheFile(t *testing.T) {
52
+ const size = 32 << 20
53
+ path := filepath.Join(t.TempDir(), "big.bin")
54
+ want := func() string {
55
+ data := bytes.Repeat([]byte("0123456789abcdef"), size/16)
56
+ if err := os.WriteFile(path, data, 0o600); err != nil {
57
+ t.Fatal(err)
58
+ }
59
+ return SHA256Bytes(data)
60
+ }()
61
+ var before, after runtime.MemStats
62
+ runtime.GC()
63
+ runtime.ReadMemStats(&before)
64
+ got, err := SHA256File(path)
65
+ runtime.ReadMemStats(&after)
66
+ if err != nil {
67
+ t.Fatal(err)
68
+ }
69
+ if got != want {
70
+ t.Errorf("SHA256File digest = %s, want %s", got, want)
71
+ }
72
+ if delta := after.TotalAlloc - before.TotalAlloc; delta > 1<<20 {
73
+ t.Errorf("SHA256File allocated %d bytes for a %d byte file, want under 1MiB", delta, size)
74
+ }
75
+ }
@@ -0,0 +1,208 @@
1
+ // Package packet implements the /overhaul packet tool: it writes the dispatch
2
+ // packet for one worker attempt and validates packets on load.
3
+ //
4
+ // write RUN TASK ATTEMPT ROLE [flags] create RUN/packets/<run>__<task>__<attempt>__<role>.json
5
+ //
6
+ // A packet is a JSON object. Flags fill the common fields; --from FILE supplies
7
+ // any further fields (plan, task, read paths, budgets) and flags override it.
8
+ // Exit: 0 written, 1 invalid packet or packet already exists, 2 usage/IO error.
9
+ package packet
10
+
11
+ import (
12
+ "flag"
13
+ "fmt"
14
+ "io"
15
+ "os"
16
+ "path/filepath"
17
+ "strings"
18
+
19
+ "github.com/devrites/devrites/internal/overhaul/ovio"
20
+ )
21
+
22
+ const usage = `usage: overhaul packet <command> ...
23
+
24
+ write RUN TASK ATTEMPT ROLE [--from FILE] [--phase P] [--wave W] [--lane L]
25
+ [--snapshot S] [--authorized-by A] [--brief PATH] [--write-path PATH]...
26
+ Exit: 0 written, 1 invalid packet or packet already exists, 2 usage/IO error.
27
+ `
28
+
29
+ // required are the string fields every packet carries.
30
+ var required = []string{"run_id", "phase", "task_id", "attempt_id", "role", "lane", "snapshot", "authorized_by", "brief", "receipt_path"}
31
+
32
+ // idFields name the path components of a packet file and must be plain names.
33
+ var idFields = []string{"run_id", "task_id", "attempt_id", "role"}
34
+
35
+ type multi []string
36
+
37
+ func (m *multi) String() string { return strings.Join(*m, ",") }
38
+ func (m *multi) Set(s string) error { *m = append(*m, s); return nil }
39
+
40
+ // Run executes the tool with its arguments (tool name excluded).
41
+ func Run(args []string, stdout, stderr io.Writer) int {
42
+ if len(args) < 5 || args[0] != "write" {
43
+ fmt.Fprint(stderr, usage)
44
+ return 2
45
+ }
46
+ fs := flag.NewFlagSet("packet write", flag.ContinueOnError)
47
+ fs.SetOutput(stderr)
48
+ from := fs.String("from", "", "JSON object with further packet fields")
49
+ set := map[string]*string{}
50
+ for flagName, field := range map[string]string{
51
+ "phase": "phase", "wave": "wave", "lane": "lane", "snapshot": "snapshot",
52
+ "authorized-by": "authorized_by", "brief": "brief",
53
+ } {
54
+ set[field] = fs.String(flagName, "", field)
55
+ }
56
+ var paths multi
57
+ fs.Var(&paths, "write-path", "exact path the worker may write (repeatable)")
58
+ if err := fs.Parse(args[5:]); err != nil {
59
+ return 2
60
+ }
61
+ if fs.NArg() > 0 {
62
+ fmt.Fprintf(stderr, "ERROR: unexpected argument %q\n", fs.Arg(0))
63
+ return 2
64
+ }
65
+ run := args[1]
66
+ p := map[string]any{}
67
+ if *from != "" {
68
+ m, err := ovio.LoadObject(*from)
69
+ if err != nil {
70
+ fmt.Fprintf(stderr, "ERROR: %v\n", err)
71
+ return 2
72
+ }
73
+ p = m
74
+ }
75
+ p["run_id"], p["task_id"], p["attempt_id"], p["role"] = filepath.Base(filepath.Clean(run)), args[2], args[3], args[4]
76
+ for field, v := range set {
77
+ if *v != "" {
78
+ p[field] = *v
79
+ }
80
+ }
81
+ if _, ok := p["write_paths"]; !ok || len(paths) > 0 {
82
+ wp := []any{}
83
+ for _, w := range paths {
84
+ wp = append(wp, w)
85
+ }
86
+ p["write_paths"] = wp
87
+ }
88
+ if ovio.Str(p["receipt_path"]) == "" {
89
+ p["receipt_path"] = filepath.Join(run, "receipts", Name(p)+".json")
90
+ }
91
+ if why := Validate(run, p); len(why) > 0 {
92
+ for _, w := range why {
93
+ fmt.Fprintf(stderr, "REJECT: %s\n", w)
94
+ }
95
+ return 1
96
+ }
97
+ out, code, err := write(run, p)
98
+ if err != nil {
99
+ fmt.Fprintf(stderr, "ERROR: %v\n", err)
100
+ return code
101
+ }
102
+ fmt.Fprintln(stdout, out)
103
+ return 0
104
+ }
105
+
106
+ // Name is the packet file stem: <run>__<task>__<attempt>__<role>.
107
+ func Name(p map[string]any) string {
108
+ return strings.Join([]string{ovio.Str(p["run_id"]), ovio.Str(p["task_id"]), ovio.Str(p["attempt_id"]), ovio.Str(p["role"])}, "__")
109
+ }
110
+
111
+ // Validate returns every reason the packet is malformed for the run area run;
112
+ // none means valid. receipt_path must be a clean path that resolves to <run>/receipts/<name>.json.
113
+ func Validate(run string, p map[string]any) []string {
114
+ var why []string
115
+ for _, k := range required {
116
+ if ovio.Str(p[k]) == "" {
117
+ why = append(why, "missing or empty "+k)
118
+ }
119
+ }
120
+ for _, k := range idFields {
121
+ if s := ovio.Str(p[k]); s == "." || s == ".." || strings.ContainsAny(s, `/\`+"\x00") || strings.Contains(s, "__") {
122
+ why = append(why, k+" must be a plain name without path separators or \"__\"")
123
+ }
124
+ }
125
+ if rp := ovio.Str(p["receipt_path"]); rp != "" && !samePath(rp, filepath.Join(run, "receipts", Name(p)+".json")) {
126
+ why = append(why, "receipt_path must be <run>/receipts/<run_id>__<task_id>__<attempt_id>__<role>.json")
127
+ }
128
+ if w, ok := p["write_paths"].([]any); !ok {
129
+ why = append(why, "write_paths must be an array (empty for read-only roles)")
130
+ } else if len(ovio.Strings(w)) != len(w) {
131
+ why = append(why, "write_paths must hold only strings")
132
+ }
133
+ if pl, ok := p["plan"]; ok && ovio.Str(ovio.Obj(pl)["file"]) == "" {
134
+ why = append(why, "plan must be an object with a file")
135
+ }
136
+ return why
137
+ }
138
+
139
+ // samePath reports whether a is the clean spelling of the location b names.
140
+ func samePath(a, b string) bool {
141
+ x, err1 := filepath.Abs(a)
142
+ y, err2 := filepath.Abs(b)
143
+ return err1 == nil && err2 == nil && a == filepath.Clean(a) && x == y
144
+ }
145
+
146
+ // Load reads a packet file and validates it against the run area that holds
147
+ // its packets/ directory, including that the file name matches the packet's
148
+ // own identifiers.
149
+ func Load(path string) (map[string]any, error) {
150
+ p, err := ovio.LoadObject(path)
151
+ if err != nil {
152
+ return nil, err
153
+ }
154
+ why := Validate(filepath.Dir(filepath.Dir(path)), p)
155
+ if len(why) == 0 && filepath.Base(path) != Name(p)+".json" {
156
+ why = append(why, "file name does not match run_id, task_id, attempt_id and role")
157
+ }
158
+ if len(why) > 0 {
159
+ return nil, fmt.Errorf("%s: %s", path, strings.Join(why, "; "))
160
+ }
161
+ return p, nil
162
+ }
163
+
164
+ // write publishes the packet atomically and never replaces an existing one:
165
+ // the content is written to a temporary file that is then hard-linked into place.
166
+ func write(run string, p map[string]any) (string, int, error) {
167
+ if !realDir(run) {
168
+ return "", 2, fmt.Errorf("run area %s is not a directory", run)
169
+ }
170
+ dir := filepath.Join(run, "packets")
171
+ if err := os.MkdirAll(dir, 0o700); err != nil {
172
+ return "", 2, err
173
+ }
174
+ if !realDir(dir) {
175
+ return "", 2, fmt.Errorf("%s is not a plain directory", dir)
176
+ }
177
+ b, err := ovio.MarshalIndent(p)
178
+ if err != nil {
179
+ return "", 2, err
180
+ }
181
+ tmp, err := os.CreateTemp(dir, ".packet-*.tmp")
182
+ if err != nil {
183
+ return "", 2, err
184
+ }
185
+ defer func() { _ = os.Remove(tmp.Name()) }()
186
+ if _, err := tmp.Write(b); err != nil {
187
+ _ = tmp.Close()
188
+ return "", 2, err
189
+ }
190
+ if err := tmp.Close(); err != nil {
191
+ return "", 2, err
192
+ }
193
+ dest := filepath.Join(dir, Name(p)+".json")
194
+ if err := os.Link(tmp.Name(), dest); err != nil {
195
+ if os.IsExist(err) {
196
+ return "", 1, fmt.Errorf("packet %s already exists", dest)
197
+ }
198
+ return "", 2, err
199
+ }
200
+ return dest, 0, nil
201
+ }
202
+
203
+ // realDir reports whether path is a directory and not a symlink to one, so a
204
+ // packet is never written through a link out of the run area.
205
+ func realDir(path string) bool {
206
+ st, err := os.Lstat(filepath.Clean(path))
207
+ return err == nil && st.IsDir()
208
+ }