devrites 3.2.27 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (897) hide show
  1. package/CHANGELOG.md +22 -144
  2. package/NOTICE.md +6 -5
  3. package/README.md +187 -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 +139 -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 +16 -20
  58. package/engine/internal/hostpack/hostpack_test.go +6 -6
  59. package/engine/internal/install/install.go +289 -511
  60. package/engine/internal/install/install_test.go +218 -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 -1637
  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 -2732
  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,938 +0,0 @@
1
- package forge
2
-
3
- import (
4
- "bytes"
5
- "encoding/hex"
6
- "encoding/json"
7
- "errors"
8
- "flag"
9
- "fmt"
10
- "io"
11
- "os"
12
- "path/filepath"
13
- "sort"
14
- "strconv"
15
- "strings"
16
- )
17
-
18
- type PlanOptions struct {
19
- SliceID string
20
- Slug string
21
- Strategies map[CandidateID]string
22
- AcceptanceHash string
23
- TestPlanHash string
24
- }
25
-
26
- type PlanResult struct {
27
- Status string `json:"status"`
28
- Mode string `json:"mode,omitempty"`
29
- Reason string `json:"reason,omitempty"`
30
- Manifest *Manifest `json:"manifest,omitempty"`
31
- }
32
-
33
- const WorkerBindingManifestEnvV1 = "manifest-env-v1"
34
-
35
- type ProcessTokenResult struct {
36
- Status string `json:"status"`
37
- PID int `json:"pid"`
38
- ProcessStart string `json:"process_start"`
39
- }
40
-
41
- type RecordOptions struct {
42
- RunID string
43
- Candidate CandidateID
44
- State CandidateState
45
- WorkerID string
46
- PID int
47
- ProcessStart string
48
- }
49
-
50
- type ReapResult struct {
51
- RunID string `json:"run_id"`
52
- Removed []CandidateID `json:"removed,omitempty"`
53
- Preserved map[string]string `json:"preserved,omitempty"`
54
- Error string `json:"error,omitempty"`
55
- }
56
-
57
- // Run is the Forge command entry point. It never accepts a worktree path or
58
- // branch name; every destructive target is loaded from the unique manifest.
59
- func Run(root string, args []string, stdout, stderr io.Writer) int {
60
- if len(args) == 0 {
61
- fmt.Fprintln(stderr, usage)
62
- return 2
63
- }
64
- var (
65
- result any
66
- err error
67
- )
68
- switch args[0] {
69
- case "plan":
70
- result, err = runPlan(root, args[1:])
71
- case "process-token":
72
- if len(args) != 2 {
73
- err = errors.New("usage: forge process-token <pid>")
74
- break
75
- }
76
- result, err = runProcessToken(args[1])
77
- case "record":
78
- result, err = runRecord(root, args[1:])
79
- case "extract":
80
- if len(args) != 3 {
81
- err = errors.New("usage: forge extract <run-id> <A|B|C>")
82
- break
83
- }
84
- result, err = Extract(root, args[1], CandidateID(args[2]))
85
- case "merge":
86
- if len(args) != 3 {
87
- err = errors.New("usage: forge merge <run-id> <A|B|C>")
88
- break
89
- }
90
- result, err = Merge(root, args[1], CandidateID(args[2]))
91
- case "cleanup":
92
- if len(args) != 2 {
93
- err = errors.New("usage: forge cleanup <run-id>")
94
- break
95
- }
96
- result, err = Cleanup(root, args[1])
97
- case "reap":
98
- if len(args) > 2 {
99
- err = errors.New("usage: forge reap [slug]")
100
- break
101
- }
102
- slug := ""
103
- if len(args) == 2 {
104
- slug = args[1]
105
- }
106
- result, err = Reap(root, slug)
107
- default:
108
- fmt.Fprintln(stderr, usage)
109
- return 2
110
- }
111
- if err != nil {
112
- fmt.Fprintf(stderr, "%v\n", err)
113
- return 1
114
- }
115
- raw, marshalErr := json.MarshalIndent(result, "", " ")
116
- if marshalErr != nil {
117
- fmt.Fprintf(stderr, "forge: encode result: %v\n", marshalErr)
118
- return 1
119
- }
120
- fmt.Fprintln(stdout, string(raw))
121
- return 0
122
- }
123
-
124
- const usage = "usage: forge plan|process-token|record|extract|merge|cleanup|reap ..."
125
-
126
- func runPlan(root string, args []string) (PlanResult, error) {
127
- var (
128
- strategies strategyFlags
129
- slug, acceptance, testPlan string
130
- workerBinding string
131
- workerBindingSet bool
132
- positional []string
133
- )
134
- for i := 0; i < len(args); i++ {
135
- arg := args[i]
136
- switch {
137
- case arg == "--strategy" || arg == "--slug" || arg == "--acceptance-hash" || arg == "--test-plan-hash" || arg == "--worker-binding":
138
- if i+1 == len(args) {
139
- return PlanResult{}, fmt.Errorf("forge: %s requires a value", arg)
140
- }
141
- i++
142
- switch arg {
143
- case "--strategy":
144
- if err := strategies.Set(args[i]); err != nil {
145
- return PlanResult{}, err
146
- }
147
- case "--slug":
148
- slug = args[i]
149
- case "--acceptance-hash":
150
- acceptance = args[i]
151
- case "--test-plan-hash":
152
- testPlan = args[i]
153
- case "--worker-binding":
154
- if workerBindingSet {
155
- return PlanResult{}, errors.New("forge: worker binding may be declared only once")
156
- }
157
- workerBinding, workerBindingSet = args[i], true
158
- }
159
- case strings.HasPrefix(arg, "--strategy="):
160
- if err := strategies.Set(strings.TrimPrefix(arg, "--strategy=")); err != nil {
161
- return PlanResult{}, err
162
- }
163
- case strings.HasPrefix(arg, "--slug="):
164
- slug = strings.TrimPrefix(arg, "--slug=")
165
- case strings.HasPrefix(arg, "--acceptance-hash="):
166
- acceptance = strings.TrimPrefix(arg, "--acceptance-hash=")
167
- case strings.HasPrefix(arg, "--test-plan-hash="):
168
- testPlan = strings.TrimPrefix(arg, "--test-plan-hash=")
169
- case strings.HasPrefix(arg, "--worker-binding="):
170
- if workerBindingSet {
171
- return PlanResult{}, errors.New("forge: worker binding may be declared only once")
172
- }
173
- workerBinding, workerBindingSet = strings.TrimPrefix(arg, "--worker-binding="), true
174
- case strings.HasPrefix(arg, "-"):
175
- return PlanResult{}, fmt.Errorf("forge: unknown plan flag %s", arg)
176
- default:
177
- positional = append(positional, arg)
178
- }
179
- }
180
- if len(positional) < 1 || len(positional) > 2 {
181
- return PlanResult{}, errors.New("usage: forge plan <slice-id> [slug] --strategy A=text --strategy B=text --acceptance-hash <sha256> --test-plan-hash <sha256>")
182
- }
183
- if slug == "" && len(positional) == 2 {
184
- slug = positional[1]
185
- }
186
- switch {
187
- case !workerBindingSet:
188
- return degraded("supported worker binding was not declared"), nil
189
- case workerBinding != WorkerBindingManifestEnvV1:
190
- return PlanResult{}, fmt.Errorf("forge: unsupported worker binding %q (want %q)", workerBinding, WorkerBindingManifestEnvV1)
191
- }
192
- return Plan(root, PlanOptions{
193
- SliceID: positional[0],
194
- Slug: slug,
195
- Strategies: strategies.values,
196
- AcceptanceHash: acceptance,
197
- TestPlanHash: testPlan,
198
- })
199
- }
200
-
201
- func runProcessToken(value string) (ProcessTokenResult, error) {
202
- pid, err := parsePID(value)
203
- if err != nil {
204
- return ProcessTokenResult{}, err
205
- }
206
- token, err := ProcessStartToken(pid)
207
- if err != nil {
208
- return ProcessTokenResult{}, err
209
- }
210
- return ProcessTokenResult{Status: "ok", PID: pid, ProcessStart: token}, nil
211
- }
212
-
213
- func runRecord(root string, args []string) (*Manifest, error) {
214
- if len(args) < 3 {
215
- return nil, errors.New("usage: forge record <run-id> <candidate|winner|verification> <state> [flags]")
216
- }
217
- runID, subject, state := args[0], args[1], args[2]
218
- fs := flag.NewFlagSet("forge record", flag.ContinueOnError)
219
- fs.SetOutput(io.Discard)
220
- var workerID, start string
221
- var pid int
222
- fs.StringVar(&workerID, "worker-id", "", "worker or recorder identity")
223
- fs.IntVar(&pid, "pid", 0, "worker PID")
224
- fs.StringVar(&start, "process-start", "", "worker process start token")
225
- if err := fs.Parse(args[3:]); err != nil || fs.NArg() != 0 {
226
- return nil, errors.New("forge: invalid record flags")
227
- }
228
- switch subject {
229
- case "winner":
230
- return RecordWinner(root, runID, CandidateID(state), workerID)
231
- case "verification":
232
- switch state {
233
- case "verified":
234
- return RecordVerification(root, runID, true, workerID)
235
- case "failed":
236
- return RecordVerification(root, runID, false, workerID)
237
- default:
238
- return nil, fmt.Errorf("forge: invalid verification state %q", state)
239
- }
240
- default:
241
- if state == "started" {
242
- state = string(StateRunning)
243
- }
244
- return Record(root, RecordOptions{
245
- RunID: runID,
246
- Candidate: CandidateID(subject),
247
- State: CandidateState(state),
248
- WorkerID: workerID,
249
- PID: pid,
250
- ProcessStart: start,
251
- })
252
- }
253
- }
254
-
255
- type strategyFlags struct {
256
- values map[CandidateID]string
257
- }
258
-
259
- func (s *strategyFlags) Set(value string) error {
260
- idText, text, ok := strings.Cut(value, "=")
261
- id := CandidateID(idText)
262
- if !ok || !validCandidateID(id) || strings.TrimSpace(text) == "" {
263
- return fmt.Errorf("strategy must be A=text, B=text, or C=text")
264
- }
265
- if s.values == nil {
266
- s.values = map[CandidateID]string{}
267
- }
268
- if _, exists := s.values[id]; exists {
269
- return fmt.Errorf("duplicate strategy %s", id)
270
- }
271
- s.values[id] = strings.TrimSpace(text)
272
- return nil
273
- }
274
-
275
- func Plan(root string, opts PlanOptions) (PlanResult, error) {
276
- if strings.TrimSpace(opts.SliceID) == "" {
277
- return PlanResult{}, errors.New("forge: slice ID is required")
278
- }
279
- if !safeSlug.MatchString(opts.Slug) {
280
- return PlanResult{}, fmt.Errorf("forge: invalid feature slug %q", opts.Slug)
281
- }
282
- if len(opts.Strategies) < 2 || len(opts.Strategies) > 3 {
283
- return PlanResult{}, errors.New("forge: exactly 2 or 3 candidate strategies are required")
284
- }
285
- for id, strategy := range opts.Strategies {
286
- if !validCandidateID(id) || strings.TrimSpace(strategy) == "" {
287
- return PlanResult{}, fmt.Errorf("forge: invalid strategy %q", id)
288
- }
289
- }
290
- if !validSHA256(opts.AcceptanceHash) || !validSHA256(opts.TestPlanHash) {
291
- return PlanResult{}, errors.New("forge: acceptance and test-plan SHA-256 scorecard hashes are required")
292
- }
293
- physical, err := physicalExisting(root)
294
- if err != nil {
295
- return PlanResult{}, err
296
- }
297
- id, err := inspectRepo(physical)
298
- if err != nil {
299
- return degraded(err.Error()), nil
300
- }
301
- if super, _ := gitText(physical, "rev-parse", "--show-superproject-working-tree"); super != "" {
302
- return degraded("submodule checkout is not safe for parallel Forge"), nil
303
- }
304
- if inProgress(id.commonDir) {
305
- return degraded("repository has an in-progress Git operation"), nil
306
- }
307
- existingManifests, err := validatedManifestPaths(physical)
308
- if err != nil {
309
- return PlanResult{}, err
310
- }
311
- if dirty, err := dirtyStatus(physical, false, existingManifests); err != nil {
312
- return PlanResult{}, err
313
- } else if dirty {
314
- return degraded("primary index or worktree is dirty"), nil
315
- }
316
- if _, err := ProcessStartToken(os.Getpid()); err != nil {
317
- return degraded("worker liveness cannot be proven on this host"), nil
318
- }
319
- runID, nonce, err := newIdentity()
320
- if err != nil {
321
- return PlanResult{}, err
322
- }
323
- staging := forgeRoot(physical, runID)
324
- if err := validateStagingParent(staging); err != nil {
325
- return degraded(err.Error()), nil
326
- }
327
- registrations, err := registeredWorktrees(physical)
328
- if err != nil {
329
- return PlanResult{}, err
330
- }
331
- for path := range registrations {
332
- if path == staging || strings.HasPrefix(path, staging+string(filepath.Separator)) {
333
- return degraded("derived staging path collides with a registered worktree"), nil
334
- }
335
- }
336
- if _, err := os.Lstat(staging); err == nil {
337
- return degraded("derived staging path already exists"), nil
338
- } else if !errors.Is(err, os.ErrNotExist) {
339
- return PlanResult{}, fmt.Errorf("forge: inspect staging path: %w", err)
340
- }
341
- manifestPath, err := ManifestPath(physical, opts.Slug, runID)
342
- if err != nil {
343
- return PlanResult{}, err
344
- }
345
- if err := validateManifestParentBeforeCreate(physical, manifestPath); err != nil {
346
- return degraded(err.Error()), nil
347
- }
348
- ids := make([]CandidateID, 0, len(opts.Strategies))
349
- for candidateID := range opts.Strategies {
350
- ids = append(ids, candidateID)
351
- }
352
- sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
353
- for i, candidateID := range ids {
354
- want := CandidateID(rune('A' + i))
355
- if candidateID != want {
356
- return PlanResult{}, errors.New("forge: candidate IDs must be contiguous from A")
357
- }
358
- if _, err := gitText(physical, "show-ref", "--verify", "--quiet", "refs/heads/"+candidateBranch(runID, candidateID)); err == nil {
359
- return degraded("derived candidate branch already exists"), nil
360
- }
361
- }
362
- createdAt := now()
363
- m := &Manifest{
364
- Schema: Schema,
365
- RunID: runID,
366
- CreationNonce: nonce,
367
- CreatedAt: createdAt,
368
- FeatureSlug: opts.Slug,
369
- SliceID: strings.TrimSpace(opts.SliceID),
370
- AcceptanceHash: strings.ToLower(opts.AcceptanceHash),
371
- TestPlanHash: strings.ToLower(opts.TestPlanHash),
372
- PrimaryRoot: physical,
373
- GitCommonDir: id.commonDir,
374
- ForgeRoot: staging,
375
- Primary: Primary{
376
- Branch: id.branch,
377
- BaseCommit: id.head,
378
- BaselineTree: id.tree,
379
- BaselineSHA256: id.treeHash,
380
- },
381
- }
382
- for _, candidateID := range ids {
383
- m.Candidates = append(m.Candidates, Candidate{
384
- ID: candidateID,
385
- Strategy: strings.TrimSpace(opts.Strategies[candidateID]),
386
- Worktree: filepath.Join(staging, "candidate-"+strings.ToLower(string(candidateID))),
387
- Branch: candidateBranch(runID, candidateID),
388
- InitialBase: id.head,
389
- State: StatePlanned,
390
- LastTransition: createdAt,
391
- })
392
- }
393
- // The manifest owns every derived path before the first Git side effect.
394
- if err := save(manifestPath, m); err != nil {
395
- return PlanResult{}, err
396
- }
397
- for i := range m.Candidates {
398
- c := &m.Candidates[i]
399
- if _, err := gitBytes(physical, nil, "worktree", "add", "-b", c.Branch, c.Worktree, c.InitialBase); err != nil {
400
- c.Preservation = err.Error()
401
- c.LastTransition = now()
402
- _ = save(manifestPath, m)
403
- return PlanResult{}, fmt.Errorf("forge: create candidate %s: %w", c.ID, err)
404
- }
405
- c.State = StateCreated
406
- c.LastTransition = now()
407
- if err := save(manifestPath, m); err != nil {
408
- return PlanResult{}, err
409
- }
410
- }
411
- return PlanResult{Status: "planned", Manifest: m}, nil
412
- }
413
-
414
- func Record(root string, opts RecordOptions) (*Manifest, error) {
415
- m, path, err := Load(root, opts.RunID)
416
- if err != nil {
417
- return nil, err
418
- }
419
- c, err := m.Candidate(opts.Candidate)
420
- if err != nil {
421
- return nil, err
422
- }
423
- if strings.TrimSpace(opts.WorkerID) == "" {
424
- return nil, errors.New("forge: worker ID is required")
425
- }
426
- switch opts.State {
427
- case StateRunning:
428
- if c.State == StateRunning && c.Worker.ID == opts.WorkerID && c.Worker.PID == opts.PID && c.Worker.ProcessStart == opts.ProcessStart {
429
- return m, nil
430
- }
431
- if c.State != StateCreated {
432
- return nil, fmt.Errorf("forge: candidate %s cannot transition from %s to running", c.ID, c.State)
433
- }
434
- token, err := ProcessStartToken(opts.PID)
435
- if err != nil || token != opts.ProcessStart {
436
- return nil, errors.New("forge: worker liveness token is not currently provable")
437
- }
438
- c.Worker = Worker{ID: opts.WorkerID, PID: opts.PID, ProcessStart: opts.ProcessStart, StartedAt: now()}
439
- c.State = StateRunning
440
- case StateFinished, StateFailed:
441
- if (c.State == opts.State || c.State == StateExtracted || c.State == StateMerged || c.State == StateCleaned) &&
442
- c.Worker.ID == opts.WorkerID {
443
- return m, nil
444
- }
445
- if c.State != StateRunning || c.Worker.ID != opts.WorkerID {
446
- return nil, fmt.Errorf("forge: candidate %s terminal transition does not match its live owner", c.ID)
447
- }
448
- c.State = opts.State
449
- c.Worker.FinishedAt = now()
450
- c.Worker.Result = string(opts.State)
451
- default:
452
- return nil, fmt.Errorf("forge: unsupported candidate state %q", opts.State)
453
- }
454
- c.LastTransition = now()
455
- if err := save(path, m); err != nil {
456
- return nil, err
457
- }
458
- return m, nil
459
- }
460
-
461
- func RecordWinner(root, runID string, winner CandidateID, recorder string) (*Manifest, error) {
462
- m, path, err := Load(root, runID)
463
- if err != nil {
464
- return nil, err
465
- }
466
- if strings.TrimSpace(recorder) == "" || !validCandidateID(winner) {
467
- return nil, errors.New("forge: valid winner and recorder identity are required")
468
- }
469
- if _, err := m.Candidate(winner); err != nil {
470
- return nil, err
471
- }
472
- if m.Winner.Candidate != "" {
473
- if m.Winner.Candidate == winner && m.Winner.RecordedBy == recorder {
474
- return m, nil
475
- }
476
- return nil, errors.New("forge: winner is already recorded and immutable")
477
- }
478
- m.Winner = Winner{Candidate: winner, RecordedBy: recorder, RecordedAt: now()}
479
- if err := save(path, m); err != nil {
480
- return nil, err
481
- }
482
- return m, nil
483
- }
484
-
485
- func RecordVerification(root, runID string, passed bool, recorder string) (*Manifest, error) {
486
- m, path, err := Load(root, runID)
487
- if err != nil {
488
- return nil, err
489
- }
490
- if strings.TrimSpace(recorder) == "" || m.Merge.State != "landed" {
491
- return nil, errors.New("forge: landed merge and verifier identity are required")
492
- }
493
- state := "failed"
494
- if passed {
495
- state = "verified"
496
- }
497
- if m.Verification.State != "" {
498
- if m.Verification.State == state && m.Verification.RecordedBy == recorder {
499
- return m, nil
500
- }
501
- return nil, errors.New("forge: verification result is already recorded and immutable")
502
- }
503
- m.Verification = VerificationState{State: state, RecordedBy: recorder, RecordedAt: now()}
504
- if err := save(path, m); err != nil {
505
- return nil, err
506
- }
507
- return m, nil
508
- }
509
-
510
- func Extract(root, runID string, candidateID CandidateID) (*Manifest, error) {
511
- m, path, err := Load(root, runID)
512
- if err != nil {
513
- return nil, err
514
- }
515
- c, err := m.Candidate(candidateID)
516
- if err != nil {
517
- return nil, err
518
- }
519
- if c.State == StateExtracted || c.State == StateMerged || c.State == StateCleaned {
520
- return verifyExtracted(m, c, path)
521
- }
522
- if c.State != StateFinished {
523
- return nil, fmt.Errorf("forge: candidate %s must be finished before extraction", c.ID)
524
- }
525
- if live, reason := workerLiveness(c.Worker); live != livenessDead {
526
- return nil, fmt.Errorf("forge: candidate %s preserved: %s", c.ID, reason)
527
- }
528
- if err := validateCandidateRepo(m, c); err != nil {
529
- return nil, err
530
- }
531
- head, err := gitText(c.Worktree, "rev-parse", "--verify", "HEAD^{commit}")
532
- if err != nil {
533
- return nil, err
534
- }
535
- if _, err := gitBytes(c.Worktree, nil, "merge-base", "--is-ancestor", c.InitialBase, head); err != nil {
536
- return nil, fmt.Errorf("forge: candidate %s no longer descends from its initial base", c.ID)
537
- }
538
- if ignored, err := gitBytes(c.Worktree, nil, "ls-files", "--others", "--ignored", "--exclude-standard", "-z"); err != nil {
539
- return nil, err
540
- } else if len(ignored) != 0 {
541
- return preserve(path, m, c, "ignored content is not representable in the candidate tree")
542
- }
543
- if _, err := gitBytes(c.Worktree, nil, "add", "-A", "--", "."); err != nil {
544
- return nil, err
545
- }
546
- changed, err := gitBytes(c.Worktree, nil, "diff", "--cached", "--quiet", "--exit-code")
547
- if err != nil {
548
- _ = changed
549
- if _, commitErr := gitBytes(c.Worktree, nil,
550
- "-c", "user.name=DevRites Forge",
551
- "-c", "user.email=forge@devrites.local",
552
- "commit", "--no-gpg-sign", "--no-verify",
553
- "-m", "devrites forge snapshot "+m.RunID+" "+string(c.ID)); commitErr != nil {
554
- return nil, commitErr
555
- }
556
- }
557
- c.Commit, err = gitText(c.Worktree, "rev-parse", "--verify", "HEAD^{commit}")
558
- if err != nil {
559
- return nil, err
560
- }
561
- c.Tree, err = gitText(c.Worktree, "rev-parse", "--verify", "HEAD^{tree}")
562
- if err != nil {
563
- return nil, err
564
- }
565
- if err := rejectPrivateOrGitlinkChanges(c); err != nil {
566
- return preserve(path, m, c, err.Error())
567
- }
568
- delta, err := gitBytes(c.Worktree, nil, "diff", "--binary", "--full-index", "--no-renames", c.InitialBase, c.Commit, "--")
569
- if err != nil {
570
- return nil, err
571
- }
572
- c.DeltaSHA256 = sha256Hex(delta)
573
- if dirty, err := dirtyStatus(c.Worktree, true, nil); err != nil {
574
- return nil, err
575
- } else if dirty {
576
- return preserve(path, m, c, "candidate remains dirty after snapshot")
577
- }
578
- c.State = StateExtracted
579
- c.Preservation = ""
580
- c.LastTransition = now()
581
- if err := save(path, m); err != nil {
582
- return nil, err
583
- }
584
- return m, nil
585
- }
586
-
587
- func verifyExtracted(m *Manifest, c *Candidate, path string) (*Manifest, error) {
588
- if c.Commit == "" || c.Tree == "" || c.DeltaSHA256 == "" {
589
- return nil, fmt.Errorf("forge: candidate %s has incomplete extraction state", c.ID)
590
- }
591
- if c.State == StateCleaned {
592
- return m, nil
593
- }
594
- if err := validateCandidateRepo(m, c); err != nil {
595
- return nil, err
596
- }
597
- head, err := gitText(c.Worktree, "rev-parse", "HEAD^{commit}")
598
- if err != nil || head != c.Commit {
599
- return nil, fmt.Errorf("forge: candidate %s extracted commit drifted", c.ID)
600
- }
601
- delta, err := gitBytes(c.Worktree, nil, "diff", "--binary", "--full-index", "--no-renames", c.InitialBase, c.Commit, "--")
602
- if err != nil || sha256Hex(delta) != c.DeltaSHA256 {
603
- return nil, fmt.Errorf("forge: candidate %s extracted delta drifted", c.ID)
604
- }
605
- return m, nil
606
- }
607
-
608
- func Merge(root, runID string, winnerID CandidateID) (*Manifest, error) {
609
- m, path, err := Load(root, runID)
610
- if err != nil {
611
- return nil, err
612
- }
613
- if m.Winner.Candidate == "" || m.Winner.Candidate != winnerID {
614
- return nil, errors.New("forge: merge winner does not match the recorded judge winner")
615
- }
616
- winner, err := m.Candidate(winnerID)
617
- if err != nil {
618
- return nil, err
619
- }
620
- for i := range m.Candidates {
621
- c := &m.Candidates[i]
622
- if c.State != StateExtracted && c.State != StateMerged && c.State != StateCleaned {
623
- return nil, fmt.Errorf("forge: candidate %s has not been extracted", c.ID)
624
- }
625
- }
626
- id, err := inspectRepo(m.PrimaryRoot)
627
- if err != nil {
628
- return nil, err
629
- }
630
- if id.commonDir != m.GitCommonDir || id.branch != m.Primary.Branch {
631
- return nil, errors.New("forge: primary repository identity drifted")
632
- }
633
- manifestFiles, err := validatedManifestPaths(m.PrimaryRoot)
634
- if err != nil {
635
- return nil, err
636
- }
637
- if dirty, err := dirtyStatus(m.PrimaryRoot, false, manifestFiles); err != nil {
638
- return nil, err
639
- } else if dirty {
640
- return nil, errors.New("forge: primary index or worktree is dirty")
641
- }
642
- if id.head == winner.Commit && id.tree == winner.Tree {
643
- m.Merge = MergeState{State: "landed", Commit: winner.Commit, Tree: winner.Tree, RecordedAt: now()}
644
- winner.State = StateMerged
645
- winner.LastTransition = now()
646
- if err := save(path, m); err != nil {
647
- return nil, err
648
- }
649
- return m, nil
650
- }
651
- if id.head != m.Primary.BaseCommit || id.tree != m.Primary.BaselineTree {
652
- return nil, errors.New("forge: primary baseline changed before merge")
653
- }
654
- for i := range m.Candidates {
655
- c := &m.Candidates[i]
656
- if _, err := verifyExtracted(m, c, path); err != nil {
657
- return nil, err
658
- }
659
- if live, reason := workerLiveness(c.Worker); live != livenessDead {
660
- return nil, fmt.Errorf("forge: candidate %s preserved: %s", c.ID, reason)
661
- }
662
- }
663
- branchHead, err := gitText(m.PrimaryRoot, "rev-parse", "--verify", "refs/heads/"+winner.Branch+"^{commit}")
664
- if err != nil || branchHead != winner.Commit {
665
- return nil, errors.New("forge: winner branch no longer pins the recorded commit")
666
- }
667
- delta, err := gitBytes(m.PrimaryRoot, nil, "diff", "--binary", "--full-index", "--no-renames", winner.InitialBase, winner.Commit, "--")
668
- if err != nil || sha256Hex(delta) != winner.DeltaSHA256 {
669
- return nil, errors.New("forge: winner delta hash mismatch")
670
- }
671
- if _, err := gitBytes(m.PrimaryRoot, delta, "apply", "--check", "--index", "--binary", "--whitespace=nowarn", "-"); err != nil {
672
- return nil, fmt.Errorf("forge: merge conflict preflight failed; primary was not changed: %w", err)
673
- }
674
- m.Merge = MergeState{State: "preflight", Commit: winner.Commit, Tree: winner.Tree, RecordedAt: now()}
675
- if err := save(path, m); err != nil {
676
- return nil, err
677
- }
678
- if _, err := gitBytes(m.PrimaryRoot, nil, "merge", "--ff-only", "--no-edit", winner.Commit); err != nil {
679
- return nil, fmt.Errorf("forge: fast-forward merge failed; inspect primary before retry: %w", err)
680
- }
681
- id, err = inspectRepo(m.PrimaryRoot)
682
- if err != nil || id.head != winner.Commit || id.tree != winner.Tree {
683
- return nil, errors.New("forge: merge result did not match recorded winner")
684
- }
685
- if dirty, err := dirtyStatus(m.PrimaryRoot, false, manifestFiles); err != nil || dirty {
686
- return nil, errors.New("forge: primary is not clean after merge")
687
- }
688
- m.Merge = MergeState{State: "landed", Commit: winner.Commit, Tree: winner.Tree, RecordedAt: now()}
689
- winner.State = StateMerged
690
- winner.LastTransition = now()
691
- if err := save(path, m); err != nil {
692
- return nil, err
693
- }
694
- return m, nil
695
- }
696
-
697
- func Cleanup(root, runID string) (*Manifest, error) {
698
- m, path, err := Load(root, runID)
699
- if err != nil {
700
- return nil, err
701
- }
702
- if m.Merge.State != "landed" || m.Verification.State != "verified" {
703
- return nil, errors.New("forge: cleanup requires a landed winner and recorded successful verification")
704
- }
705
- if _, err := validatePrimary(m, true); err != nil {
706
- return nil, err
707
- }
708
- preserved := map[string]string{}
709
- for i := range m.Candidates {
710
- c := &m.Candidates[i]
711
- removed, reason := removeEligible(m, c)
712
- if reason != "" {
713
- preserved[string(c.ID)] = reason
714
- c.Preservation = reason
715
- continue
716
- }
717
- if removed {
718
- c.State = StateCleaned
719
- c.Preservation = ""
720
- c.LastTransition = now()
721
- if err := save(path, m); err != nil {
722
- return nil, err
723
- }
724
- }
725
- }
726
- state := "complete"
727
- if len(preserved) != 0 {
728
- state = "partial"
729
- }
730
- m.Cleanup = CleanupState{State: state, Preserved: preserved, RecordedAt: now()}
731
- if err := save(path, m); err != nil {
732
- return nil, err
733
- }
734
- return m, nil
735
- }
736
-
737
- func Reap(root, slug string) ([]ReapResult, error) {
738
- root, err := physicalExisting(root)
739
- if err != nil {
740
- return nil, err
741
- }
742
- if slug != "" && !safeSlug.MatchString(slug) {
743
- return nil, fmt.Errorf("forge: invalid feature slug %q", slug)
744
- }
745
- paths, err := manifestPaths(root, slug)
746
- if err != nil {
747
- return nil, err
748
- }
749
- counts := map[string]int{}
750
- for _, path := range paths {
751
- counts[filepath.Base(filepath.Dir(path))]++
752
- }
753
- loaded := make(map[string]*Manifest, len(paths))
754
- for _, path := range paths {
755
- m, loadErr := loadAt(root, path)
756
- if loadErr == nil {
757
- loaded[path] = m
758
- }
759
- }
760
- results := make([]ReapResult, 0, len(paths))
761
- for _, path := range paths {
762
- m, ok := loaded[path]
763
- if !ok {
764
- _, loadErr := loadAt(root, path)
765
- results = append(results, ReapResult{Error: loadErr.Error()})
766
- continue
767
- }
768
- if counts[m.RunID] != 1 {
769
- results = append(results, ReapResult{RunID: m.RunID, Error: "duplicate manifest; preserved"})
770
- continue
771
- }
772
- result := ReapResult{RunID: m.RunID, Preserved: map[string]string{}}
773
- changed := false
774
- for i := range m.Candidates {
775
- c := &m.Candidates[i]
776
- removed, reason := removeEligible(m, c)
777
- if reason != "" {
778
- result.Preserved[string(c.ID)] = reason
779
- if c.Preservation != reason {
780
- c.Preservation = reason
781
- c.LastTransition = now()
782
- changed = true
783
- }
784
- continue
785
- }
786
- if removed {
787
- result.Removed = append(result.Removed, c.ID)
788
- c.State = StateCleaned
789
- c.Preservation = ""
790
- c.LastTransition = now()
791
- changed = true
792
- }
793
- }
794
- if len(result.Preserved) == 0 {
795
- result.Preserved = nil
796
- }
797
- if changed {
798
- if err := save(path, m); err != nil {
799
- result.Error = err.Error()
800
- }
801
- }
802
- results = append(results, result)
803
- }
804
- return results, nil
805
- }
806
-
807
- func removeEligible(m *Manifest, c *Candidate) (bool, string) {
808
- if c.State == StateCleaned {
809
- return false, ""
810
- }
811
- if c.State != StateExtracted && c.State != StateMerged {
812
- return false, "candidate is not terminal and extracted"
813
- }
814
- if live, reason := workerLiveness(c.Worker); live != livenessDead {
815
- return false, reason
816
- }
817
- if c.Commit == "" || c.Tree == "" {
818
- return false, "candidate content is not recorded as a reachable commit"
819
- }
820
- head, err := gitText(m.PrimaryRoot, "rev-parse", "--verify", "refs/heads/"+c.Branch+"^{commit}")
821
- if err != nil || head != c.Commit {
822
- return false, "candidate branch no longer pins the recorded commit"
823
- }
824
- if _, err := gitBytes(m.PrimaryRoot, nil, "cat-file", "-e", c.Commit+"^{commit}"); err != nil {
825
- return false, "candidate commit is not reachable"
826
- }
827
- if _, err := os.Lstat(c.Worktree); errors.Is(err, os.ErrNotExist) {
828
- registered, listErr := registeredWorktrees(m.PrimaryRoot)
829
- if listErr != nil {
830
- return false, "cannot verify missing worktree registration"
831
- }
832
- if _, exists := registered[c.Worktree]; exists {
833
- return false, "worktree path is missing but remains registered"
834
- }
835
- return true, ""
836
- } else if err != nil {
837
- return false, "cannot inspect candidate worktree"
838
- }
839
- if err := validateCandidateRepo(m, c); err != nil {
840
- return false, err.Error()
841
- }
842
- if dirty, err := dirtyStatus(c.Worktree, true, nil); err != nil {
843
- return false, err.Error()
844
- } else if dirty {
845
- return false, "candidate contains tracked, untracked, or ignored dirt"
846
- }
847
- if _, err := gitBytes(m.PrimaryRoot, nil, "worktree", "remove", c.Worktree); err != nil {
848
- return false, err.Error()
849
- }
850
- if _, err := os.Lstat(c.Worktree); !errors.Is(err, os.ErrNotExist) {
851
- return false, "candidate worktree still exists after removal"
852
- }
853
- return true, ""
854
- }
855
-
856
- func preserve(path string, m *Manifest, c *Candidate, reason string) (*Manifest, error) {
857
- c.Preservation = reason
858
- c.LastTransition = now()
859
- if err := save(path, m); err != nil {
860
- return nil, err
861
- }
862
- return nil, fmt.Errorf("forge: candidate %s preserved: %s", c.ID, reason)
863
- }
864
-
865
- func rejectPrivateOrGitlinkChanges(c *Candidate) error {
866
- names, err := gitBytes(c.Worktree, nil, "diff", "--name-only", "-z", c.InitialBase, c.Commit, "--")
867
- if err != nil {
868
- return err
869
- }
870
- for _, name := range bytes.Split(names, []byte{0}) {
871
- clean := filepath.ToSlash(string(name))
872
- if clean == ".devrites" || strings.HasPrefix(clean, ".devrites/") {
873
- return errors.New("candidate changed root-owned .devrites content")
874
- }
875
- }
876
- tree, err := gitBytes(c.Worktree, nil, "ls-tree", "-r", "-z", c.Commit)
877
- if err != nil {
878
- return err
879
- }
880
- for _, entry := range bytes.Split(tree, []byte{0}) {
881
- if bytes.HasPrefix(entry, []byte("160000 ")) {
882
- return errors.New("candidate tree contains a gitlink")
883
- }
884
- }
885
- return nil
886
- }
887
-
888
- func validateStagingParent(staging string) error {
889
- parent := filepath.Dir(staging)
890
- if info, err := os.Lstat(parent); err == nil && info.Mode()&os.ModeSymlink != 0 {
891
- return fmt.Errorf("forge: staging parent is a symlink: %s", parent)
892
- } else if err != nil && !errors.Is(err, os.ErrNotExist) {
893
- return fmt.Errorf("forge: inspect staging parent: %w", err)
894
- }
895
- return nil
896
- }
897
-
898
- func validateManifestParentBeforeCreate(root, path string) error {
899
- current := root
900
- rel, err := filepath.Rel(root, filepath.Dir(path))
901
- if err != nil || rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator)) {
902
- return errors.New("forge: manifest path escapes primary root")
903
- }
904
- for _, part := range strings.Split(rel, string(filepath.Separator)) {
905
- current = filepath.Join(current, part)
906
- info, err := os.Lstat(current)
907
- if errors.Is(err, os.ErrNotExist) {
908
- return nil
909
- }
910
- if err != nil {
911
- return err
912
- }
913
- if info.Mode()&os.ModeSymlink != 0 {
914
- return fmt.Errorf("forge: manifest parent is a symlink: %s", current)
915
- }
916
- }
917
- return nil
918
- }
919
-
920
- func degraded(reason string) PlanResult {
921
- return PlanResult{Status: "degraded", Mode: "serial", Reason: strings.TrimPrefix(reason, "forge: ")}
922
- }
923
-
924
- func validSHA256(value string) bool {
925
- if len(value) != 64 {
926
- return false
927
- }
928
- _, err := hex.DecodeString(value)
929
- return err == nil
930
- }
931
-
932
- func parsePID(value string) (int, error) {
933
- pid, err := strconv.Atoi(value)
934
- if err != nil || pid <= 0 || strconv.Itoa(pid) != value {
935
- return 0, errors.New("forge: PID must be a canonical positive integer")
936
- }
937
- return pid, nil
938
- }