devrites 3.2.28 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (897) hide show
  1. package/CHANGELOG.md +22 -144
  2. package/NOTICE.md +6 -5
  3. package/README.md +192 -95
  4. package/SECURITY.md +103 -79
  5. package/bin/devrites.mjs +140 -24
  6. package/docs/adr/0003-gate-model-hitl-pause.md +1 -1
  7. package/docs/adr/0013-native-codex-agent-orchestration.md +74 -0
  8. package/docs/adr/0014-native-host-hook-boundary.md +64 -0
  9. package/docs/adr/0015-read-only-root-native-orchestration.md +96 -0
  10. package/docs/adr/0016-codex-writer-fail-closed.md +53 -0
  11. package/docs/adr/0017-native-codex-writer-agent.md +63 -0
  12. package/docs/adr/0018-native-sandbox-instruction-writer-boundary.md +66 -0
  13. package/docs/adr/0019-native-boundary-with-deterministic-gates.md +48 -0
  14. package/docs/adr/0020-thin-engine-native-orchestration-boundary.md +54 -0
  15. package/docs/adr/0021-observable-workspace-compatibility.md +49 -0
  16. package/docs/adr/0022-native-orchestration-thin-engine.md +90 -0
  17. package/docs/adr/0023-native-workspace-reads-line-output.md +71 -0
  18. package/docs/adr/0024-native-policy-offline-installer-boundary.md +111 -0
  19. package/docs/adr/0025-evidence-gated-workspace-upgrades.md +64 -0
  20. package/docs/adr/0026-content-bound-proof-and-bounded-inputs.md +169 -0
  21. package/docs/adr/0027-content-bound-build-readiness.md +77 -0
  22. package/docs/adr/README.md +26 -11
  23. package/docs/agents/domain.md +2 -1
  24. package/docs/agents/issue-driven-rites.md +1 -1
  25. package/docs/architecture.md +191 -103
  26. package/docs/candidate-integrity.md +138 -0
  27. package/docs/capability-surface-selection.md +15 -5
  28. package/docs/cli.md +145 -92
  29. package/docs/command-map.md +88 -63
  30. package/docs/engine/commands.md +115 -507
  31. package/docs/engine/state-schema.md +94 -113
  32. package/docs/engine/workspace-schema.md +169 -229
  33. package/docs/flow.md +113 -68
  34. package/docs/harness-compliance.md +29 -56
  35. package/docs/markdown-instruction-upgrade-2026-08-02.md +302 -0
  36. package/docs/orchestration.md +136 -149
  37. package/docs/porting-to-a-new-harness.md +22 -7
  38. package/docs/quick-reference.md +21 -8
  39. package/docs/release.md +47 -4
  40. package/docs/skills.md +111 -72
  41. package/docs/templates/CRITIC_REVIEW_PACKET_TEMPLATE.md +2 -0
  42. package/docs/upstream-workflow-benchmark-2026-08-01.md +655 -0
  43. package/docs/usage.md +99 -65
  44. package/engine/Makefile +1 -2
  45. package/engine/cmd/releasepack/main.go +45 -25
  46. package/engine/cmd/releasepack/main_test.go +69 -0
  47. package/engine/commands.go +8 -258
  48. package/engine/harnessmatrix_test.go +28 -41
  49. package/engine/internal/devritespaths/paths.go +12 -28
  50. package/engine/internal/fsutil/copy.go +8 -0
  51. package/engine/internal/gate/gate.go +104 -105
  52. package/engine/internal/gate/gate_test.go +94 -84
  53. package/engine/internal/gate/readiness_binding.go +203 -0
  54. package/engine/internal/gate/readiness_binding_test.go +271 -0
  55. package/engine/internal/gitenv/env.go +46 -0
  56. package/engine/internal/gitenv/env_test.go +48 -0
  57. package/engine/internal/hostpack/hostpack.go +23 -20
  58. package/engine/internal/hostpack/hostpack_test.go +6 -6
  59. package/engine/internal/install/install.go +321 -510
  60. package/engine/internal/install/install_test.go +346 -306
  61. package/engine/internal/lib/candidate.go +475 -0
  62. package/engine/internal/lib/candidate_test.go +503 -0
  63. package/engine/internal/lib/closeout.go +17 -21
  64. package/engine/internal/lib/closeout_test.go +23 -0
  65. package/engine/internal/lib/cursor_compat_test.go +12 -75
  66. package/engine/internal/lib/evidencefresh.go +58 -47
  67. package/engine/internal/lib/evidencefresh_test.go +120 -0
  68. package/engine/internal/lib/resolve.go +13 -35
  69. package/engine/internal/lib/resolve_remediation_test.go +5 -17
  70. package/engine/internal/lib/secretscan.go +432 -0
  71. package/engine/internal/lib/secretscan_test.go +555 -0
  72. package/engine/internal/lib/util.go +24 -65
  73. package/engine/internal/lib/util_test.go +44 -0
  74. package/engine/internal/markdowntext/markdowntext.go +108 -0
  75. package/engine/internal/markdowntext/markdowntext_test.go +58 -0
  76. package/engine/internal/markdowntext/testdata/structural.json +27 -0
  77. package/engine/internal/reason/reason.go +2 -123
  78. package/engine/internal/reason/reason_test.go +4 -2
  79. package/engine/internal/rootfacts/facts.go +6 -8
  80. package/engine/internal/rootfacts/facts_test.go +20 -0
  81. package/engine/internal/state/cmd/workflowmanifest/main.go +10 -12
  82. package/engine/internal/state/cursor.go +53 -14
  83. package/engine/internal/state/cursor_test.go +57 -0
  84. package/engine/internal/state/feature.go +64 -154
  85. package/engine/internal/state/schema.go +24 -50
  86. package/engine/internal/state/state_test.go +151 -140
  87. package/engine/internal/state/status.go +4 -17
  88. package/engine/internal/state/workflow_manifest.json +9 -89
  89. package/engine/main.go +73 -502
  90. package/engine/root_routing_test.go +183 -212
  91. package/engine/testdata/fixtures/basic/devrites-root/{features/auth-tokens/feature.md → work/auth-tokens/README.md} +0 -1
  92. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/architecture.md +3 -0
  93. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/assumptions.md +3 -0
  94. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/brief.md +3 -0
  95. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/decision-coverage.md +3 -0
  96. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/eng-review.md +3 -0
  97. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/questions.md +3 -0
  98. package/engine/testdata/fixtures/basic/devrites-root/{features/auth-tokens/status.md → work/auth-tokens/state.md} +3 -0
  99. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/test-plan.md +3 -0
  100. package/engine/testdata/fixtures/basic/devrites-root/work/auth-tokens/traceability.md +3 -0
  101. package/engine/testdata/fixtures/basic/devrites-root/{features/search-ranking/feature.md → work/search-ranking/README.md} +0 -1
  102. package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/assumptions.md +3 -0
  103. package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/brief.md +3 -0
  104. package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/decisions.md +3 -0
  105. package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/questions.md +3 -0
  106. package/engine/testdata/fixtures/basic/devrites-root/work/search-ranking/state.md +2 -0
  107. package/engine/testdata/golden/TestParityCloseOut/active_pointed_elsewhere.golden +1 -1
  108. package/engine/testdata/golden/TestParityCloseOut/active_slug_cleared.golden +1 -1
  109. package/engine/tests/adr_0003_gate_exit_code_test.go +2 -2
  110. package/engine/tests/adr_0011_define_plan_test.go +2 -2
  111. package/engine/tests/adr_0027_readiness_binding_test.go +106 -0
  112. package/engine/tests/cli_test.go +24 -107
  113. package/engine/tests/gate_test.go +177 -200
  114. package/engine/tests/meta_test.go +5 -35
  115. package/engine/tests/parity_closeout_test.go +12 -12
  116. package/engine/tests/parity_resolve_test.go +6 -16
  117. package/engine/tests/parity_test.go +8 -302
  118. package/install.sh +201 -34
  119. package/pack/.claude/agents/devrites-code-reviewer.md +9 -18
  120. package/pack/.claude/agents/devrites-devex-reviewer.md +10 -18
  121. package/pack/.claude/agents/devrites-doubt-reviewer.md +10 -20
  122. package/pack/.claude/agents/devrites-evidence-scout.md +14 -26
  123. package/pack/.claude/agents/devrites-frontend-reviewer.md +9 -15
  124. package/pack/.claude/agents/devrites-performance-reviewer.md +13 -21
  125. package/pack/.claude/agents/devrites-plan-drafter.md +24 -28
  126. package/pack/.claude/agents/devrites-plan-reviewer.md +30 -47
  127. package/pack/.claude/agents/devrites-proof-runner.md +41 -47
  128. package/pack/.claude/agents/devrites-retrospector.md +34 -79
  129. package/pack/.claude/agents/devrites-security-auditor.md +9 -17
  130. package/pack/.claude/agents/devrites-simplifier-reviewer.md +9 -18
  131. package/pack/.claude/agents/devrites-slice-wright.md +44 -62
  132. package/pack/.claude/agents/devrites-spec-reviewer.md +38 -50
  133. package/pack/.claude/agents/devrites-strategy-reviewer.md +10 -19
  134. package/pack/.claude/agents/devrites-test-analyst.md +22 -21
  135. package/pack/.claude/agents/devrites-upgrade-planner.md +52 -71
  136. package/pack/.claude/settings.json +12 -100
  137. package/pack/.claude/skills/devrites-api-interface/SKILL.md +1 -2
  138. package/pack/.claude/skills/devrites-audit/SKILL.md +6 -9
  139. package/pack/.claude/skills/devrites-browser-proof/SKILL.md +0 -1
  140. package/pack/.claude/skills/devrites-debug-recovery/SKILL.md +21 -27
  141. package/pack/.claude/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +22 -33
  142. package/pack/.claude/skills/devrites-doubt/SKILL.md +4 -6
  143. package/pack/.claude/skills/devrites-frontend-craft/SKILL.md +1 -2
  144. package/pack/.claude/skills/devrites-frontend-craft/reference/design-references.md +2 -1
  145. package/pack/.claude/skills/devrites-interview/SKILL.md +31 -36
  146. package/pack/.claude/skills/devrites-lib/SKILL.md +37 -66
  147. package/pack/.claude/skills/devrites-lib/reference/candidate-integrity.md +51 -0
  148. package/pack/.claude/skills/devrites-lib/reference/intent-map.md +20 -12
  149. package/pack/.claude/skills/devrites-lib/reference/orchestration-profiles.md +22 -0
  150. package/pack/.claude/skills/devrites-lib/reference/parallel-dispatch.md +35 -110
  151. package/pack/.claude/skills/devrites-lib/reference/reply-contract.md +26 -93
  152. package/pack/.claude/skills/devrites-lib/reference/standards/README.md +6 -3
  153. package/pack/.claude/skills/devrites-lib/reference/standards/afk-hitl.md +43 -34
  154. package/pack/.claude/skills/devrites-lib/reference/standards/agents.md +90 -216
  155. package/pack/.claude/skills/devrites-lib/reference/standards/anti-patterns.md +1 -1
  156. package/pack/.claude/skills/devrites-lib/reference/standards/code-review.md +9 -28
  157. package/pack/.claude/skills/devrites-lib/reference/standards/context-hygiene.md +13 -11
  158. package/pack/.claude/skills/devrites-lib/reference/standards/core.md +59 -54
  159. package/pack/.claude/skills/devrites-lib/reference/standards/hooks.md +3 -5
  160. package/pack/.claude/skills/devrites-lib/reference/standards/principles.md +29 -143
  161. package/pack/.claude/skills/devrites-lib/reference/standards/release/ship-checklist.md +5 -6
  162. package/pack/.claude/skills/devrites-lib/reference/standards/security.md +13 -31
  163. package/pack/.claude/skills/devrites-lib/reference/standards/skill-authoring.md +112 -82
  164. package/pack/.claude/skills/devrites-lib/reference/standards/spec-grammar.md +71 -45
  165. package/pack/.claude/skills/devrites-lib/reference/standards/testing.md +22 -11
  166. package/pack/.claude/skills/devrites-lib/reference/standards/tooling.md +15 -24
  167. package/pack/.claude/skills/devrites-lib/reference/workspace-artifact-schema.md +106 -37
  168. package/pack/.claude/skills/devrites-prose-craft/SKILL.md +3 -4
  169. package/pack/.claude/skills/devrites-source-driven/SKILL.md +3 -4
  170. package/pack/.claude/skills/devrites-ux-shape/SKILL.md +3 -3
  171. package/pack/.claude/skills/rite/SKILL.md +12 -13
  172. package/pack/.claude/skills/rite/reference/menu.md +11 -11
  173. package/pack/.claude/skills/rite-adopt/SKILL.md +29 -84
  174. package/pack/.claude/skills/rite-adopt/reference/adoption.md +16 -50
  175. package/pack/.claude/skills/rite-autocomplete/SKILL.md +65 -54
  176. package/pack/.claude/skills/rite-autocomplete/reference/loop.md +24 -17
  177. package/pack/.claude/skills/rite-autocomplete/reference/stop-conditions.md +18 -21
  178. package/pack/.claude/skills/rite-build/SKILL.md +28 -34
  179. package/pack/.claude/skills/rite-build/reference/afk-discipline.md +36 -34
  180. package/pack/.claude/skills/rite-build/reference/anti-patterns.md +5 -19
  181. package/pack/.claude/skills/rite-build/reference/checkpoint-protocol.md +10 -9
  182. package/pack/.claude/skills/rite-build/reference/checkpoint.md +17 -17
  183. package/pack/.claude/skills/rite-build/reference/frontend-trigger.md +3 -3
  184. package/pack/.claude/skills/rite-build/reference/one-slice-cycle.md +11 -14
  185. package/pack/.claude/skills/rite-build/reference/output.md +14 -24
  186. package/pack/.claude/skills/rite-build/reference/phase-contract.md +49 -188
  187. package/pack/.claude/skills/rite-build/reference/spec-drift-guard.md +1 -1
  188. package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +43 -133
  189. package/pack/.claude/skills/rite-clarify/SKILL.md +46 -40
  190. package/pack/.claude/skills/rite-clarify/reference/decision-coverage.md +4 -10
  191. package/pack/.claude/skills/rite-converge/SKILL.md +9 -33
  192. package/pack/.claude/skills/rite-converge/reference/convergence-assessment.md +2 -2
  193. package/pack/.claude/skills/rite-customize/SKILL.md +34 -50
  194. package/pack/.claude/skills/rite-define/SKILL.md +34 -58
  195. package/pack/.claude/skills/rite-define/reference/plan-template.md +15 -0
  196. package/pack/.claude/skills/rite-doctor/SKILL.md +52 -64
  197. package/pack/.claude/skills/rite-dogfood/SKILL.md +1 -2
  198. package/pack/.claude/skills/rite-explain/SKILL.md +1 -20
  199. package/pack/.claude/skills/rite-frame/SKILL.md +1 -7
  200. package/pack/.claude/skills/rite-frame/reference/failure-modes.md +1 -1
  201. package/pack/.claude/skills/rite-handoff/SKILL.md +1 -2
  202. package/pack/.claude/skills/rite-handoff/reference/handoff-template.md +1 -1
  203. package/pack/.claude/skills/rite-learn/SKILL.md +44 -104
  204. package/pack/.claude/skills/rite-plan/SKILL.md +14 -26
  205. package/pack/.claude/skills/rite-plan/reference/task-breakdown.md +4 -1
  206. package/pack/.claude/skills/rite-polish/SKILL.md +20 -28
  207. package/pack/.claude/skills/rite-polish/reference/adr-promotion.md +11 -0
  208. package/pack/{generated/claude/skills/rite-ship → .claude/skills/rite-polish}/reference/design-memory.md +23 -21
  209. package/pack/.claude/skills/rite-polish/reference/ledger.md +62 -0
  210. package/pack/.claude/skills/rite-pov/SKILL.md +28 -32
  211. package/pack/.claude/skills/rite-pr-feedback/SKILL.md +0 -1
  212. package/pack/.claude/skills/rite-pressure-test/SKILL.md +6 -13
  213. package/pack/.claude/skills/rite-prototype/SKILL.md +0 -6
  214. package/pack/.claude/skills/rite-prove/SKILL.md +73 -68
  215. package/pack/.claude/skills/rite-prove/reference/acceptance-proof.md +34 -30
  216. package/pack/.claude/skills/rite-prove/reference/test-command-discovery.md +15 -14
  217. package/pack/.claude/skills/rite-quick/SKILL.md +5 -19
  218. package/pack/.claude/skills/rite-resolve/SKILL.md +4 -21
  219. package/pack/.claude/skills/rite-resolve/reference/answer-protocol.md +2 -2
  220. package/pack/.claude/skills/rite-review/SKILL.md +34 -57
  221. package/pack/.claude/skills/rite-seal/SKILL.md +54 -87
  222. package/pack/.claude/skills/rite-seal/reference/anti-patterns.md +2 -2
  223. package/pack/.claude/skills/rite-seal/reference/final-evidence.md +31 -56
  224. package/pack/.claude/skills/rite-seal/reference/go-no-go.md +27 -51
  225. package/pack/.claude/skills/rite-seal/reference/output.md +2 -4
  226. package/pack/.claude/skills/rite-seal/reference/phase-contract.md +42 -140
  227. package/pack/.claude/skills/rite-seal/reference/risk-and-rollback.md +2 -2
  228. package/pack/.claude/skills/rite-seal/reference/seal-template.md +17 -28
  229. package/pack/.claude/skills/rite-ship/SKILL.md +65 -93
  230. package/pack/.claude/skills/rite-ship/reference/anti-patterns.md +4 -1
  231. package/pack/.claude/skills/rite-ship/reference/close-out.md +4 -12
  232. package/pack/.claude/skills/rite-ship/reference/git-ship.md +86 -48
  233. package/pack/.claude/skills/rite-ship/reference/ship-template.md +22 -16
  234. package/pack/.claude/skills/rite-spec/SKILL.md +62 -95
  235. package/pack/.claude/skills/rite-spec/reference/investigation.md +1 -4
  236. package/pack/.claude/skills/rite-spec/reference/question-protocol.md +21 -20
  237. package/pack/.claude/skills/rite-spec/reference/spec-checklists.md +16 -17
  238. package/pack/.claude/skills/rite-spec/reference/spec-template.md +47 -49
  239. package/pack/.claude/skills/rite-spec/reference/state-workspace.md +28 -13
  240. package/pack/.claude/skills/rite-status/SKILL.md +30 -88
  241. package/pack/.claude/skills/rite-temper/SKILL.md +12 -31
  242. package/pack/.claude/skills/rite-upgrade/SKILL.md +86 -101
  243. package/pack/.claude/skills/rite-vet/SKILL.md +88 -117
  244. package/pack/.claude/skills/rite-vet/reference/artifacts.md +56 -50
  245. package/pack/.claude/skills/rite-vet/reference/cross-model.md +15 -39
  246. package/pack/.claude/skills/rite-vet/reference/depth.md +2 -2
  247. package/pack/.claude/skills/rite-vet/reference/review-axes.md +3 -6
  248. package/pack/.claude/skills/rite-zoom-out/SKILL.md +0 -6
  249. package/pack/generated/README.md +2 -2
  250. package/pack/generated/claude/agents/devrites-code-reviewer.md +9 -18
  251. package/pack/generated/claude/agents/devrites-devex-reviewer.md +10 -18
  252. package/pack/generated/claude/agents/devrites-doubt-reviewer.md +10 -20
  253. package/pack/generated/claude/agents/devrites-evidence-scout.md +14 -26
  254. package/pack/generated/claude/agents/devrites-frontend-reviewer.md +9 -15
  255. package/pack/generated/claude/agents/devrites-performance-reviewer.md +13 -21
  256. package/pack/generated/claude/agents/devrites-plan-drafter.md +24 -28
  257. package/pack/generated/claude/agents/devrites-plan-reviewer.md +30 -47
  258. package/pack/generated/claude/agents/devrites-proof-runner.md +41 -47
  259. package/pack/generated/claude/agents/devrites-retrospector.md +34 -79
  260. package/pack/generated/claude/agents/devrites-security-auditor.md +9 -17
  261. package/pack/generated/claude/agents/devrites-simplifier-reviewer.md +9 -18
  262. package/pack/generated/claude/agents/devrites-slice-wright.md +44 -62
  263. package/pack/generated/claude/agents/devrites-spec-reviewer.md +38 -50
  264. package/pack/generated/claude/agents/devrites-strategy-reviewer.md +10 -19
  265. package/pack/generated/claude/agents/devrites-test-analyst.md +22 -21
  266. package/pack/generated/claude/agents/devrites-upgrade-planner.md +52 -71
  267. package/pack/generated/claude/settings.json +12 -100
  268. package/pack/generated/claude/skills/devrites-api-interface/SKILL.md +1 -2
  269. package/pack/generated/claude/skills/devrites-audit/SKILL.md +6 -9
  270. package/pack/generated/claude/skills/devrites-browser-proof/SKILL.md +0 -1
  271. package/pack/generated/claude/skills/devrites-debug-recovery/SKILL.md +21 -27
  272. package/pack/generated/claude/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +22 -33
  273. package/pack/generated/claude/skills/devrites-doubt/SKILL.md +4 -6
  274. package/pack/generated/claude/skills/devrites-frontend-craft/SKILL.md +1 -2
  275. package/pack/generated/claude/skills/devrites-frontend-craft/reference/design-references.md +2 -1
  276. package/pack/generated/claude/skills/devrites-interview/SKILL.md +31 -36
  277. package/pack/generated/claude/skills/devrites-lib/SKILL.md +37 -66
  278. package/pack/generated/claude/skills/devrites-lib/reference/candidate-integrity.md +51 -0
  279. package/pack/generated/claude/skills/devrites-lib/reference/intent-map.md +20 -12
  280. package/pack/generated/claude/skills/devrites-lib/reference/orchestration-profiles.md +22 -0
  281. package/pack/generated/claude/skills/devrites-lib/reference/parallel-dispatch.md +35 -110
  282. package/pack/generated/claude/skills/devrites-lib/reference/reply-contract.md +26 -93
  283. package/pack/generated/claude/skills/devrites-lib/reference/standards/README.md +6 -3
  284. package/pack/generated/claude/skills/devrites-lib/reference/standards/afk-hitl.md +43 -34
  285. package/pack/generated/claude/skills/devrites-lib/reference/standards/agents.md +90 -216
  286. package/pack/generated/claude/skills/devrites-lib/reference/standards/anti-patterns.md +1 -1
  287. package/pack/generated/claude/skills/devrites-lib/reference/standards/code-review.md +9 -28
  288. package/pack/generated/claude/skills/devrites-lib/reference/standards/context-hygiene.md +13 -11
  289. package/pack/generated/claude/skills/devrites-lib/reference/standards/core.md +59 -54
  290. package/pack/generated/claude/skills/devrites-lib/reference/standards/hooks.md +3 -5
  291. package/pack/generated/claude/skills/devrites-lib/reference/standards/principles.md +29 -143
  292. package/pack/generated/claude/skills/devrites-lib/reference/standards/release/ship-checklist.md +5 -6
  293. package/pack/generated/claude/skills/devrites-lib/reference/standards/security.md +13 -31
  294. package/pack/generated/claude/skills/devrites-lib/reference/standards/skill-authoring.md +112 -82
  295. package/pack/generated/claude/skills/devrites-lib/reference/standards/spec-grammar.md +71 -45
  296. package/pack/generated/claude/skills/devrites-lib/reference/standards/testing.md +22 -11
  297. package/pack/generated/claude/skills/devrites-lib/reference/standards/tooling.md +15 -24
  298. package/pack/generated/claude/skills/devrites-lib/reference/workspace-artifact-schema.md +106 -37
  299. package/pack/generated/claude/skills/devrites-prose-craft/SKILL.md +3 -4
  300. package/pack/generated/claude/skills/devrites-source-driven/SKILL.md +3 -4
  301. package/pack/generated/claude/skills/devrites-ux-shape/SKILL.md +3 -3
  302. package/pack/generated/claude/skills/rite/SKILL.md +12 -13
  303. package/pack/generated/claude/skills/rite/reference/menu.md +11 -11
  304. package/pack/generated/claude/skills/rite-adopt/SKILL.md +29 -84
  305. package/pack/generated/claude/skills/rite-adopt/reference/adoption.md +16 -50
  306. package/pack/generated/claude/skills/rite-autocomplete/SKILL.md +65 -54
  307. package/pack/generated/claude/skills/rite-autocomplete/reference/loop.md +24 -17
  308. package/pack/generated/claude/skills/rite-autocomplete/reference/stop-conditions.md +18 -21
  309. package/pack/generated/claude/skills/rite-build/SKILL.md +28 -34
  310. package/pack/generated/claude/skills/rite-build/reference/afk-discipline.md +36 -34
  311. package/pack/generated/claude/skills/rite-build/reference/anti-patterns.md +5 -19
  312. package/pack/generated/claude/skills/rite-build/reference/checkpoint-protocol.md +10 -9
  313. package/pack/generated/claude/skills/rite-build/reference/checkpoint.md +17 -17
  314. package/pack/generated/claude/skills/rite-build/reference/frontend-trigger.md +3 -3
  315. package/pack/generated/claude/skills/rite-build/reference/one-slice-cycle.md +11 -14
  316. package/pack/generated/claude/skills/rite-build/reference/output.md +14 -24
  317. package/pack/generated/claude/skills/rite-build/reference/phase-contract.md +49 -188
  318. package/pack/generated/claude/skills/rite-build/reference/spec-drift-guard.md +1 -1
  319. package/pack/generated/claude/skills/rite-build/reference/wright-dispatch.md +43 -133
  320. package/pack/generated/claude/skills/rite-clarify/SKILL.md +46 -40
  321. package/pack/generated/claude/skills/rite-clarify/reference/decision-coverage.md +4 -10
  322. package/pack/generated/claude/skills/rite-converge/SKILL.md +9 -33
  323. package/pack/generated/claude/skills/rite-converge/reference/convergence-assessment.md +2 -2
  324. package/pack/generated/claude/skills/rite-customize/SKILL.md +34 -50
  325. package/pack/generated/claude/skills/rite-define/SKILL.md +34 -58
  326. package/pack/generated/claude/skills/rite-define/reference/plan-template.md +15 -0
  327. package/pack/generated/claude/skills/rite-doctor/SKILL.md +52 -64
  328. package/pack/generated/claude/skills/rite-dogfood/SKILL.md +1 -2
  329. package/pack/generated/claude/skills/rite-explain/SKILL.md +1 -20
  330. package/pack/generated/claude/skills/rite-frame/SKILL.md +1 -7
  331. package/pack/generated/claude/skills/rite-frame/reference/failure-modes.md +1 -1
  332. package/pack/generated/claude/skills/rite-handoff/SKILL.md +1 -2
  333. package/pack/generated/claude/skills/rite-handoff/reference/handoff-template.md +1 -1
  334. package/pack/generated/claude/skills/rite-learn/SKILL.md +44 -104
  335. package/pack/generated/claude/skills/rite-plan/SKILL.md +14 -26
  336. package/pack/generated/claude/skills/rite-plan/reference/task-breakdown.md +4 -1
  337. package/pack/generated/claude/skills/rite-polish/SKILL.md +20 -28
  338. package/pack/generated/claude/skills/rite-polish/reference/adr-promotion.md +11 -0
  339. package/pack/generated/{codex/skills/rite-ship → claude/skills/rite-polish}/reference/design-memory.md +23 -21
  340. package/pack/generated/claude/skills/rite-polish/reference/ledger.md +62 -0
  341. package/pack/generated/claude/skills/rite-pov/SKILL.md +28 -32
  342. package/pack/generated/claude/skills/rite-pr-feedback/SKILL.md +0 -1
  343. package/pack/generated/claude/skills/rite-pressure-test/SKILL.md +6 -13
  344. package/pack/generated/claude/skills/rite-prototype/SKILL.md +0 -6
  345. package/pack/generated/claude/skills/rite-prove/SKILL.md +73 -68
  346. package/pack/generated/claude/skills/rite-prove/reference/acceptance-proof.md +34 -30
  347. package/pack/generated/claude/skills/rite-prove/reference/test-command-discovery.md +15 -14
  348. package/pack/generated/claude/skills/rite-quick/SKILL.md +5 -19
  349. package/pack/generated/claude/skills/rite-resolve/SKILL.md +4 -21
  350. package/pack/generated/claude/skills/rite-resolve/reference/answer-protocol.md +2 -2
  351. package/pack/generated/claude/skills/rite-review/SKILL.md +34 -57
  352. package/pack/generated/claude/skills/rite-seal/SKILL.md +54 -87
  353. package/pack/generated/claude/skills/rite-seal/reference/anti-patterns.md +2 -2
  354. package/pack/generated/claude/skills/rite-seal/reference/final-evidence.md +31 -56
  355. package/pack/generated/claude/skills/rite-seal/reference/go-no-go.md +27 -51
  356. package/pack/generated/claude/skills/rite-seal/reference/output.md +2 -4
  357. package/pack/generated/claude/skills/rite-seal/reference/phase-contract.md +42 -140
  358. package/pack/generated/claude/skills/rite-seal/reference/risk-and-rollback.md +2 -2
  359. package/pack/generated/claude/skills/rite-seal/reference/seal-template.md +17 -28
  360. package/pack/generated/claude/skills/rite-ship/SKILL.md +65 -93
  361. package/pack/generated/claude/skills/rite-ship/reference/anti-patterns.md +4 -1
  362. package/pack/generated/claude/skills/rite-ship/reference/close-out.md +4 -12
  363. package/pack/generated/claude/skills/rite-ship/reference/git-ship.md +86 -48
  364. package/pack/generated/claude/skills/rite-ship/reference/ship-template.md +22 -16
  365. package/pack/generated/claude/skills/rite-spec/SKILL.md +62 -95
  366. package/pack/generated/claude/skills/rite-spec/reference/investigation.md +1 -4
  367. package/pack/generated/claude/skills/rite-spec/reference/question-protocol.md +21 -20
  368. package/pack/generated/claude/skills/rite-spec/reference/spec-checklists.md +16 -17
  369. package/pack/generated/claude/skills/rite-spec/reference/spec-template.md +47 -49
  370. package/pack/generated/claude/skills/rite-spec/reference/state-workspace.md +28 -13
  371. package/pack/generated/claude/skills/rite-status/SKILL.md +30 -88
  372. package/pack/generated/claude/skills/rite-temper/SKILL.md +12 -31
  373. package/pack/generated/claude/skills/rite-upgrade/SKILL.md +86 -101
  374. package/pack/generated/claude/skills/rite-vet/SKILL.md +88 -117
  375. package/pack/generated/claude/skills/rite-vet/reference/artifacts.md +56 -50
  376. package/pack/generated/claude/skills/rite-vet/reference/cross-model.md +15 -39
  377. package/pack/generated/claude/skills/rite-vet/reference/depth.md +2 -2
  378. package/pack/generated/claude/skills/rite-vet/reference/review-axes.md +3 -6
  379. package/pack/generated/claude/skills/rite-zoom-out/SKILL.md +0 -6
  380. package/pack/generated/codex/AGENTS.md +5 -4
  381. package/pack/generated/codex/agents/devrites-code-reviewer.toml +8 -27
  382. package/pack/generated/codex/agents/devrites-devex-reviewer.toml +9 -27
  383. package/pack/generated/codex/agents/devrites-doubt-reviewer.toml +9 -29
  384. package/pack/generated/codex/agents/devrites-evidence-scout.toml +14 -36
  385. package/pack/generated/codex/agents/devrites-frontend-reviewer.toml +8 -24
  386. package/pack/generated/codex/agents/devrites-performance-reviewer.toml +12 -30
  387. package/pack/generated/codex/agents/devrites-plan-drafter.toml +24 -38
  388. package/pack/generated/codex/agents/devrites-plan-reviewer.toml +30 -57
  389. package/pack/generated/codex/agents/devrites-proof-runner.toml +41 -57
  390. package/pack/generated/codex/agents/devrites-retrospector.toml +34 -89
  391. package/pack/generated/codex/agents/devrites-security-auditor.toml +8 -26
  392. package/pack/generated/codex/agents/devrites-simplifier-reviewer.toml +8 -27
  393. package/pack/generated/codex/agents/devrites-slice-wright.toml +44 -71
  394. package/pack/generated/codex/agents/devrites-spec-reviewer.toml +38 -60
  395. package/pack/generated/codex/agents/devrites-strategy-reviewer.toml +9 -28
  396. package/pack/generated/codex/agents/devrites-test-analyst.toml +21 -30
  397. package/pack/generated/codex/agents/devrites-upgrade-planner.toml +52 -81
  398. package/pack/generated/codex/config.toml +7 -0
  399. package/pack/generated/codex/skills/devrites-api-interface/SKILL.md +1 -21
  400. package/pack/generated/codex/skills/devrites-audit/SKILL.md +6 -28
  401. package/pack/generated/codex/skills/devrites-browser-proof/SKILL.md +1 -21
  402. package/pack/generated/codex/skills/devrites-debug-recovery/SKILL.md +21 -46
  403. package/pack/generated/codex/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +22 -33
  404. package/pack/generated/codex/skills/devrites-doubt/SKILL.md +4 -25
  405. package/pack/generated/codex/skills/devrites-frontend-craft/SKILL.md +1 -21
  406. package/pack/generated/codex/skills/devrites-frontend-craft/reference/design-references.md +2 -1
  407. package/pack/generated/codex/skills/devrites-interview/SKILL.md +32 -56
  408. package/pack/generated/codex/skills/devrites-lib/SKILL.md +38 -86
  409. package/pack/generated/codex/skills/devrites-lib/reference/candidate-integrity.md +51 -0
  410. package/pack/generated/codex/skills/devrites-lib/reference/intent-map.md +20 -12
  411. package/pack/generated/codex/skills/devrites-lib/reference/orchestration-profiles.md +22 -0
  412. package/pack/generated/codex/skills/devrites-lib/reference/parallel-dispatch.md +35 -110
  413. package/pack/generated/codex/skills/devrites-lib/reference/reply-contract.md +26 -93
  414. package/pack/generated/codex/skills/devrites-lib/reference/standards/README.md +6 -3
  415. package/pack/generated/codex/skills/devrites-lib/reference/standards/afk-hitl.md +43 -34
  416. package/pack/generated/codex/skills/devrites-lib/reference/standards/agents.md +90 -216
  417. package/pack/generated/codex/skills/devrites-lib/reference/standards/anti-patterns.md +1 -1
  418. package/pack/generated/codex/skills/devrites-lib/reference/standards/code-review.md +9 -28
  419. package/pack/generated/codex/skills/devrites-lib/reference/standards/context-hygiene.md +13 -11
  420. package/pack/generated/codex/skills/devrites-lib/reference/standards/core.md +59 -54
  421. package/pack/generated/codex/skills/devrites-lib/reference/standards/hooks.md +3 -5
  422. package/pack/generated/codex/skills/devrites-lib/reference/standards/principles.md +29 -143
  423. package/pack/generated/codex/skills/devrites-lib/reference/standards/release/ship-checklist.md +5 -6
  424. package/pack/generated/codex/skills/devrites-lib/reference/standards/security.md +13 -31
  425. package/pack/generated/codex/skills/devrites-lib/reference/standards/skill-authoring.md +112 -82
  426. package/pack/generated/codex/skills/devrites-lib/reference/standards/spec-grammar.md +71 -45
  427. package/pack/generated/codex/skills/devrites-lib/reference/standards/testing.md +22 -11
  428. package/pack/generated/codex/skills/devrites-lib/reference/standards/tooling.md +15 -24
  429. package/pack/generated/codex/skills/devrites-lib/reference/workspace-artifact-schema.md +106 -37
  430. package/pack/generated/codex/skills/devrites-prose-craft/SKILL.md +3 -23
  431. package/pack/generated/codex/skills/devrites-source-driven/SKILL.md +3 -23
  432. package/pack/generated/codex/skills/devrites-ux-shape/SKILL.md +3 -22
  433. package/pack/generated/codex/skills/rite/SKILL.md +12 -32
  434. package/pack/generated/codex/skills/rite/reference/menu.md +11 -11
  435. package/pack/generated/codex/skills/rite-adopt/SKILL.md +29 -103
  436. package/pack/generated/codex/skills/rite-adopt/reference/adoption.md +16 -50
  437. package/pack/generated/codex/skills/rite-autocomplete/SKILL.md +65 -73
  438. package/pack/generated/codex/skills/rite-autocomplete/reference/loop.md +24 -17
  439. package/pack/generated/codex/skills/rite-autocomplete/reference/stop-conditions.md +18 -21
  440. package/pack/generated/codex/skills/rite-build/SKILL.md +28 -53
  441. package/pack/generated/codex/skills/rite-build/reference/afk-discipline.md +36 -34
  442. package/pack/generated/codex/skills/rite-build/reference/anti-patterns.md +5 -19
  443. package/pack/generated/codex/skills/rite-build/reference/checkpoint-protocol.md +10 -9
  444. package/pack/generated/codex/skills/rite-build/reference/checkpoint.md +17 -17
  445. package/pack/generated/codex/skills/rite-build/reference/frontend-trigger.md +3 -3
  446. package/pack/generated/codex/skills/rite-build/reference/one-slice-cycle.md +11 -14
  447. package/pack/generated/codex/skills/rite-build/reference/output.md +14 -24
  448. package/pack/generated/codex/skills/rite-build/reference/phase-contract.md +49 -188
  449. package/pack/generated/codex/skills/rite-build/reference/spec-drift-guard.md +1 -1
  450. package/pack/generated/codex/skills/rite-build/reference/wright-dispatch.md +43 -133
  451. package/pack/generated/codex/skills/rite-clarify/SKILL.md +46 -59
  452. package/pack/generated/codex/skills/rite-clarify/reference/decision-coverage.md +4 -10
  453. package/pack/generated/codex/skills/rite-converge/SKILL.md +9 -52
  454. package/pack/generated/codex/skills/rite-converge/reference/convergence-assessment.md +2 -2
  455. package/pack/generated/codex/skills/rite-customize/SKILL.md +32 -67
  456. package/pack/generated/codex/skills/rite-define/SKILL.md +34 -77
  457. package/pack/generated/codex/skills/rite-define/reference/plan-template.md +15 -0
  458. package/pack/generated/codex/skills/rite-doctor/SKILL.md +52 -83
  459. package/pack/generated/codex/skills/rite-dogfood/SKILL.md +1 -21
  460. package/pack/generated/codex/skills/rite-explain/SKILL.md +1 -39
  461. package/pack/generated/codex/skills/rite-frame/SKILL.md +1 -26
  462. package/pack/generated/codex/skills/rite-frame/reference/failure-modes.md +1 -1
  463. package/pack/generated/codex/skills/rite-handoff/SKILL.md +1 -21
  464. package/pack/generated/codex/skills/rite-handoff/reference/handoff-template.md +1 -1
  465. package/pack/generated/codex/skills/rite-learn/SKILL.md +44 -123
  466. package/pack/generated/codex/skills/rite-plan/SKILL.md +14 -45
  467. package/pack/generated/codex/skills/rite-plan/reference/task-breakdown.md +4 -1
  468. package/pack/generated/codex/skills/rite-polish/SKILL.md +20 -47
  469. package/pack/generated/codex/skills/rite-polish/reference/adr-promotion.md +11 -0
  470. package/pack/{.claude/skills/rite-ship → generated/codex/skills/rite-polish}/reference/design-memory.md +23 -21
  471. package/pack/generated/codex/skills/rite-polish/reference/ledger.md +62 -0
  472. package/pack/generated/codex/skills/rite-pov/SKILL.md +28 -51
  473. package/pack/generated/codex/skills/rite-pr-feedback/SKILL.md +0 -20
  474. package/pack/generated/codex/skills/rite-pressure-test/SKILL.md +6 -32
  475. package/pack/generated/codex/skills/rite-prototype/SKILL.md +0 -25
  476. package/pack/generated/codex/skills/rite-prove/SKILL.md +73 -87
  477. package/pack/generated/codex/skills/rite-prove/reference/acceptance-proof.md +34 -30
  478. package/pack/generated/codex/skills/rite-prove/reference/test-command-discovery.md +15 -14
  479. package/pack/generated/codex/skills/rite-quick/SKILL.md +5 -38
  480. package/pack/generated/codex/skills/rite-resolve/SKILL.md +4 -40
  481. package/pack/generated/codex/skills/rite-resolve/reference/answer-protocol.md +2 -2
  482. package/pack/generated/codex/skills/rite-review/SKILL.md +34 -76
  483. package/pack/generated/codex/skills/rite-seal/SKILL.md +51 -103
  484. package/pack/generated/codex/skills/rite-seal/reference/anti-patterns.md +2 -2
  485. package/pack/generated/codex/skills/rite-seal/reference/final-evidence.md +31 -56
  486. package/pack/generated/codex/skills/rite-seal/reference/go-no-go.md +27 -51
  487. package/pack/generated/codex/skills/rite-seal/reference/output.md +2 -4
  488. package/pack/generated/codex/skills/rite-seal/reference/phase-contract.md +42 -140
  489. package/pack/generated/codex/skills/rite-seal/reference/risk-and-rollback.md +2 -2
  490. package/pack/generated/codex/skills/rite-seal/reference/seal-template.md +17 -28
  491. package/pack/generated/codex/skills/rite-ship/SKILL.md +65 -112
  492. package/pack/generated/codex/skills/rite-ship/reference/anti-patterns.md +4 -1
  493. package/pack/generated/codex/skills/rite-ship/reference/close-out.md +4 -12
  494. package/pack/generated/codex/skills/rite-ship/reference/git-ship.md +86 -48
  495. package/pack/generated/codex/skills/rite-ship/reference/ship-template.md +22 -16
  496. package/pack/generated/codex/skills/rite-spec/SKILL.md +62 -114
  497. package/pack/generated/codex/skills/rite-spec/reference/investigation.md +1 -4
  498. package/pack/generated/codex/skills/rite-spec/reference/question-protocol.md +21 -20
  499. package/pack/generated/codex/skills/rite-spec/reference/spec-checklists.md +16 -17
  500. package/pack/generated/codex/skills/rite-spec/reference/spec-template.md +47 -49
  501. package/pack/generated/codex/skills/rite-spec/reference/state-workspace.md +28 -13
  502. package/pack/generated/codex/skills/rite-status/SKILL.md +30 -107
  503. package/pack/generated/codex/skills/rite-temper/SKILL.md +12 -50
  504. package/pack/generated/codex/skills/rite-upgrade/SKILL.md +86 -120
  505. package/pack/generated/codex/skills/rite-vet/SKILL.md +88 -136
  506. package/pack/generated/codex/skills/rite-vet/reference/artifacts.md +56 -50
  507. package/pack/generated/codex/skills/rite-vet/reference/cross-model.md +15 -39
  508. package/pack/generated/codex/skills/rite-vet/reference/depth.md +2 -2
  509. package/pack/generated/codex/skills/rite-vet/reference/review-axes.md +3 -6
  510. package/pack/generated/codex/skills/rite-zoom-out/SKILL.md +0 -25
  511. package/package.json +6 -5
  512. package/scripts/build-host-artifacts.sh +5 -9
  513. package/scripts/codex-generate.sh +18 -278
  514. package/scripts/install-lib.sh +121 -34
  515. package/uninstall.sh +19 -17
  516. package/update.sh +26 -18
  517. package/docs/engine/agent-contract.md +0 -172
  518. package/docs/extensions.md +0 -178
  519. package/engine/git_guard.go +0 -187
  520. package/engine/git_guard_test.go +0 -283
  521. package/engine/harnessmatrix.go +0 -60
  522. package/engine/hookpolicy.go +0 -113
  523. package/engine/hookpolicy_test.go +0 -160
  524. package/engine/hooks.go +0 -677
  525. package/engine/hooks_agent_dispatch.go +0 -1726
  526. package/engine/hooks_events_test.go +0 -431
  527. package/engine/hooks_workspace.go +0 -1196
  528. package/engine/internal/doctor/doctor.go +0 -306
  529. package/engine/internal/doctor/doctor_test.go +0 -252
  530. package/engine/internal/forge/forge.go +0 -938
  531. package/engine/internal/forge/forge_test.go +0 -576
  532. package/engine/internal/forge/git.go +0 -245
  533. package/engine/internal/forge/liveness_unix.go +0 -48
  534. package/engine/internal/forge/liveness_windows.go +0 -67
  535. package/engine/internal/forge/manifest.go +0 -402
  536. package/engine/internal/harness/compliance.go +0 -96
  537. package/engine/internal/harness/harness.go +0 -301
  538. package/engine/internal/harness/harness_test.go +0 -124
  539. package/engine/internal/iohooks/detach_other.go +0 -11
  540. package/engine/internal/iohooks/detach_unix.go +0 -11
  541. package/engine/internal/iohooks/iohooks.go +0 -839
  542. package/engine/internal/iohooks/iohooks_test.go +0 -561
  543. package/engine/internal/lib/adoption.go +0 -659
  544. package/engine/internal/lib/adoption_test.go +0 -121
  545. package/engine/internal/lib/analyze.go +0 -232
  546. package/engine/internal/lib/archivesearch.go +0 -125
  547. package/engine/internal/lib/archivesearch_test.go +0 -138
  548. package/engine/internal/lib/budget.go +0 -172
  549. package/engine/internal/lib/buildreadiness.go +0 -111
  550. package/engine/internal/lib/checkacceptance.go +0 -176
  551. package/engine/internal/lib/clarifyreturn.go +0 -91
  552. package/engine/internal/lib/clarifyreturn_test.go +0 -123
  553. package/engine/internal/lib/command_other.go +0 -7
  554. package/engine/internal/lib/command_unix.go +0 -24
  555. package/engine/internal/lib/context.go +0 -280
  556. package/engine/internal/lib/conventions.go +0 -449
  557. package/engine/internal/lib/coverage.go +0 -145
  558. package/engine/internal/lib/dispatchwaive.go +0 -31
  559. package/engine/internal/lib/dispatchwaive_test.go +0 -23
  560. package/engine/internal/lib/doubtcoverage.go +0 -78
  561. package/engine/internal/lib/extensions.go +0 -622
  562. package/engine/internal/lib/extensions_test.go +0 -305
  563. package/engine/internal/lib/footprint.go +0 -239
  564. package/engine/internal/lib/gitauthority.go +0 -601
  565. package/engine/internal/lib/gitauthority_test.go +0 -346
  566. package/engine/internal/lib/jsonout.go +0 -129
  567. package/engine/internal/lib/jsonout_test.go +0 -73
  568. package/engine/internal/lib/lanes.go +0 -112
  569. package/engine/internal/lib/learnings.go +0 -397
  570. package/engine/internal/lib/learnings_inject_test.go +0 -77
  571. package/engine/internal/lib/learnings_remediation_test.go +0 -24
  572. package/engine/internal/lib/ledger.go +0 -311
  573. package/engine/internal/lib/ledger_test.go +0 -186
  574. package/engine/internal/lib/mutationgate.go +0 -89
  575. package/engine/internal/lib/observability_test.go +0 -358
  576. package/engine/internal/lib/overrides.go +0 -164
  577. package/engine/internal/lib/overrides_test.go +0 -112
  578. package/engine/internal/lib/preamble.go +0 -159
  579. package/engine/internal/lib/preamble_questions_test.go +0 -10
  580. package/engine/internal/lib/progress.go +0 -210
  581. package/engine/internal/lib/provenance.go +0 -462
  582. package/engine/internal/lib/provenance_test.go +0 -154
  583. package/engine/internal/lib/readiness_contract.json +0 -118
  584. package/engine/internal/lib/readinessartifact.go +0 -533
  585. package/engine/internal/lib/readinessartifact_test.go +0 -422
  586. package/engine/internal/lib/reconcile.go +0 -1496
  587. package/engine/internal/lib/reconcile_test.go +0 -1071
  588. package/engine/internal/lib/recoveryattempts.go +0 -298
  589. package/engine/internal/lib/recoveryattempts_test.go +0 -215
  590. package/engine/internal/lib/reviewers.go +0 -143
  591. package/engine/internal/lib/reviewers_test.go +0 -45
  592. package/engine/internal/lib/reviewerstats.go +0 -199
  593. package/engine/internal/lib/reviewerstats_test.go +0 -104
  594. package/engine/internal/lib/reviewintegrity.go +0 -143
  595. package/engine/internal/lib/reviewintegrity_test.go +0 -103
  596. package/engine/internal/lib/runbook.go +0 -295
  597. package/engine/internal/lib/runbook_context_test.go +0 -182
  598. package/engine/internal/lib/session.go +0 -1020
  599. package/engine/internal/lib/session_test.go +0 -177
  600. package/engine/internal/lib/specparse.go +0 -125
  601. package/engine/internal/lib/specskeleton.go +0 -79
  602. package/engine/internal/lib/specvalidate.go +0 -391
  603. package/engine/internal/lib/specvalidate_test.go +0 -185
  604. package/engine/internal/lib/stuck.go +0 -206
  605. package/engine/internal/lib/templates/conventions_drift.tmpl +0 -6
  606. package/engine/internal/lib/templates/conventions_ledger_header.md +0 -6
  607. package/engine/internal/lib/templates/conventions_orient_header.txt +0 -1
  608. package/engine/internal/lib/testintegrity.go +0 -199
  609. package/engine/internal/lib/testintegrity_test.go +0 -149
  610. package/engine/internal/lib/tickafk.go +0 -86
  611. package/engine/internal/migrate/migrate.go +0 -279
  612. package/engine/internal/migrate/migrate_test.go +0 -157
  613. package/engine/internal/orient/firstrun.go +0 -50
  614. package/engine/internal/orient/firstrun_test.go +0 -72
  615. package/engine/internal/orient/orient.go +0 -69
  616. package/engine/internal/orient/orient_test.go +0 -25
  617. package/engine/internal/profile/profile.go +0 -284
  618. package/engine/internal/profile/profile_test.go +0 -13
  619. package/engine/internal/state/clarify_transition.go +0 -165
  620. package/engine/internal/state/clarify_transition_test.go +0 -130
  621. package/engine/internal/state/snapshot.go +0 -457
  622. package/engine/internal/toolpolicy/classifier.go +0 -533
  623. package/engine/internal/toolpolicy/classifier_test.go +0 -424
  624. package/engine/internal/toolpolicy/git.go +0 -616
  625. package/engine/internal/toolpolicy/scanner.go +0 -382
  626. package/engine/observability_cli_test.go +0 -52
  627. package/engine/profile_test.go +0 -76
  628. package/engine/subagent_orient_context.txt +0 -8
  629. package/engine/testdata/golden/TestParityA1Guard/devrites-edit-allowed.golden +0 -1
  630. package/engine/testdata/golden/TestParityA1Guard/no-window-silent.golden +0 -1
  631. package/engine/testdata/golden/TestParityA1Guard/non-edit-tool.golden +0 -1
  632. package/engine/testdata/golden/TestParityA1Guard/observe-mode-silent.golden +0 -1
  633. package/engine/testdata/golden/TestParityA1Guard/source-edit-enforce-denies.golden +0 -2
  634. package/engine/testdata/golden/TestParityA1Guard/subagent-allowed.golden +0 -1
  635. package/engine/testdata/golden/TestParityAnalyze/noactive.golden +0 -1
  636. package/engine/testdata/golden/TestParityAnalyze/slug=covered.golden +0 -15
  637. package/engine/testdata/golden/TestParityAnalyze/slug=dangling.golden +0 -16
  638. package/engine/testdata/golden/TestParityAnalyze/slug=ghost.golden +0 -1
  639. package/engine/testdata/golden/TestParityAnalyze/slug=noac.golden +0 -15
  640. package/engine/testdata/golden/TestParityAnalyze/slug=order.golden +0 -17
  641. package/engine/testdata/golden/TestParityAnalyze/slug=orphan.golden +0 -16
  642. package/engine/testdata/golden/TestParityAnalyze/slug=uncovered.golden +0 -16
  643. package/engine/testdata/golden/TestParityBudget/default-active.golden +0 -4
  644. package/engine/testdata/golden/TestParityBudget/extra-md.golden +0 -5
  645. package/engine/testdata/golden/TestParityBudget/no-active.golden +0 -1
  646. package/engine/testdata/golden/TestParityBudget/no-feature.golden +0 -1
  647. package/engine/testdata/golden/TestParityBudget/over-advisory.golden +0 -6
  648. package/engine/testdata/golden/TestParityBudget/over-strict.golden +0 -6
  649. package/engine/testdata/golden/TestParityBudget/within.golden +0 -6
  650. package/engine/testdata/golden/TestParityBuildReadiness/arg=approved.golden +0 -2
  651. package/engine/testdata/golden/TestParityBuildReadiness/arg=approvenone.golden +0 -1
  652. package/engine/testdata/golden/TestParityBuildReadiness/arg=await.golden +0 -1
  653. package/engine/testdata/golden/TestParityBuildReadiness/arg=blocked.golden +0 -1
  654. package/engine/testdata/golden/TestParityBuildReadiness/arg=clarifyopen.golden +0 -1
  655. package/engine/testdata/golden/TestParityBuildReadiness/arg=emptystatus.golden +0 -2
  656. package/engine/testdata/golden/TestParityBuildReadiness/arg=ghost.golden +0 -1
  657. package/engine/testdata/golden/TestParityBuildReadiness/arg=legacycontract.golden +0 -1
  658. package/engine/testdata/golden/TestParityBuildReadiness/arg=noapprove.golden +0 -1
  659. package/engine/testdata/golden/TestParityBuildReadiness/arg=noclarify.golden +0 -1
  660. package/engine/testdata/golden/TestParityBuildReadiness/arg=novet.golden +0 -1
  661. package/engine/testdata/golden/TestParityBuildReadiness/arg=stalevet.golden +0 -1
  662. package/engine/testdata/golden/TestParityBuildReadiness/arg=trailhash.golden +0 -2
  663. package/engine/testdata/golden/TestParityBuildReadiness/arg=trailpipe.golden +0 -2
  664. package/engine/testdata/golden/TestParityBuildReadiness/arg=vetnotready.golden +0 -1
  665. package/engine/testdata/golden/TestParityCheckAcceptance/arg=blank-section.golden +0 -1
  666. package/engine/testdata/golden/TestParityCheckAcceptance/arg=empty.golden +0 -1
  667. package/engine/testdata/golden/TestParityCheckAcceptance/arg=flat-dropped.golden +0 -1
  668. package/engine/testdata/golden/TestParityCheckAcceptance/arg=flat-ok.golden +0 -2
  669. package/engine/testdata/golden/TestParityCheckAcceptance/arg=flat-unchecked.golden +0 -1
  670. package/engine/testdata/golden/TestParityCheckAcceptance/arg=id-gap.golden +0 -1
  671. package/engine/testdata/golden/TestParityCheckAcceptance/arg=id-ok.golden +0 -2
  672. package/engine/testdata/golden/TestParityCheckAcceptance/arg=no-seal.golden +0 -1
  673. package/engine/testdata/golden/TestParityCheckAcceptance/arg=no-section.golden +0 -1
  674. package/engine/testdata/golden/TestParityCheckAcceptance/arg=nonexistent.golden +0 -1
  675. package/engine/testdata/golden/TestParityCheckAcceptance.golden +0 -1
  676. package/engine/testdata/golden/TestParityCoverage/arg=flat.golden +0 -7
  677. package/engine/testdata/golden/TestParityCoverage/arg=full.golden +0 -10
  678. package/engine/testdata/golden/TestParityCoverage/arg=nonexistent.golden +0 -1
  679. package/engine/testdata/golden/TestParityCoverage/arg=nospec.golden +0 -1
  680. package/engine/testdata/golden/TestParityCoverage/arg=speconly.golden +0 -9
  681. package/engine/testdata/golden/TestParityCoverage.golden +0 -1
  682. package/engine/testdata/golden/TestParityCursor/bare.golden +0 -3
  683. package/engine/testdata/golden/TestParityCursor/full-afk.golden +0 -6
  684. package/engine/testdata/golden/TestParityCursor/full-hitl.golden +0 -5
  685. package/engine/testdata/golden/TestParityCursor/no-active.golden +0 -1
  686. package/engine/testdata/golden/TestParityCursor/red.golden +0 -5
  687. package/engine/testdata/golden/TestParityCursor/zerogates.golden +0 -5
  688. package/engine/testdata/golden/TestParityDoubtCoverage/arg=doubted.golden +0 -2
  689. package/engine/testdata/golden/TestParityDoubtCoverage/arg=ghost.golden +0 -2
  690. package/engine/testdata/golden/TestParityDoubtCoverage/arg=missing.golden +0 -3
  691. package/engine/testdata/golden/TestParityDoubtCoverage/arg=nodoubt.golden +0 -4
  692. package/engine/testdata/golden/TestParityDoubtCoverage/arg=nolog.golden +0 -2
  693. package/engine/testdata/golden/TestParityDoubtCoverage/arg=nowright.golden +0 -2
  694. package/engine/testdata/golden/TestParityDoubtCoverage.golden +0 -1
  695. package/engine/testdata/golden/TestParityMutationGate/active-slug.golden +0 -3
  696. package/engine/testdata/golden/TestParityMutationGate/explicit-slug.golden +0 -3
  697. package/engine/testdata/golden/TestParityMutationGate/ghost.golden +0 -1
  698. package/engine/testdata/golden/TestParityOrientSilentPath.golden +0 -1
  699. package/engine/testdata/golden/TestParityReconcile/bad-mode.golden +0 -1
  700. package/engine/testdata/golden/TestParityReconcile/check-clean/snapshot.golden +0 -2
  701. package/engine/testdata/golden/TestParityReconcile/check-clean.golden +0 -2
  702. package/engine/testdata/golden/TestParityReconcile/check-no-base.golden +0 -1
  703. package/engine/testdata/golden/TestParityReconcile/check-no-claimed/snapshot.golden +0 -2
  704. package/engine/testdata/golden/TestParityReconcile/check-violation/snapshot.golden +0 -2
  705. package/engine/testdata/golden/TestParityReconcile/check-violation.golden +0 -1
  706. package/engine/testdata/golden/TestParityReconcile/close-window/snapshot.golden +0 -2
  707. package/engine/testdata/golden/TestParityReconcile/close-window.golden +0 -3
  708. package/engine/testdata/golden/TestParityReconcile/not-git.golden +0 -1
  709. package/engine/testdata/golden/TestParityReconcile/snapshot/snapshot.golden +0 -2
  710. package/engine/testdata/golden/TestParityReconcile/snapshot-no-allowlist.golden +0 -1
  711. package/engine/testdata/golden/TestParityReconcile/snapshot.golden +0 -2
  712. package/engine/testdata/golden/TestParityRedwatch/fail-writes-red.golden +0 -2
  713. package/engine/testdata/golden/TestParityRedwatch/non-bash-tool.golden +0 -1
  714. package/engine/testdata/golden/TestParityRedwatch/non-test-command.golden +0 -1
  715. package/engine/testdata/golden/TestParityRedwatch/pass-clears-red.golden +0 -1
  716. package/engine/testdata/golden/TestParityResolve/next-qid.golden +0 -2
  717. package/engine/testdata/golden/TestParityReviewerReadonly/agent-required-devrites-agent-denies.golden +0 -2
  718. package/engine/testdata/golden/TestParityReviewerReadonly/agent-required-non-devrites-allows.golden +0 -1
  719. package/engine/testdata/golden/TestParityReviewerReadonly/agent-required-subagent-type-only-allows.golden +0 -1
  720. package/engine/testdata/golden/TestParityReviewerReadonly/enforce-deny-git-commit.golden +0 -2
  721. package/engine/testdata/golden/TestParityReviewerReadonly/enforce-deny-mutating.golden +0 -2
  722. package/engine/testdata/golden/TestParityReviewerReadonly/non-bash-tool.golden +0 -1
  723. package/engine/testdata/golden/TestParityReviewerReadonly/non-tool-input.golden +0 -1
  724. package/engine/testdata/golden/TestParityReviewerReadonly/observe-mutating-silent.golden +0 -1
  725. package/engine/testdata/golden/TestParityReviewerReadonly/safe-bash-command.golden +0 -1
  726. package/engine/testdata/golden/TestParitySpecValidate/arg=dup.golden +0 -1
  727. package/engine/testdata/golden/TestParitySpecValidate/arg=empty.golden +0 -1
  728. package/engine/testdata/golden/TestParitySpecValidate/arg=flat.golden +0 -2
  729. package/engine/testdata/golden/TestParitySpecValidate/arg=nonexistent.golden +0 -1
  730. package/engine/testdata/golden/TestParitySpecValidate/arg=noscenario.golden +0 -1
  731. package/engine/testdata/golden/TestParitySpecValidate/arg=noshall.golden +0 -1
  732. package/engine/testdata/golden/TestParitySpecValidate/arg=nothen.golden +0 -1
  733. package/engine/testdata/golden/TestParitySpecValidate/arg=valid/spec.md.golden +0 -2
  734. package/engine/testdata/golden/TestParitySpecValidate/arg=valid.golden +0 -2
  735. package/engine/testdata/golden/TestParitySpecValidate.golden +0 -1
  736. package/engine/testdata/golden/TestParityStatusline/full-afk.golden +0 -2
  737. package/engine/testdata/golden/TestParityStatusline/full-hitl.golden +0 -2
  738. package/engine/testdata/golden/TestParityStatusline/no-active.golden +0 -1
  739. package/engine/testdata/golden/TestParityStatusline/nophase.golden +0 -2
  740. package/engine/testdata/golden/TestParityStatusline/red.golden +0 -2
  741. package/engine/testdata/golden/TestParityStuckCheck/bad-cmd.golden +0 -1
  742. package/engine/testdata/golden/TestParityStuckCheck/custom-window-2.golden +0 -2
  743. package/engine/testdata/golden/TestParityStuckCheck/dominant.golden +0 -2
  744. package/engine/testdata/golden/TestParityStuckCheck/few.golden +0 -2
  745. package/engine/testdata/golden/TestParityStuckCheck/ghost.golden +0 -2
  746. package/engine/testdata/golden/TestParityStuckCheck/identical.golden +0 -2
  747. package/engine/testdata/golden/TestParityStuckCheck/no-cmd.golden +0 -1
  748. package/engine/testdata/golden/TestParityStuckCheck/no-slug.golden +0 -1
  749. package/engine/testdata/golden/TestParityStuckCheck/nolog.golden +0 -2
  750. package/engine/testdata/golden/TestParityStuckCheck/pingpong.golden +0 -2
  751. package/engine/testdata/golden/TestParityStuckCheck/varied.golden +0 -2
  752. package/engine/testdata/golden/TestParityStuckCheck/window-04-identical.golden +0 -2
  753. package/engine/testdata/golden/TestParityStuckCheck/window-2.5-varied4.golden +0 -2
  754. package/engine/testdata/golden/TestParityStuckCheck/window-4x-varied4.golden +0 -2
  755. package/engine/testdata/golden/TestParityStuckCheck/window-leadspace-varied4.golden +0 -2
  756. package/engine/testdata/golden/TestParityStuckCheck/window-plus4-identical.golden +0 -2
  757. package/engine/testdata/golden/TestParitySubagentOrient/devrites-agent-subagent-type-key.golden +0 -2
  758. package/engine/testdata/golden/TestParitySubagentOrient/devrites-agent.golden +0 -2
  759. package/engine/testdata/golden/TestParitySubagentOrient/garbage-input.golden +0 -1
  760. package/engine/testdata/golden/TestParitySubagentOrient/non-devrites-agent.golden +0 -1
  761. package/engine/testdata/golden/TestParityTestIntegrity/assertion-dropped.golden +0 -1
  762. package/engine/testdata/golden/TestParityTestIntegrity/clean.golden +0 -2
  763. package/engine/testdata/golden/TestParityTestIntegrity/deleted.golden +0 -1
  764. package/engine/testdata/golden/TestParityTestIntegrity/ghost-workspace.golden +0 -1
  765. package/engine/testdata/golden/TestParityTestIntegrity/not-git.golden +0 -1
  766. package/engine/testdata/golden/TestParityTestIntegrity/skip-added.golden +0 -1
  767. package/engine/testdata/golden/TestParityTickAfk/budget1/state.md.golden +0 -1
  768. package/engine/testdata/golden/TestParityTickAfk/budget1.golden +0 -2
  769. package/engine/testdata/golden/TestParityTickAfk/budget3/state.md.golden +0 -5
  770. package/engine/testdata/golden/TestParityTickAfk/budget3.golden +0 -2
  771. package/engine/testdata/golden/TestParityTickAfk/bulletPipe/state.md.golden +0 -1
  772. package/engine/testdata/golden/TestParityTickAfk/bulletPipe.golden +0 -2
  773. package/engine/testdata/golden/TestParityTickAfk/missingField/state.md.golden +0 -3
  774. package/engine/testdata/golden/TestParityTickAfk/missingField.golden +0 -2
  775. package/engine/testdata/golden/TestParityTickAfk/missingFile.golden +0 -1
  776. package/engine/testdata/golden/TestParityTickAfk/nonNumeric/state.md.golden +0 -1
  777. package/engine/testdata/golden/TestParityTickAfk/nonNumeric.golden +0 -1
  778. package/engine/testdata/golden/TestParityTickAfk/none/state.md.golden +0 -1
  779. package/engine/testdata/golden/TestParityTickAfk/none.golden +0 -2
  780. package/engine/testdata/golden/TestParityWrightScope/agent-required-non-wright.golden +0 -1
  781. package/engine/testdata/golden/TestParityWrightScope/devrites-edit-denied.golden +0 -2
  782. package/engine/testdata/golden/TestParityWrightScope/in-scope-allowed.golden +0 -1
  783. package/engine/testdata/golden/TestParityWrightScope/non-edit-tool.golden +0 -1
  784. package/engine/testdata/golden/TestParityWrightScope/out-of-scope-enforce-denies.golden +0 -2
  785. package/engine/testdata/golden/TestParityWrightScope/out-of-scope-observe-silent.golden +0 -1
  786. package/engine/testdata/golden/TestSpecSkeleton/missing-some.golden +0 -2
  787. package/engine/testdata/golden/TestSpecSkeleton/present-all.golden +0 -2
  788. package/engine/testdata/golden/TestStuckLogHashParity.golden +0 -1
  789. package/engine/tests/adr_0006_clock_seam_test.go +0 -36
  790. package/engine/tests/budget_test.go +0 -88
  791. package/engine/tests/canonical_ac_ids_test.go +0 -44
  792. package/engine/tests/concurrency_cli_test.go +0 -131
  793. package/engine/tests/conventions_test.go +0 -106
  794. package/engine/tests/doctor_cli_test.go +0 -223
  795. package/engine/tests/forge_cli_test.go +0 -463
  796. package/engine/tests/hook_test.go +0 -2778
  797. package/engine/tests/hooks_io_test.go +0 -309
  798. package/engine/tests/json_contract_test.go +0 -224
  799. package/engine/tests/lib_parity_test.go +0 -930
  800. package/engine/tests/migrate_cli_test.go +0 -195
  801. package/engine/tests/parity_analyze_test.go +0 -55
  802. package/engine/tests/parity_buildreadiness_test.go +0 -199
  803. package/engine/tests/parity_learnings_test.go +0 -89
  804. package/engine/tests/parity_mutationgate_test.go +0 -36
  805. package/engine/tests/parity_reconcile_test.go +0 -94
  806. package/engine/tests/parity_testintegrity_test.go +0 -65
  807. package/engine/tests/parity_tickafk_test.go +0 -83
  808. package/engine/validatepack.go +0 -192
  809. package/engine/validatepack_test.go +0 -79
  810. package/engine/validatepackskills.go +0 -181
  811. package/engine/validatepackskills_test.go +0 -171
  812. package/pack/.claude/agents/devrites-forge-judge.md +0 -118
  813. package/pack/.claude/skills/devrites-lib/reference/model-tiers.md +0 -44
  814. package/pack/.claude/skills/devrites-refresh-indexes/SKILL.md +0 -52
  815. package/pack/.claude/skills/rite-build/reference/evidence-standard.md +0 -45
  816. package/pack/.claude/skills/rite-build/reference/forge.md +0 -210
  817. package/pack/.claude/skills/rite-seal/reference/conventions-ledger.md +0 -60
  818. package/pack/.claude/skills/rite-ship/reference/adr-promotion.md +0 -9
  819. package/pack/.claude/skills/rite-ship/reference/ledger.md +0 -56
  820. package/pack/generated/claude/agents/devrites-forge-judge.md +0 -118
  821. package/pack/generated/claude/skills/devrites-lib/reference/model-tiers.md +0 -44
  822. package/pack/generated/claude/skills/devrites-refresh-indexes/SKILL.md +0 -52
  823. package/pack/generated/claude/skills/rite-build/reference/evidence-standard.md +0 -45
  824. package/pack/generated/claude/skills/rite-build/reference/forge.md +0 -210
  825. package/pack/generated/claude/skills/rite-seal/reference/conventions-ledger.md +0 -60
  826. package/pack/generated/claude/skills/rite-ship/reference/adr-promotion.md +0 -9
  827. package/pack/generated/claude/skills/rite-ship/reference/ledger.md +0 -56
  828. package/pack/generated/codex/agents/devrites-forge-judge.toml +0 -128
  829. package/pack/generated/codex/hooks.json +0 -185
  830. package/pack/generated/codex/skills/devrites-api-interface/agents/openai.yaml +0 -2
  831. package/pack/generated/codex/skills/devrites-audit/agents/openai.yaml +0 -2
  832. package/pack/generated/codex/skills/devrites-browser-proof/agents/openai.yaml +0 -2
  833. package/pack/generated/codex/skills/devrites-debug-recovery/agents/openai.yaml +0 -2
  834. package/pack/generated/codex/skills/devrites-doubt/agents/openai.yaml +0 -2
  835. package/pack/generated/codex/skills/devrites-frontend-craft/agents/openai.yaml +0 -2
  836. package/pack/generated/codex/skills/devrites-interview/agents/openai.yaml +0 -2
  837. package/pack/generated/codex/skills/devrites-lib/reference/model-tiers.md +0 -44
  838. package/pack/generated/codex/skills/devrites-prose-craft/agents/openai.yaml +0 -2
  839. package/pack/generated/codex/skills/devrites-refresh-indexes/SKILL.md +0 -71
  840. package/pack/generated/codex/skills/devrites-refresh-indexes/agents/openai.yaml +0 -2
  841. package/pack/generated/codex/skills/devrites-source-driven/agents/openai.yaml +0 -2
  842. package/pack/generated/codex/skills/devrites-ux-shape/agents/openai.yaml +0 -2
  843. package/pack/generated/codex/skills/rite-build/reference/evidence-standard.md +0 -45
  844. package/pack/generated/codex/skills/rite-build/reference/forge.md +0 -210
  845. package/pack/generated/codex/skills/rite-seal/reference/conventions-ledger.md +0 -60
  846. package/pack/generated/codex/skills/rite-ship/reference/adr-promotion.md +0 -9
  847. package/pack/generated/codex/skills/rite-ship/reference/ledger.md +0 -56
  848. package/scripts/build-binaries.sh +0 -75
  849. package/scripts/build-release-tarball.sh +0 -105
  850. package/scripts/check-authority-drift.py +0 -125
  851. package/scripts/check-cross-refs.py +0 -139
  852. package/scripts/check-generated-skill-budget.mjs +0 -42
  853. package/scripts/check-instruction-size-baseline.mjs +0 -88
  854. package/scripts/check-invocation-integrity.py +0 -115
  855. package/scripts/check-no-global-writes.sh +0 -66
  856. package/scripts/check-no-personal-paths.py +0 -50
  857. package/scripts/check-npm-audit.mjs +0 -110
  858. package/scripts/check-reference-governance.mjs +0 -83
  859. package/scripts/check-reply-contract.sh +0 -64
  860. package/scripts/check-rule-uniqueness.sh +0 -45
  861. package/scripts/devrites-detect.sh +0 -176
  862. package/scripts/grade-feature.sh +0 -204
  863. package/scripts/live-hosts/agent-result.schema.json +0 -231
  864. package/scripts/live-hosts/claude.sh +0 -87
  865. package/scripts/live-hosts/codex.sh +0 -85
  866. package/scripts/live-hosts/common.sh +0 -113
  867. package/scripts/live-hosts/fake-host.py +0 -257
  868. package/scripts/live-hosts/host-transport.py +0 -286
  869. package/scripts/npm-audit-exceptions.json +0 -26
  870. package/scripts/pin.sh +0 -249
  871. package/scripts/release-check.sh +0 -75
  872. package/scripts/run-agent-contract-evals.py +0 -1380
  873. package/scripts/run-behavioral-evals.sh +0 -196
  874. package/scripts/run-evals.sh +0 -132
  875. package/scripts/run-live-behavioral-evals.py +0 -1310
  876. package/scripts/run-outcome-evals.sh +0 -454
  877. package/scripts/run-routing-evals.py +0 -342
  878. package/scripts/run-tests.mjs +0 -232
  879. package/scripts/scan-pack-security.py +0 -209
  880. package/scripts/scan-supply-chain-iocs.py +0 -127
  881. package/scripts/skill-pruning-audit.mjs +0 -121
  882. package/scripts/skills-inventory.mjs +0 -125
  883. package/scripts/supply-chain-iocs.json +0 -11
  884. package/scripts/sync-version.sh +0 -54
  885. package/scripts/validate-agent-composition.py +0 -57
  886. package/scripts/validate-command-parity.py +0 -70
  887. package/scripts/validate-frontmatter.py +0 -218
  888. package/scripts/validate-skill-anatomy.py +0 -139
  889. package/scripts/validate-workflow-security.py +0 -184
  890. package/scripts/validate-workspace-schema.py +0 -800
  891. package/scripts/validate.sh +0 -354
  892. package/scripts/workflow_schema.py +0 -69
  893. /package/engine/testdata/fixtures/basic/devrites-root/{features → work}/auth-tokens/decisions.md +0 -0
  894. /package/engine/testdata/fixtures/basic/devrites-root/{features → work}/auth-tokens/plan.md +0 -0
  895. /package/engine/testdata/fixtures/basic/devrites-root/{features → work}/auth-tokens/spec.md +0 -0
  896. /package/engine/testdata/fixtures/basic/devrites-root/{features → work}/auth-tokens/tasks.md +0 -0
  897. /package/engine/testdata/fixtures/basic/devrites-root/{features → work}/search-ranking/spec.md +0 -0
