devrites 3.2.28 → 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 +16 -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 -1726
  526. package/engine/hooks_events_test.go +0 -431
  527. package/engine/hooks_workspace.go +0 -1196
  528. package/engine/internal/doctor/doctor.go +0 -306
  529. package/engine/internal/doctor/doctor_test.go +0 -252
  530. package/engine/internal/forge/forge.go +0 -938
  531. package/engine/internal/forge/forge_test.go +0 -576
  532. package/engine/internal/forge/git.go +0 -245
  533. package/engine/internal/forge/liveness_unix.go +0 -48
  534. package/engine/internal/forge/liveness_windows.go +0 -67
  535. package/engine/internal/forge/manifest.go +0 -402
  536. package/engine/internal/harness/compliance.go +0 -96
  537. package/engine/internal/harness/harness.go +0 -301
  538. package/engine/internal/harness/harness_test.go +0 -124
  539. package/engine/internal/iohooks/detach_other.go +0 -11
  540. package/engine/internal/iohooks/detach_unix.go +0 -11
  541. package/engine/internal/iohooks/iohooks.go +0 -839
  542. package/engine/internal/iohooks/iohooks_test.go +0 -561
  543. package/engine/internal/lib/adoption.go +0 -659
  544. package/engine/internal/lib/adoption_test.go +0 -121
  545. package/engine/internal/lib/analyze.go +0 -232
  546. package/engine/internal/lib/archivesearch.go +0 -125
  547. package/engine/internal/lib/archivesearch_test.go +0 -138
  548. package/engine/internal/lib/budget.go +0 -172
  549. package/engine/internal/lib/buildreadiness.go +0 -111
  550. package/engine/internal/lib/checkacceptance.go +0 -176
  551. package/engine/internal/lib/clarifyreturn.go +0 -91
  552. package/engine/internal/lib/clarifyreturn_test.go +0 -123
  553. package/engine/internal/lib/command_other.go +0 -7
  554. package/engine/internal/lib/command_unix.go +0 -24
  555. package/engine/internal/lib/context.go +0 -280
  556. package/engine/internal/lib/conventions.go +0 -449
  557. package/engine/internal/lib/coverage.go +0 -145
  558. package/engine/internal/lib/dispatchwaive.go +0 -31
  559. package/engine/internal/lib/dispatchwaive_test.go +0 -23
  560. package/engine/internal/lib/doubtcoverage.go +0 -78
  561. package/engine/internal/lib/extensions.go +0 -622
  562. package/engine/internal/lib/extensions_test.go +0 -305
  563. package/engine/internal/lib/footprint.go +0 -239
  564. package/engine/internal/lib/gitauthority.go +0 -601
  565. package/engine/internal/lib/gitauthority_test.go +0 -346
  566. package/engine/internal/lib/jsonout.go +0 -129
  567. package/engine/internal/lib/jsonout_test.go +0 -73
  568. package/engine/internal/lib/lanes.go +0 -112
  569. package/engine/internal/lib/learnings.go +0 -397
  570. package/engine/internal/lib/learnings_inject_test.go +0 -77
  571. package/engine/internal/lib/learnings_remediation_test.go +0 -24
  572. package/engine/internal/lib/ledger.go +0 -311
  573. package/engine/internal/lib/ledger_test.go +0 -186
  574. package/engine/internal/lib/mutationgate.go +0 -89
  575. package/engine/internal/lib/observability_test.go +0 -358
  576. package/engine/internal/lib/overrides.go +0 -164
  577. package/engine/internal/lib/overrides_test.go +0 -112
  578. package/engine/internal/lib/preamble.go +0 -159
  579. package/engine/internal/lib/preamble_questions_test.go +0 -10
  580. package/engine/internal/lib/progress.go +0 -210
  581. package/engine/internal/lib/provenance.go +0 -462
  582. package/engine/internal/lib/provenance_test.go +0 -154
  583. package/engine/internal/lib/readiness_contract.json +0 -118
  584. package/engine/internal/lib/readinessartifact.go +0 -533
  585. package/engine/internal/lib/readinessartifact_test.go +0 -422
  586. package/engine/internal/lib/reconcile.go +0 -1496
  587. package/engine/internal/lib/reconcile_test.go +0 -1071
  588. package/engine/internal/lib/recoveryattempts.go +0 -298
  589. package/engine/internal/lib/recoveryattempts_test.go +0 -215
  590. package/engine/internal/lib/reviewers.go +0 -143
  591. package/engine/internal/lib/reviewers_test.go +0 -45
  592. package/engine/internal/lib/reviewerstats.go +0 -199
  593. package/engine/internal/lib/reviewerstats_test.go +0 -104
  594. package/engine/internal/lib/reviewintegrity.go +0 -143
  595. package/engine/internal/lib/reviewintegrity_test.go +0 -103
  596. package/engine/internal/lib/runbook.go +0 -295
  597. package/engine/internal/lib/runbook_context_test.go +0 -182
  598. package/engine/internal/lib/session.go +0 -1020
  599. package/engine/internal/lib/session_test.go +0 -177
  600. package/engine/internal/lib/specparse.go +0 -125
  601. package/engine/internal/lib/specskeleton.go +0 -79
  602. package/engine/internal/lib/specvalidate.go +0 -391
  603. package/engine/internal/lib/specvalidate_test.go +0 -185
  604. package/engine/internal/lib/stuck.go +0 -206
  605. package/engine/internal/lib/templates/conventions_drift.tmpl +0 -6
  606. package/engine/internal/lib/templates/conventions_ledger_header.md +0 -6
  607. package/engine/internal/lib/templates/conventions_orient_header.txt +0 -1
  608. package/engine/internal/lib/testintegrity.go +0 -199
  609. package/engine/internal/lib/testintegrity_test.go +0 -149
  610. package/engine/internal/lib/tickafk.go +0 -86
  611. package/engine/internal/migrate/migrate.go +0 -279
  612. package/engine/internal/migrate/migrate_test.go +0 -157
  613. package/engine/internal/orient/firstrun.go +0 -50
  614. package/engine/internal/orient/firstrun_test.go +0 -72
  615. package/engine/internal/orient/orient.go +0 -69
  616. package/engine/internal/orient/orient_test.go +0 -25
  617. package/engine/internal/profile/profile.go +0 -284
  618. package/engine/internal/profile/profile_test.go +0 -13
  619. package/engine/internal/state/clarify_transition.go +0 -165
  620. package/engine/internal/state/clarify_transition_test.go +0 -130
  621. package/engine/internal/state/snapshot.go +0 -457
  622. package/engine/internal/toolpolicy/classifier.go +0 -533
  623. package/engine/internal/toolpolicy/classifier_test.go +0 -424
  624. package/engine/internal/toolpolicy/git.go +0 -616
  625. package/engine/internal/toolpolicy/scanner.go +0 -382
  626. package/engine/observability_cli_test.go +0 -52
  627. package/engine/profile_test.go +0 -76
  628. package/engine/subagent_orient_context.txt +0 -8
  629. package/engine/testdata/golden/TestParityA1Guard/devrites-edit-allowed.golden +0 -1
  630. package/engine/testdata/golden/TestParityA1Guard/no-window-silent.golden +0 -1
  631. package/engine/testdata/golden/TestParityA1Guard/non-edit-tool.golden +0 -1
  632. package/engine/testdata/golden/TestParityA1Guard/observe-mode-silent.golden +0 -1
  633. package/engine/testdata/golden/TestParityA1Guard/source-edit-enforce-denies.golden +0 -2
  634. package/engine/testdata/golden/TestParityA1Guard/subagent-allowed.golden +0 -1
  635. package/engine/testdata/golden/TestParityAnalyze/noactive.golden +0 -1
  636. package/engine/testdata/golden/TestParityAnalyze/slug=covered.golden +0 -15
  637. package/engine/testdata/golden/TestParityAnalyze/slug=dangling.golden +0 -16
  638. package/engine/testdata/golden/TestParityAnalyze/slug=ghost.golden +0 -1
  639. package/engine/testdata/golden/TestParityAnalyze/slug=noac.golden +0 -15
  640. package/engine/testdata/golden/TestParityAnalyze/slug=order.golden +0 -17
  641. package/engine/testdata/golden/TestParityAnalyze/slug=orphan.golden +0 -16
  642. package/engine/testdata/golden/TestParityAnalyze/slug=uncovered.golden +0 -16
  643. package/engine/testdata/golden/TestParityBudget/default-active.golden +0 -4
  644. package/engine/testdata/golden/TestParityBudget/extra-md.golden +0 -5
  645. package/engine/testdata/golden/TestParityBudget/no-active.golden +0 -1
  646. package/engine/testdata/golden/TestParityBudget/no-feature.golden +0 -1
  647. package/engine/testdata/golden/TestParityBudget/over-advisory.golden +0 -6
  648. package/engine/testdata/golden/TestParityBudget/over-strict.golden +0 -6
  649. package/engine/testdata/golden/TestParityBudget/within.golden +0 -6
  650. package/engine/testdata/golden/TestParityBuildReadiness/arg=approved.golden +0 -2
  651. package/engine/testdata/golden/TestParityBuildReadiness/arg=approvenone.golden +0 -1
  652. package/engine/testdata/golden/TestParityBuildReadiness/arg=await.golden +0 -1
  653. package/engine/testdata/golden/TestParityBuildReadiness/arg=blocked.golden +0 -1
  654. package/engine/testdata/golden/TestParityBuildReadiness/arg=clarifyopen.golden +0 -1
  655. package/engine/testdata/golden/TestParityBuildReadiness/arg=emptystatus.golden +0 -2
  656. package/engine/testdata/golden/TestParityBuildReadiness/arg=ghost.golden +0 -1
  657. package/engine/testdata/golden/TestParityBuildReadiness/arg=legacycontract.golden +0 -1
  658. package/engine/testdata/golden/TestParityBuildReadiness/arg=noapprove.golden +0 -1
  659. package/engine/testdata/golden/TestParityBuildReadiness/arg=noclarify.golden +0 -1
  660. package/engine/testdata/golden/TestParityBuildReadiness/arg=novet.golden +0 -1
  661. package/engine/testdata/golden/TestParityBuildReadiness/arg=stalevet.golden +0 -1
  662. package/engine/testdata/golden/TestParityBuildReadiness/arg=trailhash.golden +0 -2
  663. package/engine/testdata/golden/TestParityBuildReadiness/arg=trailpipe.golden +0 -2
  664. package/engine/testdata/golden/TestParityBuildReadiness/arg=vetnotready.golden +0 -1
  665. package/engine/testdata/golden/TestParityCheckAcceptance/arg=blank-section.golden +0 -1
  666. package/engine/testdata/golden/TestParityCheckAcceptance/arg=empty.golden +0 -1
  667. package/engine/testdata/golden/TestParityCheckAcceptance/arg=flat-dropped.golden +0 -1
  668. package/engine/testdata/golden/TestParityCheckAcceptance/arg=flat-ok.golden +0 -2
  669. package/engine/testdata/golden/TestParityCheckAcceptance/arg=flat-unchecked.golden +0 -1
  670. package/engine/testdata/golden/TestParityCheckAcceptance/arg=id-gap.golden +0 -1
  671. package/engine/testdata/golden/TestParityCheckAcceptance/arg=id-ok.golden +0 -2
  672. package/engine/testdata/golden/TestParityCheckAcceptance/arg=no-seal.golden +0 -1
  673. package/engine/testdata/golden/TestParityCheckAcceptance/arg=no-section.golden +0 -1
  674. package/engine/testdata/golden/TestParityCheckAcceptance/arg=nonexistent.golden +0 -1
  675. package/engine/testdata/golden/TestParityCheckAcceptance.golden +0 -1
  676. package/engine/testdata/golden/TestParityCoverage/arg=flat.golden +0 -7
  677. package/engine/testdata/golden/TestParityCoverage/arg=full.golden +0 -10
  678. package/engine/testdata/golden/TestParityCoverage/arg=nonexistent.golden +0 -1
  679. package/engine/testdata/golden/TestParityCoverage/arg=nospec.golden +0 -1
  680. package/engine/testdata/golden/TestParityCoverage/arg=speconly.golden +0 -9
  681. package/engine/testdata/golden/TestParityCoverage.golden +0 -1
  682. package/engine/testdata/golden/TestParityCursor/bare.golden +0 -3
  683. package/engine/testdata/golden/TestParityCursor/full-afk.golden +0 -6
  684. package/engine/testdata/golden/TestParityCursor/full-hitl.golden +0 -5
  685. package/engine/testdata/golden/TestParityCursor/no-active.golden +0 -1
  686. package/engine/testdata/golden/TestParityCursor/red.golden +0 -5
  687. package/engine/testdata/golden/TestParityCursor/zerogates.golden +0 -5
  688. package/engine/testdata/golden/TestParityDoubtCoverage/arg=doubted.golden +0 -2
  689. package/engine/testdata/golden/TestParityDoubtCoverage/arg=ghost.golden +0 -2
  690. package/engine/testdata/golden/TestParityDoubtCoverage/arg=missing.golden +0 -3
  691. package/engine/testdata/golden/TestParityDoubtCoverage/arg=nodoubt.golden +0 -4
  692. package/engine/testdata/golden/TestParityDoubtCoverage/arg=nolog.golden +0 -2
  693. package/engine/testdata/golden/TestParityDoubtCoverage/arg=nowright.golden +0 -2
  694. package/engine/testdata/golden/TestParityDoubtCoverage.golden +0 -1
  695. package/engine/testdata/golden/TestParityMutationGate/active-slug.golden +0 -3
  696. package/engine/testdata/golden/TestParityMutationGate/explicit-slug.golden +0 -3
  697. package/engine/testdata/golden/TestParityMutationGate/ghost.golden +0 -1
  698. package/engine/testdata/golden/TestParityOrientSilentPath.golden +0 -1
  699. package/engine/testdata/golden/TestParityReconcile/bad-mode.golden +0 -1
  700. package/engine/testdata/golden/TestParityReconcile/check-clean/snapshot.golden +0 -2
  701. package/engine/testdata/golden/TestParityReconcile/check-clean.golden +0 -2
  702. package/engine/testdata/golden/TestParityReconcile/check-no-base.golden +0 -1
  703. package/engine/testdata/golden/TestParityReconcile/check-no-claimed/snapshot.golden +0 -2
  704. package/engine/testdata/golden/TestParityReconcile/check-violation/snapshot.golden +0 -2
  705. package/engine/testdata/golden/TestParityReconcile/check-violation.golden +0 -1
  706. package/engine/testdata/golden/TestParityReconcile/close-window/snapshot.golden +0 -2
  707. package/engine/testdata/golden/TestParityReconcile/close-window.golden +0 -3
  708. package/engine/testdata/golden/TestParityReconcile/not-git.golden +0 -1
  709. package/engine/testdata/golden/TestParityReconcile/snapshot/snapshot.golden +0 -2
  710. package/engine/testdata/golden/TestParityReconcile/snapshot-no-allowlist.golden +0 -1
  711. package/engine/testdata/golden/TestParityReconcile/snapshot.golden +0 -2
  712. package/engine/testdata/golden/TestParityRedwatch/fail-writes-red.golden +0 -2
  713. package/engine/testdata/golden/TestParityRedwatch/non-bash-tool.golden +0 -1
  714. package/engine/testdata/golden/TestParityRedwatch/non-test-command.golden +0 -1
  715. package/engine/testdata/golden/TestParityRedwatch/pass-clears-red.golden +0 -1
  716. package/engine/testdata/golden/TestParityResolve/next-qid.golden +0 -2
  717. package/engine/testdata/golden/TestParityReviewerReadonly/agent-required-devrites-agent-denies.golden +0 -2
  718. package/engine/testdata/golden/TestParityReviewerReadonly/agent-required-non-devrites-allows.golden +0 -1
  719. package/engine/testdata/golden/TestParityReviewerReadonly/agent-required-subagent-type-only-allows.golden +0 -1
  720. package/engine/testdata/golden/TestParityReviewerReadonly/enforce-deny-git-commit.golden +0 -2
  721. package/engine/testdata/golden/TestParityReviewerReadonly/enforce-deny-mutating.golden +0 -2
  722. package/engine/testdata/golden/TestParityReviewerReadonly/non-bash-tool.golden +0 -1
  723. package/engine/testdata/golden/TestParityReviewerReadonly/non-tool-input.golden +0 -1
  724. package/engine/testdata/golden/TestParityReviewerReadonly/observe-mutating-silent.golden +0 -1
  725. package/engine/testdata/golden/TestParityReviewerReadonly/safe-bash-command.golden +0 -1
  726. package/engine/testdata/golden/TestParitySpecValidate/arg=dup.golden +0 -1
  727. package/engine/testdata/golden/TestParitySpecValidate/arg=empty.golden +0 -1
  728. package/engine/testdata/golden/TestParitySpecValidate/arg=flat.golden +0 -2
  729. package/engine/testdata/golden/TestParitySpecValidate/arg=nonexistent.golden +0 -1
  730. package/engine/testdata/golden/TestParitySpecValidate/arg=noscenario.golden +0 -1
  731. package/engine/testdata/golden/TestParitySpecValidate/arg=noshall.golden +0 -1
  732. package/engine/testdata/golden/TestParitySpecValidate/arg=nothen.golden +0 -1
  733. package/engine/testdata/golden/TestParitySpecValidate/arg=valid/spec.md.golden +0 -2
  734. package/engine/testdata/golden/TestParitySpecValidate/arg=valid.golden +0 -2
  735. package/engine/testdata/golden/TestParitySpecValidate.golden +0 -1
  736. package/engine/testdata/golden/TestParityStatusline/full-afk.golden +0 -2
  737. package/engine/testdata/golden/TestParityStatusline/full-hitl.golden +0 -2
  738. package/engine/testdata/golden/TestParityStatusline/no-active.golden +0 -1
  739. package/engine/testdata/golden/TestParityStatusline/nophase.golden +0 -2
  740. package/engine/testdata/golden/TestParityStatusline/red.golden +0 -2
  741. package/engine/testdata/golden/TestParityStuckCheck/bad-cmd.golden +0 -1
  742. package/engine/testdata/golden/TestParityStuckCheck/custom-window-2.golden +0 -2
  743. package/engine/testdata/golden/TestParityStuckCheck/dominant.golden +0 -2
  744. package/engine/testdata/golden/TestParityStuckCheck/few.golden +0 -2
  745. package/engine/testdata/golden/TestParityStuckCheck/ghost.golden +0 -2
  746. package/engine/testdata/golden/TestParityStuckCheck/identical.golden +0 -2
  747. package/engine/testdata/golden/TestParityStuckCheck/no-cmd.golden +0 -1
  748. package/engine/testdata/golden/TestParityStuckCheck/no-slug.golden +0 -1
  749. package/engine/testdata/golden/TestParityStuckCheck/nolog.golden +0 -2
  750. package/engine/testdata/golden/TestParityStuckCheck/pingpong.golden +0 -2
  751. package/engine/testdata/golden/TestParityStuckCheck/varied.golden +0 -2
  752. package/engine/testdata/golden/TestParityStuckCheck/window-04-identical.golden +0 -2
  753. package/engine/testdata/golden/TestParityStuckCheck/window-2.5-varied4.golden +0 -2
  754. package/engine/testdata/golden/TestParityStuckCheck/window-4x-varied4.golden +0 -2
  755. package/engine/testdata/golden/TestParityStuckCheck/window-leadspace-varied4.golden +0 -2
  756. package/engine/testdata/golden/TestParityStuckCheck/window-plus4-identical.golden +0 -2
  757. package/engine/testdata/golden/TestParitySubagentOrient/devrites-agent-subagent-type-key.golden +0 -2
  758. package/engine/testdata/golden/TestParitySubagentOrient/devrites-agent.golden +0 -2
  759. package/engine/testdata/golden/TestParitySubagentOrient/garbage-input.golden +0 -1
  760. package/engine/testdata/golden/TestParitySubagentOrient/non-devrites-agent.golden +0 -1
  761. package/engine/testdata/golden/TestParityTestIntegrity/assertion-dropped.golden +0 -1
  762. package/engine/testdata/golden/TestParityTestIntegrity/clean.golden +0 -2
  763. package/engine/testdata/golden/TestParityTestIntegrity/deleted.golden +0 -1
  764. package/engine/testdata/golden/TestParityTestIntegrity/ghost-workspace.golden +0 -1
  765. package/engine/testdata/golden/TestParityTestIntegrity/not-git.golden +0 -1
  766. package/engine/testdata/golden/TestParityTestIntegrity/skip-added.golden +0 -1
  767. package/engine/testdata/golden/TestParityTickAfk/budget1/state.md.golden +0 -1
  768. package/engine/testdata/golden/TestParityTickAfk/budget1.golden +0 -2
  769. package/engine/testdata/golden/TestParityTickAfk/budget3/state.md.golden +0 -5
  770. package/engine/testdata/golden/TestParityTickAfk/budget3.golden +0 -2
  771. package/engine/testdata/golden/TestParityTickAfk/bulletPipe/state.md.golden +0 -1
  772. package/engine/testdata/golden/TestParityTickAfk/bulletPipe.golden +0 -2
  773. package/engine/testdata/golden/TestParityTickAfk/missingField/state.md.golden +0 -3
  774. package/engine/testdata/golden/TestParityTickAfk/missingField.golden +0 -2
  775. package/engine/testdata/golden/TestParityTickAfk/missingFile.golden +0 -1
  776. package/engine/testdata/golden/TestParityTickAfk/nonNumeric/state.md.golden +0 -1
  777. package/engine/testdata/golden/TestParityTickAfk/nonNumeric.golden +0 -1
  778. package/engine/testdata/golden/TestParityTickAfk/none/state.md.golden +0 -1
  779. package/engine/testdata/golden/TestParityTickAfk/none.golden +0 -2
  780. package/engine/testdata/golden/TestParityWrightScope/agent-required-non-wright.golden +0 -1
  781. package/engine/testdata/golden/TestParityWrightScope/devrites-edit-denied.golden +0 -2
  782. package/engine/testdata/golden/TestParityWrightScope/in-scope-allowed.golden +0 -1
  783. package/engine/testdata/golden/TestParityWrightScope/non-edit-tool.golden +0 -1
  784. package/engine/testdata/golden/TestParityWrightScope/out-of-scope-enforce-denies.golden +0 -2
  785. package/engine/testdata/golden/TestParityWrightScope/out-of-scope-observe-silent.golden +0 -1
  786. package/engine/testdata/golden/TestSpecSkeleton/missing-some.golden +0 -2
  787. package/engine/testdata/golden/TestSpecSkeleton/present-all.golden +0 -2
  788. package/engine/testdata/golden/TestStuckLogHashParity.golden +0 -1
  789. package/engine/tests/adr_0006_clock_seam_test.go +0 -36
  790. package/engine/tests/budget_test.go +0 -88
  791. package/engine/tests/canonical_ac_ids_test.go +0 -44
  792. package/engine/tests/concurrency_cli_test.go +0 -131
  793. package/engine/tests/conventions_test.go +0 -106
  794. package/engine/tests/doctor_cli_test.go +0 -223
  795. package/engine/tests/forge_cli_test.go +0 -463
  796. package/engine/tests/hook_test.go +0 -2778
  797. package/engine/tests/hooks_io_test.go +0 -309
  798. package/engine/tests/json_contract_test.go +0 -224
  799. package/engine/tests/lib_parity_test.go +0 -930
  800. package/engine/tests/migrate_cli_test.go +0 -195
  801. package/engine/tests/parity_analyze_test.go +0 -55
  802. package/engine/tests/parity_buildreadiness_test.go +0 -199
  803. package/engine/tests/parity_learnings_test.go +0 -89
  804. package/engine/tests/parity_mutationgate_test.go +0 -36
  805. package/engine/tests/parity_reconcile_test.go +0 -94
  806. package/engine/tests/parity_testintegrity_test.go +0 -65
  807. package/engine/tests/parity_tickafk_test.go +0 -83
  808. package/engine/validatepack.go +0 -192
  809. package/engine/validatepack_test.go +0 -79
  810. package/engine/validatepackskills.go +0 -181
  811. package/engine/validatepackskills_test.go +0 -171
  812. package/pack/.claude/agents/devrites-forge-judge.md +0 -118
  813. package/pack/.claude/skills/devrites-lib/reference/model-tiers.md +0 -44
  814. package/pack/.claude/skills/devrites-refresh-indexes/SKILL.md +0 -52
  815. package/pack/.claude/skills/rite-build/reference/evidence-standard.md +0 -45
  816. package/pack/.claude/skills/rite-build/reference/forge.md +0 -210
  817. package/pack/.claude/skills/rite-seal/reference/conventions-ledger.md +0 -60
  818. package/pack/.claude/skills/rite-ship/reference/adr-promotion.md +0 -9
  819. package/pack/.claude/skills/rite-ship/reference/ledger.md +0 -56
  820. package/pack/generated/claude/agents/devrites-forge-judge.md +0 -118
  821. package/pack/generated/claude/skills/devrites-lib/reference/model-tiers.md +0 -44
  822. package/pack/generated/claude/skills/devrites-refresh-indexes/SKILL.md +0 -52
  823. package/pack/generated/claude/skills/rite-build/reference/evidence-standard.md +0 -45
  824. package/pack/generated/claude/skills/rite-build/reference/forge.md +0 -210
  825. package/pack/generated/claude/skills/rite-seal/reference/conventions-ledger.md +0 -60
  826. package/pack/generated/claude/skills/rite-ship/reference/adr-promotion.md +0 -9
  827. package/pack/generated/claude/skills/rite-ship/reference/ledger.md +0 -56
  828. package/pack/generated/codex/agents/devrites-forge-judge.toml +0 -128
  829. package/pack/generated/codex/hooks.json +0 -185
  830. package/pack/generated/codex/skills/devrites-api-interface/agents/openai.yaml +0 -2
  831. package/pack/generated/codex/skills/devrites-audit/agents/openai.yaml +0 -2
  832. package/pack/generated/codex/skills/devrites-browser-proof/agents/openai.yaml +0 -2
  833. package/pack/generated/codex/skills/devrites-debug-recovery/agents/openai.yaml +0 -2
  834. package/pack/generated/codex/skills/devrites-doubt/agents/openai.yaml +0 -2
  835. package/pack/generated/codex/skills/devrites-frontend-craft/agents/openai.yaml +0 -2
  836. package/pack/generated/codex/skills/devrites-interview/agents/openai.yaml +0 -2
  837. package/pack/generated/codex/skills/devrites-lib/reference/model-tiers.md +0 -44
  838. package/pack/generated/codex/skills/devrites-prose-craft/agents/openai.yaml +0 -2
  839. package/pack/generated/codex/skills/devrites-refresh-indexes/SKILL.md +0 -71
  840. package/pack/generated/codex/skills/devrites-refresh-indexes/agents/openai.yaml +0 -2
  841. package/pack/generated/codex/skills/devrites-source-driven/agents/openai.yaml +0 -2
  842. package/pack/generated/codex/skills/devrites-ux-shape/agents/openai.yaml +0 -2
  843. package/pack/generated/codex/skills/rite-build/reference/evidence-standard.md +0 -45
  844. package/pack/generated/codex/skills/rite-build/reference/forge.md +0 -210
  845. package/pack/generated/codex/skills/rite-seal/reference/conventions-ledger.md +0 -60
  846. package/pack/generated/codex/skills/rite-ship/reference/adr-promotion.md +0 -9
  847. package/pack/generated/codex/skills/rite-ship/reference/ledger.md +0 -56
  848. package/scripts/build-binaries.sh +0 -75
  849. package/scripts/build-release-tarball.sh +0 -105
  850. package/scripts/check-authority-drift.py +0 -125
  851. package/scripts/check-cross-refs.py +0 -139
  852. package/scripts/check-generated-skill-budget.mjs +0 -42
  853. package/scripts/check-instruction-size-baseline.mjs +0 -88
  854. package/scripts/check-invocation-integrity.py +0 -115
  855. package/scripts/check-no-global-writes.sh +0 -66
  856. package/scripts/check-no-personal-paths.py +0 -50
  857. package/scripts/check-npm-audit.mjs +0 -110
  858. package/scripts/check-reference-governance.mjs +0 -83
  859. package/scripts/check-reply-contract.sh +0 -64
  860. package/scripts/check-rule-uniqueness.sh +0 -45
  861. package/scripts/devrites-detect.sh +0 -176
  862. package/scripts/grade-feature.sh +0 -204
  863. package/scripts/live-hosts/agent-result.schema.json +0 -231
  864. package/scripts/live-hosts/claude.sh +0 -87
  865. package/scripts/live-hosts/codex.sh +0 -85
  866. package/scripts/live-hosts/common.sh +0 -113
  867. package/scripts/live-hosts/fake-host.py +0 -257
  868. package/scripts/live-hosts/host-transport.py +0 -286
  869. package/scripts/npm-audit-exceptions.json +0 -26
  870. package/scripts/pin.sh +0 -249
  871. package/scripts/release-check.sh +0 -75
  872. package/scripts/run-agent-contract-evals.py +0 -1380
  873. package/scripts/run-behavioral-evals.sh +0 -196
  874. package/scripts/run-evals.sh +0 -132
  875. package/scripts/run-live-behavioral-evals.py +0 -1310
  876. package/scripts/run-outcome-evals.sh +0 -454
  877. package/scripts/run-routing-evals.py +0 -342
  878. package/scripts/run-tests.mjs +0 -232
  879. package/scripts/scan-pack-security.py +0 -209
  880. package/scripts/scan-supply-chain-iocs.py +0 -127
  881. package/scripts/skill-pruning-audit.mjs +0 -121
  882. package/scripts/skills-inventory.mjs +0 -125
  883. package/scripts/supply-chain-iocs.json +0 -11
  884. package/scripts/sync-version.sh +0 -54
  885. package/scripts/validate-agent-composition.py +0 -57
  886. package/scripts/validate-command-parity.py +0 -70
  887. package/scripts/validate-frontmatter.py +0 -218
  888. package/scripts/validate-skill-anatomy.py +0 -139
  889. package/scripts/validate-workflow-security.py +0 -184
  890. package/scripts/validate-workspace-schema.py +0 -800
  891. package/scripts/validate.sh +0 -354
  892. package/scripts/workflow_schema.py +0 -69
  893. /package/engine/testdata/fixtures/basic/devrites-root/{features → work}/auth-tokens/decisions.md +0 -0
  894. /package/engine/testdata/fixtures/basic/devrites-root/{features → work}/auth-tokens/plan.md +0 -0
  895. /package/engine/testdata/fixtures/basic/devrites-root/{features → work}/auth-tokens/spec.md +0 -0
  896. /package/engine/testdata/fixtures/basic/devrites-root/{features → work}/auth-tokens/tasks.md +0 -0
  897. /package/engine/testdata/fixtures/basic/devrites-root/{features → work}/search-ranking/spec.md +0 -0
