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/engine/main.go CHANGED
@@ -1,11 +1,7 @@
1
- // Command devrites-engine is the DevRites control-plane engine: a single static,
2
- // pure-Go binary that owns the deterministic workflow state (phases, gates,
3
- // completeness) over a project's .devrites/ directory. It makes zero model or
4
- // network calls: the in-session LLM remains the judgment data plane.
5
- //
6
- // Command dispatch is intentionally a small stdlib switch (no third-party deps)
7
- // so the binary cross-compiles trivially with CGO_ENABLED=0; it can be swapped
8
- // for Cobra later without changing the CLI contract.
1
+ // Command devrites-engine runs the DevRites control plane. It manages workflow
2
+ // phases, gates, and completeness under a project's .devrites directory without
3
+ // calling a model or the network. The pure-Go binary uses standard library
4
+ // dispatch so it can cross-compile with CGO_ENABLED=0.
9
5
  package main
10
6
 
11
7
  import (
@@ -13,13 +9,16 @@ import (
13
9
  "fmt"
14
10
  "io"
15
11
  "os"
12
+ "path/filepath"
16
13
 
14
+ "github.com/devrites/devrites/internal/forge"
17
15
  "github.com/devrites/devrites/internal/gate"
18
16
  "github.com/devrites/devrites/internal/harness"
19
17
  "github.com/devrites/devrites/internal/install"
20
18
  "github.com/devrites/devrites/internal/iohooks"
21
19
  "github.com/devrites/devrites/internal/lib"
22
20
  "github.com/devrites/devrites/internal/profile"
21
+ "github.com/devrites/devrites/internal/reason"
23
22
  "github.com/devrites/devrites/internal/state"
24
23
  "github.com/devrites/devrites/internal/version"
25
24
  )
@@ -42,28 +41,31 @@ Usage:
42
41
  devrites-engine footprint <sub> <slug> Fan-out footprint: log|render|roster the dispatch log
43
42
  devrites-engine evidence-fresh [slug] Gate: does the proof post-date every touched file?
44
43
  devrites-engine coverage [slug] Render the AC → slice(s) → proven traceability matrix
45
- devrites-engine doubt-coverage <slug> Did the build doubt the decisions it stood?
44
+ devrites-engine doubt-coverage <slug> Check whether the build challenged its recorded decisions
46
45
  devrites-engine budget [slug] Lint each workspace file against its context-size ceiling
47
46
  devrites-engine preamble [slug] Print the active feature's workspace-state orientation
48
47
  devrites-engine progress [slug] Render the active feature's phase/slice/flow footer
49
48
  devrites-engine profile get|refresh Cache stable repo facts for grounding skills
50
49
  devrites-engine stuck <sub> <slug> Unattended-build loop detector: log|check
50
+ devrites-engine recovery <sub> [...] Track up to three technical recovery attempts across runs
51
51
  devrites-engine tick-afk <state.md> Decrement the AFK slice budget in a state.md
52
- devrites-engine build-readiness [slug] Gate: is the plan approved and the state build-ready?
53
- devrites-engine analyze [slug] Cross-artifact spec↔tasks coverage/consistency gate
52
+ devrites-engine build-readiness [slug] Gate: are plan approval, decision coverage, and implementation readiness build-ready?
53
+ devrites-engine readiness-digest <coverage|engineering> [slug] Render the canonical artifact input digest
54
+ devrites-engine clarify-return <enter|restore> [slug] Preserve/restore a later-phase clarification cursor
55
+ devrites-engine analyze [slug] Check coverage and consistency between the spec and tasks
54
56
  devrites-engine mutation-gate [slug] Advisory: detect the mutation runner and scope it
55
57
  devrites-engine test-integrity [slug] Gate: no test deleted, skipped, or de-asserted
56
58
  devrites-engine review-integrity [slug] Gate: no adversarial review axis is silent (zero findings, no justification)
57
59
  devrites-engine package-existence [slug] Gate: every new import is declared in a manifest
58
- devrites-engine reconcile <sub> [slug] A1 gate: snapshot|check the wright's source writes
60
+ devrites-engine reconcile <sub> [slug] A1 gate: snapshot|check|close the wright's source writes
59
61
  devrites-engine resolve <qid> "<ans>" Resolve an open question; keep state.md consistent
60
62
  devrites-engine close-out <slug> Archive a shipped feature and clear ACTIVE
61
- devrites-engine archive-search "<nouns>" Surface shipped features whose spec.md overlaps the query (prior-art probe)
63
+ devrites-engine archive-search "<nouns>" Find prior shipped specs that overlap the query
62
64
  devrites-engine decisions <sub> [...] Derived decision memory: index|search
63
65
  devrites-engine ledger <sub> [...] Capability ledger (living specs/): sync|diff|validate|list|show
64
66
  devrites-engine learnings <sub> [...] Cross-feature learning ledger: add|list|top|mine|nudge
65
- devrites-engine timeline <sub> [...] Session trace: log|list skill events, decisions, and state moves
66
- devrites-engine health [run|record|list] Code-health dashboard + history
67
+ devrites-engine timeline <sub> [...] Local typed trace: log|list|report|purge
68
+ devrites-engine health [run|record|list] Run the code health dashboard or view its history
67
69
  devrites-engine config get <key> Read project config (outside_voice defaults auto)
68
70
  devrites-engine reviewers list Validate/list configured reviewer aliases
69
71
  devrites-engine outside-voice Detect outside-review availability
@@ -73,6 +75,7 @@ Usage:
73
75
  devrites-engine reviewer-stats <sub> Reviewer dispatch outcomes: record <agent> <n> [slug] | report [--json]
74
76
  devrites-engine conventions <sub> [...] Project convention ledger: band|read|orient|promote|contradict
75
77
  devrites-engine lanes plan [slug] Advisory safe-parallelism/lane plan for slices
78
+ devrites-engine forge <sub> [...] Isolated candidate worktrees: plan|record|extract|merge|cleanup|reap
76
79
  devrites-engine extensions <sub> Project extensions (.devrites/extensions/): list|validate|sync
77
80
  devrites-engine overrides <sub> Reviewer-override linter (.devrites/overrides/): list|validate
78
81
  devrites-engine context sync [file ...] Sync managed DevRites block into context files
@@ -80,7 +83,7 @@ Usage:
80
83
  devrites-engine runbook <sub> [...] Local runbooks: list|validate|run|resume
81
84
  devrites-engine doctor Report the binary / pack / state-schema version triangle
82
85
  devrites-engine migrate Normalize .devrites workspaces to the current schema
83
- devrites-engine validate-pack [dir] Lint the shipped pack's hook wiring + skill/agent frontmatter contracts + docs/command-map.md links
86
+ devrites-engine validate-pack [dir] Check shipped hook wiring, frontmatter contracts, and command-map links
84
87
  devrites-engine harness-matrix [--check F] Render (or drift-check) the harness adapter-compliance matrix
85
88
  devrites-engine version Print the engine binary's version
86
89
  devrites-engine hook <name> --harness=H Run hook <name> for harness H (claude|codex)
@@ -89,13 +92,14 @@ Hooks:
89
92
  hook allow Auto-approve the read-only devrites orientation/gate subcommands
90
93
  hook orient Emit SessionStart orientation for the active feature
91
94
  hook stop-gate Refuse to end a turn at a provably inconsistent rest point
92
- hook reviewer-readonly Deny a reviewer subagent's mutating/exfiltrating Bash command
95
+ hook reviewer-readonly Deny every mutation/dispatch surface for read-only DevRites agents
93
96
  hook subagent-orient Inject the DevRites discipline into a spawned devrites-* subagent
94
97
  hook cursor Re-inject the active feature's cursor (UserPromptSubmit)
95
98
  hook statusline One-line workspace HUD (settings.json statusLine)
96
99
  hook redwatch Fail-on-red sentinel: set/clear .red after a test/build command
97
100
  hook a1-guard Block the orchestrator editing source mid-build
98
- hook wright-scope Fence the slice-wright to its touched-files.md
101
+ hook git-guard Require exact one-shot authority for destructive Git
102
+ hook wright-scope Fence the slice-wright to an exact orchestrator allowlist
99
103
  hook source-cache-pre Serve a cached page reading on a 304 revalidation (WebFetch)
100
104
  hook source-cache-post Store a WebFetch result keyed on its origin validators
101
105
  hook refresh-indexes Refresh the code-intelligence indexes (detached) on Stop
@@ -114,13 +118,20 @@ Environment:
114
118
  the nearest .devrites found walking up from the working directory.
115
119
  DEVRITES_WORKSPACE Explicit feature workspace path for CI/agents; overrides
116
120
  .devrites/ACTIVE when a command defaults to the active feature.
121
+ DEVRITES_AGENT_RUN=1 declares a DevRites leaf run when hook payloads omit identity.
122
+ DEVRITES_ACTIVE_AGENT=devrites-<role> supplies that exact leaf identity.
123
+ DEVRITES_WRIGHT_ALLOWLIST_FILE points to the wright's exact project-relative
124
+ path manifest; defaults to the active workspace's .wright-allowlist.
125
+ DEVRITES_FORGE_RUN_ID, DEVRITES_FORGE_CANDIDATE, DEVRITES_FORGE_WORKER_ID,
126
+ DEVRITES_FORGE_WORKER_PID, and DEVRITES_FORGE_PROCESS_START bind a candidate
127
+ wright to its root-owned manifest. All five are required.
117
128
 
118
129
  Hook control plane:
119
130
  DEVRITES_HOOK_PROFILE minimal | standard (default) | strict. minimal runs
120
131
  orientation/approval hooks only; standard adds the
121
132
  gates, guards and caches; strict also enables
122
- every OBSERVE-default guard (a1-guard, stop-gate,
123
- reviewer-readonly, wright-scope) to enforce at once.
133
+ every legacy OBSERVE-default guard to enforce at once.
134
+ Declared DevRites agents are always enforced.
124
135
  DEVRITES_DISABLED_HOOKS Comma-separated hook ids to force off, e.g.
125
136
  "stop-gate,redwatch". A disabled hook is a clean
126
137
  fail-open no-op.
@@ -143,6 +154,11 @@ func run(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
143
154
  fmt.Fprint(stderr, usage)
144
155
  return exitUsage
145
156
  }
157
+ root, rootExit, err := resolveRootFor(args[0], args[1:])
158
+ if err != nil {
159
+ fmt.Fprintf(stderr, "devrites: root selection: %v\n", err)
160
+ return rootExit
161
+ }
146
162
  switch args[0] {
147
163
  case "install":
148
164
  return install.Run(args[1:], stdout, stderr, install.ModeInstall)
@@ -156,103 +172,121 @@ func run(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
156
172
  case "snapshot":
157
173
  return cmdSnapshot(args[1:], stdout, stderr)
158
174
  case "first-task":
159
- return lib.FirstTask(resolveRootLenient(), args[1:], stdout, stderr)
175
+ return lib.FirstTask(root, args[1:], stdout, stderr)
160
176
  case "readiness":
161
177
  rest, j := extractFlag(args[1:], "--json")
162
- return jsonWrap("readiness", j, stdout, stderr, func(o, e io.Writer) int { return cmdGate(gate.Readiness, rest, o, e) })
178
+ return jsonWrapReason("readiness", j, stdout, stderr, func(code int) reason.ID {
179
+ if code == exitOK || code == exitBlocked {
180
+ return gate.ResultReasonID(gate.Readiness, code == exitBlocked)
181
+ }
182
+ return ""
183
+ }, func(o, e io.Writer) int { return cmdGate(gate.Readiness, rest, o, e) })
163
184
  case "seal":
164
185
  rest, j := extractFlag(args[1:], "--json")
165
- return jsonWrap("seal", j, stdout, stderr, func(o, e io.Writer) int { return cmdGate(gate.Seal, rest, o, e) })
186
+ return jsonWrapReason("seal", j, stdout, stderr, func(code int) reason.ID {
187
+ if code == exitOK || code == exitBlocked {
188
+ return gate.ResultReasonID(gate.Seal, code == exitBlocked)
189
+ }
190
+ return ""
191
+ }, func(o, e io.Writer) int { return cmdGate(gate.Seal, rest, o, e) })
166
192
  case "spec-validate":
167
193
  rest, j := extractFlag(args[1:], "--json")
168
194
  return jsonWrap("spec-validate", j, stdout, stderr, func(o, e io.Writer) int { return cmdSpecValidate(rest, o, e) })
169
195
  case "spec-skeleton":
170
196
  return cmdSpecSkeleton(args[1:], stdout, stderr)
171
197
  case "spec-dedupe":
172
- return lib.SpecDedupe(resolveRootLenient(), args[1:], stdout, stderr)
198
+ return lib.SpecDedupe(root, args[1:], stdout, stderr)
173
199
  case "check-acceptance":
174
200
  return cmdCheckAcceptance(args[1:], stdout, stderr)
175
201
  case "footprint":
176
- return cmdFootprint(args[1:], stdout, stderr)
202
+ return cmdFootprint(root, args[1:], stdout, stderr)
177
203
  case "evidence-fresh":
178
204
  rest, j := extractFlag(args[1:], "--json")
179
- return jsonWrap("evidence-fresh", j, stdout, stderr, func(o, e io.Writer) int { return cmdEvidenceFresh(rest, o, e) })
205
+ return jsonWrap("evidence-fresh", j, stdout, stderr, func(o, e io.Writer) int { return cmdEvidenceFresh(root, rest, o, e) })
180
206
  case "coverage":
181
207
  rest, j := extractFlag(args[1:], "--json")
182
- return jsonWrap("coverage", j, stdout, stderr, func(o, e io.Writer) int { return cmdCoverage(rest, o, e) })
208
+ return jsonWrap("coverage", j, stdout, stderr, func(o, e io.Writer) int { return cmdCoverage(root, rest, o, e) })
183
209
  case "doubt-coverage":
184
- return cmdDoubtCoverage(args[1:], stdout, stderr)
210
+ return cmdDoubtCoverage(root, args[1:], stdout, stderr)
185
211
  case "budget":
186
- return lib.Budget(resolveRootLenient(), args[1:], stdout, stderr)
212
+ return lib.Budget(root, args[1:], stdout, stderr)
187
213
  case "preamble":
188
214
  rest, j := extractFlag(args[1:], "--json")
189
- return jsonWrap("preamble", j, stdout, stderr, func(o, e io.Writer) int { return cmdPreamble(rest, o, e) })
215
+ return jsonWrap("preamble", j, stdout, stderr, func(o, e io.Writer) int { return cmdPreamble(root, rest, o, e) })
190
216
  case "progress":
191
- return cmdProgress(args[1:], stdout, stderr)
217
+ return cmdProgress(root, args[1:], stdout, stderr)
192
218
  case "profile":
193
219
  return profile.Run(args[1:], stdout, stderr)
194
220
  case "stuck":
195
- return cmdStuck(args[1:], stdout, stderr)
221
+ return cmdStuck(root, args[1:], stdout, stderr)
222
+ case "recovery":
223
+ return lib.RecoveryAttempts(root, args[1:], stdout, stderr)
196
224
  case "tick-afk":
197
225
  return lib.TickAfk(args[1:], stdout, stderr)
198
226
  case "build-readiness":
199
- return lib.BuildReadiness(resolveRootLenient(), args[1:], stdout, stderr)
227
+ return lib.BuildReadiness(root, args[1:], stdout, stderr)
228
+ case "readiness-digest":
229
+ return lib.ReadinessDigest(root, args[1:], stdout, stderr)
230
+ case "clarify-return":
231
+ return lib.ClarifyReturn(root, args[1:], stdout, stderr)
200
232
  case "analyze":
201
233
  rest, j := extractFlag(args[1:], "--json")
202
- return jsonWrap("analyze", j, stdout, stderr, func(o, e io.Writer) int { return lib.Analyze(resolveRootLenient(), rest, o, e) })
234
+ return jsonWrap("analyze", j, stdout, stderr, func(o, e io.Writer) int { return lib.Analyze(root, rest, o, e) })
203
235
  case "mutation-gate":
204
- return lib.MutationGate(resolveRootLenient(), args[1:], stdout, stderr)
236
+ return lib.MutationGate(root, args[1:], stdout, stderr)
205
237
  case "test-integrity":
206
- return lib.TestIntegrity(resolveRootLenient(), args[1:], stdout, stderr)
238
+ return lib.TestIntegrity(root, args[1:], stdout, stderr)
207
239
  case "review-integrity":
208
- return lib.ReviewIntegrity(resolveRootLenient(), args[1:], stdout, stderr)
240
+ return lib.ReviewIntegrity(root, args[1:], stdout, stderr)
209
241
  case "package-existence":
210
- return lib.PackageExistence(resolveRootLenient(), args[1:], stdout, stderr)
242
+ return lib.PackageExistence(root, args[1:], stdout, stderr)
211
243
  case "reconcile":
212
- return lib.Reconcile(resolveRootLenient(), args[1:], stdout, stderr)
244
+ return lib.Reconcile(root, args[1:], stdout, stderr)
213
245
  case "resolve":
214
- return lib.Resolve(resolveRootLenient(), args[1:], stdout, stderr)
246
+ return lib.Resolve(root, args[1:], stdout, stderr)
215
247
  case "close-out":
216
- return lib.CloseOut(resolveRootLenient(), args[1:], stdout, stderr)
248
+ return lib.CloseOut(root, args[1:], stdout, stderr)
217
249
  case "archive-search":
218
- return lib.ArchiveSearch(resolveRootLenient(), args[1:], stdout, stderr)
250
+ return lib.ArchiveSearch(root, args[1:], stdout, stderr)
219
251
  case "decisions":
220
- return lib.Decisions(resolveRootLenient(), args[1:], stdout, stderr)
252
+ return lib.Decisions(root, args[1:], stdout, stderr)
221
253
  case "ledger":
222
254
  rest, j := extractFlag(args[1:], "--json")
223
- return jsonWrap("ledger", j, stdout, stderr, func(o, e io.Writer) int { return lib.Ledger(resolveRootLenient(), rest, o, e) })
255
+ return jsonWrap("ledger", j, stdout, stderr, func(o, e io.Writer) int { return lib.Ledger(root, rest, o, e) })
224
256
  case "learnings":
225
- return lib.Learnings(resolveRootLenient(), args[1:], stdout, stderr)
257
+ return lib.Learnings(root, args[1:], stdout, stderr)
226
258
  case "timeline":
227
- return lib.Timeline(resolveRootLenient(), args[1:], stdout, stderr)
259
+ return lib.Timeline(root, args[1:], stdout, stderr)
228
260
  case "health":
229
- return lib.Health(resolveRootLenient(), args[1:], stdout, stderr)
261
+ return lib.Health(root, args[1:], stdout, stderr)
230
262
  case "config":
231
- return lib.Config(resolveRootLenient(), args[1:], stdout, stderr)
263
+ return lib.Config(root, args[1:], stdout, stderr)
232
264
  case "reviewers":
233
- return lib.Reviewers(resolveRootLenient(), args[1:], stdout, stderr)
265
+ return lib.Reviewers(root, args[1:], stdout, stderr)
234
266
  case "outside-voice":
235
- return lib.OutsideVoice(resolveRootLenient(), args[1:], stdout, stderr)
267
+ return lib.OutsideVoice(root, args[1:], stdout, stderr)
236
268
  case "docs-stale":
237
- return lib.DocsStale(resolveRootLenient(), args[1:], stdout, stderr)
269
+ return lib.DocsStale(root, args[1:], stdout, stderr)
238
270
  case "secret-scan":
239
- return lib.SecretScan(resolveRootLenient(), args[1:], stdout, stderr)
271
+ return lib.SecretScan(root, args[1:], stdout, stderr)
240
272
  case "review-fingerprints":
241
- return lib.ReviewFingerprints(resolveRootLenient(), args[1:], stdout, stderr)
273
+ return lib.ReviewFingerprints(root, args[1:], stdout, stderr)
242
274
  case "reviewer-stats":
243
- return lib.ReviewerStats(resolveRootLenient(), args[1:], stdout, stderr)
275
+ return lib.ReviewerStats(root, args[1:], stdout, stderr)
244
276
  case "conventions":
245
277
  return lib.Conventions(args[1:], stdout, stderr)
246
278
  case "lanes":
247
- return lib.Lanes(resolveRootLenient(), args[1:], stdout, stderr)
279
+ return lib.Lanes(root, args[1:], stdout, stderr)
280
+ case "forge":
281
+ return forge.Run(filepath.Dir(root), args[1:], stdout, stderr)
248
282
  case "extensions":
249
- return lib.Extensions(resolveRootLenient(), args[1:], stdout, stderr)
283
+ return lib.Extensions(root, args[1:], stdout, stderr)
250
284
  case "overrides":
251
- return lib.Overrides(resolveRootLenient(), args[1:], stdout, stderr)
285
+ return lib.Overrides(root, args[1:], stdout, stderr)
252
286
  case "context":
253
- return lib.Context(resolveRootLenient(), args[1:], stdout, stderr)
287
+ return lib.Context(root, args[1:], stdout, stderr)
254
288
  case "runbook":
255
- return lib.Runbook(resolveRootLenient(), args[1:], stdout, stderr)
289
+ return lib.Runbook(root, args[1:], stdout, stderr)
256
290
  case "doctor":
257
291
  rest, j := extractFlag(args[1:], "--json")
258
292
  return jsonWrap("doctor", j, stdout, stderr, func(o, e io.Writer) int { return cmdDoctor(rest, o, e) })
@@ -286,6 +320,7 @@ func cmdStatus(args []string, stdout, stderr io.Writer) int {
286
320
  fmt.Fprintf(stderr, "devrites: %v\n", err)
287
321
  return exitUsage
288
322
  }
323
+ recordRootSelection(root, "status", stderr)
289
324
  report, err := state.Status(root, args[0])
290
325
  if err != nil {
291
326
  fmt.Fprintf(stderr, "devrites: %v\n", err)
@@ -308,11 +343,29 @@ func cmdGate(kind gate.Kind, args []string, stdout, stderr io.Writer) int {
308
343
  fmt.Fprintf(stderr, "devrites: %v\n", err)
309
344
  return exitUsage
310
345
  }
346
+ recordRootSelection(root, string(kind), stderr)
311
347
  result, err := gate.Check(kind, root, args[0])
312
348
  if err != nil {
313
349
  fmt.Fprintf(stderr, "devrites: %v\n", err)
314
350
  return exitUsage
315
351
  }
352
+ evidence := append([]string(nil), result.MissingFiles...)
353
+ if result.LegacyLayout {
354
+ evidence = evidence[:0]
355
+ for _, section := range result.Missing {
356
+ evidence = append(evidence, string(section)+".md")
357
+ }
358
+ }
359
+ if ev, eventErr := lib.NewLifecycleGateEvent(
360
+ root, result.Slug, string(result.Kind), result.Phase,
361
+ result.Blocked, result.ReasonID, evidence,
362
+ ); eventErr == nil {
363
+ if eventErr = lib.AppendEventV1(root, ev); eventErr != nil {
364
+ debugf(stderr, "lifecycle-gate event: %v", eventErr)
365
+ }
366
+ } else {
367
+ debugf(stderr, "lifecycle-gate event: %v", eventErr)
368
+ }
316
369
  fmt.Fprint(stdout, result.Render())
317
370
  if result.Blocked {
318
371
  return exitBlocked
@@ -372,47 +425,47 @@ func cmdCheckAcceptance(args []string, stdout, stderr io.Writer) int {
372
425
  return lib.CheckAcceptance(arg, stdout, stderr)
373
426
  }
374
427
 
375
- // cmdFootprint renders / logs / rosters the fan-out dispatch footprint for a
376
- // feature. Workspace state lives under <root>/work/<slug>, with features/ as an
428
+ // cmdFootprint renders, logs, or lists the fan-out dispatch footprint for a
429
+ // feature. Workspace state lives under <root>/work/<slug>, with features as an
377
430
  // alias for older workspaces.
378
- func cmdFootprint(args []string, stdout, stderr io.Writer) int {
379
- return lib.Footprint(resolveRootLenient(), args, stdout, stderr)
431
+ func cmdFootprint(root string, args []string, stdout, stderr io.Writer) int {
432
+ return lib.Footprint(root, args, stdout, stderr)
380
433
  }
381
434
 
382
435
  // cmdEvidenceFresh runs the evidence-freshness gate (0 fresh · 3 stale · 5 no
383
436
  // workspace/evidence).
384
- func cmdEvidenceFresh(args []string, stdout, stderr io.Writer) int {
385
- return lib.EvidenceFresh(resolveRootLenient(), args, stdout, stderr)
437
+ func cmdEvidenceFresh(root string, args []string, stdout, stderr io.Writer) int {
438
+ return lib.EvidenceFresh(root, args, stdout, stderr)
386
439
  }
387
440
 
388
441
  // cmdCoverage renders the AC → slice → proven traceability matrix (0 rendered ·
389
442
  // 2 no workspace/spec).
390
- func cmdCoverage(args []string, stdout, stderr io.Writer) int {
391
- return lib.Coverage(resolveRootLenient(), args, stdout, stderr)
443
+ func cmdCoverage(root string, args []string, stdout, stderr io.Writer) int {
444
+ return lib.Coverage(root, args, stdout, stderr)
392
445
  }
393
446
 
394
447
  // cmdDoubtCoverage runs the doubt-coverage assessment (0 covered/n-a · 1 no doubt
395
448
  // ran · 2 usage · 3 doubt: MISSING).
396
- func cmdDoubtCoverage(args []string, stdout, stderr io.Writer) int {
397
- return lib.DoubtCoverage(resolveRootLenient(), args, stdout, stderr)
449
+ func cmdDoubtCoverage(root string, args []string, stdout, stderr io.Writer) int {
450
+ return lib.DoubtCoverage(root, args, stdout, stderr)
398
451
  }
399
452
 
400
453
  // cmdPreamble prints the active feature's workspace-state orientation (always
401
454
  // exit 0).
402
- func cmdPreamble(args []string, stdout, stderr io.Writer) int {
403
- return lib.Preamble(resolveRootLenient(), args, stdout, stderr)
455
+ func cmdPreamble(root string, args []string, stdout, stderr io.Writer) int {
456
+ return lib.Preamble(root, args, stdout, stderr)
404
457
  }
405
458
 
406
459
  // cmdProgress renders the active feature's phase/slice/flow footer (always exit 0,
407
460
  // silent when no workspace).
408
- func cmdProgress(args []string, stdout, stderr io.Writer) int {
409
- return lib.Progress(resolveRootLenient(), args, stdout, stderr)
461
+ func cmdProgress(root string, args []string, stdout, stderr io.Writer) int {
462
+ return lib.Progress(root, args, stdout, stderr)
410
463
  }
411
464
 
412
465
  // cmdStuck is the unattended-build loop detector: `stuck log|check <slug>` (0 not
413
466
  // stuck · 2 bad args · 3 STUCK).
414
- func cmdStuck(args []string, stdout, stderr io.Writer) int {
415
- return lib.Stuck(resolveRootLenient(), args, stdout, stderr)
467
+ func cmdStuck(root string, args []string, stdout, stderr io.Writer) int {
468
+ return lib.Stuck(root, args, stdout, stderr)
416
469
  }
417
470
 
418
471
  func cmdHook(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
@@ -425,6 +478,8 @@ func cmdHook(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
425
478
  // in DEVRITES_DISABLED_HOOKS is a clean fail-open no-op, indistinguishable from
426
479
  // an absent binary. Consulted before any work, including refresh-indexes.
427
480
  if !hookActive(name) {
481
+ h, _ := harness.Parse(harnessFlag(args[1:]))
482
+ recordHookGuard(h, name, reason.HookDisabled, lib.GuardBypassed, lib.OutcomeBypassed)
428
483
  return exitOK
429
484
  }
430
485
  // These hooks carry their own positional args and need no harness parsing, so
@@ -465,12 +520,19 @@ func cmdHook(args []string, stdin io.Reader, stdout, stderr io.Writer) int {
465
520
  return hookRedwatch(h, stdin, stdout, stderr)
466
521
  case "a1-guard":
467
522
  return hookA1Guard(h, stdin, stdout, stderr)
523
+ case "git-guard":
524
+ return hookGitGuard(h, stdin, stdout, stderr)
468
525
  case "wright-scope":
469
526
  return hookWrightScope(h, stdin, stdout, stderr)
470
527
  case "source-cache-pre":
471
528
  return iohooks.SourceCachePre(stdin, stdout, stderr)
472
529
  case "source-cache-post":
473
- return iohooks.SourceCachePost(stdin, stdout, stderr)
530
+ var warning bytes.Buffer
531
+ code := iohooks.SourceCachePost(h, stdin, io.MultiWriter(stdout, &warning), stderr)
532
+ if warning.Len() > 0 {
533
+ recordHookGuard(h, "source-cache-post", reason.HookIngestWarning, lib.GuardObserved, lib.OutcomeWarning)
534
+ }
535
+ return code
474
536
  default:
475
537
  fmt.Fprintf(stderr, "devrites: unknown hook %q\n", name)
476
538
  return exitUsage
@@ -520,11 +582,32 @@ func extractFlag(args []string, flag string) ([]string, bool) {
520
582
  // otherwise. It is applied only to the AFK-parsed read commands (see the
521
583
  // --json set in run()); other commands never accept --json.
522
584
  func jsonWrap(command string, jsonMode bool, stdout, stderr io.Writer, thunk func(o, e io.Writer) int) int {
585
+ return jsonWrapReason(command, jsonMode, stdout, stderr, nil, thunk)
586
+ }
587
+
588
+ func jsonWrapReason(command string, jsonMode bool, stdout, stderr io.Writer, reasonFor func(int) reason.ID, thunk func(o, e io.Writer) int) int {
523
589
  if !jsonMode {
524
590
  return thunk(stdout, stderr)
525
591
  }
526
592
  var out, errb bytes.Buffer
527
593
  code := thunk(&out, &errb)
528
- lib.WriteEnvelope(stdout, lib.NewEnvelope(command, code, out.String(), errb.String()))
594
+ env := lib.NewEnvelope(command, code, out.String(), errb.String())
595
+ if reasonFor != nil {
596
+ env = env.WithReason(reasonFor(code))
597
+ }
598
+ lib.WriteEnvelope(stdout, env)
529
599
  return code
530
600
  }
601
+
602
+ func recordRootSelection(root, command string, stderr io.Writer) {
603
+ if root == "" {
604
+ return
605
+ }
606
+ ev, err := lib.NewRootSelectionEvent(root, command)
607
+ if err == nil {
608
+ err = lib.AppendEventV1(root, ev)
609
+ }
610
+ if err != nil {
611
+ debugf(stderr, "root-selection event: %v", err)
612
+ }
613
+ }
@@ -0,0 +1,52 @@
1
+ package main
2
+
3
+ import (
4
+ "bytes"
5
+ "os"
6
+ "path/filepath"
7
+ "strings"
8
+ "testing"
9
+
10
+ "github.com/devrites/devrites/internal/lib"
11
+ "github.com/devrites/devrites/internal/reason"
12
+ "github.com/devrites/devrites/internal/state"
13
+ )
14
+
15
+ func TestTimelineReportIgnoresItsOwnRootSelectionEvent(t *testing.T) {
16
+ project := t.TempDir()
17
+ initRootRoutingGitRepo(t, project)
18
+ root := filepath.Join(project, ".devrites")
19
+ work := filepath.Join(root, "work", "demo")
20
+ if err := os.MkdirAll(work, 0o755); err != nil {
21
+ t.Fatal(err)
22
+ }
23
+ if err := os.WriteFile(filepath.Join(root, "ACTIVE"), []byte("demo\n"), 0o644); err != nil {
24
+ t.Fatal(err)
25
+ }
26
+ if err := os.WriteFile(filepath.Join(work, "state.md"), []byte("| phase | build |\n"), 0o644); err != nil {
27
+ t.Fatal(err)
28
+ }
29
+ event := lib.NewEventV1(lib.BoundaryAgentDispatch, "run-started", reason.RootSelected)
30
+ event.TS = "2026-07-23T12:00:00Z"
31
+ event.RunID = "drv-run-v1:0123456789abcdef0123456789abcdef"
32
+ event.RootSource = lib.RootSourceExplicit
33
+ event.Workspace = ".devrites/work/demo"
34
+ event.PhaseBefore = state.PhaseBuild
35
+ event.PhaseAfter = state.PhaseBuild
36
+ event.Outcome = lib.OutcomeRecorded
37
+ if err := lib.AppendEventV1(root, event); err != nil {
38
+ t.Fatal(err)
39
+ }
40
+
41
+ withRootRoutingCWD(t, project)
42
+ t.Setenv("DEVRITES_ROOT", root)
43
+ t.Setenv("DEVRITES_WORKSPACE", "")
44
+ var stdout, stderr bytes.Buffer
45
+ if code := run([]string{"timeline", "report"}, strings.NewReader(""), &stdout, &stderr); code != exitOK {
46
+ t.Fatalf("timeline report code=%d stdout=%q stderr=%q", code, stdout.String(), stderr.String())
47
+ }
48
+ if !strings.Contains(stdout.String(), event.RunID) ||
49
+ !strings.Contains(stdout.String(), "1 v1 events") {
50
+ t.Fatalf("report selected its own root-selection event instead of the trace: %s", stdout.String())
51
+ }
52
+ }