devrites 3.0.6 → 3.1.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 (472) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +67 -45
  3. package/SECURITY.md +31 -29
  4. package/docs/adr/0001-go-engine-as-control-plane.md +1 -1
  5. package/docs/adr/0002-dual-host-harness.md +1 -1
  6. package/docs/adr/0004-state-schema-phases-sections.md +1 -2
  7. package/docs/adr/0006-clock-seam-and-engine-ci-gates.md +3 -4
  8. package/docs/adr/0009-prebuild-decision-coverage-and-readiness.md +67 -0
  9. package/docs/adr/0010-agent-first-fresh-context-orchestration.md +71 -0
  10. package/docs/adr/0011-define-plan-transition-rights.md +28 -0
  11. package/docs/adr/README.md +3 -0
  12. package/docs/agents/triage-labels.md +7 -7
  13. package/docs/architecture.md +157 -140
  14. package/docs/cli.md +41 -12
  15. package/docs/command-map.md +49 -35
  16. package/docs/engine/agent-contract.md +92 -15
  17. package/docs/engine/commands.md +242 -72
  18. package/docs/engine/state-schema.md +52 -23
  19. package/docs/engine/workspace-schema.md +94 -15
  20. package/docs/extensions.md +1 -1
  21. package/docs/flow.md +80 -50
  22. package/docs/harness-compliance.md +29 -5
  23. package/docs/orchestration.md +107 -79
  24. package/docs/quick-reference.md +7 -3
  25. package/docs/release.md +4 -3
  26. package/docs/skills.md +64 -38
  27. package/docs/usage.md +57 -38
  28. package/engine/cmd/releasepack/main.go +219 -0
  29. package/engine/cmd/releasepack/main_test.go +170 -0
  30. package/engine/commands.go +170 -23
  31. package/engine/git_guard.go +187 -0
  32. package/engine/git_guard_test.go +283 -0
  33. package/engine/hookpolicy.go +53 -55
  34. package/engine/hookpolicy_test.go +91 -1
  35. package/engine/hooks.go +296 -75
  36. package/engine/hooks_events_test.go +276 -6
  37. package/engine/hooks_workspace.go +640 -159
  38. package/engine/internal/devritespaths/paths.go +65 -10
  39. package/engine/internal/devritespaths/paths_test.go +110 -0
  40. package/engine/internal/doctor/doctor.go +153 -23
  41. package/engine/internal/doctor/doctor_test.go +74 -0
  42. package/engine/internal/forge/forge.go +940 -0
  43. package/engine/internal/forge/forge_test.go +576 -0
  44. package/engine/internal/forge/git.go +245 -0
  45. package/engine/internal/forge/liveness_unix.go +48 -0
  46. package/engine/internal/forge/liveness_windows.go +67 -0
  47. package/engine/internal/forge/manifest.go +402 -0
  48. package/engine/internal/gate/gate.go +90 -71
  49. package/engine/internal/gate/gate_test.go +71 -2
  50. package/engine/internal/harness/compliance.go +18 -24
  51. package/engine/internal/harness/harness.go +37 -44
  52. package/engine/internal/harness/harness_test.go +21 -5
  53. package/engine/internal/install/install.go +575 -58
  54. package/engine/internal/install/install_test.go +490 -9
  55. package/engine/internal/iohooks/iohooks.go +350 -59
  56. package/engine/internal/iohooks/iohooks_test.go +421 -1
  57. package/engine/internal/lib/buildreadiness.go +35 -18
  58. package/engine/internal/lib/clarifyreturn.go +91 -0
  59. package/engine/internal/lib/clarifyreturn_test.go +123 -0
  60. package/engine/internal/lib/context.go +54 -15
  61. package/engine/internal/lib/cursor_compat_test.go +8 -0
  62. package/engine/internal/lib/extensions.go +2 -3
  63. package/engine/internal/lib/gitauthority.go +601 -0
  64. package/engine/internal/lib/gitauthority_test.go +346 -0
  65. package/engine/internal/lib/jsonout.go +25 -11
  66. package/engine/internal/lib/jsonout_test.go +16 -0
  67. package/engine/internal/lib/lanes.go +14 -8
  68. package/engine/internal/lib/observability_test.go +358 -0
  69. package/engine/internal/lib/packageexistence.go +151 -35
  70. package/engine/internal/lib/packageexistence_test.go +163 -0
  71. package/engine/internal/lib/progress.go +11 -9
  72. package/engine/internal/lib/provenance.go +462 -0
  73. package/engine/internal/lib/provenance_test.go +154 -0
  74. package/engine/internal/lib/readiness_contract.json +111 -0
  75. package/engine/internal/lib/readinessartifact.go +510 -0
  76. package/engine/internal/lib/readinessartifact_test.go +321 -0
  77. package/engine/internal/lib/reconcile.go +712 -88
  78. package/engine/internal/lib/reconcile_test.go +335 -16
  79. package/engine/internal/lib/recoveryattempts.go +298 -0
  80. package/engine/internal/lib/recoveryattempts_test.go +215 -0
  81. package/engine/internal/lib/resolve.go +23 -19
  82. package/engine/internal/lib/runbook_context_test.go +20 -0
  83. package/engine/internal/lib/session.go +701 -9
  84. package/engine/internal/lib/session_test.go +80 -13
  85. package/engine/internal/lib/testintegrity.go +33 -37
  86. package/engine/internal/lib/testintegrity_test.go +63 -1
  87. package/engine/internal/migrate/migrate.go +81 -1
  88. package/engine/internal/migrate/migrate_test.go +22 -1
  89. package/engine/internal/reason/reason.go +180 -0
  90. package/engine/internal/reason/reason_test.go +35 -0
  91. package/engine/internal/rootfacts/facts.go +466 -0
  92. package/engine/internal/rootfacts/facts_test.go +306 -0
  93. package/engine/internal/safepath/safepath.go +55 -0
  94. package/engine/internal/safepath/safepath_test.go +69 -0
  95. package/engine/internal/safepath/safepath_windows_test.go +26 -0
  96. package/engine/internal/state/clarify_transition.go +165 -0
  97. package/engine/internal/state/clarify_transition_test.go +130 -0
  98. package/engine/internal/state/cmd/workflowmanifest/main.go +12 -8
  99. package/engine/internal/state/cursor.go +58 -0
  100. package/engine/internal/state/cursor_test.go +42 -1
  101. package/engine/internal/state/feature.go +35 -48
  102. package/engine/internal/state/schema.go +90 -37
  103. package/engine/internal/state/snapshot.go +18 -2
  104. package/engine/internal/state/state_test.go +187 -7
  105. package/engine/internal/state/status.go +48 -11
  106. package/engine/internal/state/workflow_manifest.json +231 -50
  107. package/engine/internal/toolpolicy/classifier.go +533 -0
  108. package/engine/internal/toolpolicy/classifier_test.go +424 -0
  109. package/engine/internal/toolpolicy/git.go +616 -0
  110. package/engine/internal/toolpolicy/scanner.go +382 -0
  111. package/engine/main.go +160 -77
  112. package/engine/observability_cli_test.go +52 -0
  113. package/engine/root_routing_test.go +277 -0
  114. package/engine/testdata/golden/TestParityBuildReadiness/arg=approved.golden +1 -1
  115. package/engine/testdata/golden/TestParityBuildReadiness/arg=emptystatus.golden +1 -1
  116. package/engine/testdata/golden/TestParityBuildReadiness/arg=noclarify.golden +1 -0
  117. package/engine/testdata/golden/TestParityBuildReadiness/arg=novet.golden +1 -0
  118. package/engine/testdata/golden/TestParityBuildReadiness/arg=stalevet.golden +1 -0
  119. package/engine/testdata/golden/TestParityBuildReadiness/arg=trailhash.golden +1 -1
  120. package/engine/testdata/golden/TestParityBuildReadiness/arg=trailpipe.golden +1 -1
  121. package/engine/testdata/golden/TestParityBuildReadiness/arg=vetnotready.golden +1 -0
  122. package/engine/testdata/golden/TestParityProgress/arg=allbuilt.golden +1 -1
  123. package/engine/testdata/golden/TestParityProgress/arg=done.golden +1 -1
  124. package/engine/testdata/golden/TestParityProgress/arg=mid.golden +1 -1
  125. package/engine/testdata/golden/TestParityProgress/arg=nophase.golden +1 -1
  126. package/engine/testdata/golden/TestParityProgress/arg=noslice.golden +1 -1
  127. package/engine/testdata/golden/TestParityProgress/arg=plan.golden +1 -1
  128. package/engine/testdata/golden/TestParityProgress/arg=seal.golden +1 -1
  129. package/engine/testdata/golden/TestParityReconcile/check-clean.golden +1 -1
  130. package/engine/testdata/golden/TestParityReconcile/inline-fallback.golden +1 -0
  131. package/engine/testdata/golden/TestParityReconcile/snapshot-no-allowlist.golden +1 -0
  132. package/engine/testdata/golden/TestParityWrightScope/devrites-edit-denied.golden +2 -0
  133. package/engine/testdata/golden/TestParityWrightScope/out-of-scope-enforce-denies.golden +1 -1
  134. package/engine/tests/adr_0011_define_plan_test.go +30 -0
  135. package/engine/tests/budget_test.go +19 -8
  136. package/engine/tests/concurrency_cli_test.go +7 -1
  137. package/engine/tests/doctor_cli_test.go +148 -2
  138. package/engine/tests/forge_cli_test.go +463 -0
  139. package/engine/tests/gate_test.go +63 -8
  140. package/engine/tests/hook_test.go +260 -8
  141. package/engine/tests/hooks_io_test.go +94 -3
  142. package/engine/tests/json_contract_test.go +127 -2
  143. package/engine/tests/migrate_cli_test.go +2 -2
  144. package/engine/tests/parity_buildreadiness_test.go +141 -10
  145. package/engine/tests/parity_learnings_test.go +16 -17
  146. package/engine/tests/parity_reconcile_test.go +20 -17
  147. package/engine/tests/parity_resolve_test.go +12 -11
  148. package/engine/tests/parity_test.go +21 -17
  149. package/pack/.claude/agents/devrites-code-reviewer.md +62 -48
  150. package/pack/.claude/agents/devrites-devex-reviewer.md +69 -53
  151. package/pack/.claude/agents/devrites-doubt-reviewer.md +29 -22
  152. package/pack/.claude/agents/devrites-evidence-scout.md +69 -0
  153. package/pack/.claude/agents/devrites-forge-judge.md +74 -61
  154. package/pack/.claude/agents/devrites-frontend-reviewer.md +48 -39
  155. package/pack/.claude/agents/devrites-performance-reviewer.md +49 -40
  156. package/pack/.claude/agents/devrites-plan-drafter.md +71 -0
  157. package/pack/.claude/agents/devrites-plan-reviewer.md +80 -47
  158. package/pack/.claude/agents/devrites-proof-runner.md +74 -0
  159. package/pack/.claude/agents/devrites-retrospector.md +48 -45
  160. package/pack/.claude/agents/devrites-security-auditor.md +46 -36
  161. package/pack/.claude/agents/devrites-simplifier-reviewer.md +50 -46
  162. package/pack/.claude/agents/devrites-slice-wright.md +153 -165
  163. package/pack/.claude/agents/devrites-spec-reviewer.md +34 -32
  164. package/pack/.claude/agents/devrites-strategy-reviewer.md +63 -34
  165. package/pack/.claude/agents/devrites-test-analyst.md +40 -30
  166. package/pack/.claude/settings.json +2 -1
  167. package/pack/.claude/skills/devrites-audit/SKILL.md +40 -61
  168. package/pack/.claude/skills/devrites-debug-recovery/SKILL.md +24 -13
  169. package/pack/.claude/skills/devrites-debug-recovery/reference/build-the-loop.md +24 -21
  170. package/pack/.claude/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +34 -6
  171. package/pack/.claude/skills/devrites-debug-recovery/reference/instrumentation.md +2 -2
  172. package/pack/.claude/skills/devrites-doubt/SKILL.md +25 -17
  173. package/pack/.claude/skills/devrites-interview/SKILL.md +53 -52
  174. package/pack/.claude/skills/devrites-lib/SKILL.md +11 -9
  175. package/pack/.claude/skills/devrites-lib/reference/intent-map.md +3 -2
  176. package/pack/.claude/skills/devrites-lib/reference/parallel-dispatch.md +82 -137
  177. package/pack/.claude/skills/devrites-lib/reference/reply-contract.md +8 -1
  178. package/pack/.claude/skills/devrites-lib/reference/standards/README.md +38 -55
  179. package/pack/.claude/skills/devrites-lib/reference/standards/afk-hitl.md +53 -27
  180. package/pack/.claude/skills/devrites-lib/reference/standards/agents.md +198 -190
  181. package/pack/.claude/skills/devrites-lib/reference/standards/anti-patterns.md +5 -15
  182. package/pack/.claude/skills/devrites-lib/reference/standards/ci-cd.md +27 -58
  183. package/pack/.claude/skills/devrites-lib/reference/standards/code-review.md +16 -52
  184. package/pack/.claude/skills/devrites-lib/reference/standards/coding-style.md +2 -10
  185. package/pack/.claude/skills/devrites-lib/reference/standards/context-hygiene.md +18 -61
  186. package/pack/.claude/skills/devrites-lib/reference/standards/core.md +23 -18
  187. package/pack/.claude/skills/devrites-lib/reference/standards/deprecation.md +17 -57
  188. package/pack/.claude/skills/devrites-lib/reference/standards/development-workflow.md +4 -33
  189. package/pack/.claude/skills/devrites-lib/reference/standards/git-workflow.md +4 -20
  190. package/pack/.claude/skills/devrites-lib/reference/standards/hooks.md +3 -14
  191. package/pack/.claude/skills/devrites-lib/reference/standards/patterns.md +9 -25
  192. package/pack/.claude/skills/devrites-lib/reference/standards/performance.md +0 -9
  193. package/pack/.claude/skills/devrites-lib/reference/standards/principles.md +1 -3
  194. package/pack/.claude/skills/devrites-lib/reference/standards/security.md +17 -7
  195. package/pack/.claude/skills/devrites-lib/reference/standards/testing.md +1 -27
  196. package/pack/.claude/skills/devrites-lib/reference/standards/tooling.md +46 -50
  197. package/pack/.claude/skills/devrites-lib/reference/workspace-artifact-schema.md +23 -10
  198. package/pack/.claude/skills/devrites-source-driven/SKILL.md +23 -22
  199. package/pack/.claude/skills/rite/SKILL.md +8 -6
  200. package/pack/.claude/skills/rite/reference/menu.md +8 -6
  201. package/pack/.claude/skills/rite-adopt/SKILL.md +33 -37
  202. package/pack/.claude/skills/rite-autocomplete/SKILL.md +33 -28
  203. package/pack/.claude/skills/rite-autocomplete/reference/loop.md +21 -21
  204. package/pack/.claude/skills/rite-autocomplete/reference/stop-conditions.md +15 -6
  205. package/pack/.claude/skills/rite-build/SKILL.md +35 -30
  206. package/pack/.claude/skills/rite-build/reference/afk-discipline.md +38 -38
  207. package/pack/.claude/skills/rite-build/reference/evidence-standard.md +10 -0
  208. package/pack/.claude/skills/rite-build/reference/forge.md +186 -156
  209. package/pack/.claude/skills/rite-build/reference/one-slice-cycle.md +4 -3
  210. package/pack/.claude/skills/rite-build/reference/phase-contract.md +96 -175
  211. package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +129 -134
  212. package/pack/.claude/skills/rite-clarify/SKILL.md +89 -0
  213. package/pack/.claude/skills/rite-clarify/reference/decision-coverage.md +59 -0
  214. package/pack/.claude/skills/rite-converge/SKILL.md +35 -25
  215. package/pack/.claude/skills/rite-define/SKILL.md +57 -32
  216. package/pack/.claude/skills/rite-define/reference/gates.md +16 -15
  217. package/pack/.claude/skills/rite-define/reference/plan-template.md +16 -8
  218. package/pack/.claude/skills/rite-frame/reference/failure-modes.md +22 -24
  219. package/pack/.claude/skills/rite-plan/SKILL.md +44 -16
  220. package/pack/.claude/skills/rite-plan/reference/task-breakdown.md +4 -0
  221. package/pack/.claude/skills/rite-polish/SKILL.md +27 -23
  222. package/pack/.claude/skills/rite-prototype/SKILL.md +25 -26
  223. package/pack/.claude/skills/rite-prove/SKILL.md +27 -17
  224. package/pack/.claude/skills/rite-resolve/SKILL.md +12 -11
  225. package/pack/.claude/skills/rite-resolve/reference/answer-protocol.md +3 -0
  226. package/pack/.claude/skills/rite-review/SKILL.md +37 -28
  227. package/pack/.claude/skills/rite-seal/reference/phase-contract.md +27 -92
  228. package/pack/.claude/skills/rite-seal/reference/risk-and-rollback.md +13 -0
  229. package/pack/.claude/skills/rite-ship/reference/design-memory.md +31 -36
  230. package/pack/.claude/skills/rite-spec/SKILL.md +84 -135
  231. package/pack/.claude/skills/rite-spec/reference/investigation.md +37 -33
  232. package/pack/.claude/skills/rite-spec/reference/question-protocol.md +6 -2
  233. package/pack/.claude/skills/rite-spec/reference/spec-checklists.md +25 -24
  234. package/pack/.claude/skills/rite-spec/reference/spec-template.md +9 -2
  235. package/pack/.claude/skills/rite-spec/reference/state-workspace.md +13 -3
  236. package/pack/.claude/skills/rite-temper/SKILL.md +62 -47
  237. package/pack/.claude/skills/rite-temper/reference/review-dimensions.md +24 -22
  238. package/pack/.claude/skills/rite-vet/SKILL.md +110 -113
  239. package/pack/.claude/skills/rite-vet/reference/artifacts.md +42 -9
  240. package/pack/.claude/skills/rite-vet/reference/review-axes.md +39 -37
  241. package/pack/generated/claude/agents/devrites-code-reviewer.md +62 -48
  242. package/pack/generated/claude/agents/devrites-devex-reviewer.md +69 -53
  243. package/pack/generated/claude/agents/devrites-doubt-reviewer.md +29 -22
  244. package/pack/generated/claude/agents/devrites-evidence-scout.md +69 -0
  245. package/pack/generated/claude/agents/devrites-forge-judge.md +74 -61
  246. package/pack/generated/claude/agents/devrites-frontend-reviewer.md +48 -39
  247. package/pack/generated/claude/agents/devrites-performance-reviewer.md +49 -40
  248. package/pack/generated/claude/agents/devrites-plan-drafter.md +71 -0
  249. package/pack/generated/claude/agents/devrites-plan-reviewer.md +80 -47
  250. package/pack/generated/claude/agents/devrites-proof-runner.md +74 -0
  251. package/pack/generated/claude/agents/devrites-retrospector.md +48 -45
  252. package/pack/generated/claude/agents/devrites-security-auditor.md +46 -36
  253. package/pack/generated/claude/agents/devrites-simplifier-reviewer.md +50 -46
  254. package/pack/generated/claude/agents/devrites-slice-wright.md +153 -165
  255. package/pack/generated/claude/agents/devrites-spec-reviewer.md +34 -32
  256. package/pack/generated/claude/agents/devrites-strategy-reviewer.md +63 -34
  257. package/pack/generated/claude/agents/devrites-test-analyst.md +40 -30
  258. package/pack/generated/claude/settings.json +2 -1
  259. package/pack/generated/claude/skills/devrites-audit/SKILL.md +40 -61
  260. package/pack/generated/claude/skills/devrites-debug-recovery/SKILL.md +24 -13
  261. package/pack/generated/claude/skills/devrites-debug-recovery/reference/build-the-loop.md +24 -21
  262. package/pack/generated/claude/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +34 -6
  263. package/pack/generated/claude/skills/devrites-debug-recovery/reference/instrumentation.md +2 -2
  264. package/pack/generated/claude/skills/devrites-doubt/SKILL.md +25 -17
  265. package/pack/generated/claude/skills/devrites-interview/SKILL.md +53 -52
  266. package/pack/generated/claude/skills/devrites-lib/SKILL.md +11 -9
  267. package/pack/generated/claude/skills/devrites-lib/reference/intent-map.md +3 -2
  268. package/pack/generated/claude/skills/devrites-lib/reference/parallel-dispatch.md +82 -137
  269. package/pack/generated/claude/skills/devrites-lib/reference/reply-contract.md +8 -1
  270. package/pack/generated/claude/skills/devrites-lib/reference/standards/README.md +38 -55
  271. package/pack/generated/claude/skills/devrites-lib/reference/standards/afk-hitl.md +53 -27
  272. package/pack/generated/claude/skills/devrites-lib/reference/standards/agents.md +198 -190
  273. package/pack/generated/claude/skills/devrites-lib/reference/standards/anti-patterns.md +5 -15
  274. package/pack/generated/claude/skills/devrites-lib/reference/standards/ci-cd.md +27 -58
  275. package/pack/generated/claude/skills/devrites-lib/reference/standards/code-review.md +16 -52
  276. package/pack/generated/claude/skills/devrites-lib/reference/standards/coding-style.md +2 -10
  277. package/pack/generated/claude/skills/devrites-lib/reference/standards/context-hygiene.md +18 -61
  278. package/pack/generated/claude/skills/devrites-lib/reference/standards/core.md +23 -18
  279. package/pack/generated/claude/skills/devrites-lib/reference/standards/deprecation.md +17 -57
  280. package/pack/generated/claude/skills/devrites-lib/reference/standards/development-workflow.md +4 -33
  281. package/pack/generated/claude/skills/devrites-lib/reference/standards/git-workflow.md +4 -20
  282. package/pack/generated/claude/skills/devrites-lib/reference/standards/hooks.md +3 -14
  283. package/pack/generated/claude/skills/devrites-lib/reference/standards/patterns.md +9 -25
  284. package/pack/generated/claude/skills/devrites-lib/reference/standards/performance.md +0 -9
  285. package/pack/generated/claude/skills/devrites-lib/reference/standards/principles.md +1 -3
  286. package/pack/generated/claude/skills/devrites-lib/reference/standards/security.md +17 -7
  287. package/pack/generated/claude/skills/devrites-lib/reference/standards/testing.md +1 -27
  288. package/pack/generated/claude/skills/devrites-lib/reference/standards/tooling.md +46 -50
  289. package/pack/generated/claude/skills/devrites-lib/reference/workspace-artifact-schema.md +23 -10
  290. package/pack/generated/claude/skills/devrites-source-driven/SKILL.md +23 -22
  291. package/pack/generated/claude/skills/rite/SKILL.md +8 -6
  292. package/pack/generated/claude/skills/rite/reference/menu.md +8 -6
  293. package/pack/generated/claude/skills/rite-adopt/SKILL.md +33 -37
  294. package/pack/generated/claude/skills/rite-autocomplete/SKILL.md +33 -28
  295. package/pack/generated/claude/skills/rite-autocomplete/reference/loop.md +21 -21
  296. package/pack/generated/claude/skills/rite-autocomplete/reference/stop-conditions.md +15 -6
  297. package/pack/generated/claude/skills/rite-build/SKILL.md +35 -30
  298. package/pack/generated/claude/skills/rite-build/reference/afk-discipline.md +38 -38
  299. package/pack/generated/claude/skills/rite-build/reference/evidence-standard.md +10 -0
  300. package/pack/generated/claude/skills/rite-build/reference/forge.md +186 -156
  301. package/pack/generated/claude/skills/rite-build/reference/one-slice-cycle.md +4 -3
  302. package/pack/generated/claude/skills/rite-build/reference/phase-contract.md +96 -175
  303. package/pack/generated/claude/skills/rite-build/reference/wright-dispatch.md +129 -134
  304. package/pack/generated/claude/skills/rite-clarify/SKILL.md +89 -0
  305. package/pack/generated/claude/skills/rite-clarify/reference/decision-coverage.md +59 -0
  306. package/pack/generated/claude/skills/rite-converge/SKILL.md +35 -25
  307. package/pack/generated/claude/skills/rite-define/SKILL.md +57 -32
  308. package/pack/generated/claude/skills/rite-define/reference/gates.md +16 -15
  309. package/pack/generated/claude/skills/rite-define/reference/plan-template.md +16 -8
  310. package/pack/generated/claude/skills/rite-frame/reference/failure-modes.md +22 -24
  311. package/pack/generated/claude/skills/rite-plan/SKILL.md +44 -16
  312. package/pack/generated/claude/skills/rite-plan/reference/task-breakdown.md +4 -0
  313. package/pack/generated/claude/skills/rite-polish/SKILL.md +27 -23
  314. package/pack/generated/claude/skills/rite-prototype/SKILL.md +25 -26
  315. package/pack/generated/claude/skills/rite-prove/SKILL.md +27 -17
  316. package/pack/generated/claude/skills/rite-resolve/SKILL.md +12 -11
  317. package/pack/generated/claude/skills/rite-resolve/reference/answer-protocol.md +3 -0
  318. package/pack/generated/claude/skills/rite-review/SKILL.md +37 -28
  319. package/pack/generated/claude/skills/rite-seal/reference/phase-contract.md +27 -92
  320. package/pack/generated/claude/skills/rite-seal/reference/risk-and-rollback.md +13 -0
  321. package/pack/generated/claude/skills/rite-ship/reference/design-memory.md +31 -36
  322. package/pack/generated/claude/skills/rite-spec/SKILL.md +84 -135
  323. package/pack/generated/claude/skills/rite-spec/reference/investigation.md +37 -33
  324. package/pack/generated/claude/skills/rite-spec/reference/question-protocol.md +6 -2
  325. package/pack/generated/claude/skills/rite-spec/reference/spec-checklists.md +25 -24
  326. package/pack/generated/claude/skills/rite-spec/reference/spec-template.md +9 -2
  327. package/pack/generated/claude/skills/rite-spec/reference/state-workspace.md +13 -3
  328. package/pack/generated/claude/skills/rite-temper/SKILL.md +62 -47
  329. package/pack/generated/claude/skills/rite-temper/reference/review-dimensions.md +24 -22
  330. package/pack/generated/claude/skills/rite-vet/SKILL.md +110 -113
  331. package/pack/generated/claude/skills/rite-vet/reference/artifacts.md +42 -9
  332. package/pack/generated/claude/skills/rite-vet/reference/review-axes.md +39 -37
  333. package/pack/generated/codex/AGENTS.md +5 -2
  334. package/pack/generated/codex/agents/devrites-code-reviewer.toml +69 -47
  335. package/pack/generated/codex/agents/devrites-devex-reviewer.toml +75 -51
  336. package/pack/generated/codex/agents/devrites-doubt-reviewer.toml +35 -20
  337. package/pack/generated/codex/agents/devrites-evidence-scout.toml +75 -0
  338. package/pack/generated/codex/agents/devrites-forge-judge.toml +80 -59
  339. package/pack/generated/codex/agents/devrites-frontend-reviewer.toml +54 -37
  340. package/pack/generated/codex/agents/devrites-performance-reviewer.toml +55 -38
  341. package/pack/generated/codex/agents/devrites-plan-drafter.toml +77 -0
  342. package/pack/generated/codex/agents/devrites-plan-reviewer.toml +82 -47
  343. package/pack/generated/codex/agents/devrites-proof-runner.toml +80 -0
  344. package/pack/generated/codex/agents/devrites-retrospector.toml +54 -43
  345. package/pack/generated/codex/agents/devrites-security-auditor.toml +53 -35
  346. package/pack/generated/codex/agents/devrites-simplifier-reviewer.toml +56 -44
  347. package/pack/generated/codex/agents/devrites-slice-wright.toml +159 -163
  348. package/pack/generated/codex/agents/devrites-spec-reviewer.toml +40 -30
  349. package/pack/generated/codex/agents/devrites-strategy-reviewer.toml +65 -34
  350. package/pack/generated/codex/agents/devrites-test-analyst.toml +46 -28
  351. package/pack/generated/codex/hooks.json +4 -14
  352. package/pack/generated/codex/skills/devrites-api-interface/SKILL.md +7 -3
  353. package/pack/generated/codex/skills/devrites-audit/SKILL.md +47 -64
  354. package/pack/generated/codex/skills/devrites-browser-proof/SKILL.md +7 -3
  355. package/pack/generated/codex/skills/devrites-debug-recovery/SKILL.md +31 -16
  356. package/pack/generated/codex/skills/devrites-debug-recovery/reference/build-the-loop.md +24 -21
  357. package/pack/generated/codex/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +34 -6
  358. package/pack/generated/codex/skills/devrites-debug-recovery/reference/instrumentation.md +2 -2
  359. package/pack/generated/codex/skills/devrites-doubt/SKILL.md +32 -20
  360. package/pack/generated/codex/skills/devrites-frontend-craft/SKILL.md +7 -3
  361. package/pack/generated/codex/skills/devrites-interview/SKILL.md +60 -55
  362. package/pack/generated/codex/skills/devrites-lib/SKILL.md +18 -12
  363. package/pack/generated/codex/skills/devrites-lib/reference/intent-map.md +3 -2
  364. package/pack/generated/codex/skills/devrites-lib/reference/parallel-dispatch.md +82 -137
  365. package/pack/generated/codex/skills/devrites-lib/reference/reply-contract.md +8 -1
  366. package/pack/generated/codex/skills/devrites-lib/reference/standards/README.md +38 -55
  367. package/pack/generated/codex/skills/devrites-lib/reference/standards/afk-hitl.md +53 -27
  368. package/pack/generated/codex/skills/devrites-lib/reference/standards/agents.md +198 -190
  369. package/pack/generated/codex/skills/devrites-lib/reference/standards/anti-patterns.md +5 -15
  370. package/pack/generated/codex/skills/devrites-lib/reference/standards/ci-cd.md +27 -58
  371. package/pack/generated/codex/skills/devrites-lib/reference/standards/code-review.md +16 -52
  372. package/pack/generated/codex/skills/devrites-lib/reference/standards/coding-style.md +2 -10
  373. package/pack/generated/codex/skills/devrites-lib/reference/standards/context-hygiene.md +18 -61
  374. package/pack/generated/codex/skills/devrites-lib/reference/standards/core.md +23 -18
  375. package/pack/generated/codex/skills/devrites-lib/reference/standards/deprecation.md +17 -57
  376. package/pack/generated/codex/skills/devrites-lib/reference/standards/development-workflow.md +4 -33
  377. package/pack/generated/codex/skills/devrites-lib/reference/standards/git-workflow.md +4 -20
  378. package/pack/generated/codex/skills/devrites-lib/reference/standards/hooks.md +3 -14
  379. package/pack/generated/codex/skills/devrites-lib/reference/standards/patterns.md +9 -25
  380. package/pack/generated/codex/skills/devrites-lib/reference/standards/performance.md +0 -9
  381. package/pack/generated/codex/skills/devrites-lib/reference/standards/principles.md +1 -3
  382. package/pack/generated/codex/skills/devrites-lib/reference/standards/security.md +17 -7
  383. package/pack/generated/codex/skills/devrites-lib/reference/standards/testing.md +1 -27
  384. package/pack/generated/codex/skills/devrites-lib/reference/standards/tooling.md +46 -50
  385. package/pack/generated/codex/skills/devrites-lib/reference/workspace-artifact-schema.md +23 -10
  386. package/pack/generated/codex/skills/devrites-prose-craft/SKILL.md +7 -3
  387. package/pack/generated/codex/skills/devrites-refresh-indexes/SKILL.md +7 -3
  388. package/pack/generated/codex/skills/devrites-source-driven/SKILL.md +29 -24
  389. package/pack/generated/codex/skills/devrites-ux-shape/SKILL.md +7 -3
  390. package/pack/generated/codex/skills/rite/SKILL.md +19 -13
  391. package/pack/generated/codex/skills/rite/reference/menu.md +8 -6
  392. package/pack/generated/codex/skills/rite-adopt/SKILL.md +40 -40
  393. package/pack/generated/codex/skills/rite-autocomplete/SKILL.md +40 -31
  394. package/pack/generated/codex/skills/rite-autocomplete/reference/loop.md +21 -21
  395. package/pack/generated/codex/skills/rite-autocomplete/reference/stop-conditions.md +15 -6
  396. package/pack/generated/codex/skills/rite-build/SKILL.md +42 -33
  397. package/pack/generated/codex/skills/rite-build/reference/afk-discipline.md +38 -38
  398. package/pack/generated/codex/skills/rite-build/reference/evidence-standard.md +10 -0
  399. package/pack/generated/codex/skills/rite-build/reference/forge.md +186 -156
  400. package/pack/generated/codex/skills/rite-build/reference/one-slice-cycle.md +4 -3
  401. package/pack/generated/codex/skills/rite-build/reference/phase-contract.md +96 -175
  402. package/pack/generated/codex/skills/rite-build/reference/wright-dispatch.md +129 -134
  403. package/pack/generated/codex/skills/rite-clarify/SKILL.md +105 -0
  404. package/pack/generated/codex/skills/rite-clarify/reference/decision-coverage.md +59 -0
  405. package/pack/generated/codex/skills/rite-converge/SKILL.md +42 -28
  406. package/pack/generated/codex/skills/rite-customize/SKILL.md +7 -3
  407. package/pack/generated/codex/skills/rite-define/SKILL.md +64 -35
  408. package/pack/generated/codex/skills/rite-define/reference/gates.md +16 -15
  409. package/pack/generated/codex/skills/rite-define/reference/plan-template.md +16 -8
  410. package/pack/generated/codex/skills/rite-doctor/SKILL.md +7 -3
  411. package/pack/generated/codex/skills/rite-dogfood/SKILL.md +7 -3
  412. package/pack/generated/codex/skills/rite-explain/SKILL.md +7 -3
  413. package/pack/generated/codex/skills/rite-frame/SKILL.md +7 -3
  414. package/pack/generated/codex/skills/rite-frame/reference/failure-modes.md +22 -24
  415. package/pack/generated/codex/skills/rite-handoff/SKILL.md +7 -3
  416. package/pack/generated/codex/skills/rite-learn/SKILL.md +7 -3
  417. package/pack/generated/codex/skills/rite-plan/SKILL.md +51 -19
  418. package/pack/generated/codex/skills/rite-plan/reference/task-breakdown.md +5 -1
  419. package/pack/generated/codex/skills/rite-polish/SKILL.md +34 -26
  420. package/pack/generated/codex/skills/rite-pov/SKILL.md +7 -3
  421. package/pack/generated/codex/skills/rite-pr-feedback/SKILL.md +7 -3
  422. package/pack/generated/codex/skills/rite-pressure-test/SKILL.md +7 -3
  423. package/pack/generated/codex/skills/rite-prototype/SKILL.md +32 -29
  424. package/pack/generated/codex/skills/rite-prove/SKILL.md +34 -20
  425. package/pack/generated/codex/skills/rite-quick/SKILL.md +7 -3
  426. package/pack/generated/codex/skills/rite-resolve/SKILL.md +19 -14
  427. package/pack/generated/codex/skills/rite-resolve/reference/answer-protocol.md +3 -0
  428. package/pack/generated/codex/skills/rite-review/SKILL.md +44 -31
  429. package/pack/generated/codex/skills/rite-seal/SKILL.md +7 -3
  430. package/pack/generated/codex/skills/rite-seal/reference/phase-contract.md +27 -92
  431. package/pack/generated/codex/skills/rite-seal/reference/risk-and-rollback.md +13 -0
  432. package/pack/generated/codex/skills/rite-ship/SKILL.md +7 -3
  433. package/pack/generated/codex/skills/rite-ship/reference/design-memory.md +31 -36
  434. package/pack/generated/codex/skills/rite-spec/SKILL.md +91 -138
  435. package/pack/generated/codex/skills/rite-spec/reference/investigation.md +37 -33
  436. package/pack/generated/codex/skills/rite-spec/reference/question-protocol.md +6 -2
  437. package/pack/generated/codex/skills/rite-spec/reference/spec-checklists.md +25 -24
  438. package/pack/generated/codex/skills/rite-spec/reference/spec-template.md +9 -2
  439. package/pack/generated/codex/skills/rite-spec/reference/state-workspace.md +13 -3
  440. package/pack/generated/codex/skills/rite-status/SKILL.md +7 -3
  441. package/pack/generated/codex/skills/rite-temper/SKILL.md +69 -50
  442. package/pack/generated/codex/skills/rite-temper/reference/review-dimensions.md +24 -22
  443. package/pack/generated/codex/skills/rite-vet/SKILL.md +117 -116
  444. package/pack/generated/codex/skills/rite-vet/reference/artifacts.md +42 -9
  445. package/pack/generated/codex/skills/rite-vet/reference/review-axes.md +40 -38
  446. package/pack/generated/codex/skills/rite-zoom-out/SKILL.md +7 -3
  447. package/package.json +1 -1
  448. package/scripts/build-release-tarball.sh +32 -15
  449. package/scripts/check-authority-drift.py +125 -0
  450. package/scripts/check-instruction-size-baseline.mjs +19 -11
  451. package/scripts/check-invocation-integrity.py +2 -0
  452. package/scripts/codex-generate.sh +69 -33
  453. package/scripts/grade-feature.sh +121 -40
  454. package/scripts/live-hosts/agent-result.schema.json +230 -0
  455. package/scripts/live-hosts/claude.sh +87 -0
  456. package/scripts/live-hosts/codex.sh +81 -0
  457. package/scripts/live-hosts/common.sh +113 -0
  458. package/scripts/live-hosts/fake-host.py +264 -0
  459. package/scripts/live-hosts/host-transport.py +287 -0
  460. package/scripts/release-check.sh +5 -1
  461. package/scripts/run-agent-contract-evals.py +1380 -0
  462. package/scripts/run-behavioral-evals.sh +24 -30
  463. package/scripts/run-evals.sh +1 -5
  464. package/scripts/run-live-behavioral-evals.py +1274 -144
  465. package/scripts/run-outcome-evals.sh +414 -88
  466. package/scripts/run-tests.mjs +30 -2
  467. package/scripts/skills-inventory.mjs +1 -1
  468. package/scripts/validate-workflow-security.py +39 -20
  469. package/scripts/validate-workspace-schema.py +362 -10
  470. package/scripts/validate.sh +21 -15
  471. package/engine/testdata/golden/TestParityWrightScope/devrites-edit-allowed.golden +0 -1
  472. /package/engine/testdata/golden/{TestParityReconcile/check-no-claimed.golden → TestParityBuildReadiness/arg=clarifyopen.golden} +0 -0
