devrites 2.6.1 → 3.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 (1078) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +85 -50
  3. package/SECURITY.md +65 -39
  4. package/bin/devrites.mjs +135 -51
  5. package/docs/agents/domain.md +58 -0
  6. package/docs/agents/issue-driven-rites.md +11 -0
  7. package/docs/agents/issue-tracker.md +29 -0
  8. package/docs/agents/triage-labels.md +15 -0
  9. package/docs/architecture.md +60 -35
  10. package/docs/capability-surface-selection.md +18 -0
  11. package/docs/cli.md +53 -0
  12. package/docs/command-map.md +59 -22
  13. package/docs/engine/agent-contract.md +92 -0
  14. package/docs/engine/commands.md +323 -0
  15. package/docs/engine/state-schema.md +134 -0
  16. package/docs/engine/workspace-schema.md +150 -0
  17. package/docs/extensions.md +178 -0
  18. package/docs/flow.md +19 -16
  19. package/docs/harness-compliance.md +45 -0
  20. package/docs/orchestration.md +6 -4
  21. package/docs/porting-to-a-new-harness.md +27 -0
  22. package/docs/quick-reference.md +22 -0
  23. package/docs/release.md +3 -3
  24. package/docs/skills.md +42 -48
  25. package/docs/usage.md +21 -8
  26. package/engine/.gosec.json +5 -0
  27. package/engine/Makefile +64 -0
  28. package/engine/commands.go +195 -0
  29. package/engine/go.mod +5 -0
  30. package/engine/harnessmatrix.go +60 -0
  31. package/engine/harnessmatrix_test.go +59 -0
  32. package/engine/hookpolicy.go +114 -0
  33. package/engine/hookpolicy_test.go +64 -0
  34. package/engine/hooks.go +336 -0
  35. package/engine/hooks_events_test.go +106 -0
  36. package/engine/hooks_workspace.go +603 -0
  37. package/engine/internal/devritespaths/paths.go +76 -0
  38. package/engine/internal/doctor/doctor.go +178 -0
  39. package/engine/internal/doctor/doctor_test.go +150 -0
  40. package/engine/internal/fsutil/copy.go +101 -0
  41. package/engine/internal/fsutil/replace_other.go +7 -0
  42. package/engine/internal/fsutil/replace_windows.go +31 -0
  43. package/engine/internal/gate/gate.go +243 -0
  44. package/engine/internal/gate/gate_test.go +145 -0
  45. package/engine/internal/harness/compliance.go +102 -0
  46. package/engine/internal/harness/harness.go +304 -0
  47. package/engine/internal/harness/harness_test.go +104 -0
  48. package/engine/internal/hostpack/hostpack.go +259 -0
  49. package/engine/internal/hostpack/hostpack_test.go +111 -0
  50. package/engine/internal/hostpack/templates/alias_skill.md.tmpl +11 -0
  51. package/engine/internal/hostpack/templates/devrites_readme.md.tmpl +14 -0
  52. package/engine/internal/install/install.go +1560 -0
  53. package/engine/internal/install/install_test.go +564 -0
  54. package/engine/internal/iohooks/detach_other.go +11 -0
  55. package/engine/internal/iohooks/detach_unix.go +11 -0
  56. package/engine/internal/iohooks/iohooks.go +546 -0
  57. package/engine/internal/iohooks/iohooks_test.go +130 -0
  58. package/engine/internal/lib/adoption.go +634 -0
  59. package/engine/internal/lib/adoption_test.go +91 -0
  60. package/engine/internal/lib/analyze.go +225 -0
  61. package/engine/internal/lib/archivesearch.go +93 -0
  62. package/engine/internal/lib/archivesearch_test.go +110 -0
  63. package/engine/internal/lib/budget.go +172 -0
  64. package/engine/internal/lib/buildreadiness.go +88 -0
  65. package/engine/internal/lib/checkacceptance.go +176 -0
  66. package/engine/internal/lib/closeout.go +69 -0
  67. package/engine/internal/lib/command_other.go +7 -0
  68. package/engine/internal/lib/command_unix.go +24 -0
  69. package/engine/internal/lib/context.go +236 -0
  70. package/engine/internal/lib/conventions.go +449 -0
  71. package/engine/internal/lib/coverage.go +147 -0
  72. package/engine/internal/lib/doubtcoverage.go +88 -0
  73. package/engine/internal/lib/evidencefresh.go +85 -0
  74. package/engine/internal/lib/extensions.go +619 -0
  75. package/engine/internal/lib/extensions_test.go +305 -0
  76. package/engine/internal/lib/footprint.go +239 -0
  77. package/engine/internal/lib/jsonout.go +115 -0
  78. package/engine/internal/lib/jsonout_test.go +57 -0
  79. package/engine/internal/lib/lanes.go +106 -0
  80. package/engine/internal/lib/learnings.go +391 -0
  81. package/engine/internal/lib/learnings_inject_test.go +77 -0
  82. package/engine/internal/lib/learnings_remediation_test.go +24 -0
  83. package/engine/internal/lib/ledger.go +298 -0
  84. package/engine/internal/lib/ledger_test.go +162 -0
  85. package/engine/internal/lib/mutationgate.go +85 -0
  86. package/engine/internal/lib/overrides.go +164 -0
  87. package/engine/internal/lib/overrides_test.go +112 -0
  88. package/engine/internal/lib/packageexistence.go +175 -0
  89. package/engine/internal/lib/preamble.go +159 -0
  90. package/engine/internal/lib/progress.go +168 -0
  91. package/engine/internal/lib/reconcile.go +173 -0
  92. package/engine/internal/lib/reconcile_test.go +197 -0
  93. package/engine/internal/lib/resolve.go +376 -0
  94. package/engine/internal/lib/resolve_remediation_test.go +49 -0
  95. package/engine/internal/lib/reviewers.go +143 -0
  96. package/engine/internal/lib/reviewers_test.go +45 -0
  97. package/engine/internal/lib/reviewerstats.go +199 -0
  98. package/engine/internal/lib/reviewerstats_test.go +104 -0
  99. package/engine/internal/lib/reviewintegrity.go +143 -0
  100. package/engine/internal/lib/reviewintegrity_test.go +103 -0
  101. package/engine/internal/lib/runbook.go +292 -0
  102. package/engine/internal/lib/runbook_context_test.go +119 -0
  103. package/engine/internal/lib/session.go +328 -0
  104. package/engine/internal/lib/session_test.go +110 -0
  105. package/engine/internal/lib/specparse.go +125 -0
  106. package/engine/internal/lib/specskeleton.go +79 -0
  107. package/engine/internal/lib/specvalidate.go +391 -0
  108. package/engine/internal/lib/specvalidate_test.go +185 -0
  109. package/engine/internal/lib/stuck.go +206 -0
  110. package/engine/internal/lib/templates/conventions_drift.tmpl +6 -0
  111. package/engine/internal/lib/templates/conventions_ledger_header.md +6 -0
  112. package/engine/internal/lib/templates/conventions_orient_header.txt +1 -0
  113. package/engine/internal/lib/testintegrity.go +203 -0
  114. package/engine/internal/lib/testintegrity_test.go +72 -0
  115. package/engine/internal/lib/tickafk.go +99 -0
  116. package/engine/internal/lib/util.go +68 -0
  117. package/engine/internal/migrate/migrate.go +213 -0
  118. package/engine/internal/migrate/migrate_test.go +105 -0
  119. package/engine/internal/orient/firstrun.go +50 -0
  120. package/engine/internal/orient/firstrun_test.go +72 -0
  121. package/engine/internal/orient/orient.go +69 -0
  122. package/engine/internal/orient/orient_test.go +25 -0
  123. package/engine/internal/profile/profile.go +270 -0
  124. package/engine/internal/state/concurrency_test.go +184 -0
  125. package/engine/internal/state/feature.go +309 -0
  126. package/engine/internal/state/lock_other.go +24 -0
  127. package/engine/internal/state/lock_unix.go +35 -0
  128. package/engine/internal/state/lock_windows.go +56 -0
  129. package/engine/internal/state/schema.go +102 -0
  130. package/engine/internal/state/snapshot.go +384 -0
  131. package/engine/internal/state/state_test.go +260 -0
  132. package/engine/internal/state/status.go +90 -0
  133. package/engine/internal/state/write.go +59 -0
  134. package/engine/internal/testutil/testutil.go +66 -0
  135. package/engine/internal/version/version.go +57 -0
  136. package/engine/internal/workflow/commands.go +64 -0
  137. package/engine/main.go +530 -0
  138. package/engine/profile_test.go +76 -0
  139. package/engine/subagent_orient_context.txt +6 -0
  140. package/engine/testdata/fixtures/basic/devrites-root/features/auth-tokens/decisions.md +4 -0
  141. package/engine/testdata/fixtures/basic/devrites-root/features/auth-tokens/feature.md +8 -0
  142. package/engine/testdata/fixtures/basic/devrites-root/features/auth-tokens/plan.md +5 -0
  143. package/engine/testdata/fixtures/basic/devrites-root/features/auth-tokens/spec.md +6 -0
  144. package/engine/testdata/fixtures/basic/devrites-root/features/auth-tokens/status.md +4 -0
  145. package/engine/testdata/fixtures/basic/devrites-root/features/auth-tokens/tasks.md +1 -0
  146. package/engine/testdata/fixtures/basic/devrites-root/features/search-ranking/feature.md +8 -0
  147. package/engine/testdata/fixtures/basic/devrites-root/features/search-ranking/spec.md +6 -0
  148. package/engine/testdata/golden/TestParityA1Guard/devrites-edit-allowed.golden +1 -0
  149. package/engine/testdata/golden/TestParityA1Guard/inline-fallback-silent.golden +1 -0
  150. package/engine/testdata/golden/TestParityA1Guard/no-window-silent.golden +1 -0
  151. package/engine/testdata/golden/TestParityA1Guard/non-edit-tool.golden +1 -0
  152. package/engine/testdata/golden/TestParityA1Guard/observe-mode-silent.golden +1 -0
  153. package/engine/testdata/golden/TestParityA1Guard/source-edit-enforce-denies.golden +2 -0
  154. package/engine/testdata/golden/TestParityA1Guard/subagent-allowed.golden +1 -0
  155. package/engine/testdata/golden/TestParityAnalyze/noactive.golden +1 -0
  156. package/engine/testdata/golden/TestParityAnalyze/slug=covered.golden +15 -0
  157. package/engine/testdata/golden/TestParityAnalyze/slug=dangling.golden +16 -0
  158. package/engine/testdata/golden/TestParityAnalyze/slug=ghost.golden +1 -0
  159. package/engine/testdata/golden/TestParityAnalyze/slug=noac.golden +15 -0
  160. package/engine/testdata/golden/TestParityAnalyze/slug=order.golden +17 -0
  161. package/engine/testdata/golden/TestParityAnalyze/slug=orphan.golden +16 -0
  162. package/engine/testdata/golden/TestParityAnalyze/slug=uncovered.golden +16 -0
  163. package/engine/testdata/golden/TestParityBudget/default-active.golden +4 -0
  164. package/engine/testdata/golden/TestParityBudget/extra-md.golden +5 -0
  165. package/engine/testdata/golden/TestParityBudget/no-active.golden +1 -0
  166. package/engine/testdata/golden/TestParityBudget/no-feature.golden +1 -0
  167. package/engine/testdata/golden/TestParityBudget/over-advisory.golden +6 -0
  168. package/engine/testdata/golden/TestParityBudget/over-strict.golden +6 -0
  169. package/engine/testdata/golden/TestParityBudget/within.golden +6 -0
  170. package/engine/testdata/golden/TestParityBuildReadiness/arg=approved.golden +2 -0
  171. package/engine/testdata/golden/TestParityBuildReadiness/arg=approvenone.golden +1 -0
  172. package/engine/testdata/golden/TestParityBuildReadiness/arg=await.golden +1 -0
  173. package/engine/testdata/golden/TestParityBuildReadiness/arg=blocked.golden +1 -0
  174. package/engine/testdata/golden/TestParityBuildReadiness/arg=emptystatus.golden +2 -0
  175. package/engine/testdata/golden/TestParityBuildReadiness/arg=ghost.golden +1 -0
  176. package/engine/testdata/golden/TestParityBuildReadiness/arg=noapprove.golden +1 -0
  177. package/engine/testdata/golden/TestParityBuildReadiness/arg=trailhash.golden +2 -0
  178. package/engine/testdata/golden/TestParityBuildReadiness/arg=trailpipe.golden +2 -0
  179. package/engine/testdata/golden/TestParityCheckAcceptance/arg=blank-section.golden +1 -0
  180. package/engine/testdata/golden/TestParityCheckAcceptance/arg=empty.golden +1 -0
  181. package/engine/testdata/golden/TestParityCheckAcceptance/arg=flat-dropped.golden +1 -0
  182. package/engine/testdata/golden/TestParityCheckAcceptance/arg=flat-ok.golden +2 -0
  183. package/engine/testdata/golden/TestParityCheckAcceptance/arg=flat-unchecked.golden +1 -0
  184. package/engine/testdata/golden/TestParityCheckAcceptance/arg=id-gap.golden +1 -0
  185. package/engine/testdata/golden/TestParityCheckAcceptance/arg=id-ok.golden +2 -0
  186. package/engine/testdata/golden/TestParityCheckAcceptance/arg=no-seal.golden +1 -0
  187. package/engine/testdata/golden/TestParityCheckAcceptance/arg=no-section.golden +1 -0
  188. package/engine/testdata/golden/TestParityCheckAcceptance/arg=nonexistent.golden +1 -0
  189. package/engine/testdata/golden/TestParityCheckAcceptance.golden +1 -0
  190. package/engine/testdata/golden/TestParityCloseOut/active_pointed_elsewhere.golden +2 -0
  191. package/engine/testdata/golden/TestParityCloseOut/active_slug_cleared.golden +2 -0
  192. package/engine/testdata/golden/TestParityCloseOut/archive_clobber.golden +1 -0
  193. package/engine/testdata/golden/TestParityCloseOut/missing_slug.golden +1 -0
  194. package/engine/testdata/golden/TestParityCloseOut/missing_workspace.golden +1 -0
  195. package/engine/testdata/golden/TestParityCoverage/arg=flat.golden +7 -0
  196. package/engine/testdata/golden/TestParityCoverage/arg=full.golden +10 -0
  197. package/engine/testdata/golden/TestParityCoverage/arg=nonexistent.golden +1 -0
  198. package/engine/testdata/golden/TestParityCoverage/arg=nospec.golden +1 -0
  199. package/engine/testdata/golden/TestParityCoverage/arg=speconly.golden +9 -0
  200. package/engine/testdata/golden/TestParityCoverage.golden +1 -0
  201. package/engine/testdata/golden/TestParityCursor/bare.golden +3 -0
  202. package/engine/testdata/golden/TestParityCursor/full-afk.golden +6 -0
  203. package/engine/testdata/golden/TestParityCursor/full-hitl.golden +5 -0
  204. package/engine/testdata/golden/TestParityCursor/no-active.golden +1 -0
  205. package/engine/testdata/golden/TestParityCursor/red.golden +5 -0
  206. package/engine/testdata/golden/TestParityCursor/zerogates.golden +5 -0
  207. package/engine/testdata/golden/TestParityDoubtCoverage/arg=doubted.golden +2 -0
  208. package/engine/testdata/golden/TestParityDoubtCoverage/arg=ghost.golden +2 -0
  209. package/engine/testdata/golden/TestParityDoubtCoverage/arg=inline.golden +3 -0
  210. package/engine/testdata/golden/TestParityDoubtCoverage/arg=missing-inline.golden +3 -0
  211. package/engine/testdata/golden/TestParityDoubtCoverage/arg=missing.golden +3 -0
  212. package/engine/testdata/golden/TestParityDoubtCoverage/arg=nodoubt.golden +4 -0
  213. package/engine/testdata/golden/TestParityDoubtCoverage/arg=nolog.golden +2 -0
  214. package/engine/testdata/golden/TestParityDoubtCoverage/arg=nowright.golden +2 -0
  215. package/engine/testdata/golden/TestParityDoubtCoverage.golden +1 -0
  216. package/engine/testdata/golden/TestParityLearnings/add.golden +2 -0
  217. package/engine/testdata/golden/TestParityLearnings/list.golden +5 -0
  218. package/engine/testdata/golden/TestParityLearnings/mine-no-archive.golden +2 -0
  219. package/engine/testdata/golden/TestParityLearnings/mine.golden +5 -0
  220. package/engine/testdata/golden/TestParityLearnings/nudge.golden +2 -0
  221. package/engine/testdata/golden/TestParityLearnings/unknown.golden +1 -0
  222. package/engine/testdata/golden/TestParityMutationGate/active-slug.golden +3 -0
  223. package/engine/testdata/golden/TestParityMutationGate/explicit-slug.golden +3 -0
  224. package/engine/testdata/golden/TestParityMutationGate/ghost.golden +1 -0
  225. package/engine/testdata/golden/TestParityOrientSilentPath.golden +1 -0
  226. package/engine/testdata/golden/TestParityPackageExistence/declared.golden +2 -0
  227. package/engine/testdata/golden/TestParityPackageExistence/default-import-subpath.golden +2 -0
  228. package/engine/testdata/golden/TestParityPackageExistence/ghost-workspace.golden +1 -0
  229. package/engine/testdata/golden/TestParityPackageExistence/no-manifest.golden +1 -0
  230. package/engine/testdata/golden/TestParityPackageExistence/not-git.golden +1 -0
  231. package/engine/testdata/golden/TestParityPackageExistence/undeclared.golden +1 -0
  232. package/engine/testdata/golden/TestParityPreamble/afk/a.golden +14 -0
  233. package/engine/testdata/golden/TestParityPreamble/hitl/active.golden +18 -0
  234. package/engine/testdata/golden/TestParityPreamble/hitl/bare.golden +10 -0
  235. package/engine/testdata/golden/TestParityPreamble/hitl/full.golden +18 -0
  236. package/engine/testdata/golden/TestParityPreamble/hitl/ghost.golden +2 -0
  237. package/engine/testdata/golden/TestParityPreamble/hitl/nonl.golden +11 -0
  238. package/engine/testdata/golden/TestParityPreamble/hitl/openend.golden +13 -0
  239. package/engine/testdata/golden/TestParityProgress/arg=allbuilt.golden +4 -0
  240. package/engine/testdata/golden/TestParityProgress/arg=done.golden +3 -0
  241. package/engine/testdata/golden/TestParityProgress/arg=ghost.golden +1 -0
  242. package/engine/testdata/golden/TestParityProgress/arg=mid.golden +4 -0
  243. package/engine/testdata/golden/TestParityProgress/arg=nophase.golden +3 -0
  244. package/engine/testdata/golden/TestParityProgress/arg=noslice.golden +3 -0
  245. package/engine/testdata/golden/TestParityProgress/arg=plan.golden +4 -0
  246. package/engine/testdata/golden/TestParityProgress/arg=seal.golden +3 -0
  247. package/engine/testdata/golden/TestParityReconcile/bad-mode.golden +1 -0
  248. package/engine/testdata/golden/TestParityReconcile/check-clean/snapshot.golden +2 -0
  249. package/engine/testdata/golden/TestParityReconcile/check-clean.golden +2 -0
  250. package/engine/testdata/golden/TestParityReconcile/check-no-base.golden +1 -0
  251. package/engine/testdata/golden/TestParityReconcile/check-no-claimed/snapshot.golden +2 -0
  252. package/engine/testdata/golden/TestParityReconcile/check-no-claimed.golden +1 -0
  253. package/engine/testdata/golden/TestParityReconcile/check-violation/snapshot.golden +2 -0
  254. package/engine/testdata/golden/TestParityReconcile/check-violation.golden +1 -0
  255. package/engine/testdata/golden/TestParityReconcile/inline-fallback/snapshot.golden +2 -0
  256. package/engine/testdata/golden/TestParityReconcile/inline-fallback.golden +1 -0
  257. package/engine/testdata/golden/TestParityReconcile/not-git.golden +1 -0
  258. package/engine/testdata/golden/TestParityReconcile/snapshot/snapshot.golden +2 -0
  259. package/engine/testdata/golden/TestParityReconcile/snapshot.golden +2 -0
  260. package/engine/testdata/golden/TestParityRedwatch/fail-writes-red.golden +2 -0
  261. package/engine/testdata/golden/TestParityRedwatch/non-bash-tool.golden +1 -0
  262. package/engine/testdata/golden/TestParityRedwatch/non-test-command.golden +1 -0
  263. package/engine/testdata/golden/TestParityRedwatch/pass-clears-red.golden +1 -0
  264. package/engine/testdata/golden/TestParityResolve/answer/questions.md.golden +9 -0
  265. package/engine/testdata/golden/TestParityResolve/answer/state.md.golden +6 -0
  266. package/engine/testdata/golden/TestParityResolve/answer.golden +4 -0
  267. package/engine/testdata/golden/TestParityResolve/batch/questions.md.golden +9 -0
  268. package/engine/testdata/golden/TestParityResolve/batch-unterminated/questions.md.golden +9 -0
  269. package/engine/testdata/golden/TestParityResolve/batch-unterminated.golden +2 -0
  270. package/engine/testdata/golden/TestParityResolve/batch.golden +3 -0
  271. package/engine/testdata/golden/TestParityResolve/drop/questions.md.golden +9 -0
  272. package/engine/testdata/golden/TestParityResolve/drop/state.md.golden +8 -0
  273. package/engine/testdata/golden/TestParityResolve/drop.golden +4 -0
  274. package/engine/testdata/golden/TestParityResolve/missing-answer.golden +1 -0
  275. package/engine/testdata/golden/TestParityResolve/next-qid.golden +2 -0
  276. package/engine/testdata/golden/TestParityResolve/no-workspace.golden +1 -0
  277. package/engine/testdata/golden/TestParityResolve/not-found.golden +1 -0
  278. package/engine/testdata/golden/TestParityResolve/not-open.golden +1 -0
  279. package/engine/testdata/golden/TestParityReviewerReadonly/agent-required-devrites-agent-denies.golden +2 -0
  280. package/engine/testdata/golden/TestParityReviewerReadonly/agent-required-non-devrites-allows.golden +1 -0
  281. package/engine/testdata/golden/TestParityReviewerReadonly/agent-required-subagent-type-only-allows.golden +1 -0
  282. package/engine/testdata/golden/TestParityReviewerReadonly/enforce-deny-git-commit.golden +2 -0
  283. package/engine/testdata/golden/TestParityReviewerReadonly/enforce-deny-mutating.golden +2 -0
  284. package/engine/testdata/golden/TestParityReviewerReadonly/non-bash-tool.golden +1 -0
  285. package/engine/testdata/golden/TestParityReviewerReadonly/non-tool-input.golden +1 -0
  286. package/engine/testdata/golden/TestParityReviewerReadonly/observe-mutating-silent.golden +1 -0
  287. package/engine/testdata/golden/TestParityReviewerReadonly/safe-bash-command.golden +1 -0
  288. package/engine/testdata/golden/TestParitySpecValidate/arg=dup.golden +1 -0
  289. package/engine/testdata/golden/TestParitySpecValidate/arg=empty.golden +1 -0
  290. package/engine/testdata/golden/TestParitySpecValidate/arg=flat.golden +2 -0
  291. package/engine/testdata/golden/TestParitySpecValidate/arg=nonexistent.golden +1 -0
  292. package/engine/testdata/golden/TestParitySpecValidate/arg=noscenario.golden +1 -0
  293. package/engine/testdata/golden/TestParitySpecValidate/arg=noshall.golden +1 -0
  294. package/engine/testdata/golden/TestParitySpecValidate/arg=nothen.golden +1 -0
  295. package/engine/testdata/golden/TestParitySpecValidate/arg=valid/spec.md.golden +2 -0
  296. package/engine/testdata/golden/TestParitySpecValidate/arg=valid.golden +2 -0
  297. package/engine/testdata/golden/TestParitySpecValidate.golden +1 -0
  298. package/engine/testdata/golden/TestParityStatusline/full-afk.golden +2 -0
  299. package/engine/testdata/golden/TestParityStatusline/full-hitl.golden +2 -0
  300. package/engine/testdata/golden/TestParityStatusline/no-active.golden +1 -0
  301. package/engine/testdata/golden/TestParityStatusline/nophase.golden +2 -0
  302. package/engine/testdata/golden/TestParityStatusline/red.golden +2 -0
  303. package/engine/testdata/golden/TestParityStuckCheck/bad-cmd.golden +1 -0
  304. package/engine/testdata/golden/TestParityStuckCheck/custom-window-2.golden +2 -0
  305. package/engine/testdata/golden/TestParityStuckCheck/dominant.golden +2 -0
  306. package/engine/testdata/golden/TestParityStuckCheck/few.golden +2 -0
  307. package/engine/testdata/golden/TestParityStuckCheck/ghost.golden +2 -0
  308. package/engine/testdata/golden/TestParityStuckCheck/identical.golden +2 -0
  309. package/engine/testdata/golden/TestParityStuckCheck/no-cmd.golden +1 -0
  310. package/engine/testdata/golden/TestParityStuckCheck/no-slug.golden +1 -0
  311. package/engine/testdata/golden/TestParityStuckCheck/nolog.golden +2 -0
  312. package/engine/testdata/golden/TestParityStuckCheck/pingpong.golden +2 -0
  313. package/engine/testdata/golden/TestParityStuckCheck/varied.golden +2 -0
  314. package/engine/testdata/golden/TestParityStuckCheck/window-04-identical.golden +2 -0
  315. package/engine/testdata/golden/TestParityStuckCheck/window-2.5-varied4.golden +2 -0
  316. package/engine/testdata/golden/TestParityStuckCheck/window-4x-varied4.golden +2 -0
  317. package/engine/testdata/golden/TestParityStuckCheck/window-leadspace-varied4.golden +2 -0
  318. package/engine/testdata/golden/TestParityStuckCheck/window-plus4-identical.golden +2 -0
  319. package/engine/testdata/golden/TestParitySubagentOrient/devrites-agent-subagent-type-key.golden +2 -0
  320. package/engine/testdata/golden/TestParitySubagentOrient/devrites-agent.golden +2 -0
  321. package/engine/testdata/golden/TestParitySubagentOrient/garbage-input.golden +1 -0
  322. package/engine/testdata/golden/TestParitySubagentOrient/non-devrites-agent.golden +1 -0
  323. package/engine/testdata/golden/TestParityTestIntegrity/assertion-dropped.golden +1 -0
  324. package/engine/testdata/golden/TestParityTestIntegrity/clean.golden +2 -0
  325. package/engine/testdata/golden/TestParityTestIntegrity/deleted.golden +1 -0
  326. package/engine/testdata/golden/TestParityTestIntegrity/ghost-workspace.golden +1 -0
  327. package/engine/testdata/golden/TestParityTestIntegrity/not-git.golden +1 -0
  328. package/engine/testdata/golden/TestParityTestIntegrity/skip-added.golden +1 -0
  329. package/engine/testdata/golden/TestParityTickAfk/budget1/state.md.golden +1 -0
  330. package/engine/testdata/golden/TestParityTickAfk/budget1.golden +2 -0
  331. package/engine/testdata/golden/TestParityTickAfk/budget3/state.md.golden +5 -0
  332. package/engine/testdata/golden/TestParityTickAfk/budget3.golden +2 -0
  333. package/engine/testdata/golden/TestParityTickAfk/bulletPipe/state.md.golden +1 -0
  334. package/engine/testdata/golden/TestParityTickAfk/bulletPipe.golden +2 -0
  335. package/engine/testdata/golden/TestParityTickAfk/missingField/state.md.golden +3 -0
  336. package/engine/testdata/golden/TestParityTickAfk/missingField.golden +2 -0
  337. package/engine/testdata/golden/TestParityTickAfk/missingFile.golden +1 -0
  338. package/engine/testdata/golden/TestParityTickAfk/nonNumeric/state.md.golden +1 -0
  339. package/engine/testdata/golden/TestParityTickAfk/nonNumeric.golden +1 -0
  340. package/engine/testdata/golden/TestParityTickAfk/none/state.md.golden +1 -0
  341. package/engine/testdata/golden/TestParityTickAfk/none.golden +2 -0
  342. package/engine/testdata/golden/TestParityWrightScope/agent-required-non-wright.golden +1 -0
  343. package/engine/testdata/golden/TestParityWrightScope/devrites-edit-allowed.golden +1 -0
  344. package/engine/testdata/golden/TestParityWrightScope/in-scope-allowed.golden +1 -0
  345. package/engine/testdata/golden/TestParityWrightScope/non-edit-tool.golden +1 -0
  346. package/engine/testdata/golden/TestParityWrightScope/out-of-scope-enforce-denies.golden +2 -0
  347. package/engine/testdata/golden/TestParityWrightScope/out-of-scope-observe-silent.golden +1 -0
  348. package/engine/testdata/golden/TestSpecSkeleton/missing-some.golden +2 -0
  349. package/engine/testdata/golden/TestSpecSkeleton/present-all.golden +2 -0
  350. package/engine/testdata/golden/TestStatusLiveWorkspace.golden +10 -0
  351. package/engine/testdata/golden/TestStuckLogHashParity.golden +1 -0
  352. package/engine/testdata/golden/status/auth-tokens.txt +9 -0
  353. package/engine/testdata/golden/status/search-ranking.txt +9 -0
  354. package/engine/tests/adr_0003_gate_exit_code_test.go +32 -0
  355. package/engine/tests/adr_0004_required_by_phase_test.go +62 -0
  356. package/engine/tests/adr_0006_clock_seam_test.go +36 -0
  357. package/engine/tests/budget_test.go +77 -0
  358. package/engine/tests/cli_test.go +209 -0
  359. package/engine/tests/concurrency_cli_test.go +125 -0
  360. package/engine/tests/conventions_test.go +106 -0
  361. package/engine/tests/doctor_cli_test.go +62 -0
  362. package/engine/tests/gate_test.go +235 -0
  363. package/engine/tests/hook_test.go +390 -0
  364. package/engine/tests/hooks_io_test.go +218 -0
  365. package/engine/tests/json_contract_test.go +99 -0
  366. package/engine/tests/lib_parity_test.go +942 -0
  367. package/engine/tests/meta_test.go +67 -0
  368. package/engine/tests/migrate_cli_test.go +193 -0
  369. package/engine/tests/parity_analyze_test.go +55 -0
  370. package/engine/tests/parity_buildreadiness_test.go +42 -0
  371. package/engine/tests/parity_closeout_test.go +102 -0
  372. package/engine/tests/parity_githelpers_test.go +41 -0
  373. package/engine/tests/parity_learnings_test.go +90 -0
  374. package/engine/tests/parity_mutationgate_test.go +36 -0
  375. package/engine/tests/parity_packageexistence_test.go +64 -0
  376. package/engine/tests/parity_reconcile_test.go +88 -0
  377. package/engine/tests/parity_resolve_test.go +144 -0
  378. package/engine/tests/parity_test.go +380 -0
  379. package/engine/tests/parity_testintegrity_test.go +65 -0
  380. package/engine/tests/parity_tickafk_test.go +83 -0
  381. package/engine/validatepack.go +192 -0
  382. package/engine/validatepack_test.go +79 -0
  383. package/engine/validatepackskills.go +181 -0
  384. package/engine/validatepackskills_test.go +171 -0
  385. package/install.sh +67 -912
  386. package/pack/.claude/agents/devrites-code-reviewer.md +20 -3
  387. package/pack/.claude/agents/devrites-devex-reviewer.md +13 -3
  388. package/pack/.claude/agents/devrites-doubt-reviewer.md +16 -3
  389. package/pack/.claude/agents/devrites-forge-judge.md +14 -4
  390. package/pack/.claude/agents/devrites-frontend-reviewer.md +27 -3
  391. package/pack/.claude/agents/devrites-performance-reviewer.md +18 -2
  392. package/pack/.claude/agents/devrites-plan-reviewer.md +13 -3
  393. package/pack/.claude/agents/devrites-retrospector.md +12 -7
  394. package/pack/.claude/agents/devrites-security-auditor.md +20 -4
  395. package/pack/.claude/agents/devrites-simplifier-reviewer.md +17 -2
  396. package/pack/.claude/agents/devrites-slice-wright.md +32 -16
  397. package/pack/.claude/agents/devrites-spec-reviewer.md +17 -2
  398. package/pack/.claude/agents/devrites-strategy-reviewer.md +12 -2
  399. package/pack/.claude/agents/devrites-test-analyst.md +20 -3
  400. package/pack/.claude/settings.json +58 -8
  401. package/pack/.claude/skills/devrites-api-interface/SKILL.md +22 -5
  402. package/pack/.claude/skills/devrites-audit/SKILL.md +1 -1
  403. package/pack/.claude/skills/devrites-browser-proof/SKILL.md +26 -53
  404. package/pack/.claude/skills/devrites-browser-proof/reference/browser-performance.md +15 -0
  405. package/pack/.claude/skills/devrites-browser-proof/reference/visual-verdict.md +34 -0
  406. package/pack/.claude/skills/devrites-debug-recovery/SKILL.md +21 -6
  407. package/pack/.claude/skills/devrites-debug-recovery/reference/build-the-loop.md +11 -0
  408. package/pack/.claude/skills/devrites-debug-recovery/reference/regression-test.md +2 -3
  409. package/pack/.claude/skills/devrites-debug-recovery/reference/trace.md +25 -0
  410. package/pack/.claude/skills/devrites-doubt/SKILL.md +10 -3
  411. package/pack/.claude/skills/devrites-frontend-craft/SKILL.md +16 -13
  412. package/pack/.claude/skills/devrites-frontend-craft/reference/craft.md +15 -3
  413. package/pack/.claude/skills/devrites-frontend-craft/reference/quality-standards.md +19 -0
  414. package/pack/.claude/skills/devrites-frontend-craft/reference/reuse-first.md +3 -3
  415. package/pack/.claude/skills/devrites-interview/SKILL.md +30 -7
  416. package/pack/.claude/skills/devrites-lib/SKILL.md +35 -36
  417. package/pack/.claude/skills/devrites-lib/reference/intent-map.md +16 -0
  418. package/pack/.claude/skills/devrites-lib/reference/model-tiers.md +43 -0
  419. package/pack/.claude/skills/devrites-lib/reference/parallel-dispatch.md +104 -20
  420. package/pack/.claude/skills/devrites-lib/reference/reply-contract.md +111 -0
  421. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/README.md +14 -6
  422. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/afk-hitl.md +10 -18
  423. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/agents.md +81 -16
  424. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/anti-patterns.md +3 -4
  425. package/pack/.claude/skills/devrites-lib/reference/standards/browser-proof-checklist.md +9 -0
  426. package/pack/.claude/skills/devrites-lib/reference/standards/ci-cd.md +62 -0
  427. package/pack/.claude/skills/devrites-lib/reference/standards/code-review.md +141 -0
  428. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/context-hygiene.md +17 -0
  429. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/core.md +9 -18
  430. package/pack/.claude/skills/devrites-lib/reference/standards/definition-of-done.md +16 -0
  431. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/deprecation.md +21 -0
  432. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/developer-experience.md +3 -3
  433. package/pack/.claude/skills/devrites-lib/reference/standards/development-workflow.md +51 -0
  434. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/documentation.md +9 -1
  435. package/pack/.claude/skills/devrites-lib/reference/standards/edge-case-trace.md +19 -0
  436. package/pack/.claude/skills/devrites-lib/reference/standards/elicitation.md +80 -0
  437. package/pack/.claude/skills/devrites-lib/reference/standards/git-workflow.md +65 -0
  438. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/observability.md +13 -0
  439. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/performance.md +1 -1
  440. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/principles.md +3 -3
  441. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/prose-style.md +18 -2
  442. package/pack/.claude/skills/devrites-lib/reference/standards/release/ship-checklist.md +9 -0
  443. package/pack/.claude/skills/devrites-lib/reference/standards/review-checklist.md +10 -0
  444. package/pack/.claude/skills/devrites-lib/reference/standards/security-checklist.md +9 -0
  445. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/security.md +45 -4
  446. package/pack/.claude/skills/devrites-lib/reference/standards/skill-authoring.md +105 -0
  447. package/pack/.claude/skills/devrites-lib/reference/standards/spec-grammar.md +185 -0
  448. package/pack/.claude/skills/devrites-lib/reference/standards/test-proof-checklist.md +9 -0
  449. package/pack/.claude/skills/devrites-lib/reference/standards/testing.md +162 -0
  450. package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/tooling.md +29 -2
  451. package/pack/.claude/skills/devrites-lib/reference/workspace-artifact-schema.md +110 -0
  452. package/pack/.claude/skills/devrites-prose-craft/SKILL.md +40 -76
  453. package/pack/.claude/skills/devrites-prose-craft/reference/examples.md +19 -5
  454. package/pack/.claude/skills/devrites-refresh-indexes/SKILL.md +3 -6
  455. package/pack/.claude/skills/devrites-source-driven/SKILL.md +17 -1
  456. package/pack/.claude/skills/devrites-ux-shape/SKILL.md +20 -7
  457. package/pack/.claude/skills/devrites-ux-shape/reference/brief-template.md +25 -10
  458. package/pack/.claude/skills/devrites-ux-shape/reference/visual-direction-probe.md +2 -2
  459. package/pack/.claude/skills/rite/SKILL.md +67 -42
  460. package/pack/.claude/skills/rite/reference/menu.md +4 -1
  461. package/pack/.claude/skills/rite-adopt/SKILL.md +31 -22
  462. package/pack/.claude/skills/rite-adopt/reference/adoption.md +6 -9
  463. package/pack/.claude/skills/rite-adopt/reference/anti-patterns.md +1 -1
  464. package/pack/.claude/skills/rite-autocomplete/SKILL.md +25 -25
  465. package/pack/.claude/skills/rite-autocomplete/reference/loop.md +2 -2
  466. package/pack/.claude/skills/rite-autocomplete/reference/stop-conditions.md +1 -1
  467. package/pack/.claude/skills/rite-build/SKILL.md +24 -256
  468. package/pack/.claude/skills/rite-build/reference/afk-discipline.md +3 -3
  469. package/pack/.claude/skills/rite-build/reference/anti-patterns.md +1 -1
  470. package/pack/.claude/skills/rite-build/reference/checkpoint-protocol.md +1 -1
  471. package/pack/.claude/skills/rite-build/reference/checkpoint.md +44 -0
  472. package/pack/.claude/skills/rite-build/reference/evidence-standard.md +10 -7
  473. package/pack/.claude/skills/rite-build/reference/forge.md +17 -7
  474. package/pack/.claude/skills/rite-build/reference/one-slice-cycle.md +2 -0
  475. package/pack/.claude/skills/rite-build/reference/output.md +41 -0
  476. package/pack/.claude/skills/rite-build/reference/phase-contract.md +258 -0
  477. package/pack/.claude/skills/rite-build/reference/wright-dispatch.md +11 -10
  478. package/pack/.claude/skills/rite-converge/SKILL.md +131 -0
  479. package/pack/.claude/skills/rite-converge/reference/anti-patterns.md +35 -0
  480. package/pack/.claude/skills/rite-converge/reference/convergence-assessment.md +61 -0
  481. package/pack/.claude/skills/rite-customize/SKILL.md +67 -0
  482. package/pack/.claude/skills/rite-define/SKILL.md +76 -93
  483. package/pack/.claude/skills/rite-define/reference/anti-patterns.md +2 -1
  484. package/pack/.claude/skills/rite-define/reference/gates.md +3 -3
  485. package/pack/.claude/skills/rite-define/reference/plan-template.md +35 -6
  486. package/pack/.claude/skills/rite-doctor/SKILL.md +41 -16
  487. package/pack/.claude/skills/rite-dogfood/SKILL.md +49 -0
  488. package/pack/.claude/skills/rite-explain/SKILL.md +148 -0
  489. package/pack/.claude/skills/rite-explain/reference/intake.md +79 -0
  490. package/pack/.claude/skills/rite-frame/SKILL.md +14 -15
  491. package/pack/.claude/skills/rite-frame/reference/failure-modes.md +1 -1
  492. package/pack/.claude/skills/rite-handoff/SKILL.md +19 -17
  493. package/pack/.claude/skills/rite-handoff/reference/handoff-template.md +16 -6
  494. package/pack/.claude/skills/rite-learn/SKILL.md +46 -24
  495. package/pack/.claude/skills/rite-plan/SKILL.md +35 -26
  496. package/pack/.claude/skills/rite-plan/reference/anti-patterns.md +1 -1
  497. package/pack/.claude/skills/rite-plan/reference/dependency-graph.md +3 -3
  498. package/pack/.claude/skills/rite-plan/reference/slicing.md +20 -7
  499. package/pack/.claude/skills/rite-plan/reference/task-breakdown.md +15 -16
  500. package/pack/.claude/skills/rite-polish/SKILL.md +18 -23
  501. package/pack/.claude/skills/rite-polish/reference/anti-ai-slop.md +31 -2
  502. package/pack/.claude/skills/rite-polish/reference/anti-patterns.md +4 -1
  503. package/pack/.claude/skills/rite-polish/reference/code.md +16 -5
  504. package/pack/.claude/skills/rite-polish/reference/design-system-discovery.md +5 -32
  505. package/pack/.claude/skills/rite-pov/SKILL.md +46 -0
  506. package/pack/.claude/skills/rite-pr-feedback/SKILL.md +49 -0
  507. package/pack/.claude/skills/rite-pressure-test/SKILL.md +40 -10
  508. package/pack/.claude/skills/rite-prototype/SKILL.md +23 -2
  509. package/pack/.claude/skills/rite-prove/SKILL.md +41 -96
  510. package/pack/.claude/skills/rite-prove/reference/acceptance-proof.md +48 -0
  511. package/pack/.claude/skills/rite-prove/reference/anti-patterns.md +1 -1
  512. package/pack/.claude/skills/rite-prove/reference/browser-proof.md +36 -13
  513. package/pack/.claude/skills/rite-quick/SKILL.md +19 -12
  514. package/pack/.claude/skills/rite-resolve/SKILL.md +21 -25
  515. package/pack/.claude/skills/rite-resolve/reference/answer-protocol.md +2 -2
  516. package/pack/.claude/skills/rite-review/SKILL.md +43 -45
  517. package/pack/.claude/skills/rite-review/reference/anti-patterns.md +1 -1
  518. package/pack/.claude/skills/rite-review/reference/performance-checklist.md +1 -1
  519. package/pack/.claude/skills/rite-review/reference/performance-review.md +4 -22
  520. package/pack/.claude/skills/rite-review/reference/security-review.md +2 -2
  521. package/pack/.claude/skills/rite-seal/SKILL.md +40 -174
  522. package/pack/.claude/skills/rite-seal/reference/anti-patterns.md +1 -1
  523. package/pack/.claude/skills/rite-seal/reference/conventions-ledger.md +6 -9
  524. package/pack/.claude/skills/rite-seal/reference/final-evidence.md +6 -14
  525. package/pack/.claude/skills/rite-seal/reference/go-no-go.md +3 -3
  526. package/pack/.claude/skills/rite-seal/reference/output.md +7 -0
  527. package/pack/.claude/skills/rite-seal/reference/phase-contract.md +211 -0
  528. package/pack/.claude/skills/rite-seal/reference/seal-template.md +1 -1
  529. package/pack/.claude/skills/rite-ship/SKILL.md +45 -75
  530. package/pack/.claude/skills/rite-ship/reference/adr-promotion.md +9 -0
  531. package/pack/.claude/skills/rite-ship/reference/anti-patterns.md +1 -1
  532. package/pack/.claude/skills/rite-ship/reference/close-out.md +12 -1
  533. package/pack/.claude/skills/rite-ship/reference/design-memory.md +2 -2
  534. package/pack/.claude/skills/rite-ship/reference/git-ship.md +32 -1
  535. package/pack/.claude/skills/rite-ship/reference/ledger.md +56 -0
  536. package/pack/.claude/skills/rite-ship/reference/rollout.md +43 -0
  537. package/pack/.claude/skills/rite-spec/SKILL.md +108 -60
  538. package/pack/.claude/skills/rite-spec/reference/ai-spec-template.md +33 -0
  539. package/pack/.claude/skills/rite-spec/reference/anti-patterns.md +4 -1
  540. package/pack/.claude/skills/rite-spec/reference/investigation.md +34 -14
  541. package/pack/.claude/skills/rite-spec/reference/question-protocol.md +7 -37
  542. package/pack/.claude/skills/rite-spec/reference/references-intake.md +23 -18
  543. package/pack/.claude/skills/rite-spec/reference/spec-template.md +94 -118
  544. package/pack/.claude/skills/rite-spec/reference/state-workspace.md +128 -139
  545. package/pack/.claude/skills/rite-status/SKILL.md +26 -22
  546. package/pack/.claude/skills/rite-temper/SKILL.md +34 -27
  547. package/pack/.claude/skills/rite-temper/reference/anti-patterns.md +1 -1
  548. package/pack/.claude/skills/rite-temper/reference/scope-modes.md +1 -1
  549. package/pack/.claude/skills/rite-temper/reference/significance.md +1 -1
  550. package/pack/.claude/skills/rite-vet/SKILL.md +58 -70
  551. package/pack/.claude/skills/rite-vet/reference/anti-patterns.md +1 -1
  552. package/pack/.claude/skills/rite-vet/reference/cross-model.md +7 -5
  553. package/pack/.claude/skills/rite-vet/reference/depth.md +1 -1
  554. package/pack/.claude/skills/rite-vet/reference/review-axes.md +3 -3
  555. package/pack/.claude/skills/rite-zoom-out/SKILL.md +16 -17
  556. package/pack/generated/README.md +10 -0
  557. package/pack/generated/claude/agents/devrites-code-reviewer.md +103 -0
  558. package/pack/generated/claude/agents/devrites-devex-reviewer.md +104 -0
  559. package/pack/generated/claude/agents/devrites-doubt-reviewer.md +68 -0
  560. package/pack/generated/claude/agents/devrites-forge-judge.md +102 -0
  561. package/pack/generated/claude/agents/devrites-frontend-reviewer.md +84 -0
  562. package/pack/generated/claude/agents/devrites-performance-reviewer.md +111 -0
  563. package/pack/generated/claude/agents/devrites-plan-reviewer.md +89 -0
  564. package/pack/generated/claude/agents/devrites-retrospector.md +96 -0
  565. package/pack/generated/claude/agents/devrites-security-auditor.md +85 -0
  566. package/pack/generated/claude/agents/devrites-simplifier-reviewer.md +90 -0
  567. package/pack/generated/claude/agents/devrites-slice-wright.md +210 -0
  568. package/pack/generated/claude/agents/devrites-spec-reviewer.md +87 -0
  569. package/pack/generated/claude/agents/devrites-strategy-reviewer.md +72 -0
  570. package/pack/generated/claude/agents/devrites-test-analyst.md +64 -0
  571. package/pack/generated/claude/settings.json +103 -0
  572. package/pack/generated/claude/skills/devrites-api-interface/SKILL.md +61 -0
  573. package/pack/generated/claude/skills/devrites-audit/SKILL.md +73 -0
  574. package/pack/generated/claude/skills/devrites-browser-proof/SKILL.md +76 -0
  575. package/pack/generated/claude/skills/devrites-browser-proof/reference/browser-performance.md +15 -0
  576. package/pack/generated/claude/skills/devrites-browser-proof/reference/visual-verdict.md +34 -0
  577. package/pack/generated/claude/skills/devrites-debug-recovery/SKILL.md +65 -0
  578. package/pack/generated/claude/skills/devrites-debug-recovery/reference/build-the-loop.md +58 -0
  579. package/pack/generated/claude/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +17 -0
  580. package/pack/generated/claude/skills/devrites-debug-recovery/reference/hypotheses.md +17 -0
  581. package/pack/generated/claude/skills/devrites-debug-recovery/reference/instrumentation.md +21 -0
  582. package/pack/generated/claude/skills/devrites-debug-recovery/reference/regression-test.md +30 -0
  583. package/pack/generated/claude/skills/devrites-debug-recovery/reference/trace.md +25 -0
  584. package/pack/generated/claude/skills/devrites-doubt/SKILL.md +82 -0
  585. package/pack/generated/claude/skills/devrites-frontend-craft/SKILL.md +99 -0
  586. package/pack/generated/claude/skills/devrites-frontend-craft/reference/craft.md +71 -0
  587. package/pack/generated/claude/skills/devrites-frontend-craft/reference/design-references.md +116 -0
  588. package/pack/generated/claude/skills/devrites-frontend-craft/reference/fullstack.md +45 -0
  589. package/pack/generated/claude/skills/devrites-frontend-craft/reference/quality-standards.md +234 -0
  590. package/pack/generated/claude/skills/devrites-frontend-craft/reference/reuse-first.md +59 -0
  591. package/pack/generated/claude/skills/devrites-frontend-craft/reference/shape.md +60 -0
  592. package/pack/generated/claude/skills/devrites-interview/SKILL.md +104 -0
  593. package/pack/generated/claude/skills/devrites-lib/SKILL.md +82 -0
  594. package/pack/generated/claude/skills/devrites-lib/reference/intent-map.md +16 -0
  595. package/pack/generated/claude/skills/devrites-lib/reference/model-tiers.md +43 -0
  596. package/pack/generated/claude/skills/devrites-lib/reference/parallel-dispatch.md +165 -0
  597. package/pack/generated/claude/skills/devrites-lib/reference/reply-contract.md +111 -0
  598. package/pack/generated/claude/skills/devrites-lib/reference/standards/README.md +61 -0
  599. package/pack/generated/claude/skills/devrites-lib/reference/standards/afk-hitl.md +243 -0
  600. package/pack/generated/claude/skills/devrites-lib/reference/standards/agents.md +192 -0
  601. package/pack/generated/claude/skills/devrites-lib/reference/standards/anti-patterns.md +58 -0
  602. package/pack/generated/claude/skills/devrites-lib/reference/standards/browser-proof-checklist.md +9 -0
  603. package/pack/generated/claude/skills/devrites-lib/reference/standards/ci-cd.md +62 -0
  604. package/pack/generated/claude/skills/devrites-lib/reference/standards/code-review.md +141 -0
  605. package/pack/generated/claude/skills/devrites-lib/reference/standards/coding-style.md +55 -0
  606. package/pack/generated/claude/skills/devrites-lib/reference/standards/context-hygiene.md +114 -0
  607. package/pack/generated/claude/skills/devrites-lib/reference/standards/core.md +119 -0
  608. package/pack/generated/claude/skills/devrites-lib/reference/standards/definition-of-done.md +16 -0
  609. package/pack/generated/claude/skills/devrites-lib/reference/standards/deprecation.md +71 -0
  610. package/pack/generated/claude/skills/devrites-lib/reference/standards/developer-experience.md +119 -0
  611. package/pack/generated/claude/skills/devrites-lib/reference/standards/development-workflow.md +51 -0
  612. package/pack/generated/claude/skills/devrites-lib/reference/standards/documentation.md +35 -0
  613. package/pack/generated/claude/skills/devrites-lib/reference/standards/edge-case-trace.md +19 -0
  614. package/pack/generated/claude/skills/devrites-lib/reference/standards/elicitation.md +80 -0
  615. package/pack/generated/claude/skills/devrites-lib/reference/standards/error-handling.md +33 -0
  616. package/pack/generated/claude/skills/devrites-lib/reference/standards/git-workflow.md +65 -0
  617. package/pack/generated/claude/skills/devrites-lib/reference/standards/hooks.md +38 -0
  618. package/pack/generated/claude/skills/devrites-lib/reference/standards/observability.md +73 -0
  619. package/pack/generated/claude/skills/devrites-lib/reference/standards/patterns.md +48 -0
  620. package/pack/generated/claude/skills/devrites-lib/reference/standards/performance.md +36 -0
  621. package/pack/generated/claude/skills/devrites-lib/reference/standards/principles.md +158 -0
  622. package/pack/generated/claude/skills/devrites-lib/reference/standards/prose-style.md +117 -0
  623. package/pack/generated/claude/skills/devrites-lib/reference/standards/release/ship-checklist.md +9 -0
  624. package/pack/generated/claude/skills/devrites-lib/reference/standards/review-checklist.md +10 -0
  625. package/pack/generated/claude/skills/devrites-lib/reference/standards/security-checklist.md +9 -0
  626. package/pack/generated/claude/skills/devrites-lib/reference/standards/security.md +135 -0
  627. package/pack/generated/claude/skills/devrites-lib/reference/standards/skill-authoring.md +105 -0
  628. package/pack/generated/claude/skills/devrites-lib/reference/standards/spec-grammar.md +185 -0
  629. package/pack/generated/claude/skills/devrites-lib/reference/standards/test-proof-checklist.md +9 -0
  630. package/pack/generated/claude/skills/devrites-lib/reference/standards/testing.md +162 -0
  631. package/pack/generated/claude/skills/devrites-lib/reference/standards/tooling.md +99 -0
  632. package/pack/generated/claude/skills/devrites-lib/reference/workspace-artifact-schema.md +110 -0
  633. package/pack/generated/claude/skills/devrites-prose-craft/SKILL.md +69 -0
  634. package/pack/generated/claude/skills/devrites-prose-craft/reference/banned-phrases.md +95 -0
  635. package/pack/generated/claude/skills/devrites-prose-craft/reference/examples.md +102 -0
  636. package/pack/generated/claude/skills/devrites-prose-craft/reference/structures.md +134 -0
  637. package/pack/generated/claude/skills/devrites-refresh-indexes/SKILL.md +51 -0
  638. package/pack/generated/claude/skills/devrites-source-driven/SKILL.md +52 -0
  639. package/pack/generated/claude/skills/devrites-ux-shape/SKILL.md +134 -0
  640. package/pack/generated/claude/skills/devrites-ux-shape/reference/brief-template.md +108 -0
  641. package/pack/generated/claude/skills/devrites-ux-shape/reference/visual-direction-probe.md +48 -0
  642. package/pack/generated/claude/skills/rite/SKILL.md +142 -0
  643. package/pack/generated/claude/skills/rite/reference/menu.md +42 -0
  644. package/pack/generated/claude/skills/rite-adopt/SKILL.md +104 -0
  645. package/pack/generated/claude/skills/rite-adopt/reference/adoption.md +55 -0
  646. package/pack/generated/claude/skills/rite-adopt/reference/anti-patterns.md +19 -0
  647. package/pack/generated/claude/skills/rite-autocomplete/SKILL.md +98 -0
  648. package/pack/generated/claude/skills/rite-autocomplete/reference/decision-policy.md +35 -0
  649. package/pack/generated/claude/skills/rite-autocomplete/reference/loop.md +54 -0
  650. package/pack/generated/claude/skills/rite-autocomplete/reference/stop-conditions.md +59 -0
  651. package/pack/generated/claude/skills/rite-build/SKILL.md +84 -0
  652. package/pack/generated/claude/skills/rite-build/reference/afk-discipline.md +145 -0
  653. package/pack/generated/claude/skills/rite-build/reference/anti-patterns.md +37 -0
  654. package/pack/generated/claude/skills/rite-build/reference/checkpoint-protocol.md +149 -0
  655. package/pack/generated/claude/skills/rite-build/reference/checkpoint.md +44 -0
  656. package/pack/generated/claude/skills/rite-build/reference/evidence-standard.md +35 -0
  657. package/pack/generated/claude/skills/rite-build/reference/forge.md +181 -0
  658. package/pack/generated/claude/skills/rite-build/reference/frontend-trigger.md +39 -0
  659. package/pack/generated/claude/skills/rite-build/reference/one-slice-cycle.md +42 -0
  660. package/pack/generated/claude/skills/rite-build/reference/output.md +41 -0
  661. package/pack/generated/claude/skills/rite-build/reference/phase-contract.md +258 -0
  662. package/pack/generated/claude/skills/rite-build/reference/spec-drift-guard.md +43 -0
  663. package/pack/generated/claude/skills/rite-build/reference/tdd.md +26 -0
  664. package/pack/generated/claude/skills/rite-build/reference/wright-dispatch.md +140 -0
  665. package/pack/generated/claude/skills/rite-converge/SKILL.md +131 -0
  666. package/pack/generated/claude/skills/rite-converge/reference/anti-patterns.md +35 -0
  667. package/pack/generated/claude/skills/rite-converge/reference/convergence-assessment.md +61 -0
  668. package/pack/generated/claude/skills/rite-customize/SKILL.md +67 -0
  669. package/pack/generated/claude/skills/rite-define/SKILL.md +153 -0
  670. package/pack/generated/claude/skills/rite-define/reference/anti-patterns.md +26 -0
  671. package/pack/generated/claude/skills/rite-define/reference/gates.md +152 -0
  672. package/pack/generated/claude/skills/rite-define/reference/plan-template.md +94 -0
  673. package/pack/generated/claude/skills/rite-doctor/SKILL.md +76 -0
  674. package/pack/generated/claude/skills/rite-dogfood/SKILL.md +49 -0
  675. package/pack/generated/claude/skills/rite-explain/SKILL.md +148 -0
  676. package/pack/generated/claude/skills/rite-explain/reference/intake.md +79 -0
  677. package/pack/generated/claude/skills/rite-frame/SKILL.md +120 -0
  678. package/pack/generated/claude/skills/rite-frame/reference/failure-modes.md +68 -0
  679. package/pack/generated/claude/skills/rite-handoff/SKILL.md +97 -0
  680. package/pack/generated/claude/skills/rite-handoff/reference/handoff-template.md +44 -0
  681. package/pack/generated/claude/skills/rite-learn/SKILL.md +117 -0
  682. package/pack/generated/claude/skills/rite-plan/SKILL.md +95 -0
  683. package/pack/generated/claude/skills/rite-plan/reference/anti-patterns.md +24 -0
  684. package/pack/generated/claude/skills/rite-plan/reference/dependency-graph.md +33 -0
  685. package/pack/generated/claude/skills/rite-plan/reference/replan-and-repair.md +42 -0
  686. package/pack/generated/claude/skills/rite-plan/reference/slicing.md +65 -0
  687. package/pack/generated/claude/skills/rite-plan/reference/task-breakdown.md +33 -0
  688. package/pack/generated/claude/skills/rite-polish/SKILL.md +87 -0
  689. package/pack/generated/claude/skills/rite-polish/reference/anti-ai-slop.md +206 -0
  690. package/pack/generated/claude/skills/rite-polish/reference/anti-patterns.md +30 -0
  691. package/pack/generated/claude/skills/rite-polish/reference/backend-polish.md +80 -0
  692. package/pack/generated/claude/skills/rite-polish/reference/browser-polish-evidence.md +31 -0
  693. package/pack/generated/claude/skills/rite-polish/reference/code.md +100 -0
  694. package/pack/generated/claude/skills/rite-polish/reference/design-system-discovery.md +8 -0
  695. package/pack/generated/claude/skills/rite-polish/reference/harden-checklist.md +109 -0
  696. package/pack/generated/claude/skills/rite-polish/reference/ui.md +136 -0
  697. package/pack/generated/claude/skills/rite-pov/SKILL.md +46 -0
  698. package/pack/generated/claude/skills/rite-pr-feedback/SKILL.md +49 -0
  699. package/pack/generated/claude/skills/rite-pressure-test/SKILL.md +74 -0
  700. package/pack/generated/claude/skills/rite-prototype/SKILL.md +110 -0
  701. package/pack/generated/claude/skills/rite-prove/SKILL.md +104 -0
  702. package/pack/generated/claude/skills/rite-prove/reference/acceptance-proof.md +48 -0
  703. package/pack/generated/claude/skills/rite-prove/reference/anti-patterns.md +25 -0
  704. package/pack/generated/claude/skills/rite-prove/reference/browser-proof.md +49 -0
  705. package/pack/generated/claude/skills/rite-prove/reference/failure-triage.md +25 -0
  706. package/pack/generated/claude/skills/rite-prove/reference/proof-ladder.md +28 -0
  707. package/pack/generated/claude/skills/rite-prove/reference/test-command-discovery.md +30 -0
  708. package/pack/generated/claude/skills/rite-quick/SKILL.md +93 -0
  709. package/pack/generated/claude/skills/rite-resolve/SKILL.md +109 -0
  710. package/pack/generated/claude/skills/rite-resolve/reference/answer-protocol.md +115 -0
  711. package/pack/generated/claude/skills/rite-review/SKILL.md +171 -0
  712. package/pack/generated/claude/skills/rite-review/reference/anti-patterns.md +32 -0
  713. package/pack/generated/claude/skills/rite-review/reference/cognitive-load.md +92 -0
  714. package/pack/generated/claude/skills/rite-review/reference/feature-scoped-review.md +26 -0
  715. package/pack/generated/claude/skills/rite-review/reference/five-axis-review.md +60 -0
  716. package/pack/generated/claude/skills/rite-review/reference/nielsen-heuristics.md +130 -0
  717. package/pack/generated/claude/skills/rite-review/reference/performance-checklist.md +80 -0
  718. package/pack/generated/claude/skills/rite-review/reference/performance-review.md +14 -0
  719. package/pack/generated/claude/skills/rite-review/reference/security-review.md +37 -0
  720. package/pack/generated/claude/skills/rite-seal/SKILL.md +101 -0
  721. package/pack/generated/claude/skills/rite-seal/reference/anti-patterns.md +29 -0
  722. package/pack/generated/claude/skills/rite-seal/reference/conventions-ledger.md +60 -0
  723. package/pack/generated/claude/skills/rite-seal/reference/final-evidence.md +64 -0
  724. package/pack/generated/claude/skills/rite-seal/reference/go-no-go.md +53 -0
  725. package/pack/generated/claude/skills/rite-seal/reference/output.md +7 -0
  726. package/pack/generated/claude/skills/rite-seal/reference/phase-contract.md +211 -0
  727. package/pack/generated/claude/skills/rite-seal/reference/risk-and-rollback.md +30 -0
  728. package/pack/generated/claude/skills/rite-seal/reference/seal-template.md +36 -0
  729. package/pack/generated/claude/skills/rite-ship/SKILL.md +111 -0
  730. package/pack/generated/claude/skills/rite-ship/reference/adr-promotion.md +9 -0
  731. package/pack/generated/claude/skills/rite-ship/reference/anti-patterns.md +25 -0
  732. package/pack/generated/claude/skills/rite-ship/reference/close-out.md +42 -0
  733. package/pack/generated/claude/skills/rite-ship/reference/design-memory.md +120 -0
  734. package/pack/generated/claude/skills/rite-ship/reference/git-ship.md +73 -0
  735. package/pack/generated/claude/skills/rite-ship/reference/ledger.md +56 -0
  736. package/pack/generated/claude/skills/rite-ship/reference/rollout.md +43 -0
  737. package/pack/generated/claude/skills/rite-ship/reference/ship-template.md +33 -0
  738. package/pack/generated/claude/skills/rite-spec/SKILL.md +217 -0
  739. package/pack/generated/claude/skills/rite-spec/reference/acceptance-criteria.md +31 -0
  740. package/pack/generated/claude/skills/rite-spec/reference/ai-spec-template.md +33 -0
  741. package/pack/generated/claude/skills/rite-spec/reference/anti-patterns.md +28 -0
  742. package/pack/generated/claude/skills/rite-spec/reference/interview-patterns.md +56 -0
  743. package/pack/generated/claude/skills/rite-spec/reference/investigation.md +84 -0
  744. package/pack/generated/claude/skills/rite-spec/reference/question-protocol.md +31 -0
  745. package/pack/generated/claude/skills/rite-spec/reference/references-intake.md +62 -0
  746. package/pack/generated/claude/skills/rite-spec/reference/spec-checklists.md +73 -0
  747. package/pack/generated/claude/skills/rite-spec/reference/spec-template.md +110 -0
  748. package/pack/generated/claude/skills/rite-spec/reference/state-workspace.md +156 -0
  749. package/pack/generated/claude/skills/rite-status/SKILL.md +107 -0
  750. package/pack/generated/claude/skills/rite-temper/SKILL.md +126 -0
  751. package/pack/generated/claude/skills/rite-temper/reference/anti-patterns.md +29 -0
  752. package/pack/generated/claude/skills/rite-temper/reference/review-dimensions.md +65 -0
  753. package/pack/generated/claude/skills/rite-temper/reference/scope-modes.md +53 -0
  754. package/pack/generated/claude/skills/rite-temper/reference/significance.md +46 -0
  755. package/pack/generated/claude/skills/rite-temper/reference/strategy-template.md +90 -0
  756. package/pack/generated/claude/skills/rite-vet/SKILL.md +175 -0
  757. package/pack/generated/claude/skills/rite-vet/reference/anti-patterns.md +29 -0
  758. package/pack/generated/claude/skills/rite-vet/reference/artifacts.md +135 -0
  759. package/pack/generated/claude/skills/rite-vet/reference/cross-model.md +43 -0
  760. package/pack/generated/claude/skills/rite-vet/reference/depth.md +53 -0
  761. package/pack/generated/claude/skills/rite-vet/reference/eng-lenses.md +48 -0
  762. package/pack/generated/claude/skills/rite-vet/reference/review-axes.md +167 -0
  763. package/pack/generated/claude/skills/rite-zoom-out/SKILL.md +75 -0
  764. package/pack/generated/codex/AGENTS.md +23 -0
  765. package/pack/generated/codex/agents/devrites-code-reviewer.toml +101 -0
  766. package/pack/generated/codex/agents/devrites-devex-reviewer.toml +102 -0
  767. package/pack/generated/codex/agents/devrites-doubt-reviewer.toml +66 -0
  768. package/pack/generated/codex/agents/devrites-forge-judge.toml +100 -0
  769. package/pack/generated/codex/agents/devrites-frontend-reviewer.toml +80 -0
  770. package/pack/generated/codex/agents/devrites-performance-reviewer.toml +109 -0
  771. package/pack/generated/codex/agents/devrites-plan-reviewer.toml +93 -0
  772. package/pack/generated/codex/agents/devrites-retrospector.toml +94 -0
  773. package/pack/generated/codex/agents/devrites-security-auditor.toml +83 -0
  774. package/pack/generated/codex/agents/devrites-simplifier-reviewer.toml +88 -0
  775. package/pack/generated/codex/agents/devrites-slice-wright.toml +207 -0
  776. package/pack/generated/codex/agents/devrites-spec-reviewer.toml +85 -0
  777. package/pack/generated/codex/agents/devrites-strategy-reviewer.toml +76 -0
  778. package/pack/generated/codex/agents/devrites-test-analyst.toml +62 -0
  779. package/pack/generated/codex/hooks.json +151 -0
  780. package/pack/generated/codex/skills/devrites-api-interface/SKILL.md +73 -0
  781. package/pack/generated/codex/skills/devrites-api-interface/agents/openai.yaml +2 -0
  782. package/pack/generated/codex/skills/devrites-audit/SKILL.md +85 -0
  783. package/pack/generated/codex/skills/devrites-audit/agents/openai.yaml +2 -0
  784. package/pack/generated/codex/skills/devrites-browser-proof/SKILL.md +88 -0
  785. package/pack/generated/codex/skills/devrites-browser-proof/agents/openai.yaml +2 -0
  786. package/pack/generated/codex/skills/devrites-browser-proof/reference/browser-performance.md +15 -0
  787. package/pack/generated/codex/skills/devrites-browser-proof/reference/visual-verdict.md +34 -0
  788. package/pack/generated/codex/skills/devrites-debug-recovery/SKILL.md +77 -0
  789. package/pack/generated/codex/skills/devrites-debug-recovery/agents/openai.yaml +2 -0
  790. package/pack/generated/codex/skills/devrites-debug-recovery/reference/build-the-loop.md +58 -0
  791. package/pack/generated/codex/skills/devrites-debug-recovery/reference/cleanup-and-classify.md +17 -0
  792. package/pack/generated/codex/skills/devrites-debug-recovery/reference/hypotheses.md +17 -0
  793. package/pack/generated/codex/skills/devrites-debug-recovery/reference/instrumentation.md +21 -0
  794. package/pack/generated/codex/skills/devrites-debug-recovery/reference/regression-test.md +30 -0
  795. package/pack/generated/codex/skills/devrites-debug-recovery/reference/trace.md +25 -0
  796. package/pack/generated/codex/skills/devrites-doubt/SKILL.md +94 -0
  797. package/pack/generated/codex/skills/devrites-doubt/agents/openai.yaml +2 -0
  798. package/pack/generated/codex/skills/devrites-frontend-craft/SKILL.md +111 -0
  799. package/pack/generated/codex/skills/devrites-frontend-craft/agents/openai.yaml +2 -0
  800. package/pack/generated/codex/skills/devrites-frontend-craft/reference/craft.md +71 -0
  801. package/pack/generated/codex/skills/devrites-frontend-craft/reference/design-references.md +116 -0
  802. package/pack/generated/codex/skills/devrites-frontend-craft/reference/fullstack.md +45 -0
  803. package/pack/generated/codex/skills/devrites-frontend-craft/reference/quality-standards.md +234 -0
  804. package/pack/generated/codex/skills/devrites-frontend-craft/reference/reuse-first.md +59 -0
  805. package/pack/generated/codex/skills/devrites-frontend-craft/reference/shape.md +60 -0
  806. package/pack/generated/codex/skills/devrites-interview/SKILL.md +116 -0
  807. package/pack/generated/codex/skills/devrites-interview/agents/openai.yaml +2 -0
  808. package/pack/generated/codex/skills/devrites-lib/SKILL.md +94 -0
  809. package/pack/generated/codex/skills/devrites-lib/agents/openai.yaml +2 -0
  810. package/pack/generated/codex/skills/devrites-lib/reference/intent-map.md +16 -0
  811. package/pack/generated/codex/skills/devrites-lib/reference/model-tiers.md +43 -0
  812. package/pack/generated/codex/skills/devrites-lib/reference/parallel-dispatch.md +165 -0
  813. package/pack/generated/codex/skills/devrites-lib/reference/reply-contract.md +111 -0
  814. package/pack/generated/codex/skills/devrites-lib/reference/standards/README.md +61 -0
  815. package/pack/generated/codex/skills/devrites-lib/reference/standards/afk-hitl.md +243 -0
  816. package/pack/generated/codex/skills/devrites-lib/reference/standards/agents.md +192 -0
  817. package/pack/generated/codex/skills/devrites-lib/reference/standards/anti-patterns.md +58 -0
  818. package/pack/generated/codex/skills/devrites-lib/reference/standards/browser-proof-checklist.md +9 -0
  819. package/pack/generated/codex/skills/devrites-lib/reference/standards/ci-cd.md +62 -0
  820. package/pack/generated/codex/skills/devrites-lib/reference/standards/code-review.md +141 -0
  821. package/pack/generated/codex/skills/devrites-lib/reference/standards/coding-style.md +55 -0
  822. package/pack/generated/codex/skills/devrites-lib/reference/standards/context-hygiene.md +114 -0
  823. package/pack/generated/codex/skills/devrites-lib/reference/standards/core.md +119 -0
  824. package/pack/generated/codex/skills/devrites-lib/reference/standards/definition-of-done.md +16 -0
  825. package/pack/generated/codex/skills/devrites-lib/reference/standards/deprecation.md +71 -0
  826. package/pack/generated/codex/skills/devrites-lib/reference/standards/developer-experience.md +119 -0
  827. package/pack/generated/codex/skills/devrites-lib/reference/standards/development-workflow.md +51 -0
  828. package/pack/generated/codex/skills/devrites-lib/reference/standards/documentation.md +35 -0
  829. package/pack/generated/codex/skills/devrites-lib/reference/standards/edge-case-trace.md +19 -0
  830. package/pack/generated/codex/skills/devrites-lib/reference/standards/elicitation.md +80 -0
  831. package/pack/generated/codex/skills/devrites-lib/reference/standards/error-handling.md +33 -0
  832. package/pack/generated/codex/skills/devrites-lib/reference/standards/git-workflow.md +65 -0
  833. package/pack/generated/codex/skills/devrites-lib/reference/standards/hooks.md +38 -0
  834. package/pack/generated/codex/skills/devrites-lib/reference/standards/observability.md +73 -0
  835. package/pack/generated/codex/skills/devrites-lib/reference/standards/patterns.md +48 -0
  836. package/pack/generated/codex/skills/devrites-lib/reference/standards/performance.md +36 -0
  837. package/pack/generated/codex/skills/devrites-lib/reference/standards/principles.md +158 -0
  838. package/pack/generated/codex/skills/devrites-lib/reference/standards/prose-style.md +117 -0
  839. package/pack/generated/codex/skills/devrites-lib/reference/standards/release/ship-checklist.md +9 -0
  840. package/pack/generated/codex/skills/devrites-lib/reference/standards/review-checklist.md +10 -0
  841. package/pack/generated/codex/skills/devrites-lib/reference/standards/security-checklist.md +9 -0
  842. package/pack/generated/codex/skills/devrites-lib/reference/standards/security.md +135 -0
  843. package/pack/generated/codex/skills/devrites-lib/reference/standards/skill-authoring.md +105 -0
  844. package/pack/generated/codex/skills/devrites-lib/reference/standards/spec-grammar.md +185 -0
  845. package/pack/generated/codex/skills/devrites-lib/reference/standards/test-proof-checklist.md +9 -0
  846. package/pack/generated/codex/skills/devrites-lib/reference/standards/testing.md +162 -0
  847. package/pack/generated/codex/skills/devrites-lib/reference/standards/tooling.md +99 -0
  848. package/pack/generated/codex/skills/devrites-lib/reference/workspace-artifact-schema.md +110 -0
  849. package/pack/generated/codex/skills/devrites-prose-craft/SKILL.md +81 -0
  850. package/pack/generated/codex/skills/devrites-prose-craft/agents/openai.yaml +2 -0
  851. package/pack/generated/codex/skills/devrites-prose-craft/reference/banned-phrases.md +95 -0
  852. package/pack/generated/codex/skills/devrites-prose-craft/reference/examples.md +102 -0
  853. package/pack/generated/codex/skills/devrites-prose-craft/reference/structures.md +134 -0
  854. package/pack/generated/codex/skills/devrites-refresh-indexes/SKILL.md +63 -0
  855. package/pack/generated/codex/skills/devrites-refresh-indexes/agents/openai.yaml +2 -0
  856. package/pack/generated/codex/skills/devrites-source-driven/SKILL.md +64 -0
  857. package/pack/generated/codex/skills/devrites-source-driven/agents/openai.yaml +2 -0
  858. package/pack/generated/codex/skills/devrites-ux-shape/SKILL.md +146 -0
  859. package/pack/generated/codex/skills/devrites-ux-shape/agents/openai.yaml +2 -0
  860. package/pack/generated/codex/skills/devrites-ux-shape/reference/brief-template.md +108 -0
  861. package/pack/generated/codex/skills/devrites-ux-shape/reference/visual-direction-probe.md +48 -0
  862. package/pack/generated/codex/skills/rite/SKILL.md +154 -0
  863. package/pack/generated/codex/skills/rite/agents/openai.yaml +2 -0
  864. package/pack/generated/codex/skills/rite/reference/menu.md +42 -0
  865. package/pack/generated/codex/skills/rite-adopt/SKILL.md +116 -0
  866. package/pack/generated/codex/skills/rite-adopt/reference/adoption.md +55 -0
  867. package/pack/generated/codex/skills/rite-adopt/reference/anti-patterns.md +19 -0
  868. package/pack/generated/codex/skills/rite-autocomplete/SKILL.md +110 -0
  869. package/pack/generated/codex/skills/rite-autocomplete/reference/decision-policy.md +35 -0
  870. package/pack/generated/codex/skills/rite-autocomplete/reference/loop.md +54 -0
  871. package/pack/generated/codex/skills/rite-autocomplete/reference/stop-conditions.md +59 -0
  872. package/pack/generated/codex/skills/rite-build/SKILL.md +96 -0
  873. package/pack/generated/codex/skills/rite-build/reference/afk-discipline.md +145 -0
  874. package/pack/generated/codex/skills/rite-build/reference/anti-patterns.md +37 -0
  875. package/pack/generated/codex/skills/rite-build/reference/checkpoint-protocol.md +149 -0
  876. package/pack/generated/codex/skills/rite-build/reference/checkpoint.md +44 -0
  877. package/pack/generated/codex/skills/rite-build/reference/evidence-standard.md +35 -0
  878. package/pack/generated/codex/skills/rite-build/reference/forge.md +181 -0
  879. package/pack/generated/codex/skills/rite-build/reference/frontend-trigger.md +39 -0
  880. package/pack/generated/codex/skills/rite-build/reference/one-slice-cycle.md +42 -0
  881. package/pack/generated/codex/skills/rite-build/reference/output.md +41 -0
  882. package/pack/generated/codex/skills/rite-build/reference/phase-contract.md +258 -0
  883. package/pack/generated/codex/skills/rite-build/reference/spec-drift-guard.md +43 -0
  884. package/pack/generated/codex/skills/rite-build/reference/tdd.md +26 -0
  885. package/pack/generated/codex/skills/rite-build/reference/wright-dispatch.md +140 -0
  886. package/pack/generated/codex/skills/rite-converge/SKILL.md +143 -0
  887. package/pack/generated/codex/skills/rite-converge/reference/anti-patterns.md +35 -0
  888. package/pack/generated/codex/skills/rite-converge/reference/convergence-assessment.md +61 -0
  889. package/pack/generated/codex/skills/rite-customize/SKILL.md +79 -0
  890. package/pack/generated/codex/skills/rite-customize/agents/openai.yaml +2 -0
  891. package/pack/generated/codex/skills/rite-define/SKILL.md +165 -0
  892. package/pack/generated/codex/skills/rite-define/reference/anti-patterns.md +26 -0
  893. package/pack/generated/codex/skills/rite-define/reference/gates.md +152 -0
  894. package/pack/generated/codex/skills/rite-define/reference/plan-template.md +94 -0
  895. package/pack/generated/codex/skills/rite-doctor/SKILL.md +88 -0
  896. package/pack/generated/codex/skills/rite-dogfood/SKILL.md +61 -0
  897. package/pack/generated/codex/skills/rite-dogfood/agents/openai.yaml +2 -0
  898. package/pack/generated/codex/skills/rite-explain/SKILL.md +160 -0
  899. package/pack/generated/codex/skills/rite-explain/agents/openai.yaml +2 -0
  900. package/pack/generated/codex/skills/rite-explain/reference/intake.md +79 -0
  901. package/pack/generated/codex/skills/rite-frame/SKILL.md +132 -0
  902. package/pack/generated/codex/skills/rite-frame/reference/failure-modes.md +68 -0
  903. package/pack/generated/codex/skills/rite-handoff/SKILL.md +109 -0
  904. package/pack/generated/codex/skills/rite-handoff/agents/openai.yaml +2 -0
  905. package/pack/generated/codex/skills/rite-handoff/reference/handoff-template.md +44 -0
  906. package/pack/generated/codex/skills/rite-learn/SKILL.md +129 -0
  907. package/pack/generated/codex/skills/rite-learn/agents/openai.yaml +2 -0
  908. package/pack/generated/codex/skills/rite-plan/SKILL.md +107 -0
  909. package/pack/generated/codex/skills/rite-plan/reference/anti-patterns.md +24 -0
  910. package/pack/generated/codex/skills/rite-plan/reference/dependency-graph.md +33 -0
  911. package/pack/generated/codex/skills/rite-plan/reference/replan-and-repair.md +42 -0
  912. package/pack/generated/codex/skills/rite-plan/reference/slicing.md +65 -0
  913. package/pack/generated/codex/skills/rite-plan/reference/task-breakdown.md +33 -0
  914. package/pack/generated/codex/skills/rite-polish/SKILL.md +99 -0
  915. package/pack/generated/codex/skills/rite-polish/reference/anti-ai-slop.md +206 -0
  916. package/pack/generated/codex/skills/rite-polish/reference/anti-patterns.md +30 -0
  917. package/pack/generated/codex/skills/rite-polish/reference/backend-polish.md +80 -0
  918. package/pack/generated/codex/skills/rite-polish/reference/browser-polish-evidence.md +31 -0
  919. package/pack/generated/codex/skills/rite-polish/reference/code.md +100 -0
  920. package/pack/generated/codex/skills/rite-polish/reference/design-system-discovery.md +8 -0
  921. package/pack/generated/codex/skills/rite-polish/reference/harden-checklist.md +109 -0
  922. package/pack/generated/codex/skills/rite-polish/reference/ui.md +136 -0
  923. package/pack/generated/codex/skills/rite-pov/SKILL.md +58 -0
  924. package/pack/generated/codex/skills/rite-pr-feedback/SKILL.md +61 -0
  925. package/pack/generated/codex/skills/rite-pr-feedback/agents/openai.yaml +2 -0
  926. package/pack/generated/codex/skills/rite-pressure-test/SKILL.md +86 -0
  927. package/pack/generated/codex/skills/rite-prototype/SKILL.md +122 -0
  928. package/pack/generated/codex/skills/rite-prototype/agents/openai.yaml +2 -0
  929. package/pack/generated/codex/skills/rite-prove/SKILL.md +116 -0
  930. package/pack/generated/codex/skills/rite-prove/reference/acceptance-proof.md +48 -0
  931. package/pack/generated/codex/skills/rite-prove/reference/anti-patterns.md +25 -0
  932. package/pack/generated/codex/skills/rite-prove/reference/browser-proof.md +49 -0
  933. package/pack/generated/codex/skills/rite-prove/reference/failure-triage.md +25 -0
  934. package/pack/generated/codex/skills/rite-prove/reference/proof-ladder.md +28 -0
  935. package/pack/generated/codex/skills/rite-prove/reference/test-command-discovery.md +30 -0
  936. package/pack/generated/codex/skills/rite-quick/SKILL.md +105 -0
  937. package/pack/generated/codex/skills/rite-resolve/SKILL.md +121 -0
  938. package/pack/generated/codex/skills/rite-resolve/agents/openai.yaml +2 -0
  939. package/pack/generated/codex/skills/rite-resolve/reference/answer-protocol.md +115 -0
  940. package/pack/generated/codex/skills/rite-review/SKILL.md +183 -0
  941. package/pack/generated/codex/skills/rite-review/reference/anti-patterns.md +32 -0
  942. package/pack/generated/codex/skills/rite-review/reference/cognitive-load.md +92 -0
  943. package/pack/generated/codex/skills/rite-review/reference/feature-scoped-review.md +26 -0
  944. package/pack/generated/codex/skills/rite-review/reference/five-axis-review.md +60 -0
  945. package/pack/generated/codex/skills/rite-review/reference/nielsen-heuristics.md +130 -0
  946. package/pack/generated/codex/skills/rite-review/reference/performance-checklist.md +80 -0
  947. package/pack/generated/codex/skills/rite-review/reference/performance-review.md +14 -0
  948. package/pack/generated/codex/skills/rite-review/reference/security-review.md +37 -0
  949. package/pack/generated/codex/skills/rite-seal/SKILL.md +113 -0
  950. package/pack/generated/codex/skills/rite-seal/reference/anti-patterns.md +29 -0
  951. package/pack/generated/codex/skills/rite-seal/reference/conventions-ledger.md +60 -0
  952. package/pack/generated/codex/skills/rite-seal/reference/final-evidence.md +64 -0
  953. package/pack/generated/codex/skills/rite-seal/reference/go-no-go.md +53 -0
  954. package/pack/generated/codex/skills/rite-seal/reference/output.md +7 -0
  955. package/pack/generated/codex/skills/rite-seal/reference/phase-contract.md +211 -0
  956. package/pack/generated/codex/skills/rite-seal/reference/risk-and-rollback.md +30 -0
  957. package/pack/generated/codex/skills/rite-seal/reference/seal-template.md +36 -0
  958. package/pack/generated/codex/skills/rite-ship/SKILL.md +123 -0
  959. package/pack/generated/codex/skills/rite-ship/reference/adr-promotion.md +9 -0
  960. package/pack/generated/codex/skills/rite-ship/reference/anti-patterns.md +25 -0
  961. package/pack/generated/codex/skills/rite-ship/reference/close-out.md +42 -0
  962. package/pack/generated/codex/skills/rite-ship/reference/design-memory.md +120 -0
  963. package/pack/generated/codex/skills/rite-ship/reference/git-ship.md +73 -0
  964. package/pack/generated/codex/skills/rite-ship/reference/ledger.md +56 -0
  965. package/pack/generated/codex/skills/rite-ship/reference/rollout.md +43 -0
  966. package/pack/generated/codex/skills/rite-ship/reference/ship-template.md +33 -0
  967. package/pack/generated/codex/skills/rite-spec/SKILL.md +229 -0
  968. package/pack/generated/codex/skills/rite-spec/reference/acceptance-criteria.md +31 -0
  969. package/pack/generated/codex/skills/rite-spec/reference/ai-spec-template.md +33 -0
  970. package/pack/generated/codex/skills/rite-spec/reference/anti-patterns.md +28 -0
  971. package/pack/generated/codex/skills/rite-spec/reference/interview-patterns.md +56 -0
  972. package/pack/generated/codex/skills/rite-spec/reference/investigation.md +84 -0
  973. package/pack/generated/codex/skills/rite-spec/reference/question-protocol.md +31 -0
  974. package/pack/generated/codex/skills/rite-spec/reference/references-intake.md +62 -0
  975. package/pack/generated/codex/skills/rite-spec/reference/spec-checklists.md +73 -0
  976. package/pack/generated/codex/skills/rite-spec/reference/spec-template.md +110 -0
  977. package/pack/generated/codex/skills/rite-spec/reference/state-workspace.md +156 -0
  978. package/pack/generated/codex/skills/rite-status/SKILL.md +119 -0
  979. package/pack/generated/codex/skills/rite-status/agents/openai.yaml +2 -0
  980. package/pack/generated/codex/skills/rite-temper/SKILL.md +138 -0
  981. package/pack/generated/codex/skills/rite-temper/reference/anti-patterns.md +29 -0
  982. package/pack/generated/codex/skills/rite-temper/reference/review-dimensions.md +65 -0
  983. package/pack/generated/codex/skills/rite-temper/reference/scope-modes.md +53 -0
  984. package/pack/generated/codex/skills/rite-temper/reference/significance.md +46 -0
  985. package/pack/generated/codex/skills/rite-temper/reference/strategy-template.md +90 -0
  986. package/pack/generated/codex/skills/rite-vet/SKILL.md +187 -0
  987. package/pack/generated/codex/skills/rite-vet/reference/anti-patterns.md +29 -0
  988. package/pack/generated/codex/skills/rite-vet/reference/artifacts.md +135 -0
  989. package/pack/generated/codex/skills/rite-vet/reference/cross-model.md +43 -0
  990. package/pack/generated/codex/skills/rite-vet/reference/depth.md +53 -0
  991. package/pack/generated/codex/skills/rite-vet/reference/eng-lenses.md +48 -0
  992. package/pack/generated/codex/skills/rite-vet/reference/review-axes.md +167 -0
  993. package/pack/generated/codex/skills/rite-zoom-out/SKILL.md +87 -0
  994. package/pack/generated/codex/skills/rite-zoom-out/agents/openai.yaml +2 -0
  995. package/package.json +8 -4
  996. package/scripts/build-binaries.sh +75 -0
  997. package/scripts/build-host-artifacts.sh +100 -0
  998. package/scripts/build-release-tarball.sh +16 -2
  999. package/scripts/check-cross-refs.py +17 -3
  1000. package/scripts/check-generated-skill-budget.mjs +41 -0
  1001. package/scripts/check-instruction-size-baseline.mjs +79 -0
  1002. package/scripts/check-invocation-integrity.py +113 -0
  1003. package/scripts/check-no-global-writes.sh +22 -0
  1004. package/scripts/check-no-personal-paths.py +50 -0
  1005. package/scripts/check-reference-governance.mjs +82 -0
  1006. package/scripts/check-reply-contract.sh +64 -0
  1007. package/scripts/check-rule-uniqueness.sh +4 -32
  1008. package/scripts/codex-generate.sh +300 -0
  1009. package/scripts/devrites-detect.sh +2 -1
  1010. package/scripts/eval-runner.py +4 -2
  1011. package/scripts/eval-scorer.mjs +46 -0
  1012. package/scripts/grade-feature.sh +24 -7
  1013. package/scripts/install-lib.sh +112 -19
  1014. package/scripts/pin.sh +4 -4
  1015. package/scripts/release-check.sh +71 -0
  1016. package/scripts/run-behavioral-evals.sh +34 -2
  1017. package/scripts/run-evals.sh +45 -30
  1018. package/scripts/run-live-behavioral-evals.py +180 -0
  1019. package/scripts/run-outcome-evals.sh +27 -0
  1020. package/scripts/run-routing-evals.py +342 -0
  1021. package/scripts/run-tests.mjs +203 -0
  1022. package/scripts/skill-pruning-audit.mjs +120 -0
  1023. package/scripts/skills-inventory.mjs +107 -0
  1024. package/scripts/validate-agent-composition.py +57 -0
  1025. package/scripts/validate-command-parity.py +70 -0
  1026. package/scripts/validate-frontmatter.py +43 -7
  1027. package/scripts/validate-skill-anatomy.py +139 -0
  1028. package/scripts/validate-workflow-security.py +22 -3
  1029. package/scripts/validate-workspace-schema.py +512 -0
  1030. package/scripts/validate.sh +174 -34
  1031. package/uninstall.sh +22 -183
  1032. package/update.sh +29 -185
  1033. package/docs/cli-mcp.md +0 -62
  1034. package/mcp/devrites-mcp.mjs +0 -105
  1035. package/pack/.claude/hooks/devrites-a1-guard.sh +0 -99
  1036. package/pack/.claude/hooks/devrites-allow.sh +0 -44
  1037. package/pack/.claude/hooks/devrites-cursor.sh +0 -28
  1038. package/pack/.claude/hooks/devrites-orient.sh +0 -53
  1039. package/pack/.claude/hooks/devrites-redwatch.sh +0 -39
  1040. package/pack/.claude/hooks/devrites-refresh-indexes.sh +0 -127
  1041. package/pack/.claude/hooks/devrites-reviewer-readonly.sh +0 -37
  1042. package/pack/.claude/hooks/devrites-statusline.sh +0 -18
  1043. package/pack/.claude/hooks/devrites-stop-gate.sh +0 -45
  1044. package/pack/.claude/hooks/devrites-wright-scope.sh +0 -64
  1045. package/pack/.claude/hooks/hooks.json +0 -52
  1046. package/pack/.claude/rules/code-review.md +0 -48
  1047. package/pack/.claude/rules/development-workflow.md +0 -40
  1048. package/pack/.claude/rules/git-workflow.md +0 -35
  1049. package/pack/.claude/rules/spec-grammar.md +0 -106
  1050. package/pack/.claude/rules/testing.md +0 -88
  1051. package/pack/.claude/skills/devrites-lib/scripts/analyze.sh +0 -78
  1052. package/pack/.claude/skills/devrites-lib/scripts/check-acceptance.sh +0 -75
  1053. package/pack/.claude/skills/devrites-lib/scripts/close-out.sh +0 -47
  1054. package/pack/.claude/skills/devrites-lib/scripts/conventions.py +0 -273
  1055. package/pack/.claude/skills/devrites-lib/scripts/coverage.sh +0 -51
  1056. package/pack/.claude/skills/devrites-lib/scripts/devrites.sh +0 -77
  1057. package/pack/.claude/skills/devrites-lib/scripts/doctor.sh +0 -156
  1058. package/pack/.claude/skills/devrites-lib/scripts/doubt-coverage.sh +0 -59
  1059. package/pack/.claude/skills/devrites-lib/scripts/evidence-fresh.sh +0 -63
  1060. package/pack/.claude/skills/devrites-lib/scripts/footprint.sh +0 -45
  1061. package/pack/.claude/skills/devrites-lib/scripts/learnings.sh +0 -74
  1062. package/pack/.claude/skills/devrites-lib/scripts/mutation-gate.sh +0 -52
  1063. package/pack/.claude/skills/devrites-lib/scripts/package-existence.sh +0 -68
  1064. package/pack/.claude/skills/devrites-lib/scripts/preamble.sh +0 -76
  1065. package/pack/.claude/skills/devrites-lib/scripts/progress.sh +0 -103
  1066. package/pack/.claude/skills/devrites-lib/scripts/readiness.sh +0 -62
  1067. package/pack/.claude/skills/devrites-lib/scripts/reconcile.sh +0 -123
  1068. package/pack/.claude/skills/devrites-lib/scripts/resolve.sh +0 -279
  1069. package/pack/.claude/skills/devrites-lib/scripts/rites.sh +0 -41
  1070. package/pack/.claude/skills/devrites-lib/scripts/spec-validate.sh +0 -130
  1071. package/pack/.claude/skills/devrites-lib/scripts/stuck.sh +0 -67
  1072. package/pack/.claude/skills/devrites-lib/scripts/test-integrity.sh +0 -87
  1073. package/pack/.claude/skills/devrites-lib/scripts/tick-afk.sh +0 -52
  1074. package/scripts/merge-codex-hooks.mjs +0 -78
  1075. /package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/coding-style.md +0 -0
  1076. /package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/error-handling.md +0 -0
  1077. /package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/hooks.md +0 -0
  1078. /package/pack/.claude/{rules → skills/devrites-lib/reference/standards}/patterns.md +0 -0
