devrites 3.0.7 → 3.2.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 (484) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +82 -50
  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/0012-semantic-workspace-upgrades.md +77 -0
  12. package/docs/adr/README.md +4 -0
  13. package/docs/agents/triage-labels.md +7 -7
  14. package/docs/architecture.md +179 -141
  15. package/docs/cli.md +47 -12
  16. package/docs/command-map.md +61 -38
  17. package/docs/engine/agent-contract.md +92 -15
  18. package/docs/engine/commands.md +248 -72
  19. package/docs/engine/state-schema.md +52 -23
  20. package/docs/engine/workspace-schema.md +103 -15
  21. package/docs/extensions.md +1 -1
  22. package/docs/flow.md +86 -51
  23. package/docs/harness-compliance.md +29 -5
  24. package/docs/orchestration.md +107 -79
  25. package/docs/quick-reference.md +11 -3
  26. package/docs/release.md +4 -3
  27. package/docs/skills.md +67 -38
  28. package/docs/usage.md +84 -39
  29. package/engine/cmd/releasepack/main.go +219 -0
  30. package/engine/cmd/releasepack/main_test.go +170 -0
  31. package/engine/commands.go +170 -23
  32. package/engine/git_guard.go +187 -0
  33. package/engine/git_guard_test.go +283 -0
  34. package/engine/hookpolicy.go +53 -55
  35. package/engine/hookpolicy_test.go +91 -1
  36. package/engine/hooks.go +296 -75
  37. package/engine/hooks_events_test.go +276 -6
  38. package/engine/hooks_workspace.go +640 -159
  39. package/engine/internal/devritespaths/paths.go +65 -10
  40. package/engine/internal/devritespaths/paths_test.go +110 -0
  41. package/engine/internal/doctor/doctor.go +153 -23
  42. package/engine/internal/doctor/doctor_test.go +74 -0
  43. package/engine/internal/forge/forge.go +940 -0
  44. package/engine/internal/forge/forge_test.go +576 -0
  45. package/engine/internal/forge/git.go +245 -0
  46. package/engine/internal/forge/liveness_unix.go +48 -0
  47. package/engine/internal/forge/liveness_windows.go +67 -0
  48. package/engine/internal/forge/manifest.go +402 -0
  49. package/engine/internal/gate/gate.go +90 -71
  50. package/engine/internal/gate/gate_test.go +71 -2
  51. package/engine/internal/harness/compliance.go +18 -24
  52. package/engine/internal/harness/harness.go +37 -44
  53. package/engine/internal/harness/harness_test.go +21 -5
  54. package/engine/internal/install/install.go +486 -38
  55. package/engine/internal/install/install_test.go +383 -10
  56. package/engine/internal/iohooks/iohooks.go +350 -59
  57. package/engine/internal/iohooks/iohooks_test.go +421 -1
  58. package/engine/internal/lib/buildreadiness.go +43 -18
  59. package/engine/internal/lib/clarifyreturn.go +91 -0
  60. package/engine/internal/lib/clarifyreturn_test.go +123 -0
  61. package/engine/internal/lib/context.go +54 -15
  62. package/engine/internal/lib/cursor_compat_test.go +8 -0
  63. package/engine/internal/lib/extensions.go +2 -3
  64. package/engine/internal/lib/gitauthority.go +601 -0
  65. package/engine/internal/lib/gitauthority_test.go +346 -0
  66. package/engine/internal/lib/jsonout.go +25 -11
  67. package/engine/internal/lib/jsonout_test.go +16 -0
  68. package/engine/internal/lib/lanes.go +14 -8
  69. package/engine/internal/lib/observability_test.go +358 -0
  70. package/engine/internal/lib/packageexistence.go +151 -35
  71. package/engine/internal/lib/packageexistence_test.go +163 -0
  72. package/engine/internal/lib/progress.go +11 -9
  73. package/engine/internal/lib/provenance.go +462 -0
  74. package/engine/internal/lib/provenance_test.go +154 -0
  75. package/engine/internal/lib/readiness_contract.json +118 -0
  76. package/engine/internal/lib/readinessartifact.go +533 -0
  77. package/engine/internal/lib/readinessartifact_test.go +422 -0
  78. package/engine/internal/lib/reconcile.go +712 -88
  79. package/engine/internal/lib/reconcile_test.go +335 -16
  80. package/engine/internal/lib/recoveryattempts.go +298 -0
  81. package/engine/internal/lib/recoveryattempts_test.go +215 -0
  82. package/engine/internal/lib/resolve.go +23 -19
  83. package/engine/internal/lib/runbook_context_test.go +20 -0
  84. package/engine/internal/lib/session.go +701 -9
  85. package/engine/internal/lib/session_test.go +80 -13
  86. package/engine/internal/lib/testintegrity.go +33 -37
  87. package/engine/internal/lib/testintegrity_test.go +63 -1
  88. package/engine/internal/migrate/migrate.go +81 -1
  89. package/engine/internal/migrate/migrate_test.go +22 -1
  90. package/engine/internal/reason/reason.go +180 -0
  91. package/engine/internal/reason/reason_test.go +35 -0
  92. package/engine/internal/rootfacts/facts.go +466 -0
  93. package/engine/internal/rootfacts/facts_test.go +306 -0
  94. package/engine/internal/safepath/safepath.go +55 -0
  95. package/engine/internal/safepath/safepath_test.go +69 -0
  96. package/engine/internal/safepath/safepath_windows_test.go +26 -0
  97. package/engine/internal/state/clarify_transition.go +165 -0
  98. package/engine/internal/state/clarify_transition_test.go +130 -0
  99. package/engine/internal/state/cmd/workflowmanifest/main.go +12 -8
  100. package/engine/internal/state/cursor.go +58 -0
  101. package/engine/internal/state/cursor_test.go +42 -1
  102. package/engine/internal/state/feature.go +35 -48
  103. package/engine/internal/state/schema.go +90 -37
  104. package/engine/internal/state/snapshot.go +18 -2
  105. package/engine/internal/state/state_test.go +187 -7
  106. package/engine/internal/state/status.go +48 -11
  107. package/engine/internal/state/workflow_manifest.json +231 -50
  108. package/engine/internal/toolpolicy/classifier.go +533 -0
  109. package/engine/internal/toolpolicy/classifier_test.go +424 -0
  110. package/engine/internal/toolpolicy/git.go +616 -0
  111. package/engine/internal/toolpolicy/scanner.go +382 -0
  112. package/engine/main.go +160 -77
  113. package/engine/observability_cli_test.go +52 -0
  114. package/engine/root_routing_test.go +277 -0
  115. package/engine/testdata/golden/TestParityBuildReadiness/arg=approved.golden +1 -1
  116. package/engine/testdata/golden/TestParityBuildReadiness/arg=emptystatus.golden +1 -1
  117. package/engine/testdata/golden/TestParityBuildReadiness/arg=legacycontract.golden +1 -0
  118. package/engine/testdata/golden/TestParityBuildReadiness/arg=noclarify.golden +1 -0
  119. package/engine/testdata/golden/TestParityBuildReadiness/arg=novet.golden +1 -0
  120. package/engine/testdata/golden/TestParityBuildReadiness/arg=stalevet.golden +1 -0
  121. package/engine/testdata/golden/TestParityBuildReadiness/arg=trailhash.golden +1 -1
  122. package/engine/testdata/golden/TestParityBuildReadiness/arg=trailpipe.golden +1 -1
  123. package/engine/testdata/golden/TestParityBuildReadiness/arg=vetnotready.golden +1 -0
  124. package/engine/testdata/golden/TestParityProgress/arg=allbuilt.golden +1 -1
  125. package/engine/testdata/golden/TestParityProgress/arg=done.golden +1 -1
  126. package/engine/testdata/golden/TestParityProgress/arg=mid.golden +1 -1
  127. package/engine/testdata/golden/TestParityProgress/arg=nophase.golden +1 -1
  128. package/engine/testdata/golden/TestParityProgress/arg=noslice.golden +1 -1
  129. package/engine/testdata/golden/TestParityProgress/arg=plan.golden +1 -1
  130. package/engine/testdata/golden/TestParityProgress/arg=seal.golden +1 -1
  131. package/engine/testdata/golden/TestParityReconcile/check-clean.golden +1 -1
  132. package/engine/testdata/golden/TestParityReconcile/inline-fallback.golden +1 -0
  133. package/engine/testdata/golden/TestParityReconcile/snapshot-no-allowlist.golden +1 -0
  134. package/engine/testdata/golden/TestParityWrightScope/devrites-edit-denied.golden +2 -0
  135. package/engine/testdata/golden/TestParityWrightScope/out-of-scope-enforce-denies.golden +1 -1
  136. package/engine/tests/adr_0011_define_plan_test.go +30 -0
  137. package/engine/tests/budget_test.go +19 -8
  138. package/engine/tests/concurrency_cli_test.go +7 -1
  139. package/engine/tests/doctor_cli_test.go +148 -2
  140. package/engine/tests/forge_cli_test.go +463 -0
  141. package/engine/tests/gate_test.go +63 -8
  142. package/engine/tests/hook_test.go +260 -8
  143. package/engine/tests/hooks_io_test.go +94 -3
  144. package/engine/tests/json_contract_test.go +127 -2
  145. package/engine/tests/migrate_cli_test.go +2 -2
  146. package/engine/tests/parity_buildreadiness_test.go +167 -10
  147. package/engine/tests/parity_learnings_test.go +16 -17
  148. package/engine/tests/parity_reconcile_test.go +20 -17
  149. package/engine/tests/parity_resolve_test.go +12 -11
  150. package/engine/tests/parity_test.go +21 -17
  151. package/pack/.claude/agents/devrites-code-reviewer.md +62 -48
  152. package/pack/.claude/agents/devrites-devex-reviewer.md +69 -53
  153. package/pack/.claude/agents/devrites-doubt-reviewer.md +29 -22
  154. package/pack/.claude/agents/devrites-evidence-scout.md +69 -0
  155. package/pack/.claude/agents/devrites-forge-judge.md +74 -61
  156. package/pack/.claude/agents/devrites-frontend-reviewer.md +48 -39
  157. package/pack/.claude/agents/devrites-performance-reviewer.md +49 -40
  158. package/pack/.claude/agents/devrites-plan-drafter.md +73 -0
  159. package/pack/.claude/agents/devrites-plan-reviewer.md +80 -47
  160. package/pack/.claude/agents/devrites-proof-runner.md +74 -0
  161. package/pack/.claude/agents/devrites-retrospector.md +48 -45
  162. package/pack/.claude/agents/devrites-security-auditor.md +46 -36
  163. package/pack/.claude/agents/devrites-simplifier-reviewer.md +50 -46
  164. package/pack/.claude/agents/devrites-slice-wright.md +153 -165
  165. package/pack/.claude/agents/devrites-spec-reviewer.md +34 -32
  166. package/pack/.claude/agents/devrites-strategy-reviewer.md +63 -34
  167. package/pack/.claude/agents/devrites-test-analyst.md +40 -30
  168. package/pack/.claude/agents/devrites-upgrade-planner.md +100 -0
  169. package/pack/.claude/settings.json +2 -1
  170. package/pack/.claude/skills/devrites-audit/SKILL.md +40 -61
  171. package/pack/.claude/skills/devrites-debug-recovery/SKILL.md +24 -13
  172. package/pack/.claude/skills/devrites-debug-recovery/reference/build-the-loop.md +24 -21
  173. package/pack/.claude/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +34 -6
  174. package/pack/.claude/skills/devrites-debug-recovery/reference/instrumentation.md +2 -2
  175. package/pack/.claude/skills/devrites-doubt/SKILL.md +25 -17
  176. package/pack/.claude/skills/devrites-interview/SKILL.md +53 -52
  177. package/pack/.claude/skills/devrites-lib/SKILL.md +12 -9
  178. package/pack/.claude/skills/devrites-lib/reference/intent-map.md +4 -2
  179. package/pack/.claude/skills/devrites-lib/reference/parallel-dispatch.md +82 -137
  180. package/pack/.claude/skills/devrites-lib/reference/reply-contract.md +8 -1
  181. package/pack/.claude/skills/devrites-lib/reference/standards/README.md +38 -55
  182. package/pack/.claude/skills/devrites-lib/reference/standards/afk-hitl.md +53 -27
  183. package/pack/.claude/skills/devrites-lib/reference/standards/agents.md +200 -190
  184. package/pack/.claude/skills/devrites-lib/reference/standards/anti-patterns.md +5 -15
  185. package/pack/.claude/skills/devrites-lib/reference/standards/ci-cd.md +27 -58
  186. package/pack/.claude/skills/devrites-lib/reference/standards/code-review.md +16 -52
  187. package/pack/.claude/skills/devrites-lib/reference/standards/coding-style.md +2 -10
  188. package/pack/.claude/skills/devrites-lib/reference/standards/context-hygiene.md +18 -61
  189. package/pack/.claude/skills/devrites-lib/reference/standards/core.md +23 -18
  190. package/pack/.claude/skills/devrites-lib/reference/standards/deprecation.md +17 -57
  191. package/pack/.claude/skills/devrites-lib/reference/standards/development-workflow.md +4 -33
  192. package/pack/.claude/skills/devrites-lib/reference/standards/git-workflow.md +4 -20
  193. package/pack/.claude/skills/devrites-lib/reference/standards/hooks.md +3 -14
  194. package/pack/.claude/skills/devrites-lib/reference/standards/patterns.md +9 -25
  195. package/pack/.claude/skills/devrites-lib/reference/standards/performance.md +0 -9
  196. package/pack/.claude/skills/devrites-lib/reference/standards/principles.md +1 -3
  197. package/pack/.claude/skills/devrites-lib/reference/standards/security.md +17 -7
  198. package/pack/.claude/skills/devrites-lib/reference/standards/testing.md +1 -27
  199. package/pack/.claude/skills/devrites-lib/reference/standards/tooling.md +46 -50
  200. package/pack/.claude/skills/devrites-lib/reference/workspace-artifact-schema.md +40 -10
  201. package/pack/.claude/skills/devrites-source-driven/SKILL.md +23 -22
  202. package/pack/.claude/skills/rite/SKILL.md +10 -6
  203. package/pack/.claude/skills/rite/reference/menu.md +13 -7
  204. package/pack/.claude/skills/rite-adopt/SKILL.md +33 -37
  205. package/pack/.claude/skills/rite-autocomplete/SKILL.md +33 -28
  206. package/pack/.claude/skills/rite-autocomplete/reference/loop.md +21 -21
  207. package/pack/.claude/skills/rite-autocomplete/reference/stop-conditions.md +15 -6
  208. package/pack/.claude/skills/rite-build/SKILL.md +35 -30
  209. package/pack/.claude/skills/rite-build/reference/afk-discipline.md +41 -39
  210. package/pack/.claude/skills/rite-build/reference/evidence-standard.md +10 -0
  211. package/pack/.claude/skills/rite-build/reference/forge.md +186 -156
  212. package/pack/.claude/skills/rite-build/reference/one-slice-cycle.md +4 -3
  213. package/pack/.claude/skills/rite-build/reference/phase-contract.md +96 -175
  214. package/pack/.claude/skills/rite-build/reference/spec-drift-guard.md +10 -4
  215. package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +129 -134
  216. package/pack/.claude/skills/rite-clarify/SKILL.md +90 -0
  217. package/pack/.claude/skills/rite-clarify/reference/decision-coverage.md +61 -0
  218. package/pack/.claude/skills/rite-converge/SKILL.md +35 -25
  219. package/pack/.claude/skills/rite-define/SKILL.md +58 -32
  220. package/pack/.claude/skills/rite-define/reference/gates.md +16 -15
  221. package/pack/.claude/skills/rite-define/reference/plan-template.md +18 -8
  222. package/pack/.claude/skills/rite-frame/reference/failure-modes.md +22 -24
  223. package/pack/.claude/skills/rite-plan/SKILL.md +47 -16
  224. package/pack/.claude/skills/rite-plan/reference/task-breakdown.md +4 -0
  225. package/pack/.claude/skills/rite-polish/SKILL.md +27 -23
  226. package/pack/.claude/skills/rite-prototype/SKILL.md +25 -26
  227. package/pack/.claude/skills/rite-prove/SKILL.md +27 -17
  228. package/pack/.claude/skills/rite-resolve/SKILL.md +12 -11
  229. package/pack/.claude/skills/rite-resolve/reference/answer-protocol.md +3 -0
  230. package/pack/.claude/skills/rite-review/SKILL.md +37 -28
  231. package/pack/.claude/skills/rite-seal/reference/phase-contract.md +27 -92
  232. package/pack/.claude/skills/rite-seal/reference/risk-and-rollback.md +13 -0
  233. package/pack/.claude/skills/rite-ship/reference/design-memory.md +31 -36
  234. package/pack/.claude/skills/rite-spec/SKILL.md +84 -135
  235. package/pack/.claude/skills/rite-spec/reference/investigation.md +37 -33
  236. package/pack/.claude/skills/rite-spec/reference/question-protocol.md +6 -2
  237. package/pack/.claude/skills/rite-spec/reference/spec-checklists.md +25 -24
  238. package/pack/.claude/skills/rite-spec/reference/spec-template.md +9 -2
  239. package/pack/.claude/skills/rite-spec/reference/state-workspace.md +13 -3
  240. package/pack/.claude/skills/rite-temper/SKILL.md +62 -47
  241. package/pack/.claude/skills/rite-temper/reference/review-dimensions.md +24 -22
  242. package/pack/.claude/skills/rite-upgrade/SKILL.md +125 -0
  243. package/pack/.claude/skills/rite-vet/SKILL.md +114 -113
  244. package/pack/.claude/skills/rite-vet/reference/artifacts.md +50 -9
  245. package/pack/.claude/skills/rite-vet/reference/review-axes.md +39 -37
  246. package/pack/generated/claude/agents/devrites-code-reviewer.md +62 -48
  247. package/pack/generated/claude/agents/devrites-devex-reviewer.md +69 -53
  248. package/pack/generated/claude/agents/devrites-doubt-reviewer.md +29 -22
  249. package/pack/generated/claude/agents/devrites-evidence-scout.md +69 -0
  250. package/pack/generated/claude/agents/devrites-forge-judge.md +74 -61
  251. package/pack/generated/claude/agents/devrites-frontend-reviewer.md +48 -39
  252. package/pack/generated/claude/agents/devrites-performance-reviewer.md +49 -40
  253. package/pack/generated/claude/agents/devrites-plan-drafter.md +73 -0
  254. package/pack/generated/claude/agents/devrites-plan-reviewer.md +80 -47
  255. package/pack/generated/claude/agents/devrites-proof-runner.md +74 -0
  256. package/pack/generated/claude/agents/devrites-retrospector.md +48 -45
  257. package/pack/generated/claude/agents/devrites-security-auditor.md +46 -36
  258. package/pack/generated/claude/agents/devrites-simplifier-reviewer.md +50 -46
  259. package/pack/generated/claude/agents/devrites-slice-wright.md +153 -165
  260. package/pack/generated/claude/agents/devrites-spec-reviewer.md +34 -32
  261. package/pack/generated/claude/agents/devrites-strategy-reviewer.md +63 -34
  262. package/pack/generated/claude/agents/devrites-test-analyst.md +40 -30
  263. package/pack/generated/claude/agents/devrites-upgrade-planner.md +100 -0
  264. package/pack/generated/claude/settings.json +2 -1
  265. package/pack/generated/claude/skills/devrites-audit/SKILL.md +40 -61
  266. package/pack/generated/claude/skills/devrites-debug-recovery/SKILL.md +24 -13
  267. package/pack/generated/claude/skills/devrites-debug-recovery/reference/build-the-loop.md +24 -21
  268. package/pack/generated/claude/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +34 -6
  269. package/pack/generated/claude/skills/devrites-debug-recovery/reference/instrumentation.md +2 -2
  270. package/pack/generated/claude/skills/devrites-doubt/SKILL.md +25 -17
  271. package/pack/generated/claude/skills/devrites-interview/SKILL.md +53 -52
  272. package/pack/generated/claude/skills/devrites-lib/SKILL.md +12 -9
  273. package/pack/generated/claude/skills/devrites-lib/reference/intent-map.md +4 -2
  274. package/pack/generated/claude/skills/devrites-lib/reference/parallel-dispatch.md +82 -137
  275. package/pack/generated/claude/skills/devrites-lib/reference/reply-contract.md +8 -1
  276. package/pack/generated/claude/skills/devrites-lib/reference/standards/README.md +38 -55
  277. package/pack/generated/claude/skills/devrites-lib/reference/standards/afk-hitl.md +53 -27
  278. package/pack/generated/claude/skills/devrites-lib/reference/standards/agents.md +200 -190
  279. package/pack/generated/claude/skills/devrites-lib/reference/standards/anti-patterns.md +5 -15
  280. package/pack/generated/claude/skills/devrites-lib/reference/standards/ci-cd.md +27 -58
  281. package/pack/generated/claude/skills/devrites-lib/reference/standards/code-review.md +16 -52
  282. package/pack/generated/claude/skills/devrites-lib/reference/standards/coding-style.md +2 -10
  283. package/pack/generated/claude/skills/devrites-lib/reference/standards/context-hygiene.md +18 -61
  284. package/pack/generated/claude/skills/devrites-lib/reference/standards/core.md +23 -18
  285. package/pack/generated/claude/skills/devrites-lib/reference/standards/deprecation.md +17 -57
  286. package/pack/generated/claude/skills/devrites-lib/reference/standards/development-workflow.md +4 -33
  287. package/pack/generated/claude/skills/devrites-lib/reference/standards/git-workflow.md +4 -20
  288. package/pack/generated/claude/skills/devrites-lib/reference/standards/hooks.md +3 -14
  289. package/pack/generated/claude/skills/devrites-lib/reference/standards/patterns.md +9 -25
  290. package/pack/generated/claude/skills/devrites-lib/reference/standards/performance.md +0 -9
  291. package/pack/generated/claude/skills/devrites-lib/reference/standards/principles.md +1 -3
  292. package/pack/generated/claude/skills/devrites-lib/reference/standards/security.md +17 -7
  293. package/pack/generated/claude/skills/devrites-lib/reference/standards/testing.md +1 -27
  294. package/pack/generated/claude/skills/devrites-lib/reference/standards/tooling.md +46 -50
  295. package/pack/generated/claude/skills/devrites-lib/reference/workspace-artifact-schema.md +40 -10
  296. package/pack/generated/claude/skills/devrites-source-driven/SKILL.md +23 -22
  297. package/pack/generated/claude/skills/rite/SKILL.md +10 -6
  298. package/pack/generated/claude/skills/rite/reference/menu.md +13 -7
  299. package/pack/generated/claude/skills/rite-adopt/SKILL.md +33 -37
  300. package/pack/generated/claude/skills/rite-autocomplete/SKILL.md +33 -28
  301. package/pack/generated/claude/skills/rite-autocomplete/reference/loop.md +21 -21
  302. package/pack/generated/claude/skills/rite-autocomplete/reference/stop-conditions.md +15 -6
  303. package/pack/generated/claude/skills/rite-build/SKILL.md +35 -30
  304. package/pack/generated/claude/skills/rite-build/reference/afk-discipline.md +41 -39
  305. package/pack/generated/claude/skills/rite-build/reference/evidence-standard.md +10 -0
  306. package/pack/generated/claude/skills/rite-build/reference/forge.md +186 -156
  307. package/pack/generated/claude/skills/rite-build/reference/one-slice-cycle.md +4 -3
  308. package/pack/generated/claude/skills/rite-build/reference/phase-contract.md +96 -175
  309. package/pack/generated/claude/skills/rite-build/reference/spec-drift-guard.md +10 -4
  310. package/pack/generated/claude/skills/rite-build/reference/wright-dispatch.md +129 -134
  311. package/pack/generated/claude/skills/rite-clarify/SKILL.md +90 -0
  312. package/pack/generated/claude/skills/rite-clarify/reference/decision-coverage.md +61 -0
  313. package/pack/generated/claude/skills/rite-converge/SKILL.md +35 -25
  314. package/pack/generated/claude/skills/rite-define/SKILL.md +58 -32
  315. package/pack/generated/claude/skills/rite-define/reference/gates.md +16 -15
  316. package/pack/generated/claude/skills/rite-define/reference/plan-template.md +18 -8
  317. package/pack/generated/claude/skills/rite-frame/reference/failure-modes.md +22 -24
  318. package/pack/generated/claude/skills/rite-plan/SKILL.md +47 -16
  319. package/pack/generated/claude/skills/rite-plan/reference/task-breakdown.md +4 -0
  320. package/pack/generated/claude/skills/rite-polish/SKILL.md +27 -23
  321. package/pack/generated/claude/skills/rite-prototype/SKILL.md +25 -26
  322. package/pack/generated/claude/skills/rite-prove/SKILL.md +27 -17
  323. package/pack/generated/claude/skills/rite-resolve/SKILL.md +12 -11
  324. package/pack/generated/claude/skills/rite-resolve/reference/answer-protocol.md +3 -0
  325. package/pack/generated/claude/skills/rite-review/SKILL.md +37 -28
  326. package/pack/generated/claude/skills/rite-seal/reference/phase-contract.md +27 -92
  327. package/pack/generated/claude/skills/rite-seal/reference/risk-and-rollback.md +13 -0
  328. package/pack/generated/claude/skills/rite-ship/reference/design-memory.md +31 -36
  329. package/pack/generated/claude/skills/rite-spec/SKILL.md +84 -135
  330. package/pack/generated/claude/skills/rite-spec/reference/investigation.md +37 -33
  331. package/pack/generated/claude/skills/rite-spec/reference/question-protocol.md +6 -2
  332. package/pack/generated/claude/skills/rite-spec/reference/spec-checklists.md +25 -24
  333. package/pack/generated/claude/skills/rite-spec/reference/spec-template.md +9 -2
  334. package/pack/generated/claude/skills/rite-spec/reference/state-workspace.md +13 -3
  335. package/pack/generated/claude/skills/rite-temper/SKILL.md +62 -47
  336. package/pack/generated/claude/skills/rite-temper/reference/review-dimensions.md +24 -22
  337. package/pack/generated/claude/skills/rite-upgrade/SKILL.md +125 -0
  338. package/pack/generated/claude/skills/rite-vet/SKILL.md +114 -113
  339. package/pack/generated/claude/skills/rite-vet/reference/artifacts.md +50 -9
  340. package/pack/generated/claude/skills/rite-vet/reference/review-axes.md +39 -37
  341. package/pack/generated/codex/AGENTS.md +5 -2
  342. package/pack/generated/codex/agents/devrites-code-reviewer.toml +69 -47
  343. package/pack/generated/codex/agents/devrites-devex-reviewer.toml +75 -51
  344. package/pack/generated/codex/agents/devrites-doubt-reviewer.toml +35 -20
  345. package/pack/generated/codex/agents/devrites-evidence-scout.toml +75 -0
  346. package/pack/generated/codex/agents/devrites-forge-judge.toml +80 -59
  347. package/pack/generated/codex/agents/devrites-frontend-reviewer.toml +54 -37
  348. package/pack/generated/codex/agents/devrites-performance-reviewer.toml +55 -38
  349. package/pack/generated/codex/agents/devrites-plan-drafter.toml +79 -0
  350. package/pack/generated/codex/agents/devrites-plan-reviewer.toml +82 -47
  351. package/pack/generated/codex/agents/devrites-proof-runner.toml +80 -0
  352. package/pack/generated/codex/agents/devrites-retrospector.toml +54 -43
  353. package/pack/generated/codex/agents/devrites-security-auditor.toml +53 -35
  354. package/pack/generated/codex/agents/devrites-simplifier-reviewer.toml +56 -44
  355. package/pack/generated/codex/agents/devrites-slice-wright.toml +159 -163
  356. package/pack/generated/codex/agents/devrites-spec-reviewer.toml +40 -30
  357. package/pack/generated/codex/agents/devrites-strategy-reviewer.toml +65 -34
  358. package/pack/generated/codex/agents/devrites-test-analyst.toml +46 -28
  359. package/pack/generated/codex/agents/devrites-upgrade-planner.toml +106 -0
  360. package/pack/generated/codex/hooks.json +4 -14
  361. package/pack/generated/codex/skills/devrites-api-interface/SKILL.md +7 -3
  362. package/pack/generated/codex/skills/devrites-audit/SKILL.md +47 -64
  363. package/pack/generated/codex/skills/devrites-browser-proof/SKILL.md +7 -3
  364. package/pack/generated/codex/skills/devrites-debug-recovery/SKILL.md +31 -16
  365. package/pack/generated/codex/skills/devrites-debug-recovery/reference/build-the-loop.md +24 -21
  366. package/pack/generated/codex/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +34 -6
  367. package/pack/generated/codex/skills/devrites-debug-recovery/reference/instrumentation.md +2 -2
  368. package/pack/generated/codex/skills/devrites-doubt/SKILL.md +32 -20
  369. package/pack/generated/codex/skills/devrites-frontend-craft/SKILL.md +7 -3
  370. package/pack/generated/codex/skills/devrites-interview/SKILL.md +60 -55
  371. package/pack/generated/codex/skills/devrites-lib/SKILL.md +19 -12
  372. package/pack/generated/codex/skills/devrites-lib/reference/intent-map.md +4 -2
  373. package/pack/generated/codex/skills/devrites-lib/reference/parallel-dispatch.md +82 -137
  374. package/pack/generated/codex/skills/devrites-lib/reference/reply-contract.md +8 -1
  375. package/pack/generated/codex/skills/devrites-lib/reference/standards/README.md +38 -55
  376. package/pack/generated/codex/skills/devrites-lib/reference/standards/afk-hitl.md +53 -27
  377. package/pack/generated/codex/skills/devrites-lib/reference/standards/agents.md +200 -190
  378. package/pack/generated/codex/skills/devrites-lib/reference/standards/anti-patterns.md +5 -15
  379. package/pack/generated/codex/skills/devrites-lib/reference/standards/ci-cd.md +27 -58
  380. package/pack/generated/codex/skills/devrites-lib/reference/standards/code-review.md +16 -52
  381. package/pack/generated/codex/skills/devrites-lib/reference/standards/coding-style.md +2 -10
  382. package/pack/generated/codex/skills/devrites-lib/reference/standards/context-hygiene.md +18 -61
  383. package/pack/generated/codex/skills/devrites-lib/reference/standards/core.md +23 -18
  384. package/pack/generated/codex/skills/devrites-lib/reference/standards/deprecation.md +17 -57
  385. package/pack/generated/codex/skills/devrites-lib/reference/standards/development-workflow.md +4 -33
  386. package/pack/generated/codex/skills/devrites-lib/reference/standards/git-workflow.md +4 -20
  387. package/pack/generated/codex/skills/devrites-lib/reference/standards/hooks.md +3 -14
  388. package/pack/generated/codex/skills/devrites-lib/reference/standards/patterns.md +9 -25
  389. package/pack/generated/codex/skills/devrites-lib/reference/standards/performance.md +0 -9
  390. package/pack/generated/codex/skills/devrites-lib/reference/standards/principles.md +1 -3
  391. package/pack/generated/codex/skills/devrites-lib/reference/standards/security.md +17 -7
  392. package/pack/generated/codex/skills/devrites-lib/reference/standards/testing.md +1 -27
  393. package/pack/generated/codex/skills/devrites-lib/reference/standards/tooling.md +46 -50
  394. package/pack/generated/codex/skills/devrites-lib/reference/workspace-artifact-schema.md +40 -10
  395. package/pack/generated/codex/skills/devrites-prose-craft/SKILL.md +7 -3
  396. package/pack/generated/codex/skills/devrites-refresh-indexes/SKILL.md +7 -3
  397. package/pack/generated/codex/skills/devrites-source-driven/SKILL.md +29 -24
  398. package/pack/generated/codex/skills/devrites-ux-shape/SKILL.md +7 -3
  399. package/pack/generated/codex/skills/rite/SKILL.md +21 -13
  400. package/pack/generated/codex/skills/rite/reference/menu.md +13 -7
  401. package/pack/generated/codex/skills/rite-adopt/SKILL.md +40 -40
  402. package/pack/generated/codex/skills/rite-autocomplete/SKILL.md +40 -31
  403. package/pack/generated/codex/skills/rite-autocomplete/reference/loop.md +21 -21
  404. package/pack/generated/codex/skills/rite-autocomplete/reference/stop-conditions.md +15 -6
  405. package/pack/generated/codex/skills/rite-build/SKILL.md +42 -33
  406. package/pack/generated/codex/skills/rite-build/reference/afk-discipline.md +41 -39
  407. package/pack/generated/codex/skills/rite-build/reference/evidence-standard.md +10 -0
  408. package/pack/generated/codex/skills/rite-build/reference/forge.md +186 -156
  409. package/pack/generated/codex/skills/rite-build/reference/one-slice-cycle.md +4 -3
  410. package/pack/generated/codex/skills/rite-build/reference/phase-contract.md +96 -175
  411. package/pack/generated/codex/skills/rite-build/reference/spec-drift-guard.md +10 -4
  412. package/pack/generated/codex/skills/rite-build/reference/wright-dispatch.md +129 -134
  413. package/pack/generated/codex/skills/rite-clarify/SKILL.md +106 -0
  414. package/pack/generated/codex/skills/rite-clarify/reference/decision-coverage.md +61 -0
  415. package/pack/generated/codex/skills/rite-converge/SKILL.md +42 -28
  416. package/pack/generated/codex/skills/rite-customize/SKILL.md +7 -3
  417. package/pack/generated/codex/skills/rite-define/SKILL.md +65 -35
  418. package/pack/generated/codex/skills/rite-define/reference/gates.md +16 -15
  419. package/pack/generated/codex/skills/rite-define/reference/plan-template.md +18 -8
  420. package/pack/generated/codex/skills/rite-doctor/SKILL.md +7 -3
  421. package/pack/generated/codex/skills/rite-dogfood/SKILL.md +7 -3
  422. package/pack/generated/codex/skills/rite-explain/SKILL.md +7 -3
  423. package/pack/generated/codex/skills/rite-frame/SKILL.md +7 -3
  424. package/pack/generated/codex/skills/rite-frame/reference/failure-modes.md +22 -24
  425. package/pack/generated/codex/skills/rite-handoff/SKILL.md +7 -3
  426. package/pack/generated/codex/skills/rite-learn/SKILL.md +7 -3
  427. package/pack/generated/codex/skills/rite-plan/SKILL.md +54 -19
  428. package/pack/generated/codex/skills/rite-plan/reference/task-breakdown.md +5 -1
  429. package/pack/generated/codex/skills/rite-polish/SKILL.md +34 -26
  430. package/pack/generated/codex/skills/rite-pov/SKILL.md +7 -3
  431. package/pack/generated/codex/skills/rite-pr-feedback/SKILL.md +7 -3
  432. package/pack/generated/codex/skills/rite-pressure-test/SKILL.md +7 -3
  433. package/pack/generated/codex/skills/rite-prototype/SKILL.md +32 -29
  434. package/pack/generated/codex/skills/rite-prove/SKILL.md +34 -20
  435. package/pack/generated/codex/skills/rite-quick/SKILL.md +7 -3
  436. package/pack/generated/codex/skills/rite-resolve/SKILL.md +19 -14
  437. package/pack/generated/codex/skills/rite-resolve/reference/answer-protocol.md +3 -0
  438. package/pack/generated/codex/skills/rite-review/SKILL.md +44 -31
  439. package/pack/generated/codex/skills/rite-seal/SKILL.md +7 -3
  440. package/pack/generated/codex/skills/rite-seal/reference/phase-contract.md +27 -92
  441. package/pack/generated/codex/skills/rite-seal/reference/risk-and-rollback.md +13 -0
  442. package/pack/generated/codex/skills/rite-ship/SKILL.md +7 -3
  443. package/pack/generated/codex/skills/rite-ship/reference/design-memory.md +31 -36
  444. package/pack/generated/codex/skills/rite-spec/SKILL.md +91 -138
  445. package/pack/generated/codex/skills/rite-spec/reference/investigation.md +37 -33
  446. package/pack/generated/codex/skills/rite-spec/reference/question-protocol.md +6 -2
  447. package/pack/generated/codex/skills/rite-spec/reference/spec-checklists.md +25 -24
  448. package/pack/generated/codex/skills/rite-spec/reference/spec-template.md +9 -2
  449. package/pack/generated/codex/skills/rite-spec/reference/state-workspace.md +13 -3
  450. package/pack/generated/codex/skills/rite-status/SKILL.md +7 -3
  451. package/pack/generated/codex/skills/rite-temper/SKILL.md +69 -50
  452. package/pack/generated/codex/skills/rite-temper/reference/review-dimensions.md +24 -22
  453. package/pack/generated/codex/skills/rite-upgrade/SKILL.md +141 -0
  454. package/pack/generated/codex/skills/rite-upgrade/agents/openai.yaml +2 -0
  455. package/pack/generated/codex/skills/rite-vet/SKILL.md +121 -116
  456. package/pack/generated/codex/skills/rite-vet/reference/artifacts.md +50 -9
  457. package/pack/generated/codex/skills/rite-vet/reference/review-axes.md +40 -38
  458. package/pack/generated/codex/skills/rite-zoom-out/SKILL.md +7 -3
  459. package/package.json +1 -1
  460. package/scripts/build-release-tarball.sh +32 -15
  461. package/scripts/check-authority-drift.py +125 -0
  462. package/scripts/check-instruction-size-baseline.mjs +19 -11
  463. package/scripts/check-invocation-integrity.py +2 -0
  464. package/scripts/codex-generate.sh +69 -33
  465. package/scripts/grade-feature.sh +121 -40
  466. package/scripts/live-hosts/agent-result.schema.json +230 -0
  467. package/scripts/live-hosts/claude.sh +87 -0
  468. package/scripts/live-hosts/codex.sh +81 -0
  469. package/scripts/live-hosts/common.sh +113 -0
  470. package/scripts/live-hosts/fake-host.py +264 -0
  471. package/scripts/live-hosts/host-transport.py +287 -0
  472. package/scripts/release-check.sh +5 -1
  473. package/scripts/run-agent-contract-evals.py +1380 -0
  474. package/scripts/run-behavioral-evals.sh +24 -30
  475. package/scripts/run-evals.sh +1 -5
  476. package/scripts/run-live-behavioral-evals.py +1274 -144
  477. package/scripts/run-outcome-evals.sh +445 -88
  478. package/scripts/run-tests.mjs +30 -2
  479. package/scripts/skills-inventory.mjs +1 -1
  480. package/scripts/validate-workflow-security.py +39 -20
  481. package/scripts/validate-workspace-schema.py +362 -10
  482. package/scripts/validate.sh +21 -15
  483. package/engine/testdata/golden/TestParityWrightScope/devrites-edit-allowed.golden +0 -1
  484. /package/engine/testdata/golden/{TestParityReconcile/check-no-claimed.golden → TestParityBuildReadiness/arg=clarifyopen.golden} +0 -0