@@ -1,800 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Validate generated DevRites workspace artifacts against the Markdown contract.
3
-
4
- The validator uses only the standard library, so it does not add a runtime
5
- parser dependency.
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- import argparse
11
- import hashlib
12
- import json
13
- import re
14
- import sys
15
- from pathlib import Path
16
-
17
- from workflow_schema import PHASES, cursor_field
18
-
19
-
20
- READINESS_CONTRACT_PATH = (
21
- Path(__file__).resolve().parents[1]
22
- / "engine"
23
- / "internal"
24
- / "lib"
25
- / "readiness_contract.json"
26
- )
27
- READINESS_CONTRACT = json.loads(READINESS_CONTRACT_PATH.read_text(encoding="utf-8"))
28
- READINESS_PLACEHOLDER_RE = re.compile(
29
- r"<[^>\n]+>|\b(?:TODO|TBD|FIXME|UNKNOWN)\b", re.IGNORECASE
30
- )
31
- READINESS_DIGEST_RE = re.compile(r"^[0-9a-f]{64}$")
32
- READINESS_AC_RE = re.compile(r"\bAC-?\d+\b", re.IGNORECASE)
33
-
34
-
35
- ID_PATTERNS = {
36
- "AC": re.compile(r"\bAC-\d{3}\b"),
37
- "REQ": re.compile(r"\bREQ-\d{3}\b"),
38
- "SLICE": re.compile(r"\bSLICE-\d{3}\b"),
39
- "DEC": re.compile(r"\bDEC-\d{3}\b"),
40
- "Q": re.compile(r"\bQ-\d{3}\b"),
41
- "DRIFT": re.compile(r"\bDRIFT-\d{3}\b"),
42
- "EVID": re.compile(r"\bEVID-\d{3}\b"),
43
- }
44
-
45
- LEGACY_AC_RE = re.compile(r"\bAC\d+\b")
46
- LEGACY_SLICE_RE = re.compile(r"\bSlice\s+\d+\b", re.IGNORECASE)
47
- MD_LINK_RE = re.compile(r"(?<!!)\[[^\]]+\]\(([^)]+)\)")
48
- MERMAID_STARTS = (
49
- "graph ",
50
- "flowchart ",
51
- "sequenceDiagram",
52
- "stateDiagram",
53
- "stateDiagram-v2",
54
- "classDiagram",
55
- "erDiagram",
56
- "journey",
57
- "gantt",
58
- "timeline",
59
- "mindmap",
60
- "quadrantChart",
61
- )
62
-
63
- HIGH_TRAFFIC_BUDGETS = {
64
- "README.md": 120,
65
- "index.md": 120,
66
- "feature.md": 120,
67
- "brief.md": 80,
68
- "spec.md": 260,
69
- "decision-coverage.md": 200,
70
- "ai-spec.md": 160,
71
- "plan.md": 220,
72
- "tasks.md": 280,
73
- "traceability.md": 220,
74
- "eng-review.md": 240,
75
- "test-plan.md": 260,
76
- "state.md": 120,
77
- "handoff.md": 120,
78
- "evidence.md": 280,
79
- "proof.md": 280,
80
- "browser-evidence.md": 220,
81
- }
82
-
83
- REQUIRED_HEADINGS = {
84
- "README.md": ["Artifact map", "Read next", "Blocking gates"],
85
- "index.md": ["Artifact map", "Read next", "Blocking gates"],
86
- "brief.md": ["Objective", "Non-goals", "Success definition"],
87
- "spec.md": [
88
- "Problem",
89
- "Goal",
90
- "Non-goals",
91
- "Users / actors",
92
- "Requirements",
93
- "Acceptance criteria",
94
- "Edge Coverage",
95
- "Prohibitions (must-NOT)",
96
- "Edge cases",
97
- "Measurable success",
98
- "Scope boundaries",
99
- ],
100
- "decision-coverage.md": [
101
- "Topology",
102
- "Coverage matrix",
103
- "Assumption audit",
104
- "Residual uncertainty",
105
- "Readiness verdict",
106
- ],
107
- "architecture.md": [
108
- "Owning module / layer",
109
- "Integration points",
110
- "Data / API / events",
111
- "Dependencies",
112
- "Risks",
113
- "Affected boundaries",
114
- ],
115
- "plan.md": ["Approach", "Slice strategy", "Validation strategy", "Rollback"],
116
- "tasks.md": ["Slice index"],
117
- "traceability.md": ["Coverage matrix"],
118
- "state.md": ["Cursor"],
119
- "decisions.md": ["Decision log"],
120
- "assumptions.md": ["Assumption register"],
121
- "questions.md": ["Question register"],
122
- "evidence.md": ["Evidence log"],
123
- "proof.md": ["Evidence log"],
124
- "drift.md": ["Drift register"],
125
- "touched-files.md": ["Touched files"],
126
- "design-brief.md": ["Design direction", "States", "Interaction model"],
127
- "browser-evidence.md": ["Browser evidence", "Visual Verdict"],
128
- "handoff.md": ["Resume", "Read next", "Next action"],
129
- "references.md": ["Reference index"],
130
- }
131
-
132
- WORKSPACE_MAP_FIELDS = ("phase", "status", "next_action", "last_updated")
133
- SLICE_REQUIRED_FIELDS = (
134
- "Goal",
135
- "Satisfies",
136
- "Forge",
137
- "Forge strategies",
138
- "Forge scorecard",
139
- "Files likely touched",
140
- "Tests/proof",
141
- "Mode",
142
- "Gate",
143
- "Dependencies",
144
- "Done condition",
145
- )
146
-
147
- def read(path: Path) -> str:
148
- return path.read_text(encoding="utf-8")
149
-
150
-
151
- def headings(text: str) -> set[str]:
152
- found = set()
153
- for line in text.splitlines():
154
- m = re.match(r"^#{1,6}\s+(.+?)\s*#*\s*$", line)
155
- if m:
156
- found.add(m.group(1).strip())
157
- return found
158
-
159
-
160
- def line_count(text: str) -> int:
161
- return len(text.splitlines())
162
-
163
-
164
- def has_budget_override(text: str) -> bool:
165
- return re.search(r"(?im)^Budget override:\s*\S", text) is not None
166
-
167
-
168
- def phase_for(workspace: Path) -> str:
169
- for name in ("state.md", "status.md", "README.md", "index.md", "feature.md"):
170
- p = workspace / name
171
- value = cursor_field(p, "phase")
172
- if value:
173
- return value.split()[0].lower()
174
- return "spec"
175
-
176
-
177
- def workspace_index_present(workspace: Path) -> bool:
178
- return any((workspace / name).is_file() for name in ("README.md", "index.md", "feature.md"))
179
-
180
-
181
- def evidence_file(workspace: Path) -> Path | None:
182
- for name in ("evidence.md", "proof.md"):
183
- p = workspace / name
184
- if p.is_file():
185
- return p
186
- return None
187
-
188
-
189
- def existing_or_alias(workspace: Path, name: str) -> bool:
190
- if (workspace / name).is_file():
191
- return True
192
- if name == "evidence.md" and (workspace / "proof.md").is_file():
193
- return True
194
- if name == "proof.md" and (workspace / "evidence.md").is_file():
195
- return True
196
- if name == "README.md" and workspace_index_present(workspace):
197
- return True
198
- return False
199
-
200
-
201
- def find_local_workspaces(root: Path) -> list[Path]:
202
- # Detect workspaces by DevRites artifacts, not README.md. Most repository
203
- # roots have a README, which would misclassify the root and stop the
204
- # .devrites/work scan before it starts.
205
- if root.is_dir() and any((root / name).exists() for name in ("spec.md", "state.md", "feature.md")):
206
- return [root]
207
- out: list[Path] = []
208
- for base in (
209
- root / ".devrites" / "work",
210
- root / ".devrites" / "features",
211
- root / ".devrites" / "archive",
212
- root / "work",
213
- root / "features",
214
- root / "archive",
215
- ):
216
- if not base.is_dir():
217
- continue
218
- for child in sorted(base.iterdir()):
219
- if child.is_dir() and any((child / n).exists() for n in ("spec.md", "state.md", "feature.md")):
220
- out.append(child)
221
- return out
222
-
223
-
224
- def local_link_target(workspace: Path, raw: str) -> Path | None:
225
- target = raw.split("#", 1)[0].strip()
226
- if not target or re.match(r"^[a-z][a-z0-9+.-]*:", target, re.I):
227
- return None
228
- if target.startswith("#"):
229
- return None
230
- return (workspace / target).resolve()
231
-
232
-
233
- def validate_mermaid(path: Path, text: str, errors: list[str]) -> None:
234
- in_block = False
235
- first = ""
236
- start_line = 0
237
- for i, line in enumerate(text.splitlines(), 1):
238
- if line.strip() == "```mermaid" and not in_block:
239
- in_block = True
240
- first = ""
241
- start_line = i
242
- continue
243
- if in_block and line.startswith("```"):
244
- if not first:
245
- errors.append(f"{path}: mermaid block at line {start_line} is empty")
246
- elif not first.startswith(MERMAID_STARTS):
247
- errors.append(f"{path}: mermaid block at line {start_line} starts with unsupported syntax: {first!r}")
248
- in_block = False
249
- continue
250
- if in_block and not first and line.strip():
251
- first = line.strip()
252
- if in_block:
253
- errors.append(f"{path}: mermaid block at line {start_line} is not closed")
254
-
255
-
256
- def mermaid_block_starts(text: str) -> list[int]:
257
- return [i for i, line in enumerate(text.splitlines(), 1) if line.strip() == "```mermaid"]
258
-
259
-
260
- def table_rows(text: str) -> list[str]:
261
- return [line for line in text.splitlines() if line.strip().startswith("|") and not re.match(r"^\s*\|?\s*:?-{2,}", line)]
262
-
263
-
264
- def validate_workspace_map(path: Path, text: str, errors: list[str]) -> None:
265
- for field in WORKSPACE_MAP_FIELDS:
266
- if not re.search(rf"(?im)^\s*{re.escape(field)}\s*:\s*\S+", text):
267
- errors.append(f"{path}: missing workspace map field '{field}:'")
268
-
269
-
270
- def validate_flows(path: Path, text: str, errors: list[str]) -> None:
271
- for line_no in mermaid_block_starts(text):
272
- before = "\n".join(text.splitlines()[max(0, line_no - 6):line_no - 1])
273
- if not re.search(r"(?i)why this matters\s*:", before):
274
- errors.append(f"{path}: mermaid block at line {line_no} needs a preceding 'Why this matters:' sentence")
275
- if not re.search(r"\b(AC|REQ|SLICE|DEC|DRIFT)-\d{3}\b", before):
276
- errors.append(f"{path}: mermaid block at line {line_no} needs related stable IDs near the why-it-matters text")
277
-
278
-
279
- def validate_tasks(path: Path, text: str, errors: list[str]) -> None:
280
- chunks = re.split(r"(?m)^##\s+(SLICE-\d{3}[^\n]*)\n", text)
281
- for i in range(1, len(chunks), 2):
282
- heading = chunks[i]
283
- body = chunks[i + 1]
284
- slice_id = ID_PATTERNS["SLICE"].search(heading).group(0)
285
- for field in SLICE_REQUIRED_FIELDS:
286
- if not re.search(rf"(?im)^{re.escape(field)}\s*:\s*\S+", body):
287
- errors.append(f"{path}: {slice_id} missing field '{field}:'")
288
-
289
- def field(name: str) -> str:
290
- match = re.search(rf"(?im)^{re.escape(name)}\s*:\s*(.+?)\s*$", body)
291
- return match.group(1).strip() if match else ""
292
-
293
- forge = field("Forge")
294
- strategies = field("Forge strategies")
295
- scorecard = field("Forge scorecard")
296
- if not forge:
297
- continue
298
- if re.fullmatch(r"(?i)no", forge):
299
- if strategies.lower() != "none" or scorecard.lower() != "none":
300
- errors.append(
301
- f"{path}: {slice_id} Forge:no requires strategies and scorecard 'none'"
302
- )
303
- continue
304
- if not re.fullmatch(r"(?i)yes\s+[—-]\s+\S.*", forge):
305
- errors.append(f"{path}: {slice_id} Forge must be 'no' or 'yes — <reason>'")
306
- continue
307
-
308
- parsed: list[tuple[str, str]] = []
309
- for part in strategies.split("|"):
310
- match = re.fullmatch(r"\s*([ABC])\s*=\s*(\S.*?)\s*", part)
311
- if not match:
312
- parsed = []
313
- break
314
- parsed.append((match.group(1), " ".join(match.group(2).split())))
315
- ids = [item[0] for item in parsed]
316
- descriptions = [item[1].casefold() for item in parsed]
317
- if ids not in (["A", "B"], ["A", "B", "C"]) or len(set(descriptions)) != len(
318
- descriptions
319
- ):
320
- errors.append(
321
- f"{path}: {slice_id} Forge strategies must be 2-3 distinct contiguous A-C entries"
322
- )
323
-
324
- acceptance = re.search(r"(?i)\bacceptance\s*=\s*[^;\n]*", scorecard)
325
- satisfies_ids = set(ID_PATTERNS["AC"].findall(field("Satisfies")))
326
- scorecard_ids = set(ID_PATTERNS["AC"].findall(acceptance.group(0))) if acceptance else set()
327
- test_plan = re.search(
328
- r"(?i)\btest-plan\s*=\s*(?=\S)(?!none\b).*test-plan\.md", scorecard
329
- )
330
- if (
331
- not satisfies_ids
332
- or not satisfies_ids.issubset(scorecard_ids)
333
- or not test_plan
334
- ):
335
- errors.append(
336
- f"{path}: {slice_id} Forge scorecard must bind every Satisfies AC ID and exact test-plan.md rows or commands"
337
- )
338
-
339
-
340
- def validate_id_register(path: Path, text: str, kind: str, errors: list[str]) -> None:
341
- if text and not ID_PATTERNS[kind].search(text):
342
- errors.append(f"{path}: no {kind}-### IDs found")
343
-
344
-
345
- def validate_evidence_entries(path: Path, text: str, errors: list[str]) -> None:
346
- for line in text.splitlines():
347
- evids = ID_PATTERNS["EVID"].findall(line)
348
- if not evids:
349
- continue
350
- if not ID_PATTERNS["AC"].search(line):
351
- errors.append(f"{path}: {evids[0]} missing related AC-### on the same entry")
352
- if not ID_PATTERNS["SLICE"].search(line):
353
- errors.append(f"{path}: {evids[0]} missing related SLICE-### on the same entry")
354
-
355
-
356
- def completed_slices(tasks: str) -> set[str]:
357
- done = set()
358
- current = ""
359
- for line in tasks.splitlines():
360
- ids = ID_PATTERNS["SLICE"].findall(line)
361
- if ids and re.match(r"^#{2,6}\s+", line):
362
- current = ids[0]
363
- if current and re.search(r"(?i)\b(status|done)\s*:\s*(built|done|complete|completed)\b", line):
364
- done.add(current)
365
- if ids and re.search(r"(?i)\b(built|done|complete|completed)\b", line):
366
- done.update(ids)
367
- if re.match(r"^\s*-\s*\[[xX]\]", line) and ids:
368
- done.update(ids)
369
- return done
370
-
371
-
372
- def blocking_questions(questions: str) -> list[str]:
373
- out = []
374
- chunks = re.split(r"(?m)^##\s+", questions)
375
- for chunk in chunks:
376
- if not chunk.strip():
377
- continue
378
- qid = (ID_PATTERNS["Q"].search(chunk) or re.search(r"\bq-\d{4}-\d{2}-\d{2}-\d{3}\b", chunk))
379
- status = re.search(r"(?im)^status:\s*(\w+)", chunk)
380
- gate = re.search(r"(?im)^gate:\s*(\w+)", chunk)
381
- if status and status.group(1).lower() == "open" and gate and gate.group(1).lower() in {"blocking", "validating", "escalating"}:
382
- out.append(qid.group(0) if qid else "<unknown>")
383
-
384
- status_index = gate_index = qid_index = -1
385
- for raw in questions.splitlines():
386
- line = raw.strip()
387
- if not (line.startswith("|") and line.endswith("|")):
388
- status_index = gate_index = qid_index = -1
389
- continue
390
- cells = [cell.strip() for cell in line[1:-1].split("|")]
391
- lowered = [cell.lower() for cell in cells]
392
- if status_index < 0:
393
- status_index = lowered.index("status") if "status" in lowered else -1
394
- gate_index = lowered.index("gate") if "gate" in lowered else -1
395
- for label in ("question id", "question", "id"):
396
- if label in lowered:
397
- qid_index = lowered.index(label)
398
- break
399
- if status_index < 0 or gate_index < 0:
400
- status_index = gate_index = qid_index = -1
401
- continue
402
- if status_index >= len(cells) or gate_index >= len(cells):
403
- continue
404
- if cells[status_index].lower() != "open" or cells[gate_index].lower() not in {
405
- "blocking",
406
- "validating",
407
- "escalating",
408
- }:
409
- continue
410
- qid = cells[qid_index] if 0 <= qid_index < len(cells) else "<unknown>"
411
- out.append(qid or "<unknown>")
412
- return list(dict.fromkeys(out))
413
-
414
-
415
- def readiness_digest(workspace: Path, names: list[str]) -> str:
416
- digest = hashlib.sha256()
417
- for name in names:
418
- path = workspace / name
419
- data = path.read_bytes()
420
- if not data.strip():
421
- raise ValueError(f"{name} is empty")
422
- digest.update(name.encode())
423
- digest.update(b"\0")
424
- digest.update(str(len(data)).encode())
425
- digest.update(b"\0")
426
- digest.update(data)
427
- digest.update(b"\0")
428
- return digest.hexdigest()
429
-
430
-
431
- def cursor_values(text: str, key: str) -> list[str]:
432
- want = key.strip().lower().replace("_", " ")
433
- values: list[str] = []
434
- for raw in text.splitlines():
435
- line = raw.strip()
436
- if line.startswith("|") and line.endswith("|"):
437
- cells = [cell.strip() for cell in line[1:-1].split("|")]
438
- if len(cells) >= 2 and cells[0].lower().replace("_", " ") == want:
439
- values.append(cells[1])
440
- continue
441
- line = line.lstrip("-*+ \t")
442
- if ":" not in line:
443
- continue
444
- found, value = line.split(":", 1)
445
- if found.strip().lower().replace("_", " ") == want:
446
- values.append(value.strip())
447
- return values
448
-
449
-
450
- def markdown_section(text: str, wanted: str) -> str | None:
451
- lines = text.splitlines()
452
- start = -1
453
- level = 0
454
- for index, line in enumerate(lines):
455
- match = re.match(r"^(#{1,6})\s+(.+?)\s*#*\s*$", line.strip())
456
- if not match:
457
- continue
458
- if start < 0:
459
- if match.group(2).strip().lower() == wanted.lower():
460
- start = index + 1
461
- level = len(match.group(1))
462
- continue
463
- if len(match.group(1)) <= level:
464
- return "\n".join(lines[start:index])
465
- return "\n".join(lines[start:]) if start >= 0 else None
466
-
467
-
468
- def markdown_table(text: str, heading: str) -> list[list[str]]:
469
- section = markdown_section(text, heading)
470
- if section is None:
471
- return []
472
- rows: list[list[str]] = []
473
- header_seen = False
474
- for raw in section.splitlines():
475
- line = raw.strip()
476
- if not (line.startswith("|") and line.endswith("|")):
477
- continue
478
- cells = [cell.strip() for cell in line[1:-1].split("|")]
479
- if all(not cell.strip(" :-") for cell in cells):
480
- continue
481
- if not header_seen:
482
- header_seen = True
483
- continue
484
- rows.append(cells)
485
- return rows
486
-
487
-
488
- def empty_or_na(value: str) -> bool:
489
- return value.strip().lower() in {"", "-", "n/a", "none"}
490
-
491
-
492
- def substantive_cells(row: list[str], *indexes: int) -> bool:
493
- return all(index < len(row) and not empty_or_na(row[index]) for index in indexes)
494
-
495
-
496
- def none_row(value: str) -> bool:
497
- return value.strip().lower() in {
498
- "none",
499
- "no material assumptions",
500
- "no residual uncertainty",
501
- }
502
-
503
-
504
- def validate_readiness_base(
505
- workspace: Path, contract: dict[str, object], errors: list[str]
506
- ) -> str | None:
507
- path = workspace / str(contract["artifact"])
508
- if not path.exists():
509
- errors.append(f"{path}: missing readiness artifact")
510
- return None
511
- text = read(path)
512
- if not text.strip():
513
- errors.append(f"{path}: empty readiness artifact")
514
- return None
515
- if READINESS_PLACEHOLDER_RE.search(text):
516
- errors.append(f"{path}: contains an unresolved placeholder")
517
- for heading in contract.get("requiredHeadings", []):
518
- if markdown_section(text, str(heading)) is None:
519
- errors.append(f"{path}: missing heading '{heading}'")
520
- for heading in contract.get("requiredTables", []):
521
- if not markdown_table(text, str(heading)):
522
- errors.append(f"{path}: heading '{heading}' has no table data rows")
523
-
524
- verdicts = cursor_values(text, str(contract["verdictField"]))
525
- if len(verdicts) != 1 or verdicts[0].upper() != str(contract["readyValue"]).upper():
526
- errors.append(
527
- f"{path}: must contain exactly one "
528
- f"{contract['verdictField']}: {contract['readyValue']}"
529
- )
530
- digests = cursor_values(text, str(contract["digestField"]))
531
- if len(digests) != 1 or not READINESS_DIGEST_RE.fullmatch(digests[0].lower()):
532
- errors.append(f"{path}: must contain exactly one valid {contract['digestField']}")
533
- else:
534
- try:
535
- expected = readiness_digest(workspace, list(contract["inputs"]))
536
- except (OSError, ValueError) as exc:
537
- errors.append(f"{path}: cannot compute readiness digest: {exc}")
538
- else:
539
- if digests[0].lower() != expected:
540
- errors.append(f"{path}: input digest is stale")
541
- return text
542
-
543
-
544
- def validate_decision_coverage(workspace: Path, errors: list[str]) -> None:
545
- contract = READINESS_CONTRACT["coverage"]
546
- text = validate_readiness_base(workspace, contract, errors)
547
- if text is None:
548
- return
549
- path = workspace / "decision-coverage.md"
550
- for index, row in enumerate(markdown_table(text, "Topology"), 1):
551
- if len(row) < 4 or not substantive_cells(row, 0, 1, 3):
552
- errors.append(f"{path}: topology row {index} is not evidence-backed")
553
- rows = markdown_table(text, "Coverage matrix")
554
- allowed = {"closed", "agent-owned", "not-applicable", "deferred-nonblocking"}
555
- for index, row in enumerate(rows, 1):
556
- if len(row) < 6:
557
- errors.append(f"{path}: coverage row {index} has fewer than 6 cells")
558
- continue
559
- status = row[2].strip().lower()
560
- if not substantive_cells(row, 0, 1, 5):
561
- errors.append(f"{path}: coverage row {index} is incomplete")
562
- if status not in allowed:
563
- errors.append(
564
- f"{path}: coverage row {index} has unresolved status {row[2]!r}"
565
- )
566
- if status == "closed" and not substantive_cells(row, 3):
567
- errors.append(f"{path}: coverage row {index} is closed without a canonical reference")
568
- if status in {"agent-owned", "deferred-nonblocking"} and empty_or_na(row[4]):
569
- errors.append(
570
- f"{path}: coverage row {index} has no owner/validation gate"
571
- )
572
- for index, row in enumerate(markdown_table(text, "Assumption audit"), 1):
573
- if len(row) < 6:
574
- errors.append(f"{path}: assumption row {index} has fewer than 6 cells")
575
- elif not none_row(row[0]) and not substantive_cells(row, 0, 1, 2, 3, 4, 5):
576
- errors.append(f"{path}: assumption row {index} is unowned or unverifiable")
577
- for index, row in enumerate(markdown_table(text, "Residual uncertainty"), 1):
578
- if len(row) < 4:
579
- errors.append(f"{path}: residual row {index} has fewer than 4 cells")
580
- elif not none_row(row[0]) and not substantive_cells(row, 0, 1, 2, 3):
581
- errors.append(f"{path}: residual row {index} is unowned or unverifiable")
582
- questions_path = workspace / "questions.md"
583
- if questions_path.exists():
584
- open_gates = blocking_questions(read(questions_path))
585
- if open_gates:
586
- errors.append(
587
- f"{questions_path}: open blocking/validating/escalating questions: "
588
- + ", ".join(open_gates)
589
- )
590
-
591
-
592
- def validate_engineering_readiness(workspace: Path, errors: list[str]) -> None:
593
- contract = READINESS_CONTRACT["engineering"]
594
- text = validate_readiness_base(workspace, contract, errors)
595
- if text is None:
596
- return
597
- review_path = workspace / "eng-review.md"
598
- for index, row in enumerate(markdown_table(text, "2a. Build-entry preflight"), 1):
599
- if len(row) < 7:
600
- errors.append(f"{review_path}: preflight row {index} has fewer than 7 cells")
601
- continue
602
- verdict = row[6].strip().lower()
603
- if verdict not in {"pass", "n/a"}:
604
- errors.append(f"{review_path}: preflight row {index} is not passing")
605
- if not substantive_cells(row, 0) or (
606
- verdict == "pass" and not substantive_cells(row, 1, 2, 4, 5)
607
- ):
608
- errors.append(f"{review_path}: preflight row {index} lacks executable provenance")
609
- for index, row in enumerate(markdown_table(text, "2b. Implementation readiness"), 1):
610
- if (
611
- len(row) < 6
612
- or row[5].strip().lower() != "ready"
613
- or not substantive_cells(row, 0, 1, 2, 3, 4)
614
- ):
615
- errors.append(f"{review_path}: readiness row {index} is not ready")
616
-
617
- test_contract = READINESS_CONTRACT["testPlan"]
618
- test_path = workspace / str(test_contract["artifact"])
619
- if not test_path.exists():
620
- errors.append(f"{test_path}: missing test plan")
621
- return
622
- test_text = read(test_path)
623
- if not test_text.strip() or READINESS_PLACEHOLDER_RE.search(test_text):
624
- errors.append(f"{test_path}: empty or contains an unresolved placeholder")
625
- return
626
- for heading in test_contract.get("requiredHeadings", []):
627
- if markdown_section(test_text, str(heading)) is None:
628
- errors.append(f"{test_path}: missing heading '{heading}'")
629
- for heading in test_contract.get("requiredTables", []):
630
- rows = markdown_table(test_text, str(heading))
631
- if not rows:
632
- errors.append(f"{test_path}: heading '{heading}' has no table data rows")
633
- continue
634
- required_cells = (0, 1, 2, 3, 5)
635
- if heading == "Per-gap test requirements":
636
- required_cells = (0, 1, 2, 3, 4, 5, 6)
637
- for index, row in enumerate(rows, 1):
638
- if not substantive_cells(row, *required_cells):
639
- errors.append(f"{test_path}: heading '{heading}' row {index} is incomplete")
640
- mapping = markdown_section(test_text, "Acceptance → test map") or ""
641
- if "→" not in mapping and "->" not in mapping:
642
- errors.append(f"{test_path}: acceptance map has no mappings")
643
- spec_path = workspace / "spec.md"
644
- if spec_path.exists():
645
- for acceptance_id in sorted(set(READINESS_AC_RE.findall(read(spec_path)))):
646
- if acceptance_id.upper() not in mapping.upper():
647
- errors.append(f"{test_path}: acceptance map does not map {acceptance_id}")
648
-
649
-
650
- def validate_workspace(workspace: Path) -> list[str]:
651
- errors: list[str] = []
652
- phase = phase_for(workspace)
653
-
654
- if not workspace_index_present(workspace):
655
- errors.append(f"{workspace}: missing README.md/index.md/feature.md workspace map")
656
-
657
- metadata = PHASES.get(phase, PHASES["spec"])
658
- required = list(metadata["workspaceRequired"])
659
- for name in required:
660
- if not existing_or_alias(workspace, name):
661
- errors.append(f"{workspace}: phase {phase} requires {name}")
662
- if "decision-coverage.md" in required:
663
- validate_decision_coverage(workspace, errors)
664
- if "eng-review.md" in required:
665
- validate_engineering_readiness(workspace, errors)
666
-
667
- for path in sorted(workspace.glob("*.md")):
668
- text = read(path)
669
- rel = path.name
670
- if rel in HIGH_TRAFFIC_BUDGETS and line_count(text) > HIGH_TRAFFIC_BUDGETS[rel] and not has_budget_override(text):
671
- errors.append(f"{path}: {line_count(text)} lines exceeds budget {HIGH_TRAFFIC_BUDGETS[rel]} without Budget override")
672
- validate_mermaid(path, text, errors)
673
-
674
- if rel in REQUIRED_HEADINGS:
675
- present = headings(text)
676
- for heading in REQUIRED_HEADINGS[rel]:
677
- if heading not in present:
678
- errors.append(f"{path}: missing heading '{heading}'")
679
- if rel in {"README.md", "index.md"}:
680
- validate_workspace_map(path, text, errors)
681
- if rel == "flows.md":
682
- validate_flows(path, text, errors)
683
- if rel == "tasks.md":
684
- validate_tasks(path, text, errors)
685
- if rel == "decisions.md":
686
- validate_id_register(path, text, "DEC", errors)
687
- if rel == "questions.md":
688
- validate_id_register(path, text, "Q", errors)
689
- if rel == "drift.md":
690
- validate_id_register(path, text, "DRIFT", errors)
691
- if rel in {"evidence.md", "proof.md", "browser-evidence.md"}:
692
- validate_evidence_entries(path, text, errors)
693
-
694
- for link in MD_LINK_RE.findall(text):
695
- target = local_link_target(workspace, link)
696
- if target is None:
697
- continue
698
- try:
699
- target.relative_to(workspace.resolve())
700
- except ValueError:
701
- continue
702
- if not target.exists():
703
- errors.append(f"{path}: stale local link to {link}")
704
-
705
- spec = read(workspace / "spec.md") if (workspace / "spec.md").exists() else ""
706
- tasks = read(workspace / "tasks.md") if (workspace / "tasks.md").exists() else ""
707
- trace = read(workspace / "traceability.md") if (workspace / "traceability.md").exists() else ""
708
- evidence_path = evidence_file(workspace)
709
- evidence = read(evidence_path) if evidence_path else ""
710
- browser_evidence = read(workspace / "browser-evidence.md") if (workspace / "browser-evidence.md").exists() else ""
711
-
712
- ac_ids = set(ID_PATTERNS["AC"].findall(spec))
713
- req_ids = set(ID_PATTERNS["REQ"].findall(spec))
714
- slice_ids = set(ID_PATTERNS["SLICE"].findall(tasks))
715
- evid_ids = set(ID_PATTERNS["EVID"].findall(evidence + "\n" + browser_evidence))
716
-
717
- if spec and not ac_ids:
718
- errors.append(f"{workspace / 'spec.md'}: no AC-### acceptance criteria found")
719
- for old in sorted(set(LEGACY_AC_RE.findall(spec + tasks + trace))):
720
- errors.append(f"{workspace}: legacy acceptance id {old}; use AC-###")
721
- for old in sorted(set(LEGACY_SLICE_RE.findall(tasks))):
722
- errors.append(f"{workspace}: legacy slice label {old}; use SLICE-###")
723
-
724
- for ac in sorted(ac_ids):
725
- if tasks and ac not in tasks:
726
- errors.append(f"{workspace / 'tasks.md'}: {ac} is not referenced by any slice")
727
- if trace and ac not in trace:
728
- errors.append(f"{workspace / 'traceability.md'}: missing {ac}")
729
-
730
- if tasks:
731
- for slice_id in sorted(slice_ids):
732
- if not re.search(rf"{slice_id}.*AC-\d{{3}}|AC-\d{{3}}.*{slice_id}", tasks, re.S):
733
- errors.append(f"{workspace / 'tasks.md'}: {slice_id} has no AC-### reference")
734
- if trace and slice_id not in trace:
735
- errors.append(f"{workspace / 'traceability.md'}: missing {slice_id}")
736
-
737
- if trace:
738
- rows = "\n".join(table_rows(trace))
739
- for ac in sorted(ac_ids):
740
- if ac not in rows:
741
- errors.append(f"{workspace / 'traceability.md'}: {ac} absent from coverage matrix")
742
- if bool(metadata.get("proofRequired")):
743
- for eid in sorted(evid_ids):
744
- if eid not in trace:
745
- errors.append(f"{workspace / 'traceability.md'}: evidence ID {eid} from evidence/browser proof is not mapped")
746
-
747
- for slice_id in sorted(completed_slices(tasks)):
748
- if not evidence:
749
- errors.append(f"{workspace}: completed {slice_id} has no evidence.md/proof.md")
750
- elif slice_id not in evidence:
751
- errors.append(f"{evidence_path}: completed {slice_id} is not referenced by evidence")
752
-
753
- if bool(metadata.get("blocksOpenQuestions")):
754
- qfile = workspace / "questions.md"
755
- if qfile.exists():
756
- for qid in blocking_questions(read(qfile)):
757
- errors.append(f"{qfile}: unresolved blocking/escalating question {qid} blocks phase {phase}")
758
-
759
- if req_ids and trace:
760
- for req in sorted(req_ids):
761
- if req not in trace:
762
- errors.append(f"{workspace / 'traceability.md'}: missing {req}")
763
-
764
- return errors
765
-
766
-
767
- def main(argv: list[str]) -> int:
768
- parser = argparse.ArgumentParser(description=__doc__)
769
- parser.add_argument(
770
- "paths",
771
- nargs="*",
772
- default=["."],
773
- help="workspace directories or roots containing .devrites/work|features|archive",
774
- )
775
- args = parser.parse_args(argv)
776
-
777
- workspaces: list[Path] = []
778
- for raw in args.paths:
779
- workspaces.extend(find_local_workspaces(Path(raw)))
780
-
781
- if not workspaces:
782
- print("workspace-schema: no workspaces found", file=sys.stderr)
783
- return 2
784
-
785
- errors: list[str] = []
786
- for workspace in sorted(set(p.resolve() for p in workspaces)):
787
- errors.extend(validate_workspace(workspace))
788
-
789
- if errors:
790
- for err in errors:
791
- print(f"FAIL: {err}", file=sys.stderr)
792
- print(f"workspace-schema: {len(errors)} error(s) across {len(set(workspaces))} workspace(s)", file=sys.stderr)
793
- return 1
794
-
795
- print(f"workspace-schema: OK: {len(set(workspaces))} workspace(s) validated")
796
- return 0
797
-
798
-
799
- if __name__ == "__main__":
800
- raise SystemExit(main(sys.argv[1:]))