package/docs/usage.md CHANGED
@@ -1,10 +1,11 @@
1
1
  # Using DevRites
2
2
 
3
- These examples show the common DevRites workflows. A greenfield feature starts
4
- with `/rite-spec`; an existing codebase may enter through `/rite-adopt`.
5
- `/rite-quick` and `/rite-frame` handle bounded work outside the full feature arc.
6
- Workspace-operating phases read the active workspace (`.devrites/ACTIVE` →
7
- `.devrites/work/<slug>/`) first and report the appropriate on-ramp when none exists.
3
+ These examples cover the common DevRites workflows. Start a new feature with
4
+ `/rite-spec` and bring an existing codebase in with `/rite-adopt`.
5
+ `/rite-quick` and `/rite-frame` handle bounded work outside the full feature
6
+ lifecycle. Workspace phases first read the active workspace from
7
+ `.devrites/ACTIVE` and `.devrites/work/<slug>/`. If none exists, they report the
8
+ command that can create or select one.
8
9
 
9
10
  - **Full command reference** → [`command-map.md`](command-map.md)
10
11
  - **Flow diagrams** → [`flow.md`](flow.md)
@@ -14,15 +15,16 @@ Workspace-operating phases read the active workspace (`.devrites/ACTIVE` →
14
15
  ## The workspace
15
16
 
16
17
  `/rite-spec` creates `.devrites/work/<slug>/` and writes the spec.
17
- `/rite-define` adds the architecture, plan, tasks, and traceability. Together,
18
- these human-readable Markdown files carry the work across compaction and new
19
- sessions:
18
+ `/rite-clarify` adds decision coverage, `/rite-define` adds the plan, and
19
+ `/rite-vet` adds implementation readiness. These human-readable files preserve
20
+ the work across compaction and new sessions:
20
21
 
21
22
  | File | Created by | Holds |
22
23
  |---|---|---|
23
24
  | `README.md` / `index.md` / `feature.md` | `/rite-spec` | compact workspace map: phase, status, next action, artifact map, read-next table, gates |
24
25
  | `brief.md` | `/rite-spec` | one-line objective + definition of done |
25
26
  | `spec.md` | `/rite-spec` | product WHAT/WHY, requirements, acceptance, boundaries, measurable success |
27
+ | `decision-coverage.md` | `/rite-clarify` | topology-first coverage plus semantic `CLEAR` verdict bound to all decision inputs |
26
28
  | `architecture.md` | `/rite-define` | owning module/layer, integration points, data/API/events, dependencies, risks |
27
29
  | `flows.md` | `/rite-spec` or `/rite-define` | optional Mermaid diagrams when sequence/state/data flow clarifies behavior |
28
30
  | `references/` + `references.md` | `/rite-spec` | saved design refs: screenshots, Figma, video, links |
@@ -30,9 +32,11 @@ sessions:
30
32
  | `plan.md` | `/rite-define` | approach, dependency graph, checkpoints, rollback |
31
33
  | `tasks.md` | `/rite-define` | ordered `SLICE-###` vertical slices, each mapped to `AC-###` and tagged `Mode: AFK \| HITL` + gate fields |
32
34
  | `traceability.md` | `/rite-define` | AC/REQ → slices → tests/proofs → evidence → touched files matrix |
33
- | `eng-review.md` | `/rite-vet` | mandatory engineering plan review, light or full by stakes: scope challenge, axis findings, failure modes, parallelization |
35
+ | `eng-review.md` | `/rite-vet` | mandatory engineering review with semantic, input-digest-bound readiness verdict |
34
36
  | `test-plan.md` | `/rite-vet` | build-readable coverage target: coverage diagram, per-gap test requirements, acceptance→test map (read by `/rite-build` + `/rite-prove`) |
35
- | `state.md` | every phase | working ledger: phase, active slice + slice mode, risk, next step; plus `Awaiting human` block when paused (run mode is derived from `.devrites/AFK`, not stored here) |
37
+ | `state.md` | every phase | working cursor: phase, status, next action, slice, AFK budget, durable clarification return fields, and `Awaiting human` only when paused |
38
+ | `recovery-attempts.jsonl` | technical recovery | durable three-failure budget per root-cause fingerprint |
39
+ | `.wright-allowlist` | `/rite-build` root | exact normalized source/test paths the sole wright may change |
36
40
  | `status.md` | every phase | compatibility alias for the canonical `state.md` cursor |
37
41
  | `questions.md` | every phase | append-only Q&A: qid, slice, gate, status (`open` / `answered` / `dropped`), proposed answer, raised/answered timestamps |
38
42
  | `decisions.md` / `assumptions.md` | every phase | running logs |
@@ -49,14 +53,16 @@ sessions:
49
53
 
50
54
  When `/rite-ship` closes the task, it archives the whole workspace from
51
55
  `.devrites/work/<slug>/` to `.devrites/archive/<slug>/` and clears
52
- `.devrites/ACTIVE`. It preserves every Markdown file, so the audit trail remains
53
- under `.devrites/archive/<slug>/`.
56
+ `.devrites/ACTIVE`. Every Markdown file remains in
57
+ `.devrites/archive/<slug>/` as an audit trail.
54
58
 
55
59
  Backward compatibility: older `.devrites/features/<slug>/` workspaces remain
56
60
  readable; migration should add the canonical `.devrites/work` shape without
57
61
  deleting the old files. `feature.md`/`index.md` can still act as the workspace
58
62
  map, `status.md` as the cursor alias for `state.md`, and `proof.md` as the proof
59
- alias for `evidence.md`.
63
+ alias for `evidence.md`. Workspace maps use schema v2; migration upgrades
64
+ compatible declarations but never fabricates clarification, readiness, or proof
65
+ evidence.
60
66
 
61
67
  Project-root sentinel (outside the workspace):
62
68
 
@@ -81,6 +87,10 @@ You: I want some kind of reporting thing for admins.
81
87
  → gathers any design references you give
82
88
  → writes spec.md (creates the workspace)
83
89
 
90
+ /rite-clarify
91
+ → scans the full topology; asks zero questions when the contract is complete
92
+ → writes fresh Decision coverage: CLEAR
93
+
84
94
  /rite-define
85
95
  → reads the approved spec
86
96
  → writes plan.md + vertical task slices + state
@@ -95,7 +105,8 @@ You: I want some kind of reporting thing for admins.
95
105
 
96
106
  ```text
97
107
  /rite-spec add-csv-export # investigate → spec.md
98
- /rite-define # specplan + vertical slices + state
108
+ /rite-clarify # topology scan Decision coverage: CLEAR
109
+ /rite-define # clarified spec → plan + vertical slices + state
99
110
  /rite-vet # mandatory plan review; light or full based on stakes
100
111
  /rite-build # slice 1 ("export endpoint returns CSV"); stops with evidence
101
112
  /rite-build # slice 2 ("download button + states"); repeat for each slice
@@ -106,7 +117,10 @@ You: I want some kind of reporting thing for admins.
106
117
  /rite-ship # type-GO + irreversible git ladder + close the task (archive + clear ACTIVE)
107
118
  ```
108
119
 
109
- `/rite-build` never auto-advances: you decide when the next slice runs.
120
+ `/rite-build` never starts the next slice automatically; you decide when it
121
+ runs. For each slice, the root writes an exact `.wright-allowlist`. The snapshot,
122
+ reconciliation check, test/package integrity, and close steps use the same
123
+ original baseline. A retry snapshot refreshes only the dispatch boundary.
110
124
  `/rite-seal` **decides**; `/rite-ship` **executes + closes**. To run the whole
111
125
  sequence unattended, see `/rite-autocomplete` (§11).
112
126
 
@@ -133,7 +147,7 @@ sequence unattended, see `/rite-autocomplete` (§11).
133
147
  You: 2
134
148
 
135
149
  /rite-plan repair # updates spec/plan/tasks to per-session, marks drift resolved
136
- /rite-build # resumes on the corrected plan
150
+ /rite-vet # rechecks the repaired plan before build
137
151
  ```
138
152
 
139
153
  ## 4) UI feature with Playwright MCP
@@ -170,14 +184,16 @@ You: 2
170
184
  /rite-ship
171
185
  ```
172
186
 
173
- If no browser tooling is available, proof is recorded as **pending (manual)**
174
- with exact steps: the seal then weighs the UI risk.
187
+ If browser tooling is unavailable, the proof records exact manual steps and a
188
+ status of **pending (manual)**. The seal then accounts for the remaining UI
189
+ risk.
175
190
 
176
191
  ## 5) Backend-only feature
177
192
 
178
193
  ```text
179
194
  /rite-spec rate-limit-api # investigate → spec.md (no UI)
180
- /rite-define # spec plan + slices
195
+ /rite-clarify # topology scan; zero questions when already complete
196
+ /rite-define # clarified spec → plan + slices
181
197
  /rite-vet # mandatory plan review; checks architecture, tests, perf
182
198
  /rite-build # no UI → no frontend craft / browser proof
183
199
  /rite-prove # targeted tests + build/typecheck; runtime check of the limiter
@@ -225,7 +241,7 @@ Other modes: `quieter` · `distill` · `harden`.
225
241
  → the next session (or a fresh agent) reads the workspace alone
226
242
  ```
227
243
 
228
- Run before `/clear` if leaving for > a few hours.
244
+ Run this before `/clear` or a break of more than a few hours.
229
245
 
230
246
  ## 9) HITL gate: pre-code pause and resume
231
247
 
@@ -234,17 +250,17 @@ Run before `/clear` if leaving for > a few hours.
234
250
  → reads tasks.md slice 03; Mode: HITL, Gate: blocking
235
251
  → STOPS before writing any code:
236
252
 
237
- SLICE-003: list endpoint is HITL (blocking, SLA 15m).
238
- Checkpoint: Composite (user_id, created_at) index, or two single-col indexes?
239
- Proposed approach: composite: single read path, both columns used together
240
- in the most common filter; downside is rebuild cost on bulk updates.
241
- Decision needed before this slice can build.
253
+ SLICE-003: export policy is HITL (blocking, SLA 15m).
254
+ Checkpoint: Should deactivated users appear in the admin export?
255
+ Proposed approach: exclude them by default and expose an explicit
256
+ include-deactivated filter; this changes visible product behavior.
257
+ Product decision needed before this slice can build.
242
258
  Resume: /rite-resolve q-2026-05-28-001 "<answer>"
243
259
 
244
260
  → appends q-...-001 to questions.md (status: open, gate: blocking)
245
261
  → writes `Awaiting human` block to state.md, sets Status: awaiting_human
246
262
 
247
- You: /rite-resolve q-2026-05-28-001 "composite: single-col is fine for now"
263
+ You: /rite-resolve q-2026-05-28-001 "exclude by default; add the filter"
248
264
 
249
265
  /rite-resolve
250
266
  → flips q-...-001 status → answered (with answered_at + answer)
@@ -288,9 +304,12 @@ EOF
288
304
  /rite-build # continue
289
305
  ```
290
306
 
291
- The loop refuses to mark a slice `built` if tests / types / lint go red: it
292
- writes a blocking question and stops regardless of `allow_gates`. AFK never
293
- silently accepts irreversible risk; see
307
+ The loop does not mark a slice `built` while tests, type checks, or lint are
308
+ red. It uses the same wright and durable three-failure recovery budget for each
309
+ root-cause fingerprint. If the budget runs out, it records a blocker with the
310
+ reproduction and unsuccessful approaches instead of asking for retry approval.
311
+ AFK never silently accepts
312
+ genuine product, risk, or access decisions; see
294
313
  [`pack/.claude/skills/devrites-lib/reference/standards/afk-hitl.md`](../pack/.claude/skills/devrites-lib/reference/standards/afk-hitl.md) for the
295
314
  full list.
296
315
 
@@ -298,9 +317,9 @@ full list.
298
317
 
299
318
  ```text
300
319
  /rite-autocomplete "add CSV export for admins" --max-slices 8
301
- → vague idea → runs devrites-interview once, up front (the only interactive
302
- window), to ~95% confidence
303
- → arms AFK, then drives every phase in order: /rite-spec → /rite-temper →
320
+ → vague idea → runs devrites-interview, then /rite-spec + /rite-clarify in
321
+ the only interactive window
322
+ Decision coverage: CLEAR → arms AFK, then drives: /rite-temper →
304
323
  /rite-define → /rite-vet → /rite-build ×N → /rite-prove → /rite-polish →
305
324
  /rite-review → /rite-seal (→ /rite-ship too when --ship is set)
306
325
  → at each soft gate, picks the option the relevant specialist/reviewer
@@ -311,12 +330,12 @@ full list.
311
330
  You: GO # → commit · push · tag, then archive + clear ACTIVE
312
331
  ```
313
332
 
314
- Add `--ship` (alias `--yolo`) to auto-confirm the final type-`GO` for a
315
- zero-touch push: autocomplete then proceeds straight to `/rite-ship`. It still
316
- pauses on hard irreversible-risk (auth / migration / public-API / red tests),
317
- blocking / escalating gates, an open `gate: validating`, a NO-GO, exhausted
318
- `max_slices`, or low confidence: writing `state.md` and surfacing *why* before
319
- it stops. Args: `[idea] [--ship|--yolo] [--max-slices N]`.
333
+ Add `--ship` (alias `--yolo`) to confirm the final type-`GO` automatically.
334
+ Autocomplete then proceeds directly to `/rite-ship` without another prompt. It
335
+ still pauses for genuine product/scope/policy decisions, irreversible risk,
336
+ human-only access/actions, a NO-GO, exhausted `max_slices`, or low confidence.
337
+ Objective red checks use bounded recovery instead. Args:
338
+ `[idea] [--ship|--yolo] [--max-slices N]`.
320
339
 
321
340
  ## Checking in
322
341
 
@@ -0,0 +1,219 @@
1
+ // Command releasepack writes a deterministic tar.gz from a staged release tree.
2
+ package main
3
+
4
+ import (
5
+ "archive/tar"
6
+ "compress/gzip"
7
+ "errors"
8
+ "flag"
9
+ "fmt"
10
+ "io"
11
+ "math"
12
+ "os"
13
+ "path"
14
+ "path/filepath"
15
+ "sort"
16
+ "strconv"
17
+ "strings"
18
+ "time"
19
+ )
20
+
21
+ type archiveEntry struct {
22
+ archiveName string
23
+ sourcePath string
24
+ info os.FileInfo
25
+ }
26
+
27
+ func main() {
28
+ root := flag.String("root", "", "staged release tree")
29
+ output := flag.String("output", "", "output .tar.gz")
30
+ prefix := flag.String("prefix", "", "archive top-level directory")
31
+ epochText := flag.String("epoch", "0", "SOURCE_DATE_EPOCH")
32
+ flag.Parse()
33
+
34
+ epoch, err := strconv.ParseUint(*epochText, 10, 32)
35
+ if err != nil {
36
+ exitf("invalid epoch %q: %v", *epochText, err)
37
+ }
38
+ if *root == "" || *output == "" || *prefix == "" {
39
+ exitf("-root, -output, and -prefix are required")
40
+ }
41
+ if err := writeArchive(*root, *output, *prefix, time.Unix(int64(epoch), 0).UTC()); err != nil {
42
+ exitf("%v", err)
43
+ }
44
+ }
45
+
46
+ func exitf(format string, args ...any) {
47
+ fmt.Fprintf(os.Stderr, "releasepack: "+format+"\n", args...)
48
+ os.Exit(1)
49
+ }
50
+
51
+ func writeArchive(root, output, prefix string, epoch time.Time) error {
52
+ if err := validatePrefix(prefix); err != nil {
53
+ return err
54
+ }
55
+ if epoch.Unix() < 0 || epoch.Unix() > math.MaxUint32 {
56
+ return fmt.Errorf("epoch must fit the gzip timestamp field")
57
+ }
58
+
59
+ canonicalRoot, err := filepath.EvalSymlinks(root)
60
+ if err != nil {
61
+ return fmt.Errorf("resolve root: %w", err)
62
+ }
63
+ canonicalRoot, err = filepath.Abs(canonicalRoot)
64
+ if err != nil {
65
+ return fmt.Errorf("resolve root: %w", err)
66
+ }
67
+ outputDir, err := filepath.EvalSymlinks(filepath.Dir(output))
68
+ if err != nil {
69
+ return fmt.Errorf("resolve output: %w", err)
70
+ }
71
+ output, err = filepath.Abs(filepath.Join(outputDir, filepath.Base(output)))
72
+ if err != nil {
73
+ return fmt.Errorf("resolve output: %w", err)
74
+ }
75
+ if within(canonicalRoot, output) {
76
+ return errors.New("output must be outside the staged release tree")
77
+ }
78
+
79
+ entries, err := collectEntries(canonicalRoot, prefix)
80
+ if err != nil {
81
+ return err
82
+ }
83
+ if err := os.MkdirAll(filepath.Dir(output), 0o755); err != nil {
84
+ return fmt.Errorf("create output directory: %w", err)
85
+ }
86
+
87
+ tmp, err := os.CreateTemp(filepath.Dir(output), "."+filepath.Base(output)+".tmp-*")
88
+ if err != nil {
89
+ return fmt.Errorf("create temporary archive: %w", err)
90
+ }
91
+ tmpName := tmp.Name()
92
+ defer os.Remove(tmpName)
93
+ if err := tmp.Chmod(0o644); err != nil {
94
+ return errors.Join(fmt.Errorf("set archive mode: %w", err), tmp.Close())
95
+ }
96
+
97
+ gz, err := gzip.NewWriterLevel(tmp, gzip.BestCompression)
98
+ if err != nil {
99
+ return errors.Join(fmt.Errorf("create gzip writer: %w", err), tmp.Close())
100
+ }
101
+ gz.Header.ModTime = epoch
102
+ gz.Header.OS = 255
103
+ tw := tar.NewWriter(gz)
104
+
105
+ writeErr := writeEntries(tw, entries, epoch)
106
+ if err := tw.Close(); writeErr == nil {
107
+ writeErr = err
108
+ }
109
+ if err := gz.Close(); writeErr == nil {
110
+ writeErr = err
111
+ }
112
+ if err := tmp.Close(); writeErr == nil {
113
+ writeErr = err
114
+ }
115
+ if writeErr != nil {
116
+ return fmt.Errorf("write archive: %w", writeErr)
117
+ }
118
+ if err := os.Remove(output); err != nil && !errors.Is(err, os.ErrNotExist) {
119
+ return fmt.Errorf("replace output: %w", err)
120
+ }
121
+ if err := os.Rename(tmpName, output); err != nil {
122
+ return fmt.Errorf("publish archive: %w", err)
123
+ }
124
+ return nil
125
+ }
126
+
127
+ func validatePrefix(prefix string) error {
128
+ if prefix == "" || prefix == "." || path.IsAbs(prefix) || path.Clean(prefix) != prefix || strings.ContainsAny(prefix, `/\`) {
129
+ return fmt.Errorf("unsafe archive prefix %q", prefix)
130
+ }
131
+ return nil
132
+ }
133
+
134
+ func within(root, candidate string) bool {
135
+ rel, err := filepath.Rel(root, candidate)
136
+ return err == nil && (rel == "." || filepath.IsLocal(rel))
137
+ }
138
+
139
+ func collectEntries(root, prefix string) ([]archiveEntry, error) {
140
+ var entries []archiveEntry
141
+ err := filepath.Walk(root, func(sourcePath string, info os.FileInfo, walkErr error) error {
142
+ if walkErr != nil {
143
+ return walkErr
144
+ }
145
+ if sourcePath == root {
146
+ entries = append(entries, archiveEntry{archiveName: prefix + "/", sourcePath: root, info: info})
147
+ return nil
148
+ }
149
+ rel, err := filepath.Rel(root, sourcePath)
150
+ if err != nil || !filepath.IsLocal(rel) {
151
+ return fmt.Errorf("path escapes staged release tree: %q", sourcePath)
152
+ }
153
+ if info.Mode()&os.ModeSymlink != 0 {
154
+ return fmt.Errorf("symlink is not allowed in release payload: %s", filepath.ToSlash(rel))
155
+ }
156
+ if !info.Mode().IsRegular() && !info.IsDir() {
157
+ return fmt.Errorf("unsupported release payload entry: %s (%s)", filepath.ToSlash(rel), info.Mode())
158
+ }
159
+ archiveRel := filepath.ToSlash(rel)
160
+ if strings.Contains(archiveRel, `\`) {
161
+ return fmt.Errorf("non-portable release payload path: %s", archiveRel)
162
+ }
163
+ name := path.Join(prefix, archiveRel)
164
+ if info.IsDir() {
165
+ name += "/"
166
+ }
167
+ entries = append(entries, archiveEntry{archiveName: name, sourcePath: sourcePath, info: info})
168
+ return nil
169
+ })
170
+ if err != nil {
171
+ return nil, fmt.Errorf("collect release payload: %w", err)
172
+ }
173
+ sort.Slice(entries, func(i, j int) bool {
174
+ return entries[i].archiveName < entries[j].archiveName
175
+ })
176
+ return entries, nil
177
+ }
178
+
179
+ func writeEntries(tw *tar.Writer, entries []archiveEntry, epoch time.Time) error {
180
+ for _, entry := range entries {
181
+ mode := int64(0o644)
182
+ typeflag := byte(tar.TypeReg)
183
+ size := entry.info.Size()
184
+ if entry.info.IsDir() {
185
+ mode, typeflag, size = 0o755, tar.TypeDir, 0
186
+ } else if entry.info.Mode().Perm()&0o111 != 0 || path.Ext(entry.archiveName) == ".sh" {
187
+ mode = 0o755
188
+ }
189
+ header := &tar.Header{
190
+ Name: entry.archiveName,
191
+ Mode: mode,
192
+ Size: size,
193
+ ModTime: epoch,
194
+ AccessTime: epoch,
195
+ ChangeTime: epoch,
196
+ Typeflag: typeflag,
197
+ Format: tar.FormatPAX,
198
+ }
199
+ if err := tw.WriteHeader(header); err != nil {
200
+ return err
201
+ }
202
+ if typeflag != tar.TypeReg {
203
+ continue
204
+ }
205
+ file, err := os.Open(entry.sourcePath)
206
+ if err != nil {
207
+ return err
208
+ }
209
+ _, copyErr := io.Copy(tw, file)
210
+ closeErr := file.Close()
211
+ if copyErr != nil {
212
+ return copyErr
213
+ }
214
+ if closeErr != nil {
215
+ return closeErr
216
+ }
217
+ }
218
+ return nil
219
+ }
@@ -0,0 +1,170 @@
1
+ package main
2
+
3
+ import (
4
+ "archive/tar"
5
+ "bytes"
6
+ "compress/gzip"
7
+ "io"
8
+ "os"
9
+ "path/filepath"
10
+ "reflect"
11
+ "strings"
12
+ "testing"
13
+ "time"
14
+ )
15
+
16
+ func TestWriteArchiveIsDeterministic(t *testing.T) {
17
+ t.Parallel()
18
+ epoch := time.Unix(1_700_000_000, 0).UTC()
19
+ firstRoot := makeTree(t, time.Unix(100, 0))
20
+ secondRoot := makeTree(t, time.Unix(2_000_000_000, 0))
21
+ firstArchive := filepath.Join(t.TempDir(), "release.tar.gz")
22
+ secondArchive := filepath.Join(t.TempDir(), "release.tar.gz")
23
+
24
+ if err := writeArchive(firstRoot, firstArchive, "devrites-v1.2.3", epoch); err != nil {
25
+ t.Fatal(err)
26
+ }
27
+ if err := writeArchive(secondRoot, secondArchive, "devrites-v1.2.3", epoch); err != nil {
28
+ t.Fatal(err)
29
+ }
30
+ firstBytes, err := os.ReadFile(firstArchive)
31
+ if err != nil {
32
+ t.Fatal(err)
33
+ }
34
+ secondBytes, err := os.ReadFile(secondArchive)
35
+ if err != nil {
36
+ t.Fatal(err)
37
+ }
38
+ if !bytes.Equal(firstBytes, secondBytes) {
39
+ t.Fatal("archives differ across source roots and mtimes")
40
+ }
41
+
42
+ got := readArchive(t, firstArchive, epoch)
43
+ wantNames := []string{
44
+ "devrites-v1.2.3/",
45
+ "devrites-v1.2.3/README.md",
46
+ "devrites-v1.2.3/install.sh",
47
+ "devrites-v1.2.3/nested/",
48
+ "devrites-v1.2.3/nested/data.txt",
49
+ }
50
+ if !reflect.DeepEqual(got.names, wantNames) {
51
+ t.Fatalf("archive names = %#v, want %#v", got.names, wantNames)
52
+ }
53
+ if got.modes["devrites-v1.2.3/"] != 0o755 ||
54
+ got.modes["devrites-v1.2.3/install.sh"] != 0o755 ||
55
+ got.modes["devrites-v1.2.3/README.md"] != 0o644 {
56
+ t.Fatalf("archive modes = %#v", got.modes)
57
+ }
58
+ if got.contents["devrites-v1.2.3/install.sh"] != "#!/bin/sh\nexit 0\n" ||
59
+ got.contents["devrites-v1.2.3/nested/data.txt"] != "payload\n" {
60
+ t.Fatalf("archive contents = %#v", got.contents)
61
+ }
62
+ }
63
+
64
+ func TestWriteArchiveRejectsUnsafePaths(t *testing.T) {
65
+ t.Parallel()
66
+ root := t.TempDir()
67
+ if err := os.WriteFile(filepath.Join(root, "file"), []byte("safe"), 0o644); err != nil {
68
+ t.Fatal(err)
69
+ }
70
+ output := filepath.Join(t.TempDir(), "release.tar.gz")
71
+
72
+ if err := writeArchive(root, filepath.Join(root, "release.tar.gz"), "devrites-v1", time.Unix(0, 0)); err == nil {
73
+ t.Fatal("output inside the staged tree was accepted")
74
+ }
75
+ if err := writeArchive(root, output, "../escape", time.Unix(0, 0)); err == nil {
76
+ t.Fatal("escaping archive prefix was accepted")
77
+ }
78
+ if err := writeArchive(root, output, `devrites-v1\escape`, time.Unix(0, 0)); err == nil {
79
+ t.Fatal("non-portable archive prefix was accepted")
80
+ }
81
+
82
+ link := filepath.Join(root, "unsafe-link")
83
+ if err := os.Symlink(filepath.Join(t.TempDir(), "outside"), link); err != nil {
84
+ t.Skipf("symlinks unavailable: %v", err)
85
+ }
86
+ err := writeArchive(root, output, "devrites-v1", time.Unix(0, 0))
87
+ if err == nil || !strings.Contains(err.Error(), "symlink is not allowed") {
88
+ t.Fatalf("symlink error = %v", err)
89
+ }
90
+ if _, statErr := os.Stat(output); !os.IsNotExist(statErr) {
91
+ t.Fatalf("unsafe archive output exists: %v", statErr)
92
+ }
93
+ }
94
+
95
+ func makeTree(t *testing.T, mtime time.Time) string {
96
+ t.Helper()
97
+ root := t.TempDir()
98
+ files := map[string]struct {
99
+ content string
100
+ mode os.FileMode
101
+ }{
102
+ "README.md": {"read me\n", 0o644},
103
+ "install.sh": {"#!/bin/sh\nexit 0\n", 0o644},
104
+ "nested/data.txt": {"payload\n", 0o644},
105
+ }
106
+ for name, file := range files {
107
+ fullPath := filepath.Join(root, name)
108
+ if err := os.MkdirAll(filepath.Dir(fullPath), 0o755); err != nil {
109
+ t.Fatal(err)
110
+ }
111
+ if err := os.WriteFile(fullPath, []byte(file.content), file.mode); err != nil {
112
+ t.Fatal(err)
113
+ }
114
+ if err := os.Chtimes(fullPath, mtime, mtime); err != nil {
115
+ t.Fatal(err)
116
+ }
117
+ }
118
+ return root
119
+ }
120
+
121
+ type archiveContents struct {
122
+ names []string
123
+ modes map[string]int64
124
+ contents map[string]string
125
+ }
126
+
127
+ func readArchive(t *testing.T, archivePath string, epoch time.Time) archiveContents {
128
+ t.Helper()
129
+ file, err := os.Open(archivePath)
130
+ if err != nil {
131
+ t.Fatal(err)
132
+ }
133
+ defer file.Close()
134
+ gz, err := gzip.NewReader(file)
135
+ if err != nil {
136
+ t.Fatal(err)
137
+ }
138
+ defer gz.Close()
139
+ if !gz.ModTime.Equal(epoch) || gz.OS != 255 || gz.Name != "" || gz.Comment != "" || len(gz.Extra) != 0 {
140
+ t.Fatalf("gzip header is not normalized: %#v", gz.Header)
141
+ }
142
+
143
+ got := archiveContents{modes: map[string]int64{}, contents: map[string]string{}}
144
+ tr := tar.NewReader(gz)
145
+ for {
146
+ header, err := tr.Next()
147
+ if err == io.EOF {
148
+ break
149
+ }
150
+ if err != nil {
151
+ t.Fatal(err)
152
+ }
153
+ got.names = append(got.names, header.Name)
154
+ got.modes[header.Name] = header.Mode
155
+ if header.Uid != 0 || header.Gid != 0 || header.Uname != "" || header.Gname != "" {
156
+ t.Fatalf("%s ownership is not normalized: %#v", header.Name, header)
157
+ }
158
+ if !header.ModTime.Equal(epoch) || !header.AccessTime.Equal(epoch) || !header.ChangeTime.Equal(epoch) {
159
+ t.Fatalf("%s timestamps are not normalized: %#v", header.Name, header)
160
+ }
161
+ if header.Typeflag == tar.TypeReg {
162
+ content, err := io.ReadAll(tr)
163
+ if err != nil {
164
+ t.Fatal(err)
165
+ }
166
+ got.contents[header.Name] = string(content)
167
+ }
168
+ }
169
+ return got
170
+ }