@@ -2,6 +2,7 @@ package main
2
2
 
3
3
  import (
4
4
  "encoding/json"
5
+ "errors"
5
6
  "fmt"
6
7
  "io"
7
8
  "os"
@@ -11,18 +12,161 @@ import (
11
12
  "github.com/devrites/devrites/internal/devritespaths"
12
13
  "github.com/devrites/devrites/internal/doctor"
13
14
  "github.com/devrites/devrites/internal/migrate"
15
+ "github.com/devrites/devrites/internal/rootfacts"
14
16
  "github.com/devrites/devrites/internal/state"
15
17
  )
16
18
 
17
- // resolveRootLenient resolves the .devrites root for the workspace-orientation
18
- // commands (preamble / progress / stuck), which must degrade gracefully outside a
19
- // workspace rather than erroring like the gates do. When no .devrites is found it
20
- // returns a nonexistent <cwd>/.devrites so the command reads an empty workspace
21
- // and no-ops (preamble's "No active workspace", progress's silence).
19
+ type rootMode uint8
20
+
21
+ const (
22
+ rootUnused rootMode = iota
23
+ rootLenient
24
+ rootStrict
25
+ )
26
+
27
+ // rootModeFor is the single policy boundary between diagnostic/read-only
28
+ // commands, which may degrade outside a workspace, and commands that can write
29
+ // workspace or Git state, which must never fall back after an unsafe root
30
+ // selection.
31
+ func rootModeFor(command string, args []string) rootMode {
32
+ subcommand := firstRootOperand(args)
33
+ switch command {
34
+ case "first-task", "spec-dedupe", "evidence-fresh", "coverage",
35
+ "doubt-coverage", "budget", "preamble", "progress",
36
+ "build-readiness", "readiness-digest", "analyze", "mutation-gate",
37
+ "test-integrity", "review-integrity", "package-existence",
38
+ "archive-search", "config", "reviewers", "outside-voice", "docs-stale",
39
+ "secret-scan", "lanes", "overrides":
40
+ return rootLenient
41
+ case "clarify-return", "reconcile", "close-out", "forge":
42
+ return rootStrict
43
+ case "resolve":
44
+ if subcommand == "next-qid" {
45
+ return rootLenient
46
+ }
47
+ return rootStrict
48
+ case "footprint", "stuck":
49
+ if subcommand == "log" {
50
+ return rootStrict
51
+ }
52
+ return rootLenient
53
+ case "recovery":
54
+ if subcommand == "record" || subcommand == "clear" {
55
+ return rootStrict
56
+ }
57
+ return rootLenient
58
+ case "decisions":
59
+ if subcommand == "index" {
60
+ return rootStrict
61
+ }
62
+ return rootLenient
63
+ case "ledger":
64
+ if subcommand == "sync" {
65
+ return rootStrict
66
+ }
67
+ return rootLenient
68
+ case "learnings":
69
+ if subcommand == "add" {
70
+ return rootStrict
71
+ }
72
+ return rootLenient
73
+ case "timeline":
74
+ if subcommand == "log" || subcommand == "purge" {
75
+ return rootStrict
76
+ }
77
+ return rootLenient
78
+ case "health":
79
+ if subcommand == "" || subcommand == "run" || subcommand == "check" || subcommand == "record" {
80
+ return rootStrict
81
+ }
82
+ return rootLenient
83
+ case "review-fingerprints":
84
+ if hasRootFlag(args, "--write") {
85
+ return rootStrict
86
+ }
87
+ return rootLenient
88
+ case "reviewer-stats":
89
+ if subcommand == "record" {
90
+ return rootStrict
91
+ }
92
+ return rootLenient
93
+ case "extensions":
94
+ if subcommand == "sync" {
95
+ return rootStrict
96
+ }
97
+ return rootLenient
98
+ case "context":
99
+ if subcommand == "sync" {
100
+ return rootStrict
101
+ }
102
+ return rootLenient
103
+ case "runbook":
104
+ if subcommand == "run" || subcommand == "resume" {
105
+ return rootStrict
106
+ }
107
+ return rootLenient
108
+ default:
109
+ return rootUnused
110
+ }
111
+ }
112
+
113
+ func firstRootOperand(args []string) string {
114
+ for _, arg := range args {
115
+ if arg == "--json" {
116
+ continue
117
+ }
118
+ return strings.ToLower(strings.TrimSpace(arg))
119
+ }
120
+ return ""
121
+ }
122
+
123
+ func hasRootFlag(args []string, flag string) bool {
124
+ for _, arg := range args {
125
+ if arg == flag {
126
+ return true
127
+ }
128
+ }
129
+ return false
130
+ }
131
+
132
+ // resolveRootFor resolves exactly once per command invocation. Strict commands
133
+ // retain root-safety refusals; lenient readers preserve their historical
134
+ // diagnostic/no-workspace behavior.
135
+ func resolveRootFor(command string, args []string) (string, int, error) {
136
+ switch rootModeFor(command, args) {
137
+ case rootUnused:
138
+ return "", exitOK, nil
139
+ case rootLenient:
140
+ return resolveRootLenient(), exitOK, nil
141
+ case rootStrict:
142
+ root, err := state.ResolveRoot(os.Getenv("DEVRITES_ROOT"))
143
+ if err == nil {
144
+ return root, exitOK, nil
145
+ }
146
+ if errors.Is(err, rootfacts.ErrUnsafeRoot) {
147
+ return "", exitBlocked, err
148
+ }
149
+ if errors.Is(err, rootfacts.ErrNoRoot) {
150
+ return fallbackRoot(), exitOK, nil
151
+ }
152
+ return "", exitUsage, err
153
+ default:
154
+ panic("unknown root resolution mode")
155
+ }
156
+ }
157
+
158
+ // resolveRootLenient resolves the .devrites root for read-only and diagnostic
159
+ // commands that must degrade cleanly outside a workspace. When no root is found,
160
+ // it returns a nonexistent <cwd>/.devrites so those commands see an empty
161
+ // workspace and keep their established no-workspace behavior.
22
162
  func resolveRootLenient() string {
23
163
  if root, err := state.ResolveRoot(os.Getenv("DEVRITES_ROOT")); err == nil {
24
164
  return root
25
165
  }
166
+ return fallbackRoot()
167
+ }
168
+
169
+ func fallbackRoot() string {
26
170
  cwd, err := os.Getwd()
27
171
  if err != nil {
28
172
  return ".devrites"
@@ -54,8 +198,11 @@ func gitDir(projectDir string) string {
54
198
  return path
55
199
  }
56
200
 
57
- func gitOperation(projectDir string) string {
58
- dir := gitDir(projectDir)
201
+ func gitOperation(projectDir, resolvedGitDir string) string {
202
+ dir := resolvedGitDir
203
+ if dir == "" {
204
+ dir = gitDir(projectDir)
205
+ }
59
206
  if _, err := os.Stat(filepath.Join(dir, "MERGE_HEAD")); err == nil {
60
207
  return "merge"
61
208
  }
@@ -67,37 +214,37 @@ func gitOperation(projectDir string) string {
67
214
  return ""
68
215
  }
69
216
 
70
- // cmdDoctor reports the binary / pack / state-schema version triangle and its
71
- // skew verdict. It exits non-zero only when the state schema is a newer major
72
- // than the binary can safely parse (a genuine refuse); a mere pack-vs-binary
73
- // skew is a warning that still exits 0.
217
+ // cmdDoctor reports canonical root facts and the binary, pack, and state schema
218
+ // versions. It exits nonzero for an unsafe root or newer state schema. Missing
219
+ // optional data and warnings remain diagnostic.
74
220
  func cmdDoctor(args []string, stdout, stderr io.Writer) int {
75
221
  if len(args) != 0 {
76
222
  fmt.Fprintln(stderr, "usage: devrites-engine doctor")
77
223
  return exitUsage
78
224
  }
79
- root, err := state.ResolveRoot(os.Getenv("DEVRITES_ROOT"))
80
- if err != nil {
81
- fmt.Fprintf(stderr, "devrites: %v\n", err)
225
+ facts, resolveErr := rootfacts.Resolve(os.Getenv("DEVRITES_ROOT"))
226
+ if resolveErr != nil && len(facts.Hazards) == 0 {
227
+ fmt.Fprintf(stderr, "devrites: %v\n", resolveErr)
82
228
  return exitUsage
83
229
  }
84
- // The project directory is the parent of the .devrites root: that is where
85
- // an installed pack's version marker (.claude/devrites.version, package.json)
86
- // lives.
87
- projectDir := filepath.Dir(root)
88
- report, err := doctor.Diagnose(projectDir, root)
230
+ root := facts.PhysicalRoot
231
+ projectDir := facts.PhysicalProject
232
+ report, err := doctor.DiagnoseFacts(facts)
89
233
  if err != nil {
90
234
  fmt.Fprintf(stderr, "devrites: %v\n", err)
91
235
  return exitUsage
92
236
  }
93
237
  fmt.Fprint(stdout, report.Render())
94
- if op := gitOperation(projectDir); op != "" {
238
+ if op := gitOperation(projectDir, facts.Git.Dir); op != "" {
95
239
  fmt.Fprintf(stdout, "git-state: %s in progress: resolve with .claude/skills/devrites-lib/reference/standards/git-workflow.md#merge-conflict-recovery\n", op)
96
240
  }
97
- for _, warning := range extensionProvenanceWarnings(root) {
98
- fmt.Fprintf(stdout, "warning: %s\n", warning)
241
+ if root != "" {
242
+ for _, warning := range extensionProvenanceWarnings(root) {
243
+ fmt.Fprintf(stdout, "warning: %s\n", warning)
244
+ }
99
245
  }
100
- if slug := strings.TrimSpace(readFile(filepath.Join(root, "ACTIVE"))); slug != "" {
246
+ if root != "" {
247
+ slug := strings.TrimSpace(readFile(filepath.Join(root, "ACTIVE")))
101
248
  if snap, err := state.Snapshot(root, slug); err == nil {
102
249
  fmt.Fprintln(stdout)
103
250
  fmt.Fprintln(stdout, "readiness-dashboard:")
@@ -0,0 +1,187 @@
1
+ package main
2
+
3
+ import (
4
+ "fmt"
5
+ "io"
6
+ "os"
7
+ "strings"
8
+
9
+ "github.com/devrites/devrites/internal/harness"
10
+ "github.com/devrites/devrites/internal/lib"
11
+ "github.com/devrites/devrites/internal/orient"
12
+ drvreason "github.com/devrites/devrites/internal/reason"
13
+ "github.com/devrites/devrites/internal/toolpolicy"
14
+ )
15
+
16
+ const gitGuardSuffix = " (devrites-git-guard)"
17
+
18
+ // hookGitGuard denies ambiguous high-impact Git and requires an exact, fresh,
19
+ // consumed-on-attempt authority record for an unambiguous destructive command.
20
+ func hookGitGuard(h harness.Harness, stdin io.Reader, stdout, stderr io.Writer) int {
21
+ in := h.ParsePreToolInput(stdin)
22
+ if !isShellTool(in.ToolName) || strings.TrimSpace(in.Command) == "" {
23
+ return exitOK
24
+ }
25
+
26
+ classified := toolpolicy.ClassifyGitCommand(in.Command)
27
+ if classified.Verdict == toolpolicy.VerdictSafe {
28
+ return exitOK
29
+ }
30
+ classifierReasons := gitClassifierReasons(classified)
31
+ if classified.Verdict == toolpolicy.VerdictAmbiguous {
32
+ primary := gitReasonID(classified.ReasonID, drvreason.GitAuthorityUnavailable)
33
+ root, slug := gitGuardWorkspace()
34
+ recordGitPolicy(root, slug, h, primary, classifierReasons, lib.OutcomeDenied)
35
+ return emitGitDeny(h, stdout, stderr,
36
+ fmt.Sprintf("DevRites denied an ambiguous high-impact Git request (%s). %s%s",
37
+ primary, classified.Remediation, gitGuardSuffix))
38
+ }
39
+
40
+ root, slug := gitGuardWorkspace()
41
+ if root == "" {
42
+ return emitGitDeny(h, stdout, stderr,
43
+ "DevRites cannot authorize destructive Git without an active DevRites workspace ("+
44
+ string(drvreason.GitWorkspaceUnavailable)+")."+gitGuardSuffix)
45
+ }
46
+ if slug == "" {
47
+ recordGitPolicy(root, "", h, drvreason.GitWorkspaceUnavailable, classifierReasons, lib.OutcomeDenied)
48
+ return emitGitDeny(h, stdout, stderr,
49
+ "DevRites cannot authorize destructive Git without an active DevRites workspace ("+
50
+ string(drvreason.GitWorkspaceUnavailable)+")."+gitGuardSuffix)
51
+ }
52
+
53
+ decision := lib.AuthorizeGitOperation(root, slug, classified.Digest, destructiveClassifierReasons(classified))
54
+ if decision.Allowed {
55
+ out, err := h.PreToolAllow("DevRites consumed one fresh exact-operation Git authorization (" +
56
+ string(decision.ReasonID) + ")." + gitGuardSuffix)
57
+ if err != nil {
58
+ recordGitPolicy(root, slug, h, drvreason.GitAuthorityUnavailable, classifierReasons, lib.OutcomeDenied)
59
+ return exitOK
60
+ }
61
+ fmt.Fprintln(stdout, out)
62
+ recordGitPolicy(root, slug, h, decision.ReasonID, classifierReasons, lib.OutcomeAllowed)
63
+ return exitOK
64
+ }
65
+
66
+ recordGitPolicy(root, slug, h, decision.ReasonID, classifierReasons, lib.OutcomeDenied)
67
+ return emitGitDeny(h, stdout, stderr, gitAuthorityDenyMessage(decision))
68
+ }
69
+
70
+ func gitGuardWorkspace() (string, string) {
71
+ root, err := orient.ResolveRoot(os.Getenv("DEVRITES_ROOT"))
72
+ if err != nil {
73
+ return "", ""
74
+ }
75
+ slug, err := orient.ActiveSlug(root)
76
+ if err != nil {
77
+ return root, ""
78
+ }
79
+ return root, slug
80
+ }
81
+
82
+ func emitGitDeny(h harness.Harness, stdout, stderr io.Writer, message string) int {
83
+ out, err := h.PreToolDeny(message)
84
+ if err != nil {
85
+ debugf(stderr, "git-guard decision unavailable")
86
+ return exitOK
87
+ }
88
+ fmt.Fprintln(stdout, out)
89
+ return exitOK
90
+ }
91
+
92
+ func gitAuthorityDenyMessage(decision lib.GitAuthorityDecision) string {
93
+ reasonID := string(decision.ReasonID)
94
+ switch decision.ReasonID {
95
+ case drvreason.GitAuthorityPending, drvreason.GitAuthorityExpired, drvreason.GitAuthorityReplayed:
96
+ if decision.QuestionID != "" {
97
+ return fmt.Sprintf(
98
+ `DevRites requires one fresh exact-operation Git authorization (%s). Resolve %s with /rite-resolve %s "%s", then retry.%s`,
99
+ reasonID, decision.QuestionID, decision.QuestionID, lib.GitAuthorityAnswer, gitGuardSuffix)
100
+ }
101
+ case drvreason.GitAuthorityRefused:
102
+ return fmt.Sprintf("DevRites denied this destructive Git operation because its exact authorization was refused (%s).%s",
103
+ reasonID, gitGuardSuffix)
104
+ case drvreason.GitAuthorityCorrupt:
105
+ return fmt.Sprintf("DevRites denied destructive Git because its authority record or consumption ledger "+
106
+ "is invalid (%s). Repair the workspace authority state before retrying.%s",
107
+ reasonID, gitGuardSuffix)
108
+ case drvreason.GitWorkspaceUnavailable:
109
+ return fmt.Sprintf("DevRites cannot authorize destructive Git without an active DevRites workspace (%s).%s",
110
+ reasonID, gitGuardSuffix)
111
+ }
112
+ return fmt.Sprintf("DevRites could not persist or consume destructive Git authority (%s). Repair the workspace or hook, then retry.%s",
113
+ reasonID, gitGuardSuffix)
114
+ }
115
+
116
+ func destructiveClassifierReasons(classified toolpolicy.Result) []toolpolicy.ReasonID {
117
+ seen := map[toolpolicy.ReasonID]bool{}
118
+ var out []toolpolicy.ReasonID
119
+ for _, finding := range classified.Findings {
120
+ if finding.Verdict != toolpolicy.VerdictDestructive || seen[finding.ReasonID] {
121
+ continue
122
+ }
123
+ seen[finding.ReasonID] = true
124
+ out = append(out, finding.ReasonID)
125
+ }
126
+ return out
127
+ }
128
+
129
+ func gitClassifierReasons(classified toolpolicy.Result) []drvreason.ID {
130
+ seen := map[drvreason.ID]bool{}
131
+ var out []drvreason.ID
132
+ for _, finding := range classified.Findings {
133
+ id := gitReasonID(finding.ReasonID, "")
134
+ if id == "" || seen[id] {
135
+ continue
136
+ }
137
+ seen[id] = true
138
+ out = append(out, id)
139
+ }
140
+ if len(out) == 0 {
141
+ if id := gitReasonID(classified.ReasonID, ""); id != "" {
142
+ out = append(out, id)
143
+ }
144
+ }
145
+ return out
146
+ }
147
+
148
+ func gitReasonID(value toolpolicy.ReasonID, fallback drvreason.ID) drvreason.ID {
149
+ id, err := drvreason.Parse(string(value))
150
+ if err != nil {
151
+ return fallback
152
+ }
153
+ return id
154
+ }
155
+
156
+ func recordGitPolicy(root, slug string, h harness.Harness, primary drvreason.ID, classifier []drvreason.ID, outcome lib.EventOutcome) {
157
+ if root == "" || !drvreason.Known(primary) {
158
+ return
159
+ }
160
+ ev := lib.NewEventV1(lib.BoundaryGitPolicy, "git-guard", primary)
161
+ ev.GuardStrength = lib.GuardEnforced
162
+ ev.Outcome = outcome
163
+ ev.Host = lib.EventHost(h)
164
+ if ev.Host != lib.HostClaude && ev.Host != lib.HostCodex {
165
+ ev.Host = lib.HostEngine
166
+ }
167
+ ev.RuleIDs = []drvreason.ID{primary}
168
+ for _, id := range classifier {
169
+ if len(ev.RuleIDs) == 16 {
170
+ break
171
+ }
172
+ duplicate := false
173
+ for _, existing := range ev.RuleIDs {
174
+ if existing == id {
175
+ duplicate = true
176
+ break
177
+ }
178
+ }
179
+ if !duplicate {
180
+ ev.RuleIDs = append(ev.RuleIDs, id)
181
+ }
182
+ }
183
+ if err := lib.BindEventWorkspace(root, slug, &ev); err != nil {
184
+ return
185
+ }
186
+ _ = lib.AppendEventV1(root, ev)
187
+ }