@@ -1,19 +1,14 @@
1
1
  package install
2
2
 
3
3
  import (
4
- "archive/tar"
5
4
  "bytes"
6
- "compress/gzip"
7
5
  "crypto/sha256"
8
- "encoding/json"
9
6
  "fmt"
10
- "io/fs"
11
- "net/http"
12
- "net/http/httptest"
13
7
  "os"
14
8
  "os/exec"
15
9
  "path/filepath"
16
10
  "runtime"
11
+ "slices"
17
12
  "strings"
18
13
  "testing"
19
14
  "time"
@@ -44,83 +39,41 @@ func TestInstallDryRunWritesNothing(t *testing.T) {
44
39
  if !strings.Contains(out.String(), "[install] .claude/skills/rite/SKILL.md") {
45
40
  t.Fatalf("dry-run output missing planned install:\n%s", out.String())
46
41
  }
42
+ if strings.Contains(out.String(), "Next:") {
43
+ t.Fatalf("dry-run output claims a next move:\n%s", out.String())
44
+ }
47
45
  }
48
46
 
49
- func TestExtractTarGzRejectsTooManyEntries(t *testing.T) {
50
- tarball := filepath.Join(t.TempDir(), "many.tar.gz")
51
- f, err := os.Create(tarball)
52
- if err != nil {
53
- t.Fatal(err)
54
- }
55
- gz := gzip.NewWriter(f)
56
- tw := tar.NewWriter(gz)
57
- for i := 0; i <= maxUpdateEntries; i++ {
58
- hdr := &tar.Header{Name: fmt.Sprintf("entry-%05d", i), Typeflag: tar.TypeDir, Mode: 0o755}
59
- if err := tw.WriteHeader(hdr); err != nil {
60
- t.Fatal(err)
61
- }
62
- }
63
- if err := tw.Close(); err != nil {
64
- t.Fatal(err)
65
- }
66
- if err := gz.Close(); err != nil {
67
- t.Fatal(err)
68
- }
69
- if err := f.Close(); err != nil {
70
- t.Fatal(err)
71
- }
47
+ func TestInstallPrintsFirstMoveForInstalledHosts(t *testing.T) {
48
+ t.Setenv("DEVRITES_NO_BINARY", "1")
72
49
 
73
- err = extractTarGz(tarball, t.TempDir())
74
- if err == nil || !strings.Contains(err.Error(), "too many entries") {
75
- t.Fatalf("extractTarGz error = %v, want entry-count rejection", err)
50
+ for _, tc := range []struct {
51
+ name string
52
+ withCodex bool
53
+ want string
54
+ }{
55
+ {name: "Claude and Codex", withCodex: true, want: "Next: reopen the project, then run /rite (Claude) or $rite (Codex)."},
56
+ {name: "Claude only", withCodex: false, want: "Next: reopen the project, then run /rite."},
57
+ } {
58
+ t.Run(tc.name, func(t *testing.T) {
59
+ var out bytes.Buffer
60
+ opts := DefaultOptions(ModeInstall)
61
+ opts.Target = t.TempDir()
62
+ opts.PayloadDir = testPayload(t)
63
+ opts.WithCodex = tc.withCodex
64
+ opts.Stdout = &out
65
+ opts.Stderr = &bytes.Buffer{}
66
+
67
+ if err := Apply(opts); err != nil {
68
+ t.Fatal(err)
69
+ }
70
+ if !strings.Contains(out.String(), tc.want) {
71
+ t.Fatalf("install output missing first move %q:\n%s", tc.want, out.String())
72
+ }
73
+ })
76
74
  }
77
75
  }
78
76
 
79
- func FuzzExtractTarGzPaths(f *testing.F) {
80
- f.Add("safe/file.txt", []byte("content"))
81
- f.Add("../escape", []byte("blocked"))
82
- f.Add("/absolute", []byte("blocked"))
83
- f.Fuzz(func(t *testing.T, name string, content []byte) {
84
- if len(name) > 256 || len(content) > 4096 || strings.ContainsRune(name, '\x00') {
85
- t.Skip()
86
- }
87
- base := t.TempDir()
88
- tarball := filepath.Join(base, "input.tar.gz")
89
- file, err := os.Create(tarball)
90
- if err != nil {
91
- t.Fatal(err)
92
- }
93
- gz := gzip.NewWriter(file)
94
- tw := tar.NewWriter(gz)
95
- if err := tw.WriteHeader(&tar.Header{Name: name, Mode: 0o644, Size: int64(len(content)), Typeflag: tar.TypeReg}); err != nil {
96
- _ = tw.Close()
97
- _ = gz.Close()
98
- _ = file.Close()
99
- return
100
- }
101
- if _, err := tw.Write(content); err != nil {
102
- t.Fatal(err)
103
- }
104
- if err := tw.Close(); err != nil {
105
- t.Fatal(err)
106
- }
107
- if err := gz.Close(); err != nil {
108
- t.Fatal(err)
109
- }
110
- if err := file.Close(); err != nil {
111
- t.Fatal(err)
112
- }
113
- dest := filepath.Join(base, "dest")
114
- if err := os.Mkdir(dest, 0o755); err != nil {
115
- t.Fatal(err)
116
- }
117
- _ = extractTarGz(tarball, dest)
118
- if _, err := os.Stat(filepath.Join(base, "escape")); !os.IsNotExist(err) {
119
- t.Fatalf("archive escaped destination through %q", name)
120
- }
121
- })
122
- }
123
-
124
77
  func TestInstallManifestConflictAndPrune(t *testing.T) {
125
78
  t.Setenv("DEVRITES_NO_BINARY", "1")
126
79
  payload := testPayload(t)
@@ -154,7 +107,8 @@ func TestMarkerMergeAndUninstallPreserveUserContent(t *testing.T) {
154
107
  target := t.TempDir()
155
108
  testutil.WriteFile(t, filepath.Join(target, "AGENTS.md"), "user guidance\n")
156
109
  testutil.WriteFile(t, filepath.Join(target, ".codex", "config.toml"), "model = \"x\"\n")
157
- testutil.WriteFile(t, filepath.Join(target, ".codex", "hooks.json"), `{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"echo user"}]}]}}`+"\n")
110
+ userHooks := `{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"echo user"}]}]}}` + "\n"
111
+ testutil.WriteFile(t, filepath.Join(target, ".codex", "hooks.json"), userHooks)
158
112
 
159
113
  runInstall(t, target, payload, func(o *Options) {})
160
114
  runInstall(t, target, payload, func(o *Options) {})
@@ -166,12 +120,13 @@ func TestMarkerMergeAndUninstallPreserveUserContent(t *testing.T) {
166
120
  t.Fatal("AGENTS user content lost")
167
121
  }
168
122
  config := testutil.ReadFile(t, filepath.Join(target, ".codex", "config.toml"))
169
- if strings.Contains(config, "DEVRITES CODEX") || !strings.Contains(config, `model = "x"`) {
123
+ if strings.Count(config, "# BEGIN DEVRITES CODEX PERMISSIONS") != 1 ||
124
+ !strings.Contains(config, `default_permissions = "devrites-orchestrator"`) ||
125
+ !strings.Contains(config, `model = "x"`) {
170
126
  t.Fatalf("config preservation wrong:\n%s", config)
171
127
  }
172
- hooks := testutil.ReadFile(t, filepath.Join(target, ".codex", "hooks.json"))
173
- if strings.Count(hooks, "devrites-engine hook stop-gate") != 1 || !strings.Contains(hooks, "echo user") {
174
- t.Fatalf("hooks merge wrong:\n%s", hooks)
128
+ if hooks := testutil.ReadFile(t, filepath.Join(target, ".codex", "hooks.json")); hooks != userHooks {
129
+ t.Fatalf("installer changed native Codex hooks:\n%s", hooks)
175
130
  }
176
131
 
177
132
  runUninstall(t, target)
@@ -181,7 +136,7 @@ func TestMarkerMergeAndUninstallPreserveUserContent(t *testing.T) {
181
136
  if got := testutil.ReadFile(t, filepath.Join(target, ".codex", "config.toml")); !strings.Contains(got, `model = "x"`) || strings.Contains(got, "DEVRITES CODEX") {
182
137
  t.Fatalf("config uninstall preservation wrong:\n%s", got)
183
138
  }
184
- if got := testutil.ReadFile(t, filepath.Join(target, ".codex", "hooks.json")); !strings.Contains(got, "echo user") || strings.Contains(got, "devrites-engine hook") {
139
+ if got := testutil.ReadFile(t, filepath.Join(target, ".codex", "hooks.json")); got != userHooks {
185
140
  t.Fatalf("hooks uninstall preservation wrong:\n%s", got)
186
141
  }
187
142
  if !exists(filepath.Join(target, ".devrites", "ACTIVE")) {
@@ -233,21 +188,19 @@ func TestUninstallReportsUnreadableManifest(t *testing.T) {
233
188
  }
234
189
  }
235
190
 
236
- func TestInstallMergesClaudeHooksIntoExistingSettings(t *testing.T) {
191
+ func TestInstallMergesClaudePermissionsIntoExistingSettings(t *testing.T) {
237
192
  t.Setenv("DEVRITES_NO_BINARY", "1")
238
193
  payload := testPayload(t)
239
- testutil.WriteFile(t, filepath.Join(payload, "claude", "settings.json"), `{
240
- "statusLine": {"type":"command","command":"devrites-engine hook statusline --harness=claude"},
241
- "hooks": {
242
- "Stop": [{"hooks":[{"type":"command","command":"devrites-engine hook stop-gate --harness=claude"}]}],
243
- "SessionStart": [{"hooks":[{"type":"command","command":"devrites-engine hook orient --harness=claude"}]}]
244
- }
245
- }`+"\n")
246
194
  target := t.TempDir()
247
195
  testutil.WriteFile(t, filepath.Join(target, ".claude", "settings.json"), `{
248
- "$comment": "DevRites hooks: keep my local notes",
196
+ "$comment": "keep my local notes",
249
197
  "theme": "dark",
250
198
  "statusLine": {"type":"command","command":"DEVRITES_THEME=dark echo user-status"},
199
+ "permissions": {
200
+ "defaultMode": "plan",
201
+ "allow": ["Bash(user-tool *)"],
202
+ "ask": ["Bash(rm *)"]
203
+ },
251
204
  "hooks": {"Stop":[{"hooks":[
252
205
  {"type":"command","command":"echo user-stop"},
253
206
  {"type":"command","command":"devrites-engine hook old-gate --harness=claude"}
@@ -259,42 +212,41 @@ func TestInstallMergesClaudeHooksIntoExistingSettings(t *testing.T) {
259
212
  runInstall(t, target, payload, func(o *Options) { o.Stderr = &stderr })
260
213
 
261
214
  settings := testutil.ReadFile(t, filepath.Join(target, ".claude", "settings.json"))
262
- for _, preserved := range []string{"DevRites hooks: keep my local notes", `"theme": "dark"`, "echo user-status", "echo user-stop"} {
215
+ for _, preserved := range []string{"keep my local notes", `"theme": "dark"`, "echo user-status", "echo user-stop", "Bash(user-tool *)", "Bash(rm *)"} {
263
216
  if !strings.Contains(settings, preserved) {
264
217
  t.Fatalf("Claude settings lost user content %q:\n%s", preserved, settings)
265
218
  }
266
219
  }
267
- for _, command := range []string{"devrites-engine hook stop-gate", "devrites-engine hook orient"} {
268
- if strings.Count(settings, command) != 1 {
269
- t.Fatalf("Claude hook %q was not merged exactly once:\n%s", command, settings)
270
- }
220
+ if strings.Count(settings, "Bash(devrites-engine check readiness *)") != 1 {
221
+ t.Fatalf("Claude permission was not merged exactly once:\n%s", settings)
271
222
  }
272
- if !strings.Contains(stderr.String(), "preserved existing Claude statusLine") {
273
- t.Fatalf("missing statusLine conflict warning:\n%s", stderr.String())
223
+ if strings.Contains(settings, "devrites-engine hook") {
224
+ t.Fatalf("installer retained a legacy DevRites hook:\n%s", settings)
274
225
  }
275
226
  manifest := testutil.ReadFile(t, filepath.Join(target, ManifestName))
276
227
  if !strings.Contains(manifest, "\n.claude/devrites.claude-hooks-merge\n") {
277
- t.Fatalf("Claude hook merge marker missing:\n%s", manifest)
228
+ t.Fatalf("Claude settings merge marker missing:\n%s", manifest)
229
+ }
230
+ marker := testutil.ReadFile(t, filepath.Join(target, ".claude", "devrites.claude-hooks-merge"))
231
+ if !strings.Contains(marker, "default-mode=preexisting") {
232
+ t.Fatalf("Claude settings marker lost pre-existing plan-mode ownership:\n%s", marker)
278
233
  }
279
234
 
280
235
  runUninstall(t, target)
281
236
  settings = testutil.ReadFile(t, filepath.Join(target, ".claude", "settings.json"))
282
- for _, preserved := range []string{"DevRites hooks: keep my local notes", `"theme": "dark"`, "echo user-status", "echo user-stop"} {
237
+ for _, preserved := range []string{"keep my local notes", `"theme": "dark"`, "echo user-status", "echo user-stop", "Bash(user-tool *)", "Bash(rm *)", `"defaultMode": "plan"`} {
283
238
  if !strings.Contains(settings, preserved) {
284
239
  t.Fatalf("Claude settings uninstall lost user content %q:\n%s", preserved, settings)
285
240
  }
286
241
  }
287
- if strings.Contains(settings, "devrites-engine hook") {
288
- t.Fatalf("Claude settings uninstall left DevRites hooks:\n%s", settings)
242
+ if strings.Contains(settings, "Bash(devrites-engine ") || strings.Contains(settings, "devrites-engine hook") {
243
+ t.Fatalf("Claude settings uninstall left DevRites configuration:\n%s", settings)
289
244
  }
290
245
  }
291
246
 
292
247
  func TestInstallKeepsClaudeMergeOwnershipAcrossReinstall(t *testing.T) {
293
248
  t.Setenv("DEVRITES_NO_BINARY", "1")
294
249
  payload := testPayload(t)
295
- testutil.WriteFile(t, filepath.Join(payload, "claude", "settings.json"), `{
296
- "hooks": {"Stop":[{"hooks":[{"type":"command","command":"devrites-engine hook stop-gate --harness=claude"}]}]}
297
- }`+"\n")
298
250
  target := t.TempDir()
299
251
  settingsPath := filepath.Join(target, ".claude", "settings.json")
300
252
  testutil.WriteFile(t, settingsPath, "{}\n")
@@ -302,7 +254,7 @@ func TestInstallKeepsClaudeMergeOwnershipAcrossReinstall(t *testing.T) {
302
254
  runInstall(t, target, payload, func(o *Options) {})
303
255
  markerRel := ".claude/devrites.claude-hooks-merge"
304
256
  if !exists(filepath.Join(target, filepath.FromSlash(markerRel))) {
305
- t.Fatal("first install did not create the Claude hook merge marker")
257
+ t.Fatal("first install did not create the Claude settings merge marker")
306
258
  }
307
259
  manifestRecords, err := readManifest(filepath.Join(target, ManifestName))
308
260
  if err != nil {
@@ -314,13 +266,17 @@ func TestInstallKeepsClaudeMergeOwnershipAcrossReinstall(t *testing.T) {
314
266
  runInstall(t, target, payload, func(o *Options) {})
315
267
 
316
268
  settings := testutil.ReadFile(t, settingsPath)
317
- if strings.Count(settings, "devrites-engine hook stop-gate") != 1 {
318
- t.Fatalf("Claude hooks lost merge ownership on reinstall (marker exists: %t):\nsettings:\n%s\nmanifest:\n%s",
269
+ if strings.Count(settings, `"defaultMode": "plan"`) != 1 ||
270
+ strings.Count(settings, "Bash(devrites-engine check readiness *)") != 1 {
271
+ t.Fatalf("Claude permissions lost merge ownership on reinstall (marker exists: %t):\nsettings:\n%s\nmanifest:\n%s",
319
272
  exists(filepath.Join(target, filepath.FromSlash(markerRel))), settings, testutil.ReadFile(t, filepath.Join(target, ManifestName)))
320
273
  }
274
+ if marker := testutil.ReadFile(t, filepath.Join(target, filepath.FromSlash(markerRel))); !strings.Contains(marker, "default-mode=added") {
275
+ t.Fatalf("Claude settings marker did not record owned plan mode:\n%s", marker)
276
+ }
321
277
  manifest := testutil.ReadFile(t, filepath.Join(target, ManifestName))
322
278
  if !strings.Contains(manifest, "\n.claude/devrites.claude-hooks-merge\n") {
323
- t.Fatalf("Claude hook merge marker missing after reinstall:\n%s", manifest)
279
+ t.Fatalf("Claude settings merge marker missing after reinstall:\n%s", manifest)
324
280
  }
325
281
 
326
282
  runUninstall(t, target)
@@ -329,36 +285,23 @@ func TestInstallKeepsClaudeMergeOwnershipAcrossReinstall(t *testing.T) {
329
285
  }
330
286
  }
331
287
 
332
- func TestInstallRefreshesSeededClaudeHooksWithoutManagingSettings(t *testing.T) {
288
+ func TestInstallRejectsConflictingClaudeDefaultMode(t *testing.T) {
333
289
  t.Setenv("DEVRITES_NO_BINARY", "1")
334
290
  payload := testPayload(t)
335
- settingsPayload := filepath.Join(payload, "claude", "settings.json")
336
- testutil.WriteFile(t, settingsPayload, `{
337
- "$comment": "DevRites hooks",
338
- "hooks": {"Stop":[{"hooks":[{"type":"command","command":"bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/devrites-stop-gate.sh\""}]}]}
339
- }`+"\n")
340
291
  target := t.TempDir()
292
+ settingsPath := filepath.Join(target, ".claude", "settings.json")
293
+ original := `{"permissions":{"defaultMode":"acceptEdits"},"theme":"dark"}` + "\n"
294
+ testutil.WriteFile(t, settingsPath, original)
341
295
 
342
- runInstall(t, target, payload, func(o *Options) {})
343
- testutil.WriteFile(t, settingsPayload, `{
344
- "$comment": "DevRites hooks auto-approve the read-only orientation/gate scripts.",
345
- "hooks": {"Stop":[{"hooks":[{"type":"command","command":"devrites-engine hook new-gate --harness=claude"}]}]}
346
- }`+"\n")
347
- runInstall(t, target, payload, func(o *Options) {})
348
-
349
- settings := testutil.ReadFile(t, filepath.Join(target, ".claude", "settings.json"))
350
- if strings.Contains(settings, ".claude/hooks/devrites-") || strings.Count(settings, "new-gate") != 1 {
351
- t.Fatalf("seeded Claude hooks were not refreshed:\n%s", settings)
296
+ err := applyInstall(target, payload, false, false, &bytes.Buffer{})
297
+ if err == nil || !strings.Contains(err.Error(), "requires plan mode") {
298
+ t.Fatalf("install error = %v, want conflicting default-mode rejection", err)
352
299
  }
353
- manifest := testutil.ReadFile(t, filepath.Join(target, ManifestName))
354
- if strings.Contains(manifest, ".claude/devrites.claude-hooks-merge") {
355
- t.Fatalf("seeded Claude settings became merge-managed:\n%s", manifest)
300
+ if got := testutil.ReadFile(t, settingsPath); got != original {
301
+ t.Fatalf("failed install changed Claude settings:\n%s", got)
356
302
  }
357
-
358
- runUninstall(t, target)
359
- settings = testutil.ReadFile(t, filepath.Join(target, ".claude", "settings.json"))
360
- if !strings.Contains(settings, "new-gate") {
361
- t.Fatalf("uninstall removed refreshed seeded Claude settings:\n%s", settings)
303
+ if exists(filepath.Join(target, ".claude", "devrites.claude-hooks-merge")) {
304
+ t.Fatal("failed install created a Claude settings marker")
362
305
  }
363
306
  }
364
307
 
@@ -406,91 +349,50 @@ func TestInstallBinaryUsesEngineHandoff(t *testing.T) {
406
349
  }
407
350
  }
408
351
 
409
- func TestAcquireBinaryBuildsWithoutVCSMetadata(t *testing.T) {
410
- t.Setenv("DEVRITES_ENGINE_CLI", "")
411
- t.Setenv("DEVRITES_UPDATE_BUNDLE", "")
412
- t.Setenv("GOFLAGS", "-buildvcs=true")
413
- source := t.TempDir()
414
- if err := os.Mkdir(filepath.Join(source, ".git"), 0o755); err != nil {
415
- t.Fatal(err)
416
- }
417
- testutil.WriteFile(t, filepath.Join(source, "engine", "go.mod"), "module github.com/devrites/devrites\n\ngo 1.23\n")
418
- testutil.WriteFile(t, filepath.Join(source, "engine", "main.go"), "package main\nfunc main() {}\n")
352
+ func TestAcquireBinaryRequiresCompatibleEngineHandoff(t *testing.T) {
353
+ engine := buildVersionBinary(t, "1.2.2")
354
+ t.Setenv("DEVRITES_ENGINE_CLI", engine)
419
355
 
420
- r := runner{source: source}
421
- staged, cleanup, err := r.acquireBinary("v1.2.3", githubBaseURL)
356
+ r := runner{}
357
+ _, cleanup, err := r.acquireBinary("v1.2.3")
422
358
  defer cleanup()
423
- if err != nil {
424
- t.Fatalf("acquireBinary with unavailable VCS metadata: %v", err)
425
- }
426
- if !exists(staged) {
427
- t.Fatalf("acquireBinary did not build %s", staged)
359
+ if err == nil || !strings.Contains(err.Error(), "version mismatch") {
360
+ t.Fatalf("acquireBinary error = %v, want handoff version mismatch", err)
428
361
  }
429
362
  }
430
363
 
431
- func TestAcquireBinaryPrefersVerifiedReleaseOverStaleHandoff(t *testing.T) {
432
- stale := filepath.Join(t.TempDir(), "devrites-engine")
433
- testutil.WriteExecutable(t, stale, "#!/bin/sh\nif [ \"$1\" = version ]; then echo v1.2.2; fi\n")
434
- t.Setenv("DEVRITES_ENGINE_CLI", stale)
435
- t.Setenv("DEVRITES_UPDATE_BUNDLE", "")
436
- t.Setenv("DEVRITES_REPO", "owner/repo")
437
- tag := "v1.2.3"
438
- asset := fmt.Sprintf("devrites-%s-%s", runtime.GOOS, runtime.GOARCH)
439
- if runtime.GOOS == "windows" {
440
- asset += ".exe"
441
- }
442
- path := "/owner/repo/releases/download/" + tag + "/" + asset
443
- body := []byte("verified release binary")
444
- sum := fmt.Sprintf("%x %s\n", sha256.Sum256(body), asset)
445
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
446
- switch req.URL.Path {
447
- case path:
448
- _, _ = w.Write(body)
449
- case path + ".sha256":
450
- _, _ = w.Write([]byte(sum))
451
- default:
452
- http.NotFound(w, req)
453
- }
454
- }))
455
- defer server.Close()
364
+ func TestInstallBinaryRejectsIncompatibleEngineHandoff(t *testing.T) {
365
+ engine := buildVersionBinary(t, "1.2.2")
366
+ t.Setenv("DEVRITES_ENGINE_CLI", engine)
367
+ t.Setenv("DEVRITES_BIN_DIR", t.TempDir())
368
+ t.Setenv("DEVRITES_REF", "v1.2.3")
456
369
 
457
- r := runner{releaseBinaryTag: tag}
458
- staged, cleanup, err := r.acquireBinary(tag, server.URL)
459
- defer cleanup()
460
- if err != nil {
461
- t.Fatalf("acquire verified release binary: %v", err)
370
+ r := runner{opts: DefaultOptions(ModeInstall)}
371
+ if err := r.installBinary(); err == nil || !strings.Contains(err.Error(), "version mismatch") {
372
+ t.Fatalf("installBinary error = %v, want handoff version mismatch", err)
462
373
  }
463
- got, err := os.ReadFile(staged)
464
- if err != nil {
465
- t.Fatal(err)
466
- }
467
- if !bytes.Equal(got, body) {
468
- t.Fatalf("acquired binary = %q, want %q", got, body)
374
+ }
375
+
376
+ func TestInstallBinaryRejectsMissingConfiguredEngineHandoff(t *testing.T) {
377
+ handoff := filepath.Join(t.TempDir(), "missing-devrites-engine")
378
+ t.Setenv("DEVRITES_ENGINE_CLI", handoff)
379
+ t.Setenv("DEVRITES_BIN_DIR", t.TempDir())
380
+ t.Setenv("DEVRITES_REF", "v1.2.3")
381
+
382
+ r := runner{opts: DefaultOptions(ModeInstall)}
383
+ if err := r.installBinary(); err == nil || !strings.Contains(err.Error(), handoff) {
384
+ t.Fatalf("installBinary error = %v, want missing configured handoff error", err)
469
385
  }
470
386
  }
471
387
 
472
- func TestAcquireBinaryRejectsReleaseChecksumMismatch(t *testing.T) {
388
+ func TestAcquireBinaryRejectsMissingEngineHandoff(t *testing.T) {
473
389
  t.Setenv("DEVRITES_ENGINE_CLI", "")
474
- t.Setenv("DEVRITES_UPDATE_BUNDLE", "")
475
- t.Setenv("DEVRITES_REPO", "owner/repo")
476
- tag := "v1.2.3"
477
- source := t.TempDir()
478
- testutil.WriteFile(t, filepath.Join(source, "engine", "go.mod"), "module github.com/devrites/devrites\n\ngo 1.23\n")
479
- testutil.WriteFile(t, filepath.Join(source, "engine", "main.go"), "package main\nfunc main() {}\n")
480
- server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
481
- if strings.HasSuffix(req.URL.Path, ".sha256") {
482
- _, _ = w.Write([]byte("deadbeef\n"))
483
- return
484
- }
485
- _, _ = w.Write([]byte("tampered release binary"))
486
- }))
487
- defer server.Close()
488
390
 
489
- r := runner{source: source, releaseBinaryTag: tag}
490
- _, cleanup, err := r.acquireBinary(tag, server.URL)
391
+ r := runner{}
392
+ _, cleanup, err := r.acquireBinary("v1.2.3")
491
393
  defer cleanup()
492
- if err == nil || !strings.Contains(err.Error(), "checksum mismatch") {
493
- t.Fatalf("acquireBinary error = %v, want checksum mismatch", err)
394
+ if err == nil || !strings.Contains(err.Error(), "DEVRITES_ENGINE_CLI") {
395
+ t.Fatalf("acquireBinary error = %v, want missing handoff error", err)
494
396
  }
495
397
  }
496
398
 
@@ -511,7 +413,24 @@ func TestInstallBinaryFailsWhenPreparedUpdateCannotBeWritten(t *testing.T) {
511
413
  }
512
414
  }
513
415
 
514
- func TestInstallBinaryWarnsWhenHooksCannotResolveEngine(t *testing.T) {
416
+ func TestInstallBinaryWithoutBinaryReportsSkip(t *testing.T) {
417
+ var stdout bytes.Buffer
418
+ opts := DefaultOptions(ModeInstall)
419
+ opts.WithBinary = false
420
+ opts.Stdout = &stdout
421
+
422
+ r := runner{opts: opts}
423
+ if err := r.installBinary(); err != nil {
424
+ t.Fatalf("installBinary() error = %v", err)
425
+ }
426
+
427
+ output := stdout.String()
428
+ if output != " engine binary: skipped (--no-binary).\n" {
429
+ t.Fatalf("stdout = %q, want binary skip diagnostic", output)
430
+ }
431
+ }
432
+
433
+ func TestInstallBinaryDoesNotRequirePATH(t *testing.T) {
515
434
  payload := testPayload(t)
516
435
  target := t.TempDir()
517
436
  binDir := t.TempDir()
@@ -528,8 +447,28 @@ func TestInstallBinaryWarnsWhenHooksCannotResolveEngine(t *testing.T) {
528
447
  o.Stderr = &stderr
529
448
  })
530
449
 
531
- if !strings.Contains(stderr.String(), "not on PATH") {
532
- t.Fatalf("missing PATH reachability warning:\n%s", stderr.String())
450
+ if stderr.Len() != 0 {
451
+ t.Fatalf("stderr = %q, want no PATH warning", stderr.String())
452
+ }
453
+ }
454
+
455
+ func TestBinaryInstallFailureWarnsAndContinues(t *testing.T) {
456
+ t.Setenv("DEVRITES_ENGINE_CLI", "")
457
+ var stderr bytes.Buffer
458
+ opts := DefaultOptions(ModeInstall)
459
+ opts.Stderr = &stderr
460
+
461
+ r := runner{opts: opts}
462
+ if err := r.binaryInstallFailure(fmt.Errorf("handoff unavailable")); err != nil {
463
+ t.Fatalf("binaryInstallFailure() error = %v, want nil", err)
464
+ }
465
+
466
+ warning := stderr.String()
467
+ if !strings.Contains(warning, "handoff unavailable") {
468
+ t.Fatalf("warning = %q, want handoff failure", warning)
469
+ }
470
+ if !strings.Contains(warning, "continuing without it") {
471
+ t.Fatalf("warning = %q, want non-blocking fallback", warning)
533
472
  }
534
473
  }
535
474
 
@@ -555,74 +494,200 @@ func TestBinaryCandidatesSkipsUnsetBinDir(t *testing.T) {
555
494
  }
556
495
  }
557
496
 
558
- func TestUpdateInstallsRequestedBundle(t *testing.T) {
497
+ func TestUpdateRejectsRemovedAcquisitionFlags(t *testing.T) {
498
+ for _, arg := range []string{"--to=v2.0.0", "--pre"} {
499
+ t.Run(arg, func(t *testing.T) {
500
+ var stderr bytes.Buffer
501
+ if code := Run([]string{arg}, &bytes.Buffer{}, &stderr, ModeUpdate); code != 2 {
502
+ t.Fatalf("Run(%q) code = %d, want 2", arg, code)
503
+ }
504
+ if !strings.Contains(stderr.String(), "flag provided but not defined") {
505
+ t.Fatalf("Run(%q) stderr = %q, want unknown flag error", arg, stderr.String())
506
+ }
507
+ })
508
+ }
509
+ }
510
+
511
+ func TestUpdateInstallsLocalPayload(t *testing.T) {
559
512
  t.Setenv("DEVRITES_NO_BINARY", "1")
560
513
  oldPayload := testPayload(t)
561
514
  target := t.TempDir()
562
515
  oldSource := testSource(t, "1.0.0")
563
- runInstall(t, target, oldPayload, func(o *Options) { o.SourceDir = oldSource })
516
+ runInstall(t, target, oldPayload, func(o *Options) {
517
+ o.SourceDir = oldSource
518
+ o.WithAgents = false
519
+ })
564
520
 
565
- bundleRoot := t.TempDir()
566
- bundle := filepath.Join(bundleRoot, "devrites-v2.0.0")
567
- testutil.WriteFile(t, filepath.Join(bundle, "install.sh"), "#!/usr/bin/env bash\n")
568
- testutil.WriteFile(t, filepath.Join(bundle, "package.json"), `{"version":"2.0.0"}`+"\n")
569
- payload := filepath.Join(bundle, "pack", "generated")
521
+ source := testSource(t, "2.0.0")
522
+ payload := filepath.Join(t.TempDir(), "generated")
570
523
  writeTestPayload(t, payload)
571
524
  testutil.WriteFile(t, filepath.Join(payload, "codex", "skills", "rite", "SKILL.md"), "updated rite\n")
572
- t.Setenv("DEVRITES_UPDATE_BUNDLE", tarGzDir(t, bundleRoot))
573
525
 
574
526
  opts := DefaultOptions(ModeUpdate)
575
527
  opts.Target = target
576
- opts.UpdateTo = "v2.0.0"
528
+ opts.SourceDir = source
529
+ opts.PayloadDir = payload
577
530
  opts.Stdout = &bytes.Buffer{}
578
531
  opts.Stderr = &bytes.Buffer{}
532
+ check := opts
533
+ check.UpdateCheck = true
534
+ if err := Apply(check); err == nil || !strings.Contains(err.Error(), "update available: 1.0.0 -> 2.0.0") {
535
+ t.Fatalf("update check error = %v, want local candidate report", err)
536
+ }
537
+ if got := manifestHeader(filepath.Join(target, ManifestName), "devrites-version"); got != "1.0.0" {
538
+ t.Fatalf("update check changed manifest version to %q", got)
539
+ }
579
540
  if err := Apply(opts); err != nil {
580
541
  t.Fatal(err)
581
542
  }
582
543
 
583
544
  if got := testutil.ReadFile(t, filepath.Join(target, ".agents", "skills", "rite", "SKILL.md")); got != "updated rite\n" {
584
- t.Fatalf("update did not install requested bundle payload: %q", got)
545
+ t.Fatalf("update did not install local payload: %q", got)
585
546
  }
586
547
  if got := manifestHeader(filepath.Join(target, ManifestName), "devrites-version"); got != "2.0.0" {
587
548
  t.Fatalf("manifest version = %q, want 2.0.0", got)
588
549
  }
550
+ if exists(filepath.Join(target, ".claude", "agents")) {
551
+ t.Fatal("update did not replay --no-agents from the manifest")
552
+ }
553
+ }
554
+
555
+ func TestUpdateCleansLegacyCodexHooks(t *testing.T) {
556
+ t.Setenv("DEVRITES_NO_BINARY", "1")
557
+ payload := testPayload(t)
558
+ source := testSource(t, "4.0.0")
559
+
560
+ t.Run("preserves user hooks", func(t *testing.T) {
561
+ target := t.TempDir()
562
+ hooks := `{
563
+ "$comment": "DevRites hooks for Codex. Project hooks load only after trust.",
564
+ "hooks": {"Stop":[{"hooks":[
565
+ {"type":"command","command":"devrites-engine hook stop-gate --harness=codex"},
566
+ {"type":"command","command":"echo user"}
567
+ ]}]}
568
+ }` + "\n"
569
+ seedLegacyCodexHooksInstall(t, target, hooks)
570
+
571
+ runLocalUpdate(t, target, source, payload)
572
+
573
+ if exists(filepath.Join(target, ".claude", "devrites.codex-hooks-merge")) {
574
+ t.Fatal("update kept the legacy Codex hooks marker")
575
+ }
576
+ got := testutil.ReadFile(t, filepath.Join(target, ".codex", "hooks.json"))
577
+ if strings.Contains(got, "devrites-engine hook") || strings.Contains(got, "DevRites hooks") || !strings.Contains(got, "echo user") {
578
+ t.Fatalf("legacy Codex hook cleanup mismatch:\n%s", got)
579
+ }
580
+ })
581
+
582
+ t.Run("removes empty hooks file", func(t *testing.T) {
583
+ target := t.TempDir()
584
+ hooks := `{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"devrites-engine hook stop-gate --harness=codex"}]}]}}` + "\n"
585
+ seedLegacyCodexHooksInstall(t, target, hooks)
586
+
587
+ runLocalUpdate(t, target, source, payload)
588
+
589
+ if exists(filepath.Join(target, ".codex", "hooks.json")) {
590
+ t.Fatal("update kept an empty legacy Codex hooks file")
591
+ }
592
+ })
593
+
594
+ t.Run("preserves unrecognized user hook shape", func(t *testing.T) {
595
+ target := t.TempDir()
596
+ seedLegacyCodexHooksInstall(t, target, `{"hooks":"user-defined"}`+"\n")
597
+
598
+ runLocalUpdate(t, target, source, payload)
599
+
600
+ got := testutil.ReadFile(t, filepath.Join(target, ".codex", "hooks.json"))
601
+ if !strings.Contains(got, `"hooks": "user-defined"`) {
602
+ t.Fatalf("legacy cleanup removed unrecognized user hooks: %s", got)
603
+ }
604
+ })
605
+
606
+ t.Run("malformed hooks keep ownership marker", func(t *testing.T) {
607
+ target := t.TempDir()
608
+ seedLegacyCodexHooksInstall(t, target, "{\n")
609
+
610
+ err := applyUpdate(target, source, payload)
611
+ if err == nil || !strings.Contains(err.Error(), "load hooks config") {
612
+ t.Fatalf("update error = %v, want malformed legacy hooks error", err)
613
+ }
614
+ if !exists(filepath.Join(target, ".claude", "devrites.codex-hooks-merge")) {
615
+ t.Fatal("failed cleanup removed the legacy ownership marker")
616
+ }
617
+ if got := testutil.ReadFile(t, filepath.Join(target, ".codex", "hooks.json")); got != "{\n" {
618
+ t.Fatalf("failed cleanup changed hooks: %q", got)
619
+ }
620
+ })
621
+
622
+ t.Run("uninstall preserves user hooks", func(t *testing.T) {
623
+ target := t.TempDir()
624
+ hooks := `{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"devrites-engine hook stop-gate"},{"type":"command","command":"echo user"}]}]}}` + "\n"
625
+ seedLegacyCodexHooksInstall(t, target, hooks)
626
+
627
+ runUninstall(t, target)
628
+
629
+ got := testutil.ReadFile(t, filepath.Join(target, ".codex", "hooks.json"))
630
+ if strings.Contains(got, "devrites-engine hook") || !strings.Contains(got, "echo user") {
631
+ t.Fatalf("legacy Codex hook uninstall mismatch:\n%s", got)
632
+ }
633
+ })
634
+ }
635
+
636
+ func TestLegacyCodexHooksMergeIsCleanupOnly(t *testing.T) {
637
+ legacy := hostpack.LegacyCodexHooksMerge
638
+ merge, ok := hostpack.ManagedMergeForMarker(legacy.MarkerRel)
639
+ if !ok || merge != legacy {
640
+ t.Fatalf("legacy marker lookup = %#v, %t", merge, ok)
641
+ }
642
+ if slices.Contains(hostpack.RequiredPayload(true), "codex/hooks.json") {
643
+ t.Fatal("legacy Codex hooks entered the required payload")
644
+ }
645
+ r := runner{opts: DefaultOptions(ModeInstall), payloadFS: os.DirFS(testPayload(t))}
646
+ desired, err := r.desiredInstallPaths()
647
+ if err != nil {
648
+ t.Fatal(err)
649
+ }
650
+ if desired[legacy.MarkerRel] || desired[legacy.TargetRel] || slices.Contains(r.installMergeTargets(), legacy.TargetRel) {
651
+ t.Fatalf("legacy Codex hooks entered active install paths: desired=%v merge-targets=%v", desired, r.installMergeTargets())
652
+ }
589
653
  }
590
654
 
591
- func TestUpdateBuildsGeneratedPayloadForSourceArchive(t *testing.T) {
655
+ func TestUpdateRejectsMissingGeneratedPayload(t *testing.T) {
592
656
  t.Setenv("DEVRITES_NO_BINARY", "1")
593
657
  oldPayload := testPayload(t)
594
658
  target := t.TempDir()
595
659
  runInstall(t, target, oldPayload, func(o *Options) { o.SourceDir = testSource(t, "1.0.0") })
596
660
 
597
- bundleRoot := t.TempDir()
598
- bundle := filepath.Join(bundleRoot, "devrites-v2.1.0")
599
- testutil.WriteFile(t, filepath.Join(bundle, "install.sh"), "#!/usr/bin/env bash\n")
600
- testutil.WriteFile(t, filepath.Join(bundle, "package.json"), `{"version":"2.1.0"}`+"\n")
601
- testutil.WriteExecutable(t, filepath.Join(bundle, "scripts", "build-host-artifacts.sh"), `#!/usr/bin/env bash
602
- set -eu
603
- out="${DEVRITES_HOST_ARTIFACT_DIR:?}"
604
- mkdir -p "$out/claude/skills/rite" "$out/claude/agents" "$out/codex/skills/rite" "$out/codex/agents"
605
- printf 'source archive claude\n' > "$out/claude/skills/rite/SKILL.md"
606
- printf 'agent\n' > "$out/claude/agents/devrites-code-reviewer.md"
607
- printf '{}\n' > "$out/claude/settings.json"
608
- printf 'source archive codex\n' > "$out/codex/skills/rite/SKILL.md"
609
- printf 'name = "devrites-code-reviewer"\n' > "$out/codex/agents/devrites-code-reviewer.toml"
610
- printf '<!-- BEGIN DEVRITES CODEX -->\nDevRites\n<!-- END DEVRITES CODEX -->\n' > "$out/codex/AGENTS.md"
611
- printf '{"hooks":{"Stop":[{"hooks":[{"type":"command","command":"devrites-engine hook stop-gate"}]}]}}\n' > "$out/codex/hooks.json"
661
+ source := testSource(t, "2.1.0")
662
+ payload := filepath.Join(t.TempDir(), "generated")
663
+ builderMarker := filepath.Join(t.TempDir(), "builder-invoked")
664
+ t.Setenv("DEVRITES_TEST_BUILDER_MARKER", builderMarker)
665
+ testutil.WriteExecutable(t, filepath.Join(source, "scripts", "build-host-artifacts.sh"), `#!/usr/bin/env bash
666
+ touch "${DEVRITES_TEST_BUILDER_MARKER:?}"
667
+ exit 42
612
668
  `)
613
- t.Setenv("DEVRITES_UPDATE_BUNDLE", tarGzDir(t, bundleRoot))
614
669
 
615
670
  opts := DefaultOptions(ModeUpdate)
616
671
  opts.Target = target
617
- opts.UpdateTo = "v2.1.0"
672
+ opts.SourceDir = source
673
+ opts.PayloadDir = payload
618
674
  opts.Stdout = &bytes.Buffer{}
619
675
  opts.Stderr = &bytes.Buffer{}
620
- if err := Apply(opts); err != nil {
621
- t.Fatal(err)
676
+ err := Apply(opts)
677
+ if err == nil ||
678
+ !strings.Contains(err.Error(), "local update payload") ||
679
+ !strings.Contains(err.Error(), "missing claude/skills") ||
680
+ !strings.Contains(err.Error(), payload) {
681
+ t.Fatalf("update error = %v, want actionable missing payload error", err)
622
682
  }
623
-
624
- if got := testutil.ReadFile(t, filepath.Join(target, ".agents", "skills", "rite", "SKILL.md")); got != "source archive codex\n" {
625
- t.Fatalf("source archive update did not build generated payload: %q", got)
683
+ if exists(builderMarker) {
684
+ t.Fatal("update invoked the host artifact builder")
685
+ }
686
+ if got := testutil.ReadFile(t, filepath.Join(target, ".agents", "skills", "rite", "SKILL.md")); got != "codex rite\n" {
687
+ t.Fatalf("rejected update changed installed payload: %q", got)
688
+ }
689
+ if got := manifestHeader(filepath.Join(target, ManifestName), "devrites-version"); got != "1.0.0" {
690
+ t.Fatalf("manifest version = %q, want 1.0.0 after rejected update", got)
626
691
  }
627
692
  }
628
693
 
@@ -975,6 +1040,33 @@ func applyInstall(target, payload string, force, dryRun bool, out *bytes.Buffer)
975
1040
  return Apply(opts)
976
1041
  }
977
1042
 
1043
+ func applyUpdate(target, source, payload string) error {
1044
+ opts := DefaultOptions(ModeUpdate)
1045
+ opts.Target = target
1046
+ opts.SourceDir = source
1047
+ opts.PayloadDir = payload
1048
+ opts.Stdout = &bytes.Buffer{}
1049
+ opts.Stderr = &bytes.Buffer{}
1050
+ return Apply(opts)
1051
+ }
1052
+
1053
+ func runLocalUpdate(t *testing.T, target, source, payload string) {
1054
+ t.Helper()
1055
+ if err := applyUpdate(target, source, payload); err != nil {
1056
+ t.Fatal(err)
1057
+ }
1058
+ }
1059
+
1060
+ func seedLegacyCodexHooksInstall(t *testing.T, target, hooks string) {
1061
+ t.Helper()
1062
+ markerRel := ".claude/devrites.codex-hooks-merge"
1063
+ marker := []byte(".codex/hooks.json contains DevRites managed hook entries.\n")
1064
+ testutil.WriteFile(t, filepath.Join(target, ".codex", "hooks.json"), hooks)
1065
+ testutil.WriteFile(t, filepath.Join(target, filepath.FromSlash(markerRel)), string(marker))
1066
+ testutil.WriteFile(t, filepath.Join(target, ManifestName), "# DevRites install manifest - do not edit by hand.\n# devrites-version: 3.2.27\n# devrites-flags: \n")
1067
+ addManifestRecord(t, filepath.Join(target, ManifestName), markerRel, marker)
1068
+ }
1069
+
978
1070
  func addManifestRecord(t *testing.T, manifest, rel string, data []byte) {
979
1071
  t.Helper()
980
1072
  hash := fmt.Sprintf("sha256:%x", sha256.Sum256(data))
@@ -1017,16 +1109,21 @@ func writeTestPayload(t *testing.T, root string) {
1017
1109
  t.Helper()
1018
1110
  testutil.WriteFile(t, filepath.Join(root, "claude", "skills", "rite", "SKILL.md"), "claude rite\n")
1019
1111
  testutil.WriteFile(t, filepath.Join(root, "claude", "agents", "devrites-code-reviewer.md"), "agent\n")
1020
- testutil.WriteFile(t, filepath.Join(root, "claude", "settings.json"), "{}\n")
1112
+ testutil.WriteFile(t, filepath.Join(root, "claude", "settings.json"), `{
1113
+ "permissions": {
1114
+ "defaultMode": "plan",
1115
+ "allow": ["Bash(devrites-engine check readiness *)"]
1116
+ }
1117
+ }`+"\n")
1021
1118
  testutil.WriteFile(t, filepath.Join(root, "codex", "skills", "rite", "SKILL.md"), "codex rite\n")
1022
1119
  testutil.WriteFile(t, filepath.Join(root, "codex", "agents", "devrites-code-reviewer.toml"), "name = \"devrites-code-reviewer\"\n")
1023
1120
  testutil.WriteFile(t, filepath.Join(root, "codex", "AGENTS.md"), "<!-- BEGIN DEVRITES CODEX -->\nDevRites\n<!-- END DEVRITES CODEX -->\n")
1024
- hooks := map[string]any{"hooks": map[string]any{"Stop": []any{map[string]any{"hooks": []any{map[string]any{"type": "command", "command": "devrites-engine hook stop-gate"}}}}}}
1025
- data, err := json.MarshalIndent(hooks, "", " ")
1026
- if err != nil {
1027
- t.Fatal(err)
1028
- }
1029
- testutil.WriteFile(t, filepath.Join(root, "codex", "hooks.json"), string(data)+"\n")
1121
+ testutil.WriteFile(t, filepath.Join(root, "codex", "config.toml"), `# BEGIN DEVRITES CODEX PERMISSIONS
1122
+ default_permissions = "devrites-orchestrator"
1123
+ [permissions.devrites-orchestrator]
1124
+ extends = ":workspace"
1125
+ # END DEVRITES CODEX PERMISSIONS
1126
+ `)
1030
1127
  }
1031
1128
 
1032
1129
  func testSource(t *testing.T, version string) string {
@@ -1035,60 +1132,3 @@ func testSource(t *testing.T, version string) string {
1035
1132
  testutil.WriteFile(t, filepath.Join(root, "package.json"), `{"version":"`+version+`"}`+"\n")
1036
1133
  return root
1037
1134
  }
1038
-
1039
- func tarGzDir(t *testing.T, root string) string {
1040
- t.Helper()
1041
- out := filepath.Join(t.TempDir(), "bundle.tar.gz")
1042
- f, err := os.Create(out)
1043
- if err != nil {
1044
- t.Fatal(err)
1045
- }
1046
- gz := gzip.NewWriter(f)
1047
- tw := tar.NewWriter(gz)
1048
- err = filepath.WalkDir(root, func(path string, d fs.DirEntry, walkErr error) error {
1049
- if walkErr != nil {
1050
- return walkErr
1051
- }
1052
- if path == root {
1053
- return nil
1054
- }
1055
- info, err := d.Info()
1056
- if err != nil {
1057
- return err
1058
- }
1059
- rel, err := filepath.Rel(root, path)
1060
- if err != nil {
1061
- return err
1062
- }
1063
- hdr, err := tar.FileInfoHeader(info, "")
1064
- if err != nil {
1065
- return err
1066
- }
1067
- hdr.Name = filepath.ToSlash(rel)
1068
- if err := tw.WriteHeader(hdr); err != nil {
1069
- return err
1070
- }
1071
- if d.IsDir() {
1072
- return nil
1073
- }
1074
- data, err := os.ReadFile(path)
1075
- if err != nil {
1076
- return err
1077
- }
1078
- _, err = tw.Write(data)
1079
- return err
1080
- })
1081
- if closeErr := tw.Close(); err == nil {
1082
- err = closeErr
1083
- }
1084
- if closeErr := gz.Close(); err == nil {
1085
- err = closeErr
1086
- }
1087
- if closeErr := f.Close(); err == nil {
1088
- err = closeErr
1089
- }
1090
- if err != nil {
1091
- t.Fatal(err)
1092
- }
1093
- return out
1094
- }