@@ -0,0 +1,942 @@
1
+ package main_test
2
+
3
+ // Golden + diagnostic tests for the ported devrites-lib commands (issue 08).
4
+ //
5
+ // Golden: each command is run through the Go binary against a fixture, and its
6
+ // stdout + exit code are checked against a recorded golden snapshot (stderr is
7
+ // diagnostic, not contract). Snapshots are regenerated with UPDATE_GOLDEN=1.
8
+ //
9
+ // Diagnostic: a second pass asserts the Go stderr carries the same actionable
10
+ // finding substrings a consumer greps for, so the port keeps its diagnostic
11
+ // quality even though stderr is excluded from the golden check.
12
+
13
+ import (
14
+ "bytes"
15
+ "errors"
16
+ "os"
17
+ "os/exec"
18
+ "path/filepath"
19
+ "testing"
20
+ "time"
21
+
22
+ "github.com/devrites/devrites/internal/testutil"
23
+ )
24
+
25
+ // libEnv forces byte-order collation so `sort` in the bash script and
26
+ // sort.Strings in Go agree (matters for check-acceptance's id ordering).
27
+ var libEnv = []string{"LC_ALL=C", "DEVRITES_ROOT="}
28
+
29
+ // libRootEnv points DEVRITES_ROOT at the workspace's .devrites directory so the
30
+ // command reads the fixture under <root>/features/<slug>. LC_ALL=C pins byte-order
31
+ // collation so id ordering is deterministic.
32
+ func libRootEnv(work string) []string {
33
+ return []string{"LC_ALL=C", "DEVRITES_ROOT=" + filepath.Join(work, ".devrites")}
34
+ }
35
+
36
+ // writeFeatureFile writes fixture content to <work>/.devrites/features/<slug>/<name>.
37
+ func writeFeatureFile(t *testing.T, work, slug, name, content string) {
38
+ t.Helper()
39
+ writeFile(t, work, filepath.Join(".devrites/features", slug, name), content)
40
+ }
41
+
42
+ // makeFeatureDir creates an empty feature directory in the workspace.
43
+ func makeFeatureDir(t *testing.T, work, slug string) {
44
+ t.Helper()
45
+ mkdirAllT(t, work, filepath.Join(".devrites/features", slug))
46
+ }
47
+
48
+ // writeSpec writes content to <workdir>/<name>/spec.md and returns the subdir name.
49
+ func writeSpec(t *testing.T, workdir, name, content string) string {
50
+ t.Helper()
51
+ dir := filepath.Join(workdir, name)
52
+ if err := os.MkdirAll(dir, 0o755); err != nil {
53
+ t.Fatal(err)
54
+ }
55
+ if err := os.WriteFile(filepath.Join(dir, "spec.md"), []byte(content), 0o644); err != nil {
56
+ t.Fatal(err)
57
+ }
58
+ return name
59
+ }
60
+
61
+ func writeFile(t *testing.T, workdir, rel, content string) {
62
+ t.Helper()
63
+ testutil.WriteFile(t, filepath.Join(workdir, rel), content)
64
+ }
65
+
66
+ // runGo runs the built binary in workdir with libEnv, returning stdout, stderr, code.
67
+ func runGo(t *testing.T, workdir string, args ...string) (stdout, stderr string, code int) {
68
+ t.Helper()
69
+ cmd := exec.Command(binPath, args...)
70
+ cmd.Dir = workdir
71
+ cmd.Env = append(os.Environ(), libEnv...)
72
+ var out, errBuf bytes.Buffer
73
+ cmd.Stdout = &out
74
+ cmd.Stderr = &errBuf
75
+ if err := cmd.Run(); err != nil {
76
+ var ee *exec.ExitError
77
+ if !errors.As(err, &ee) {
78
+ t.Fatalf("running %s %v: %v", binPath, args, err)
79
+ }
80
+ code = ee.ExitCode()
81
+ }
82
+ return out.String(), errBuf.String(), code
83
+ }
84
+
85
+ // ---- spec-validate --------------------------------------------------------
86
+
87
+ // Spec fixtures cover the well-formed spec plus each malformed shape so the
88
+ // golden check exercises every spec-validate verdict.
89
+ const (
90
+ specValid = `# Spec
91
+ ## Acceptance criteria
92
+ ### Requirement: Tokens expire after inactivity
93
+ The system SHALL reject a session token older than 15 minutes.
94
+ #### Scenario: expired token
95
+ - [ ] [AC1] **WHEN** a token aged > 15m is presented **THEN** respond 401
96
+ #### Scenario: fresh token
97
+ - [ ] [AC2] **WHEN** a token aged < 15m is presented **THEN** allow
98
+ ### Requirement: Logout revokes the token
99
+ Logout MUST invalidate the token server-side.
100
+ #### Scenario: replay after logout
101
+ - [ ] [AC3] **WHEN** a logged-out token is replayed **THEN** respond 401
102
+ `
103
+ specFlat = `# Spec
104
+ ## Acceptance criteria
105
+ - [ ] [AC1] export returns a CSV with a header row
106
+ - [ ] [AC2] an empty dataset returns 204
107
+ `
108
+ specNoShall = `### Requirement: Export behaves nicely
109
+ The export produces a file and emails the user.
110
+ #### Scenario: happy path
111
+ - **WHEN** a user requests an export **THEN** a file is produced
112
+ `
113
+ specNoScenario = `### Requirement: It works
114
+ The system SHALL do the thing.
115
+ `
116
+ specNoThen = `### Requirement: It works
117
+ The system SHALL do the thing.
118
+ #### Scenario: half a scenario
119
+ - **WHEN** something happens
120
+ `
121
+ specDup = `### Requirement: Same name
122
+ The system SHALL alpha.
123
+ #### Scenario: a
124
+ - **WHEN** a **THEN** b
125
+ ### Requirement: Same name
126
+ The system SHALL beta.
127
+ #### Scenario: c
128
+ - **WHEN** c **THEN** d
129
+ `
130
+ )
131
+
132
+ func TestParitySpecValidate(t *testing.T) {
133
+ work := t.TempDir()
134
+
135
+ writeSpec(t, work, "valid", specValid)
136
+ writeSpec(t, work, "flat", specFlat)
137
+ writeSpec(t, work, "noshall", specNoShall)
138
+ writeSpec(t, work, "noscenario", specNoScenario)
139
+ writeSpec(t, work, "nothen", specNoThen)
140
+ writeSpec(t, work, "dup", specDup)
141
+ if err := os.MkdirAll(filepath.Join(work, "empty"), 0o755); err != nil {
142
+ t.Fatal(err)
143
+ }
144
+
145
+ // arg is the positional argument passed to both implementations, relative to work.
146
+ for _, arg := range []string{
147
+ "valid", // well-formed structured spec → exit 0
148
+ "flat", // flat-bullet form → exit 0 (no-op)
149
+ "noshall", // missing SHALL/MUST → exit 1
150
+ "noscenario", // requirement with no scenario → exit 1
151
+ "nothen", // scenario missing THEN → exit 1
152
+ "dup", // duplicate headers → exit 1
153
+ "valid/spec.md", // direct file path → exit 0
154
+ "empty", // dir without spec.md → exit 5
155
+ "nonexistent", // no such workspace or file → exit 2
156
+ } {
157
+ c := parityCase{
158
+ workdir: work,
159
+ env: libEnv,
160
+ goArgs: []string{"spec-validate", arg},
161
+ }
162
+ t.Run("arg="+arg, func(t *testing.T) { c.assertEqual(t) })
163
+ }
164
+
165
+ // No-argument usage path (exit 2) — asserted separately since arg is absent.
166
+ (parityCase{
167
+ workdir: work,
168
+ env: libEnv,
169
+ goArgs: []string{"spec-validate"},
170
+ }).assertEqual(t)
171
+ }
172
+
173
+ func TestSpecSkeleton(t *testing.T) {
174
+ work := t.TempDir()
175
+
176
+ writeSpec(t, work, "present", `# Contract
177
+
178
+ ## Problem
179
+ done
180
+ ## Goal
181
+ done
182
+ ## Non-goals
183
+ done
184
+ ## Users / actors
185
+ done
186
+ ## Requirements
187
+ done
188
+ ## Acceptance criteria
189
+ done
190
+ ## Edge Coverage
191
+ done
192
+ ## Prohibitions (must-NOT)
193
+ done
194
+ ## Edge cases
195
+ done
196
+ ## Measurable success
197
+ done
198
+ ## Scope boundaries
199
+ done
200
+ `)
201
+ writeSpec(t, work, "missing", `# Contract
202
+
203
+ ## Problem
204
+ done
205
+ ## Goal
206
+ done
207
+ ## Requirements
208
+ done
209
+ `)
210
+
211
+ for _, tc := range []struct {
212
+ name string
213
+ arg string
214
+ }{
215
+ {"present-all", "present"},
216
+ {"missing-some", "missing/spec.md"},
217
+ } {
218
+ tc := tc
219
+ t.Run(tc.name, func(t *testing.T) {
220
+ (parityCase{
221
+ workdir: work,
222
+ env: libEnv,
223
+ goArgs: []string{"spec-skeleton", tc.arg},
224
+ }).assertEqual(t)
225
+ })
226
+ }
227
+ }
228
+
229
+ // TestSpecValidateDiagnostics asserts the Go stderr carries the same finding
230
+ // substrings the legacy spec-validate-test.sh greps for.
231
+ func TestSpecValidateDiagnostics(t *testing.T) {
232
+ work := t.TempDir()
233
+ cases := []struct {
234
+ name, content, wantExit1 string
235
+ }{
236
+ {"noshall", specNoShall, "no SHALL/MUST"},
237
+ {"noscenario", specNoScenario, `no "#### Scenario:"`},
238
+ {"nothen", specNoThen, "no THEN line"},
239
+ {"dup", specDup, "duplicate Requirement header"},
240
+ }
241
+ for _, tc := range cases {
242
+ writeSpec(t, work, tc.name, tc.content)
243
+ _, stderr, code := runGo(t, work, "spec-validate", tc.name)
244
+ if code != 1 {
245
+ t.Errorf("%s: exit=%d, want 1", tc.name, code)
246
+ }
247
+ if !bytes.Contains([]byte(stderr), []byte(tc.wantExit1)) {
248
+ t.Errorf("%s: stderr %q missing %q", tc.name, stderr, tc.wantExit1)
249
+ }
250
+ }
251
+ }
252
+
253
+ // ---- check-acceptance -----------------------------------------------------
254
+
255
+ func TestParityCheckAcceptance(t *testing.T) {
256
+ work := t.TempDir()
257
+
258
+ // id mode, all proven → exit 0
259
+ writeFile(t, work, "id-ok/spec.md", "## Acceptance criteria\n- [ ] [AC1] a\n- [ ] [AC2] b\n- [ ] [AC3] c\n")
260
+ writeFile(t, work, "id-ok/seal.md", "## Acceptance Criteria\n- [x] [AC1] a — evidence: t1\n- [x] [AC2] b — evidence: t2\n- [x] [AC3] c — evidence: t3\n")
261
+
262
+ // id mode, one unproven → exit 1
263
+ writeFile(t, work, "id-gap/spec.md", "## Acceptance criteria\n- [ ] [AC1] a\n- [ ] [AC2] b\n- [ ] [AC3] c\n")
264
+ writeFile(t, work, "id-gap/seal.md", "## Acceptance Criteria\n- [x] [AC1] a — evidence: t1\n- [ ] [AC2] b\n- [ ] [AC3] c\n")
265
+
266
+ // fallback (no ids), all checked → exit 0
267
+ writeFile(t, work, "flat-ok/spec.md", "## Acceptance criteria\n- export returns CSV\n- empty dataset returns 204\n")
268
+ writeFile(t, work, "flat-ok/seal.md", "## Acceptance Criteria\n- [x] export returns CSV\n- [x] empty dataset returns 204\n")
269
+
270
+ // fallback, one unchecked → exit 1
271
+ writeFile(t, work, "flat-unchecked/spec.md", "## Acceptance criteria\n- export returns CSV\n- empty dataset returns 204\n")
272
+ writeFile(t, work, "flat-unchecked/seal.md", "## Acceptance Criteria\n- [x] export returns CSV\n- [ ] empty dataset returns 204\n")
273
+
274
+ // fallback, seal drops a criterion → exit 1
275
+ writeFile(t, work, "flat-dropped/spec.md", "## Acceptance criteria\n- a\n- b\n- c\n")
276
+ writeFile(t, work, "flat-dropped/seal.md", "## Acceptance Criteria\n- [x] a\n- [x] b\n")
277
+
278
+ // spec has no acceptance section → exit 1
279
+ writeFile(t, work, "no-section/spec.md", "# Spec\nsome prose, no criteria heading\n")
280
+ writeFile(t, work, "no-section/seal.md", "## Acceptance Criteria\n- [x] a\n")
281
+
282
+ // spec has an acceptance heading but only blank lines under it → still
283
+ // "nothing to grade" (bash `[ -z ]` after trailing-newline strip), exit 1.
284
+ writeFile(t, work, "blank-section/spec.md", "## Acceptance criteria\n\n\n## Notes\nprose\n")
285
+ writeFile(t, work, "blank-section/seal.md", "## Acceptance Criteria\n- [x] a\n")
286
+
287
+ // missing seal.md → exit 5
288
+ writeFile(t, work, "no-seal/spec.md", "## Acceptance criteria\n- [ ] [AC1] a\n")
289
+
290
+ // empty dir (missing spec.md) → exit 5
291
+ if err := os.MkdirAll(filepath.Join(work, "empty"), 0o755); err != nil {
292
+ t.Fatal(err)
293
+ }
294
+
295
+ for _, arg := range []string{
296
+ "id-ok", "id-gap", "flat-ok", "flat-unchecked", "flat-dropped",
297
+ "no-section", "blank-section", "no-seal", "empty", "nonexistent",
298
+ } {
299
+ c := parityCase{
300
+ workdir: work,
301
+ env: libEnv,
302
+ goArgs: []string{"check-acceptance", arg},
303
+ }
304
+ t.Run("arg="+arg, func(t *testing.T) { c.assertEqual(t) })
305
+ }
306
+
307
+ // No-argument usage path (exit 2).
308
+ (parityCase{
309
+ workdir: work,
310
+ env: libEnv,
311
+ goArgs: []string{"check-acceptance"},
312
+ }).assertEqual(t)
313
+ }
314
+
315
+ // ---- footprint ------------------------------------------------------------
316
+ //
317
+ // Golden tests: the expected stdout + exit values are asserted inline under
318
+ // LC_ALL=C, so the feature stands alone. The invariants a future edit must
319
+ // preserve: skip records never count, active-minutes = int((max-min)/60), the
320
+ // wright · reviewer · audit · doubt kind order with correct singular/plural
321
+ // forms, and the roster 0/1/3 exit taxonomy.
322
+
323
+ // goldenCase asserts the built binary's stdout + exit code for one invocation.
324
+ type goldenCase struct {
325
+ name string
326
+ args []string
327
+ wantOut string
328
+ wantCode int
329
+ }
330
+
331
+ func (gc goldenCase) assert(t *testing.T, work string) {
332
+ t.Helper()
333
+ out, _, code := runGo(t, work, gc.args...)
334
+ if out != gc.wantOut || code != gc.wantCode {
335
+ t.Errorf("%s: got exit=%d out=%q\n want exit=%d out=%q",
336
+ gc.name, code, out, gc.wantCode, gc.wantOut)
337
+ }
338
+ }
339
+
340
+ func TestFootprintGolden(t *testing.T) {
341
+ work := t.TempDir()
342
+
343
+ // render: the deterministic fixed-epoch log from tests/footprint-test.sh.
344
+ writeFile(t, work, ".devrites/features/rendered/footprint.log",
345
+ "1000 wright 01-list\n1100 wright 02-detail\n"+
346
+ "1200 reviewer devrites-code-reviewer\n1200 reviewer devrites-security-auditor\n"+
347
+ "1300 reviewer devrites-test-analyst\n")
348
+ // single reviewer → the singular "1 subagent (1 reviewer)" + 0-slice path.
349
+ writeFile(t, work, ".devrites/features/one/footprint.log", "1000 reviewer spec-reviewer\n")
350
+ // audit + doubt → those kinds' pluralization and order.
351
+ writeFile(t, work, ".devrites/features/ad/footprint.log",
352
+ "1000 wright a\n1000 audit x\n1000 audit y\n1000 doubt z\n")
353
+ mkdirAllT(t, work, ".devrites/features/nolog")
354
+ writeFile(t, work, ".devrites/features/rc-complete/footprint.log",
355
+ "1000 reviewer spec-reviewer\n1000 reviewer code-reviewer\n1000 reviewer test-analyst\n"+
356
+ "1000 reviewer frontend-reviewer\n1000 skip security-auditor\n"+
357
+ "1000 skip performance-reviewer\n1000 skip devex-reviewer\n")
358
+ writeFile(t, work, ".devrites/features/rc-unacc/footprint.log",
359
+ "1000 reviewer spec-reviewer\n1000 reviewer code-reviewer\n")
360
+ writeFile(t, work, ".devrites/features/rc-skip/footprint.log",
361
+ "1000 reviewer spec-reviewer\n1000 reviewer code-reviewer\n1000 skip test-analyst\n"+
362
+ "1000 skip frontend-reviewer\n1000 skip security-auditor\n"+
363
+ "1000 skip performance-reviewer\n1000 skip devex-reviewer\n")
364
+ mkdirAllT(t, work, ".devrites/features/live")
365
+
366
+ rosterComplete := " spec-reviewer: dispatched\n code-reviewer: dispatched\n" +
367
+ " test-analyst: dispatched\n frontend-reviewer: dispatched\n" +
368
+ " security-auditor: skipped\n performance-reviewer: skipped\n" +
369
+ " devex-reviewer: skipped\nroster: complete (every reviewer accounted for)\n"
370
+ rosterUnacc := " spec-reviewer: dispatched\n code-reviewer: dispatched\n" +
371
+ " test-analyst: UNACCOUNTED\n frontend-reviewer: UNACCOUNTED\n" +
372
+ " security-auditor: UNACCOUNTED\n performance-reviewer: UNACCOUNTED\n" +
373
+ " devex-reviewer: UNACCOUNTED\n" +
374
+ "roster: UNACCOUNTED — test-analyst frontend-reviewer security-auditor performance-reviewer devex-reviewer\n"
375
+ rosterSkip := " spec-reviewer: dispatched\n code-reviewer: dispatched\n" +
376
+ " test-analyst: skipped (always-on — verify carry-forward)\n" +
377
+ " frontend-reviewer: skipped\n security-auditor: skipped\n" +
378
+ " performance-reviewer: skipped\n devex-reviewer: skipped\n" +
379
+ "roster: always-on skipped — test-analyst\n"
380
+
381
+ for _, gc := range []goldenCase{
382
+ {"render", []string{"footprint", "render", "rendered"},
383
+ "Footprint: 5 subagents (2 wright · 3 reviewers) · 2 slices · ~5m active\n", 0},
384
+ {"render-singular", []string{"footprint", "render", "one"},
385
+ "Footprint: 1 subagent (1 reviewer) · 0 slices · ~0m active\n", 0},
386
+ {"render-audit-doubt", []string{"footprint", "render", "ad"},
387
+ "Footprint: 4 subagents (1 wright · 2 audits · 1 doubt) · 1 slice · ~0m active\n", 0},
388
+ {"render-nolog", []string{"footprint", "render", "nolog"},
389
+ "Footprint: n/a (no dispatch records)\n", 0},
390
+ {"render-missing-ws", []string{"footprint", "render", "ghost"},
391
+ "Footprint: n/a (no dispatch records)\n", 0},
392
+ {"roster-complete", []string{"footprint", "roster", "rc-complete"}, rosterComplete, 0},
393
+ {"roster-unaccounted", []string{"footprint", "roster", "rc-unacc"}, rosterUnacc, 3},
394
+ {"roster-skip-alwayson", []string{"footprint", "roster", "rc-skip"}, rosterSkip, 1},
395
+ {"roster-nolog", []string{"footprint", "roster", "nolog"},
396
+ "roster: n/a (no dispatch records — fan-out did not run)\n", 0},
397
+ {"log-missing-ws", []string{"footprint", "log", "ghost", "wright", "x"}, "", 0},
398
+ {"log-usage-no-kind", []string{"footprint", "log", "live"}, "", 2},
399
+ {"unknown-subcommand", []string{"footprint", "bogus", "live"}, "", 2},
400
+ {"missing-slug", []string{"footprint", "render"}, "", 2},
401
+ {"no-args", []string{"footprint"}, "", 2},
402
+ } {
403
+ t.Run(gc.name, func(t *testing.T) { gc.assert(t, work) })
404
+ }
405
+
406
+ // The footprint never emits a token/dollar/cost figure — DevRites cannot
407
+ // truthfully source one (the same invariant footprint-test.sh guards).
408
+ out, _, _ := runGo(t, work, "footprint", "render", "rendered")
409
+ for _, banned := range []string{"token", "$", "cost", "usd", "USD"} {
410
+ if bytes.Contains([]byte(out), []byte(banned)) {
411
+ t.Errorf("render leaked a %q figure: %q", banned, out)
412
+ }
413
+ }
414
+ }
415
+
416
+ // TestFootprintLogAppends asserts the side-effect the parity oracle can't (it
417
+ // compares only stdout+exit): `log` appends exactly one record and a missing
418
+ // workspace is a silent no-op.
419
+ func TestFootprintLogAppends(t *testing.T) {
420
+ work := t.TempDir()
421
+ mkdirAllT(t, work, ".devrites/features/feat")
422
+ logp := filepath.Join(work, ".devrites", "features", "feat", "footprint.log")
423
+
424
+ if _, _, code := runGo(t, work, "footprint", "log", "feat", "audit", "security"); code != 0 {
425
+ t.Fatalf("log exit=%d, want 0", code)
426
+ }
427
+ if n := fileLines(t, logp); n != 1 {
428
+ t.Errorf("after one log: %d lines, want 1", n)
429
+ }
430
+ runGo(t, work, "footprint", "log", "feat", "wright", "01")
431
+ if n := fileLines(t, logp); n != 2 {
432
+ t.Errorf("after two logs: %d lines, want 2", n)
433
+ }
434
+
435
+ // An empty label still writes its trailing space — byte-parity with
436
+ // footprint.sh's `printf '%s %s %s\n'`, which always emits three fields.
437
+ runGo(t, work, "footprint", "log", "feat", "wright")
438
+ if last := lastLine(t, logp); !bytes.HasSuffix([]byte(last), []byte(" wright ")) {
439
+ t.Errorf("empty-label record = %q, want a trailing space (`<epoch> wright `)", last)
440
+ }
441
+
442
+ if _, _, code := runGo(t, work, "footprint", "log", "ghost", "wright", "x"); code != 0 {
443
+ t.Errorf("log on a missing workspace: exit=%d, want 0 (never fail the caller)", code)
444
+ }
445
+ if _, err := os.Stat(filepath.Join(work, ".devrites", "features", "ghost", "footprint.log")); err == nil {
446
+ t.Error("log on a missing workspace created a log; it must be a no-op")
447
+ }
448
+ }
449
+
450
+ // ---- evidence-fresh -------------------------------------------------------
451
+ //
452
+ // Golden tests: expected stdout + exit are asserted inline. File mtimes are set
453
+ // explicitly so the freshness comparison is deterministic and independent of
454
+ // when the fixtures were written.
455
+
456
+ func TestEvidenceFreshGolden(t *testing.T) {
457
+ work := t.TempDir()
458
+
459
+ old := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
460
+ mid := time.Date(2026, 1, 2, 0, 0, 0, 0, time.UTC)
461
+ newer := time.Date(2026, 1, 3, 0, 0, 0, 0, time.UTC)
462
+
463
+ const okMsg = "evidence-fresh: OK — evidence post-dates every touched file.\n"
464
+
465
+ // Primary workspace: evidence + one touched file.
466
+ ws := ".devrites/features/ftest"
467
+ writeFile(t, work, ws+"/touched-files.md", "# touched\n- `src/app.js`\n")
468
+ writeFile(t, work, ws+"/evidence.md", "# evidence\nproof\n")
469
+ writeFile(t, work, "src/app.js", "code\n")
470
+
471
+ // STALE: the touched file is newer than the proof → exit 3.
472
+ chtimeT(t, work, ws+"/evidence.md", old)
473
+ chtimeT(t, work, "src/app.js", mid)
474
+ (goldenCase{"stale", []string{"evidence-fresh", "ftest"}, "", 3}).assert(t, work)
475
+
476
+ // FRESH: the proof now post-dates the code → exit 0.
477
+ chtimeT(t, work, ws+"/evidence.md", newer)
478
+ (goldenCase{"fresh", []string{"evidence-fresh", "ftest"}, okMsg, 0}).assert(t, work)
479
+
480
+ // proof.md is the supported alias for evidence.md. A proof-only workspace
481
+ // must pass/fail freshness by the same mtime rule.
482
+ writeFile(t, work, ".devrites/features/proofonly/touched-files.md", "# touched\n- `src/proofonly.js`\n")
483
+ writeFile(t, work, ".devrites/features/proofonly/proof.md", "# proof\n")
484
+ writeFile(t, work, "src/proofonly.js", "x\n")
485
+ chtimeT(t, work, "src/proofonly.js", old)
486
+ chtimeT(t, work, ".devrites/features/proofonly/proof.md", newer)
487
+ (goldenCase{"proof-only-fresh", []string{"evidence-fresh", "proofonly"}, okMsg, 0}).assert(t, work)
488
+
489
+ writeFile(t, work, ".devrites/features/proofstale/touched-files.md", "# touched\n- `src/proofstale.js`\n")
490
+ writeFile(t, work, ".devrites/features/proofstale/proof.md", "# proof\n")
491
+ writeFile(t, work, "src/proofstale.js", "x\n")
492
+ chtimeT(t, work, ".devrites/features/proofstale/proof.md", old)
493
+ chtimeT(t, work, "src/proofstale.js", newer)
494
+ (goldenCase{"proof-only-stale", []string{"evidence-fresh", "proofstale"}, "", 3}).assert(t, work)
495
+
496
+ // Default slug resolved from .devrites/ACTIVE, fresh → exit 0.
497
+ writeFile(t, work, ".devrites/features/defslug/touched-files.md", "# touched\n- `src/other.js`\n")
498
+ writeFile(t, work, ".devrites/features/defslug/evidence.md", "# evidence\n")
499
+ writeFile(t, work, "src/other.js", "x\n")
500
+ writeFile(t, work, ".devrites/ACTIVE", "defslug\n")
501
+ chtimeT(t, work, "src/other.js", old)
502
+ chtimeT(t, work, ".devrites/features/defslug/evidence.md", newer)
503
+ (goldenCase{"default-slug", []string{"evidence-fresh"}, okMsg, 0}).assert(t, work)
504
+
505
+ // An absolute touched path newer than the proof → STALE (exercises the
506
+ // absolute-path branch, not just repo-relative resolution).
507
+ absPath := filepath.Join(work, "absnew.js")
508
+ writeFile(t, work, "absnew.js", "x\n")
509
+ writeFile(t, work, ".devrites/features/abs/touched-files.md", "# touched\n- `"+absPath+"`\n")
510
+ writeFile(t, work, ".devrites/features/abs/evidence.md", "# evidence\n")
511
+ chtimeT(t, work, ".devrites/features/abs/evidence.md", old)
512
+ chtimeT(t, work, "absnew.js", newer)
513
+ (goldenCase{"absolute-path-stale", []string{"evidence-fresh", "abs"}, "", 3}).assert(t, work)
514
+
515
+ // No workspace directory → exit 5.
516
+ (goldenCase{"no-workspace", []string{"evidence-fresh", "ghost"}, "", 5}).assert(t, work)
517
+
518
+ // Workspace present but no evidence → exit 5.
519
+ mkdirAllT(t, work, ".devrites/features/noev")
520
+ (goldenCase{"no-evidence", []string{"evidence-fresh", "noev"}, "", 5}).assert(t, work)
521
+
522
+ // Proof present, no touched-files.md → nothing to compare, exit 0.
523
+ writeFile(t, work, ".devrites/features/notf/evidence.md", "# evidence\n")
524
+ (goldenCase{"no-touched-files", []string{"evidence-fresh", "notf"},
525
+ "evidence-fresh: no touched-files.md — nothing to compare (treating as fresh).\n", 0}).assert(t, work)
526
+ }
527
+
528
+ // mkdirAllT creates an (empty) directory under workdir.
529
+ func mkdirAllT(t *testing.T, workdir, rel string) {
530
+ t.Helper()
531
+ if err := os.MkdirAll(filepath.Join(workdir, rel), 0o755); err != nil {
532
+ t.Fatal(err)
533
+ }
534
+ }
535
+
536
+ // chtimeT sets a file's mtime (and atime) so freshness comparisons are
537
+ // deterministic and identical for both the bash and Go readers.
538
+ func chtimeT(t *testing.T, workdir, rel string, mtime time.Time) {
539
+ t.Helper()
540
+ if err := os.Chtimes(filepath.Join(workdir, rel), mtime, mtime); err != nil {
541
+ t.Fatal(err)
542
+ }
543
+ }
544
+
545
+ // fileLines counts newline-terminated lines in a file.
546
+ func fileLines(t *testing.T, path string) int {
547
+ t.Helper()
548
+ b, err := os.ReadFile(path)
549
+ if err != nil {
550
+ t.Fatal(err)
551
+ }
552
+ return bytes.Count(b, []byte("\n"))
553
+ }
554
+
555
+ // lastLine returns the final non-empty line of a file (its trailing newline
556
+ // stripped), so a caller can assert the exact bytes of the most recent record.
557
+ func lastLine(t *testing.T, path string) string {
558
+ t.Helper()
559
+ b, err := os.ReadFile(path)
560
+ if err != nil {
561
+ t.Fatal(err)
562
+ }
563
+ lines := bytes.Split(bytes.TrimRight(b, "\n"), []byte("\n"))
564
+ return string(lines[len(lines)-1])
565
+ }
566
+
567
+ // ---- coverage -------------------------------------------------------------
568
+ //
569
+ // Golden: the matrix, the AC id sort, the ";"-joined slices (including the awk
570
+ // substring quirk), the UNCOVERED / pending fallbacks, and the exit taxonomy
571
+ // are checked against golden snapshots.
572
+
573
+ func TestParityCoverage(t *testing.T) {
574
+ work := t.TempDir()
575
+
576
+ // Mixed coverage + proof, and C-locale AC ordering (AC1, AC10, AC2). The
577
+ // "AC1" row also picks up the AC10 slice — the awk match is a substring test
578
+ // and the port reproduces it.
579
+ writeFeatureFile(t, work, "full", "spec.md",
580
+ "## Acceptance criteria\n- [ ] [AC1] alpha\n- [ ] [AC2] beta\n- [ ] [AC10] dec\n")
581
+ writeFeatureFile(t, work, "full", "tasks.md",
582
+ "## Slice 1: list\n Satisfies: AC1\n## Slice 2: detail\n Satisfies: AC2, AC10\n")
583
+ writeFeatureFile(t, work, "full", "seal.md",
584
+ "## Acceptance Criteria\n- [x] [AC1] alpha — evidence: t1\n- [ ] [AC2] beta\n- [x] [AC10] dec — evidence: t3\n")
585
+
586
+ // spec only → every AC UNCOVERED + pending.
587
+ writeFeatureFile(t, work, "speconly", "spec.md",
588
+ "## Acceptance criteria\n- [ ] [AC1] a\n- [ ] [AC2] b\n")
589
+
590
+ // flat spec, no [ACn] ids → header + footer, zero rows.
591
+ writeFeatureFile(t, work, "flat", "spec.md",
592
+ "## Acceptance criteria\n- export returns CSV\n- empty dataset returns 204\n")
593
+
594
+ // workspace dir present but no spec.md → exit 2.
595
+ makeFeatureDir(t, work, "nospec")
596
+
597
+ for _, arg := range []string{
598
+ "full", // matrix with mixed proof + the substring quirk
599
+ "speconly", // all UNCOVERED / pending
600
+ "flat", // no ids → empty matrix body
601
+ "nospec", // dir, no spec.md → exit 2
602
+ "nonexistent", // no workspace dir → exit 2
603
+ } {
604
+ c := parityCase{
605
+ workdir: work,
606
+ env: libRootEnv(work),
607
+ goArgs: []string{"coverage", arg},
608
+ }
609
+ t.Run("arg="+arg, func(t *testing.T) { c.assertEqual(t) })
610
+ }
611
+
612
+ // No-argument path with no active feature → "no active workspace", exit 2.
613
+ (parityCase{
614
+ workdir: work,
615
+ env: libRootEnv(work),
616
+ goArgs: []string{"coverage"},
617
+ }).assertEqual(t)
618
+ }
619
+
620
+ // TestCoverageGolden asserts the exact matrix bytes with an inline expectation
621
+ // (fixtures chosen without an AC1/AC10 collision so the golden reads naturally;
622
+ // the substring quirk is exercised by TestParityCoverage's "full" fixture).
623
+ func TestCoverageGolden(t *testing.T) {
624
+ work := t.TempDir()
625
+ const base = ".devrites/features/"
626
+
627
+ writeFile(t, work, base+"g/spec.md",
628
+ "## Acceptance criteria\n- [ ] [AC1] a\n- [ ] [AC2] b\n- [ ] [AC3] c\n")
629
+ writeFile(t, work, base+"g/tasks.md",
630
+ "## Slice 1: list\n Satisfies: AC1\n## Slice 2: detail\n Satisfies: AC2, AC3\n")
631
+ writeFile(t, work, base+"g/seal.md",
632
+ "## Acceptance Criteria\n- [x] [AC1] a — evidence: t1\n- [x] [AC2] b — evidence: t2\n- [ ] [AC3] c\n")
633
+
634
+ const wantG = "# Coverage matrix: g\n\n" +
635
+ "| AC | Slice(s) | Proven in seal? |\n" +
636
+ "|----|----------|-----------------|\n" +
637
+ "| AC1 | Slice 1: list | yes |\n" +
638
+ "| AC2 | Slice 2: detail | yes |\n" +
639
+ "| AC3 | Slice 2: detail | pending |\n\n" +
640
+ "_Generated by devrites-engine coverage from spec.md / tasks.md / seal.md. UNCOVERED rows block the analyze gate in /rite-vet (Claude) / $rite-vet (Codex)._\n"
641
+ (goldenCase{"full-matrix", []string{"coverage", "g"}, wantG, 0}).assert(t, work)
642
+
643
+ // spec only → UNCOVERED / pending fallbacks.
644
+ writeFile(t, work, base+"u/spec.md", "## Acceptance criteria\n- [ ] [AC1] a\n")
645
+ const wantU = "# Coverage matrix: u\n\n" +
646
+ "| AC | Slice(s) | Proven in seal? |\n" +
647
+ "|----|----------|-----------------|\n" +
648
+ "| AC1 | — (UNCOVERED) | pending |\n\n" +
649
+ "_Generated by devrites-engine coverage from spec.md / tasks.md / seal.md. UNCOVERED rows block the analyze gate in /rite-vet (Claude) / $rite-vet (Codex)._\n"
650
+ (goldenCase{"uncovered", []string{"coverage", "u"}, wantU, 0}).assert(t, work)
651
+ }
652
+
653
+ // ---- doubt-coverage -------------------------------------------------------
654
+ //
655
+ // Golden: the decisions.md `doubt: MISSING` short-circuit (checked first), the
656
+ // inline-build branch, the no-log pass, the wright/doubt count line, and the
657
+ // 0/1/2/3 exit taxonomy are checked against golden snapshots.
658
+
659
+ func TestParityDoubtCoverage(t *testing.T) {
660
+ work := t.TempDir()
661
+
662
+ // decisions.md MISSING → exit 3, and it wins even over the footprint log.
663
+ writeFeatureFile(t, work, "missing", "decisions.md",
664
+ "## Decisions stood\n- use flock — doubt: MISSING\n")
665
+ writeFeatureFile(t, work, "missing", "footprint.log", "1000 wright 01\n")
666
+
667
+ // MISSING is checked BEFORE the inline marker → still exit 3.
668
+ writeFeatureFile(t, work, "missing-inline", "decisions.md", "- x — doubt: MISSING\n")
669
+ writeFeatureFile(t, work, "missing-inline", ".reconcile-inline", "")
670
+
671
+ // inline build, no MISSING → exit 0.
672
+ writeFeatureFile(t, work, "inline", ".reconcile-inline", "")
673
+ writeFeatureFile(t, work, "inline", "decisions.md", "## Decisions stood\n- x — doubt: yes\n")
674
+
675
+ // dir exists, no log / dec / marker → "no footprint log" pass.
676
+ makeFeatureDir(t, work, "nolog")
677
+
678
+ // wright dispatch(es), zero doubt → exit 1.
679
+ writeFeatureFile(t, work, "nodoubt", "footprint.log",
680
+ "1000 wright 01\n1000 reviewer code-reviewer\n1000 wright 02\n")
681
+
682
+ // wright + doubt → exit 0.
683
+ writeFeatureFile(t, work, "doubted", "footprint.log", "1000 wright 01\n1000 doubt d1\n")
684
+
685
+ // zero wright (only reviewers) → exit 0, count line "0 wright · N doubt".
686
+ writeFeatureFile(t, work, "nowright", "footprint.log",
687
+ "1000 reviewer code-reviewer\n1000 doubt d1\n")
688
+
689
+ for _, arg := range []string{
690
+ "missing", "missing-inline", "inline", "nolog",
691
+ "nodoubt", "doubted", "nowright",
692
+ "ghost", // no workspace at all → "no footprint log" pass
693
+ } {
694
+ c := parityCase{
695
+ workdir: work,
696
+ env: libRootEnv(work),
697
+ goArgs: []string{"doubt-coverage", arg},
698
+ }
699
+ t.Run("arg="+arg, func(t *testing.T) { c.assertEqual(t) })
700
+ }
701
+
702
+ // No-slug usage path → exit 2.
703
+ (parityCase{
704
+ workdir: work,
705
+ env: libRootEnv(work),
706
+ goArgs: []string{"doubt-coverage"},
707
+ }).assertEqual(t)
708
+ }
709
+
710
+ // TestDoubtCoverageGolden asserts each verdict's exact stdout inline — the
711
+ // SKIPPED / inline / no-log messages and the "no doubt ran" prompt.
712
+ func TestDoubtCoverageGolden(t *testing.T) {
713
+ work := t.TempDir()
714
+ const base = ".devrites/features/"
715
+
716
+ writeFile(t, work, base+"miss/decisions.md", "- x — doubt: MISSING\n")
717
+ writeFile(t, work, base+"in/.reconcile-inline", "")
718
+ mkdirAllT(t, work, base+"empty")
719
+ writeFile(t, work, base+"nd/footprint.log", "1000 wright 01\n1000 wright 02\n")
720
+ writeFile(t, work, base+"ok/footprint.log", "1000 wright 01\n1000 doubt d1\n")
721
+
722
+ for _, gc := range []goldenCase{
723
+ {"skipped", []string{"doubt-coverage", "miss"},
724
+ "doubt-coverage: SKIPPED — a '## Decisions stood' entry in decisions.md has doubt: MISSING.\n" +
725
+ "A decision was stood and recorded but never doubted. Re-dispatch doubt or escalate.\n", 3},
726
+ {"inline", []string{"doubt-coverage", "in"},
727
+ "doubt-coverage: inline build (.reconcile-inline) — footprint heuristic n/a; no MISSING\n" +
728
+ "verdict recorded. Verify by hand that each stood decision carries a devrites-doubt verdict.\n", 0},
729
+ {"no-log", []string{"doubt-coverage", "empty"},
730
+ "doubt-coverage: no footprint log — nothing to assess (pass)\n", 0},
731
+ {"no-doubt-ran", []string{"doubt-coverage", "nd"},
732
+ "doubt-coverage: 2 wright · 0 doubt\n" +
733
+ "doubt-coverage: no doubt dispatched across 2 wright run(s). Either every slice's\n" +
734
+ "'Decisions stood' was genuinely empty, or doubt was skipped — verify against decisions.md.\n", 1},
735
+ {"doubted", []string{"doubt-coverage", "ok"},
736
+ "doubt-coverage: 1 wright · 1 doubt\n", 0},
737
+ } {
738
+ t.Run(gc.name, func(t *testing.T) { gc.assert(t, work) })
739
+ }
740
+ }
741
+
742
+ // ---- preamble -------------------------------------------------------------
743
+ //
744
+ // Golden: the workspace-state orientation — the header, verbatim state.md (with
745
+ // and without a trailing newline), the fixed artifact-present order, the AFK/HITL
746
+ // run mode with verbatim config lines, and the questions-by-gate tally — are
747
+ // checked against golden snapshots.
748
+
749
+ func TestParityPreamble(t *testing.T) {
750
+ // A HITL workspace (no .devrites/AFK) exercising most branches.
751
+ hitl := t.TempDir()
752
+ writeFeatureFile(t, hitl, "full", "state.md", "- Phase: build\n- Status: running\n- Next step: implement slice 3\n")
753
+ writeFeatureFile(t, hitl, "full", "spec.md", "# spec\n")
754
+ writeFeatureFile(t, hitl, "full", "plan.md", "# plan\n")
755
+ writeFeatureFile(t, hitl, "full", "tasks.md", "# tasks\n")
756
+ writeFeatureFile(t, hitl, "full", "questions.md",
757
+ "## q-1\nstatus: open\ngate: blocking\n\n"+
758
+ "## q-2\nstatus: resolved\ngate: validating\n\n"+
759
+ "## q-3\nstatus: open\ngate: advisory\n\n"+
760
+ "## q-4\nstatus: open\ngate: blocking\n## Notes\nprose\n")
761
+ // questions.md ending on an OPEN q- block (no closing heading) — exercises the
762
+ // awk END-finalize path.
763
+ writeFeatureFile(t, hitl, "openend", "state.md", "- Phase: spec\n")
764
+ writeFeatureFile(t, hitl, "openend", "questions.md",
765
+ "## q-1\nstatus: resolved\ngate: blocking\n\n## q-2\nstatus: open\ngate: escalating\n")
766
+ // state.md with NO trailing newline — `cat` must not add one before the blank line.
767
+ writeFeatureFile(t, hitl, "nonl", "state.md", "- Phase: spec")
768
+ // A workspace directory with no state.md / questions.md.
769
+ makeFeatureDir(t, hitl, "bare")
770
+ writeFile(t, hitl, ".devrites/ACTIVE", "full\n")
771
+
772
+ for _, arg := range []string{"full", "openend", "nonl", "bare", "ghost"} {
773
+ c := parityCase{
774
+ workdir: hitl,
775
+ env: libRootEnv(hitl),
776
+ goArgs: []string{"preamble", arg},
777
+ }
778
+ t.Run("hitl/"+arg, func(t *testing.T) { c.assertEqual(t) })
779
+ }
780
+ // No-arg path resolves the slug from ACTIVE.
781
+ t.Run("hitl/active", func(t *testing.T) {
782
+ (parityCase{workdir: hitl, env: libRootEnv(hitl), goArgs: []string{"preamble"}}).assertEqual(t)
783
+ })
784
+
785
+ // An AFK workspace: the sentinel plus verbatim (non-comment) config lines.
786
+ afk := t.TempDir()
787
+ writeFeatureFile(t, afk, "a", "state.md", "- Phase: prove\n")
788
+ writeFile(t, afk, ".devrites/AFK", "# afk config\nmax-slices: 3\n\nescalate: true\n")
789
+ t.Run("afk/a", func(t *testing.T) {
790
+ (parityCase{workdir: afk, env: libRootEnv(afk), goArgs: []string{"preamble", "a"}}).assertEqual(t)
791
+ })
792
+ }
793
+
794
+ // ---- progress -------------------------------------------------------------
795
+ //
796
+ // Golden: the header rule width, the slice meter (round-half math, ✅ ALL BUILT
797
+ // vs the last-built tail), and the flow ribbon (conditional temper/vet, the
798
+ // plan→build and done cursor rules) are checked against golden snapshots.
799
+
800
+ func TestParityProgress(t *testing.T) {
801
+ work := t.TempDir()
802
+
803
+ sliceBlock := "\n## Slice progress\n" +
804
+ "- [x] Slice 1: list — built\n" +
805
+ "- [x] Slice 2: detail — built\n" +
806
+ "- [ ] Slice 3: polish — pending\n" +
807
+ "## Next\n- something\n"
808
+
809
+ // build phase, 2/3 slices, temper (strategy.md) + vet (eng-review.md) present.
810
+ writeFeatureFile(t, work, "mid", "state.md", "- Phase: build"+sliceBlock)
811
+ writeFeatureFile(t, work, "mid", "strategy.md", "# strategy\n")
812
+ writeFeatureFile(t, work, "mid", "eng-review.md", "# eng-review\n")
813
+
814
+ // all built → ✅ ALL BUILT; no temper/vet artifacts → shorter ribbon.
815
+ writeFeatureFile(t, work, "allbuilt", "state.md",
816
+ "- Phase: build\n## Slice progress\n- [x] Slice 1: a — built\n- [x] Slice 2: b — built\n")
817
+
818
+ // no slices at all → meter skipped entirely.
819
+ writeFeatureFile(t, work, "noslice", "state.md", "- Phase: spec\n")
820
+
821
+ // phase variants exercising the cursor rules.
822
+ writeFeatureFile(t, work, "done", "state.md", "- Phase: done\n")
823
+ writeFeatureFile(t, work, "plan", "state.md", "- Phase: plan"+sliceBlock)
824
+ writeFeatureFile(t, work, "seal", "state.md", "- Phase: seal\n")
825
+ // missing Phase → defaults to "spec".
826
+ writeFeatureFile(t, work, "nophase", "state.md", "- Status: running\n")
827
+
828
+ for _, arg := range []string{"mid", "allbuilt", "noslice", "done", "plan", "seal", "nophase", "ghost"} {
829
+ c := parityCase{
830
+ workdir: work,
831
+ env: libRootEnv(work),
832
+ goArgs: []string{"progress", arg},
833
+ }
834
+ t.Run("arg="+arg, func(t *testing.T) { c.assertEqual(t) })
835
+ }
836
+ }
837
+
838
+ // ---- stuck ----------------------------------------------------------------
839
+ //
840
+ // Golden: `check` reads only the sha1 column, so a fixture log with controlled
841
+ // hash tokens drives every verdict (too-few / identical / ping-pong / dominant /
842
+ // varied / custom window) and the 0/3 exit split, checked against golden
843
+ // snapshots. `log` is exercised separately (its stdout is empty; its side effect
844
+ // carries a nondeterministic timestamp, so only the sha1 column is snapshotted).
845
+
846
+ func TestParityStuckCheck(t *testing.T) {
847
+ work := t.TempDir()
848
+
849
+ // Each record is "<epoch> <tool> <hash>"; check only reads the hash ($3).
850
+ rec := func(h string) string { return "1700000000 Bash " + h + "\n" }
851
+ writeFeatureFile(t, work, "few", "action.log", rec("a")+rec("a")) // NR < win(4)
852
+ writeFeatureFile(t, work, "identical", "action.log", rec("a")+rec("a")+rec("a")+rec("a")) // last 4 identical
853
+ writeFeatureFile(t, work, "pingpong", "action.log", rec("a")+rec("b")+rec("a")+rec("b")+rec("a")+rec("b"))
854
+ writeFeatureFile(t, work, "dominant", "action.log", rec("a")+rec("a")+rec("a")+rec("a")+rec("a")+rec("a")+rec("b")+rec("c"))
855
+ writeFeatureFile(t, work, "varied", "action.log", rec("a")+rec("b")+rec("c")+rec("d")+rec("e"))
856
+ writeFeatureFile(t, work, "varied4", "action.log", rec("a")+rec("b")+rec("c")+rec("d")) // 4 distinct
857
+ makeFeatureDir(t, work, "nolog")
858
+
859
+ type cse struct {
860
+ name string
861
+ goArgs []string
862
+ }
863
+ for _, tc := range []cse{
864
+ {"few", []string{"check", "few"}},
865
+ {"identical", []string{"check", "identical"}},
866
+ {"pingpong", []string{"check", "pingpong"}},
867
+ {"dominant", []string{"check", "dominant"}},
868
+ {"varied", []string{"check", "varied"}},
869
+ {"nolog", []string{"check", "nolog"}},
870
+ {"ghost", []string{"check", "ghost"}},
871
+ {"custom-window-2", []string{"check", "few", "2"}}, // win=2 → last 2 identical → STUCK
872
+ // Pathological window tokens: the numeric-string vs string comparison and
873
+ // the verbatim `win` echo — edge cases the port must reproduce.
874
+ {"window-4x-varied4", []string{"check", "varied4", "4x"}},
875
+ {"window-2.5-varied4", []string{"check", "varied4", "2.5"}},
876
+ {"window-leadspace-varied4", []string{"check", "varied4", " 4"}},
877
+ {"window-04-identical", []string{"check", "identical", "04"}},
878
+ {"window-plus4-identical", []string{"check", "identical", "+4"}},
879
+ {"no-cmd", nil},
880
+ {"no-slug", []string{"check"}},
881
+ {"bad-cmd", []string{"bogus", "few"}},
882
+ } {
883
+ c := parityCase{workdir: work, env: libRootEnv(work), goArgs: append([]string{"stuck"}, tc.goArgs...)}
884
+ t.Run(tc.name, func(t *testing.T) { c.assertEqual(t) })
885
+ }
886
+ }
887
+
888
+ // TestStuckLogHashParity proves the `log` side effect: it appends a record whose
889
+ // sha1 column is deterministic given the logged target, so that column is
890
+ // snapshotted (the epoch column is nondeterministic and excluded by reading only
891
+ // field 3). A second log appends a second record, and logging to a missing
892
+ // workspace is a silent no-op.
893
+ func TestStuckLogHashParity(t *testing.T) {
894
+ field3 := func(t *testing.T, path string) string {
895
+ t.Helper()
896
+ fields := bytes.Fields(bytes.TrimRight(readFileT(t, path), "\n"))
897
+ if len(fields) < 3 {
898
+ t.Fatalf("log line has <3 fields: %q", string(readFileT(t, path)))
899
+ }
900
+ return string(fields[2])
901
+ }
902
+
903
+ // The new-schema features layout under DEVRITES_ROOT.
904
+ gw := t.TempDir()
905
+ mkdirAllT(t, gw, ".devrites/features/feat")
906
+ goLog := filepath.Join(gw, ".devrites/features/feat/action.log")
907
+ runArgv(t, gw, libRootEnv(gw), "", binPath, "stuck", "log", "feat", "Bash", "src/a.js")
908
+ goHash := field3(t, goLog)
909
+
910
+ // Snapshot the sha1 column (the epoch column is masked by reading only field 3).
911
+ assertGoldenKey(t, t.Name(), goHash)
912
+ if len(goHash) != 40 {
913
+ t.Errorf("sha1 hex = %q, want 40 chars", goHash)
914
+ }
915
+
916
+ // A second log appends a second record.
917
+ runArgv(t, gw, libRootEnv(gw), "", binPath, "stuck", "log", "feat", "Edit", "src/b.js")
918
+ if n := fileLines(t, goLog); n != 2 {
919
+ t.Errorf("after two logs: %d lines, want 2", n)
920
+ }
921
+ // Logging to a missing workspace is a no-op (never fails the caller).
922
+ if _, code := runArgv(t, gw, libRootEnv(gw), "", binPath, "stuck", "log", "ghost", "Bash", "x"); code != 0 {
923
+ t.Errorf("log on missing workspace: exit=%d, want 0", code)
924
+ }
925
+ if isFileT(filepath.Join(gw, ".devrites/features/ghost/action.log")) {
926
+ t.Error("log on missing workspace created a file; must be a no-op")
927
+ }
928
+ }
929
+
930
+ func readFileT(t *testing.T, path string) []byte {
931
+ t.Helper()
932
+ b, err := os.ReadFile(path)
933
+ if err != nil {
934
+ t.Fatal(err)
935
+ }
936
+ return b
937
+ }
938
+
939
+ func isFileT(path string) bool {
940
+ fi, err := os.Stat(path)
941
+ return err == nil && !fi.IsDir()
942
+ }