@nathapp/nax 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (459) hide show
  1. package/.gitlab-ci.yml +96 -0
  2. package/BRIEF.md +140 -0
  3. package/CHANGELOG.md +60 -0
  4. package/CLAUDE.md +159 -0
  5. package/README.md +373 -0
  6. package/US-007-IMPLEMENTATION.md +139 -0
  7. package/bin/nax.ts +930 -0
  8. package/biome.json +14 -0
  9. package/bun.lock +168 -0
  10. package/bunfig.toml +11 -0
  11. package/docs/20260216-fix-plan-context-review.md +56 -0
  12. package/docs/20260216-relentless-vs-ngent-comparison.md +208 -0
  13. package/docs/20260216-v02-plan.md +136 -0
  14. package/docs/20260216-v02-review.md +685 -0
  15. package/docs/20260217-dogfood-findings.md +56 -0
  16. package/docs/20260217-p2-plus-plan.md +117 -0
  17. package/docs/20260217-partial-fixes-plan.md +62 -0
  18. package/docs/20260217-plan-analyze-spec.md +117 -0
  19. package/docs/20260217-post-impl-review.md +1137 -0
  20. package/docs/20260217-quick-wins-plan.md +66 -0
  21. package/docs/20260217-split-runner-plan.md +75 -0
  22. package/docs/20260217-v03-impl-plan.md +80 -0
  23. package/docs/20260217-v03-post-impl-review.md +589 -0
  24. package/docs/20260217-v04-impl-plan.md +86 -0
  25. package/docs/20260217-v05-post-impl-review.md +850 -0
  26. package/docs/20260217-v06-post-impl-review.md +817 -0
  27. package/docs/20260218-adr003-port-plan.md +151 -0
  28. package/docs/20260218-review-adr003-verification.md +175 -0
  29. package/docs/20260219-fix-plan-bug16-19.md +79 -0
  30. package/docs/20260219-fix-plan-bug20-22.md +114 -0
  31. package/docs/20260219-plan-llm-routing.md +116 -0
  32. package/docs/20260219-review-bug20-22-fixes.md +135 -0
  33. package/docs/20260219-routing-baseline-keyword.md +63 -0
  34. package/docs/20260220-plan-structured-logging-p1.md +80 -0
  35. package/docs/20260220-plan-structured-logging-p2.md +37 -0
  36. package/docs/20260220-review-llm-routing.md +180 -0
  37. package/docs/20260220-review-post-fix-llm-routing.md +70 -0
  38. package/docs/20260221-fix-plan-relevantfiles-split.md +101 -0
  39. package/docs/20260221-fix-plan-routing-mode.md +125 -0
  40. package/docs/20260221-review-v0.9-implementation.md +379 -0
  41. package/docs/20260222-fix-plan-v091-routing-isolation.md +197 -0
  42. package/docs/20260223-fix-plan-prompt-audit.md +62 -0
  43. package/docs/20260224-nax-roadmap-phases.md +189 -0
  44. package/docs/20260225-phase2-llm-service-layer.md +401 -0
  45. package/docs/20260225-review-v0.10.1.md +187 -0
  46. package/docs/20260303-v010-implementation-plan.md +165 -0
  47. package/docs/CLAUDE.md.bak +191 -0
  48. package/docs/ROADMAP.md +165 -0
  49. package/docs/SPEC-rectification.md +0 -0
  50. package/docs/SPEC.md +324 -0
  51. package/docs/US-001-plugin-loading-verification.md +152 -0
  52. package/docs/architecture-analysis.md +1076 -0
  53. package/docs/bugs/BUG-21-escalation-null-attempts.md +48 -0
  54. package/docs/bugs-from-dogfood-run-c.md +243 -0
  55. package/docs/code-review-20260228.md +612 -0
  56. package/docs/code-review-v0.15.0.md +629 -0
  57. package/docs/hook-lifecycle-test-plan.md +149 -0
  58. package/docs/releases/v0.11.0-and-earlier.md +20 -0
  59. package/docs/releases/v0.12.0.md +15 -0
  60. package/docs/releases/v0.13.0.md +14 -0
  61. package/docs/releases/v0.14.0.md +20 -0
  62. package/docs/releases/v0.14.1.md +36 -0
  63. package/docs/releases/v0.14.2.md +51 -0
  64. package/docs/releases/v0.14.3.md +174 -0
  65. package/docs/releases/v0.14.4.md +94 -0
  66. package/docs/releases/v0.15.0.md +502 -0
  67. package/docs/releases/v0.15.1.md +170 -0
  68. package/docs/releases/v0.15.3.md +193 -0
  69. package/docs/specs/status-file-v0.10.1.md +812 -0
  70. package/docs/v0.10-global-config.md +206 -0
  71. package/docs/v0.10-plugin-system.md +415 -0
  72. package/docs/v0.10-prompt-optimizer.md +234 -0
  73. package/docs/v0.3-spec.md +244 -0
  74. package/docs/v0.4-spec.md +140 -0
  75. package/docs/v0.5-spec.md +237 -0
  76. package/docs/v0.6-spec.md +371 -0
  77. package/docs/v0.7-spec.md +177 -0
  78. package/docs/v0.8-llm-routing.md +206 -0
  79. package/docs/v0.8-structured-logging.md +132 -0
  80. package/docs/v0.9.3-prompt-audit.md +112 -0
  81. package/examples/plugins/console-reporter/index.test.ts +207 -0
  82. package/examples/plugins/console-reporter/index.ts +110 -0
  83. package/nax/config.json +147 -0
  84. package/nax/features/bugfix-v0171/prd.json +52 -0
  85. package/nax/features/config-management/prd.json +108 -0
  86. package/nax/features/config-management/progress.txt +5 -0
  87. package/nax/features/diagnose/acceptance.test.ts +412 -0
  88. package/nax/features/diagnose/prd.json +41 -0
  89. package/nax/features/orchestration-fixes/prd.json +89 -0
  90. package/nax/features/orchestration-fixes/progress.txt +1 -0
  91. package/nax/features/plugin-integration/US-007-VERIFICATION.md +259 -0
  92. package/nax/features/plugin-integration/prd.json +208 -0
  93. package/nax/features/plugin-integration/progress.txt +5 -0
  94. package/nax/features/precheck/prd.json +205 -0
  95. package/nax/features/precheck/progress.txt +15 -0
  96. package/nax/features/structured-logging/prd.json +199 -0
  97. package/nax/features/unlock/prd.json +36 -0
  98. package/package.json +47 -0
  99. package/src/acceptance/fix-generator.ts +348 -0
  100. package/src/acceptance/generator.ts +282 -0
  101. package/src/acceptance/index.ts +30 -0
  102. package/src/acceptance/types.ts +79 -0
  103. package/src/agents/claude-decompose.ts +169 -0
  104. package/src/agents/claude-plan.ts +139 -0
  105. package/src/agents/claude.ts +324 -0
  106. package/src/agents/cost.ts +268 -0
  107. package/src/agents/index.ts +13 -0
  108. package/src/agents/registry.ts +48 -0
  109. package/src/agents/types-extended.ts +133 -0
  110. package/src/agents/types.ts +113 -0
  111. package/src/agents/validation.ts +69 -0
  112. package/src/analyze/classifier.ts +305 -0
  113. package/src/analyze/index.ts +16 -0
  114. package/src/analyze/scanner.ts +175 -0
  115. package/src/analyze/types.ts +51 -0
  116. package/src/cli/accept.ts +108 -0
  117. package/src/cli/analyze-parser.ts +284 -0
  118. package/src/cli/analyze.ts +207 -0
  119. package/src/cli/config.ts +561 -0
  120. package/src/cli/constitution.ts +109 -0
  121. package/src/cli/diagnose-analysis.ts +159 -0
  122. package/src/cli/diagnose-formatter.ts +87 -0
  123. package/src/cli/diagnose.ts +203 -0
  124. package/src/cli/generate.ts +127 -0
  125. package/src/cli/index.ts +37 -0
  126. package/src/cli/init.ts +188 -0
  127. package/src/cli/interact.ts +295 -0
  128. package/src/cli/plan.ts +198 -0
  129. package/src/cli/plugins.ts +111 -0
  130. package/src/cli/prompts.ts +295 -0
  131. package/src/cli/runs.ts +174 -0
  132. package/src/cli/status-cost.ts +151 -0
  133. package/src/cli/status-features.ts +338 -0
  134. package/src/cli/status.ts +13 -0
  135. package/src/commands/common.ts +171 -0
  136. package/src/commands/diagnose.ts +17 -0
  137. package/src/commands/index.ts +8 -0
  138. package/src/commands/logs.ts +384 -0
  139. package/src/commands/precheck.ts +86 -0
  140. package/src/commands/unlock.ts +96 -0
  141. package/src/config/defaults.ts +160 -0
  142. package/src/config/index.ts +22 -0
  143. package/src/config/loader.ts +121 -0
  144. package/src/config/merger.ts +147 -0
  145. package/src/config/path-security.ts +121 -0
  146. package/src/config/paths.ts +27 -0
  147. package/src/config/schema.ts +56 -0
  148. package/src/config/schemas.ts +286 -0
  149. package/src/config/types.ts +423 -0
  150. package/src/config/validate.ts +103 -0
  151. package/src/constitution/generator.ts +191 -0
  152. package/src/constitution/generators/aider.ts +41 -0
  153. package/src/constitution/generators/claude.ts +35 -0
  154. package/src/constitution/generators/cursor.ts +36 -0
  155. package/src/constitution/generators/opencode.ts +38 -0
  156. package/src/constitution/generators/types.ts +33 -0
  157. package/src/constitution/generators/windsurf.ts +36 -0
  158. package/src/constitution/index.ts +10 -0
  159. package/src/constitution/loader.ts +133 -0
  160. package/src/constitution/types.ts +31 -0
  161. package/src/context/auto-detect.ts +227 -0
  162. package/src/context/builder.ts +246 -0
  163. package/src/context/elements.ts +83 -0
  164. package/src/context/formatter.ts +107 -0
  165. package/src/context/generator.ts +129 -0
  166. package/src/context/generators/aider.ts +34 -0
  167. package/src/context/generators/claude.ts +28 -0
  168. package/src/context/generators/cursor.ts +28 -0
  169. package/src/context/generators/opencode.ts +30 -0
  170. package/src/context/generators/windsurf.ts +28 -0
  171. package/src/context/greenfield.ts +114 -0
  172. package/src/context/index.ts +33 -0
  173. package/src/context/injector.ts +279 -0
  174. package/src/context/test-scanner.ts +370 -0
  175. package/src/context/types.ts +98 -0
  176. package/src/errors.ts +67 -0
  177. package/src/execution/batching.ts +157 -0
  178. package/src/execution/crash-recovery.ts +373 -0
  179. package/src/execution/escalation/escalation.ts +44 -0
  180. package/src/execution/escalation/index.ts +13 -0
  181. package/src/execution/escalation/tier-escalation.ts +295 -0
  182. package/src/execution/escalation/tier-outcome.ts +158 -0
  183. package/src/execution/helpers.ts +38 -0
  184. package/src/execution/index.ts +45 -0
  185. package/src/execution/lifecycle/acceptance-loop.ts +272 -0
  186. package/src/execution/lifecycle/headless-formatter.ts +85 -0
  187. package/src/execution/lifecycle/index.ts +12 -0
  188. package/src/execution/lifecycle/parallel-lifecycle.ts +101 -0
  189. package/src/execution/lifecycle/precheck-runner.ts +140 -0
  190. package/src/execution/lifecycle/run-cleanup.ts +81 -0
  191. package/src/execution/lifecycle/run-completion.ts +129 -0
  192. package/src/execution/lifecycle/run-initialization.ts +141 -0
  193. package/src/execution/lifecycle/run-lifecycle.ts +312 -0
  194. package/src/execution/lifecycle/run-setup.ts +204 -0
  195. package/src/execution/lifecycle/story-hooks.ts +38 -0
  196. package/src/execution/lifecycle/story-size-prompts.ts +123 -0
  197. package/src/execution/lock.ts +115 -0
  198. package/src/execution/parallel-executor.ts +216 -0
  199. package/src/execution/parallel.ts +400 -0
  200. package/src/execution/pid-registry.ts +280 -0
  201. package/src/execution/pipeline-result-handler.ts +388 -0
  202. package/src/execution/post-verify-rectification.ts +188 -0
  203. package/src/execution/post-verify.ts +274 -0
  204. package/src/execution/progress.ts +25 -0
  205. package/src/execution/prompts.ts +127 -0
  206. package/src/execution/queue-handler.ts +109 -0
  207. package/src/execution/rectification.ts +13 -0
  208. package/src/execution/runner.ts +377 -0
  209. package/src/execution/sequential-executor.ts +388 -0
  210. package/src/execution/status-file.ts +264 -0
  211. package/src/execution/status-writer.ts +139 -0
  212. package/src/execution/story-context.ts +229 -0
  213. package/src/execution/test-output-parser.ts +14 -0
  214. package/src/execution/verification.ts +72 -0
  215. package/src/hooks/index.ts +2 -0
  216. package/src/hooks/runner.ts +286 -0
  217. package/src/hooks/types.ts +67 -0
  218. package/src/interaction/chain.ts +154 -0
  219. package/src/interaction/index.ts +60 -0
  220. package/src/interaction/init.ts +83 -0
  221. package/src/interaction/plugins/auto.ts +217 -0
  222. package/src/interaction/plugins/cli.ts +300 -0
  223. package/src/interaction/plugins/telegram.ts +384 -0
  224. package/src/interaction/plugins/webhook.ts +258 -0
  225. package/src/interaction/state.ts +171 -0
  226. package/src/interaction/triggers.ts +229 -0
  227. package/src/interaction/types.ts +163 -0
  228. package/src/logger/formatters.ts +84 -0
  229. package/src/logger/index.ts +16 -0
  230. package/src/logger/logger.ts +298 -0
  231. package/src/logger/types.ts +48 -0
  232. package/src/logging/formatter.ts +355 -0
  233. package/src/logging/index.ts +22 -0
  234. package/src/logging/types.ts +93 -0
  235. package/src/metrics/aggregator.ts +190 -0
  236. package/src/metrics/index.ts +14 -0
  237. package/src/metrics/tracker.ts +200 -0
  238. package/src/metrics/types.ts +109 -0
  239. package/src/optimizer/index.ts +62 -0
  240. package/src/optimizer/noop.optimizer.ts +24 -0
  241. package/src/optimizer/rule-based.optimizer.ts +248 -0
  242. package/src/optimizer/types.ts +53 -0
  243. package/src/pipeline/events.ts +130 -0
  244. package/src/pipeline/index.ts +19 -0
  245. package/src/pipeline/runner.ts +161 -0
  246. package/src/pipeline/stages/acceptance.ts +197 -0
  247. package/src/pipeline/stages/completion.ts +99 -0
  248. package/src/pipeline/stages/constitution.ts +63 -0
  249. package/src/pipeline/stages/context.ts +117 -0
  250. package/src/pipeline/stages/execution.ts +194 -0
  251. package/src/pipeline/stages/index.ts +62 -0
  252. package/src/pipeline/stages/optimizer.ts +74 -0
  253. package/src/pipeline/stages/prompt.ts +57 -0
  254. package/src/pipeline/stages/queue-check.ts +103 -0
  255. package/src/pipeline/stages/review.ts +181 -0
  256. package/src/pipeline/stages/routing.ts +81 -0
  257. package/src/pipeline/stages/verify.ts +100 -0
  258. package/src/pipeline/types.ts +167 -0
  259. package/src/plugins/index.ts +31 -0
  260. package/src/plugins/loader.ts +287 -0
  261. package/src/plugins/registry.ts +168 -0
  262. package/src/plugins/types.ts +327 -0
  263. package/src/plugins/validator.ts +352 -0
  264. package/src/prd/index.ts +172 -0
  265. package/src/prd/types.ts +202 -0
  266. package/src/precheck/checks-blockers.ts +391 -0
  267. package/src/precheck/checks-warnings.ts +142 -0
  268. package/src/precheck/checks.ts +30 -0
  269. package/src/precheck/index.ts +247 -0
  270. package/src/precheck/story-size-gate.ts +144 -0
  271. package/src/precheck/types.ts +31 -0
  272. package/src/queue/index.ts +2 -0
  273. package/src/queue/manager.ts +254 -0
  274. package/src/queue/types.ts +54 -0
  275. package/src/review/index.ts +8 -0
  276. package/src/review/runner.ts +172 -0
  277. package/src/review/types.ts +66 -0
  278. package/src/routing/builder.ts +81 -0
  279. package/src/routing/chain.ts +74 -0
  280. package/src/routing/index.ts +16 -0
  281. package/src/routing/loader.ts +58 -0
  282. package/src/routing/router.ts +303 -0
  283. package/src/routing/strategies/adaptive.ts +215 -0
  284. package/src/routing/strategies/index.ts +8 -0
  285. package/src/routing/strategies/keyword.ts +163 -0
  286. package/src/routing/strategies/llm-prompts.ts +209 -0
  287. package/src/routing/strategies/llm.ts +235 -0
  288. package/src/routing/strategies/manual.ts +50 -0
  289. package/src/routing/strategy.ts +99 -0
  290. package/src/tdd/cleanup.ts +111 -0
  291. package/src/tdd/index.ts +23 -0
  292. package/src/tdd/isolation.ts +123 -0
  293. package/src/tdd/orchestrator.ts +383 -0
  294. package/src/tdd/prompts.ts +270 -0
  295. package/src/tdd/rectification-gate.ts +183 -0
  296. package/src/tdd/session-runner.ts +179 -0
  297. package/src/tdd/types.ts +81 -0
  298. package/src/tdd/verdict.ts +271 -0
  299. package/src/tui/App.tsx +265 -0
  300. package/src/tui/components/AgentPanel.tsx +75 -0
  301. package/src/tui/components/CostOverlay.tsx +118 -0
  302. package/src/tui/components/HelpOverlay.tsx +107 -0
  303. package/src/tui/components/StatusBar.tsx +63 -0
  304. package/src/tui/components/StoriesPanel.tsx +177 -0
  305. package/src/tui/hooks/useKeyboard.ts +142 -0
  306. package/src/tui/hooks/useLayout.ts +137 -0
  307. package/src/tui/hooks/usePipelineEvents.ts +183 -0
  308. package/src/tui/hooks/usePty.ts +194 -0
  309. package/src/tui/index.tsx +38 -0
  310. package/src/tui/types.ts +76 -0
  311. package/src/utils/git.ts +83 -0
  312. package/src/utils/queue-writer.ts +54 -0
  313. package/src/verification/executor.ts +235 -0
  314. package/src/verification/gate.ts +207 -0
  315. package/src/verification/index.ts +12 -0
  316. package/src/verification/parser.ts +230 -0
  317. package/src/verification/rectification.ts +108 -0
  318. package/src/verification/types.ts +113 -0
  319. package/src/worktree/dispatcher.ts +65 -0
  320. package/src/worktree/index.ts +2 -0
  321. package/src/worktree/manager.ts +187 -0
  322. package/src/worktree/merge.ts +301 -0
  323. package/src/worktree/types.ts +4 -0
  324. package/test/TEST_COVERAGE_US001.md +217 -0
  325. package/test/TEST_COVERAGE_US003.md +84 -0
  326. package/test/TEST_COVERAGE_US005.md +86 -0
  327. package/test/US-002-orchestrator.test.ts +246 -0
  328. package/test/acceptance/cm-003-default-view.test.ts +194 -0
  329. package/test/execution/pid-registry.test.ts +240 -0
  330. package/test/execution/post-verify.test.ts +224 -0
  331. package/test/helpers/timeout.ts +42 -0
  332. package/test/integration/US-002-TEST-SUMMARY.md +107 -0
  333. package/test/integration/US-003-TEST-SUMMARY.md +149 -0
  334. package/test/integration/US-004-TEST-SUMMARY.md +106 -0
  335. package/test/integration/US-005-TEST-SUMMARY.md +138 -0
  336. package/test/integration/US-007-TEST-SUMMARY.md +100 -0
  337. package/test/integration/agent-validation.test.ts +439 -0
  338. package/test/integration/analyze-integration.test.ts +261 -0
  339. package/test/integration/analyze-scanner.test.ts +131 -0
  340. package/test/integration/cli-config-default-edge-cases.test.ts +222 -0
  341. package/test/integration/cli-config-default-view.test.ts +229 -0
  342. package/test/integration/cli-config-diff.test.ts +460 -0
  343. package/test/integration/cli-config.test.ts +736 -0
  344. package/test/integration/cli-diagnose.test.ts +592 -0
  345. package/test/integration/cli-logs.test.ts +314 -0
  346. package/test/integration/cli-plugins.test.ts +678 -0
  347. package/test/integration/cli-precheck.test.ts +371 -0
  348. package/test/integration/cli-run-headless.test.ts +173 -0
  349. package/test/integration/cli.test.ts +75 -0
  350. package/test/integration/config/merger.test.ts +465 -0
  351. package/test/integration/config/paths.test.ts +51 -0
  352. package/test/integration/config-loader.test.ts +265 -0
  353. package/test/integration/config.test.ts +444 -0
  354. package/test/integration/context-integration.test.ts +702 -0
  355. package/test/integration/context-provider-injection.test.ts +506 -0
  356. package/test/integration/context-verification-integration.test.ts +295 -0
  357. package/test/integration/e2e.test.ts +896 -0
  358. package/test/integration/execution.test.ts +625 -0
  359. package/test/integration/helpers.test.ts +295 -0
  360. package/test/integration/hooks.test.ts +361 -0
  361. package/test/integration/interaction-chain-pipeline.test.ts +464 -0
  362. package/test/integration/isolation.test.ts +143 -0
  363. package/test/integration/logger.test.ts +461 -0
  364. package/test/integration/parallel.test.ts +250 -0
  365. package/test/integration/path-security.test.ts +173 -0
  366. package/test/integration/pipeline-acceptance.test.ts +302 -0
  367. package/test/integration/pipeline-events.test.ts +475 -0
  368. package/test/integration/pipeline.test.ts +658 -0
  369. package/test/integration/plan.test.ts +157 -0
  370. package/test/integration/plugin-routing.test.ts +921 -0
  371. package/test/integration/plugins/config-integration.test.ts +172 -0
  372. package/test/integration/plugins/config-resolution.test.ts +522 -0
  373. package/test/integration/plugins/loader.test.ts +641 -0
  374. package/test/integration/plugins/registry.test.ts +746 -0
  375. package/test/integration/plugins/validator.test.ts +563 -0
  376. package/test/integration/prd-pause.test.ts +205 -0
  377. package/test/integration/prd-resolvers.test.ts +185 -0
  378. package/test/integration/precheck-integration.test.ts +468 -0
  379. package/test/integration/precheck.test.ts +805 -0
  380. package/test/integration/progress.test.ts +34 -0
  381. package/test/integration/rectification-flow.test.ts +512 -0
  382. package/test/integration/reporter-lifecycle.test.ts +860 -0
  383. package/test/integration/review-config-commands.test.ts +319 -0
  384. package/test/integration/review-config-schema.test.ts +116 -0
  385. package/test/integration/review-plugin-integration.test.ts +722 -0
  386. package/test/integration/review.test.ts +149 -0
  387. package/test/integration/routing-stage-bug-021.test.ts +274 -0
  388. package/test/integration/routing-stage-greenfield.test.ts +286 -0
  389. package/test/integration/runner-config-plugins.test.ts +461 -0
  390. package/test/integration/runner-fixes.test.ts +399 -0
  391. package/test/integration/runner-plugin-integration.test.ts +543 -0
  392. package/test/integration/runner.test.ts +1679 -0
  393. package/test/integration/s5-greenfield-fallback.test.ts +297 -0
  394. package/test/integration/status-file-integration.test.ts +325 -0
  395. package/test/integration/status-file.test.ts +379 -0
  396. package/test/integration/status-writer.test.ts +345 -0
  397. package/test/integration/story-id-in-events.test.ts +273 -0
  398. package/test/integration/tdd-cleanup.test.ts +246 -0
  399. package/test/integration/tdd-orchestrator.test.ts +1762 -0
  400. package/test/integration/test-scanner.test.ts +403 -0
  401. package/test/integration/verification-asset-check.test.ts +142 -0
  402. package/test/integration/verify-stage.test.ts +275 -0
  403. package/test/integration/worktree/manager.test.ts +218 -0
  404. package/test/integration/worktree/merge.test.ts +341 -0
  405. package/test/manual/logging-formatter-demo.ts +158 -0
  406. package/test/ui/tui-agent-panel.test.tsx +99 -0
  407. package/test/ui/tui-controls.test.ts +334 -0
  408. package/test/ui/tui-cost-and-pty.test.ts +189 -0
  409. package/test/ui/tui-layout.test.ts +378 -0
  410. package/test/ui/tui-pty-integration.test.tsx +159 -0
  411. package/test/ui/tui-stories.test.ts +332 -0
  412. package/test/unit/acceptance.test.ts +186 -0
  413. package/test/unit/agent-stderr-capture.test.ts +146 -0
  414. package/test/unit/analyze-classifier.test.ts +215 -0
  415. package/test/unit/analyze.test.ts +224 -0
  416. package/test/unit/auto-detect.test.ts +249 -0
  417. package/test/unit/cli-status.test.ts +417 -0
  418. package/test/unit/commands/common.test.ts +320 -0
  419. package/test/unit/commands/logs.test.ts +416 -0
  420. package/test/unit/commands/unlock.test.ts +319 -0
  421. package/test/unit/constitution-generators.test.ts +160 -0
  422. package/test/unit/constitution.test.ts +209 -0
  423. package/test/unit/context.test.ts +1722 -0
  424. package/test/unit/cost.test.ts +231 -0
  425. package/test/unit/crash-recovery.test.ts +308 -0
  426. package/test/unit/escalation.test.ts +126 -0
  427. package/test/unit/execution-logging-stderr.test.ts +156 -0
  428. package/test/unit/execution-stage.test.ts +122 -0
  429. package/test/unit/fix-generator.test.ts +275 -0
  430. package/test/unit/formatters.test.ts +469 -0
  431. package/test/unit/greenfield.test.ts +179 -0
  432. package/test/unit/helpers.test.ts +317 -0
  433. package/test/unit/interaction/human-review-trigger.test.ts +164 -0
  434. package/test/unit/interaction-network-failures.test.ts +389 -0
  435. package/test/unit/interaction-plugins.test.ts +164 -0
  436. package/test/unit/isolation.test.ts +134 -0
  437. package/test/unit/logging/formatter.test.ts +455 -0
  438. package/test/unit/merge.test.ts +268 -0
  439. package/test/unit/metrics.test.ts +276 -0
  440. package/test/unit/optimizer/noop.optimizer.test.ts +125 -0
  441. package/test/unit/optimizer/rule-based.optimizer.test.ts +358 -0
  442. package/test/unit/prd-auto-default.test.ts +290 -0
  443. package/test/unit/prd-failure-category.test.ts +176 -0
  444. package/test/unit/prd-get-next-story.test.ts +186 -0
  445. package/test/unit/precheck-checks.test.ts +840 -0
  446. package/test/unit/precheck-story-size-gate.test.ts +287 -0
  447. package/test/unit/precheck-types.test.ts +142 -0
  448. package/test/unit/prompts.test.ts +475 -0
  449. package/test/unit/queue.test.ts +237 -0
  450. package/test/unit/rectification.test.ts +284 -0
  451. package/test/unit/registry.test.ts +287 -0
  452. package/test/unit/routing.test.ts +937 -0
  453. package/test/unit/run-lifecycle.test.ts +140 -0
  454. package/test/unit/storyid-events.test.ts +224 -0
  455. package/test/unit/tdd-verdict.test.ts +492 -0
  456. package/test/unit/test-output-parser.test.ts +377 -0
  457. package/test/unit/verdict.test.ts +324 -0
  458. package/test/unit/worktree-manager.test.ts +158 -0
  459. package/tsconfig.json +27 -0
@@ -0,0 +1,589 @@
1
+ # Deep Code Review: ngent v0.3.0
2
+
3
+ **Date:** 2026-02-17
4
+ **Reviewer:** Subrina (AI)
5
+ **Version:** 0.3.0-dev
6
+ **Files:** 65 TypeScript files (src: ~7,172 LOC, test: ~7,757 LOC)
7
+ **Baseline:** 342 tests passing, 881 assertions, TypeScript strict mode
8
+
9
+ ---
10
+
11
+ ## Overall Grade: A- (88/100)
12
+
13
+ The v0.3 pipeline refactor represents a significant architectural improvement, successfully decomposing the monolithic runner into composable stages while maintaining backward compatibility. The new constitution, analyze, and review modules are well-designed with strong type safety and comprehensive test coverage. However, several medium-priority issues around JSDoc coverage, error handling consistency, and incomplete verify stage logic prevent this from achieving an A grade.
14
+
15
+ **Key Strengths:**
16
+ - Clean pipeline architecture with proper separation of concerns
17
+ - Excellent test coverage for new modules (constitution: 100%, review: 100%, pipeline: 90%+)
18
+ - Strong type safety with discriminated unions for pipeline results
19
+ - Proper integration between new and existing systems
20
+
21
+ **Areas for Improvement:**
22
+ - Incomplete verify stage (placeholder with TODO)
23
+ - JSDoc coverage gaps in pipeline stages (~40%)
24
+ - Inconsistent error handling patterns between stages
25
+ - Missing integration tests for full pipeline execution with all stages
26
+
27
+ ---
28
+
29
+ ## Findings
30
+
31
+ ### 🔴 CRITICAL
32
+
33
+ None. The codebase is production-ready from a security and reliability standpoint.
34
+
35
+ ---
36
+
37
+ ### 🟡 HIGH
38
+
39
+ #### BUG-7: Verify Stage is a No-Op Placeholder
40
+ **Severity:** HIGH | **Category:** Bug
41
+ **File:** `src/pipeline/stages/verify.ts:18-25`
42
+
43
+ ```typescript
44
+ export const verifyStage: PipelineStage = {
45
+ name: "verify",
46
+ enabled: () => true,
47
+ async execute(_ctx: PipelineContext): Promise<StageResult> {
48
+ // TODO: Add verification logic here
49
+ // - Run tests
50
+ // - Check build
51
+ // - Validate output
52
+ return { action: "continue" };
53
+ },
54
+ };
55
+ ```
56
+
57
+ **Risk:** The verify stage is currently a no-op that always passes. This means agent output is never validated before being marked as passed. Stories could be marked complete even if tests fail or builds break.
58
+
59
+ **Fix:** Implement verification logic:
60
+ 1. Run `bun test` in the workdir
61
+ 2. Check exit code
62
+ 3. Return `{ action: "fail", reason: "Tests failed" }` if exit code !== 0
63
+ 4. Consider adding build verification for TypeScript projects
64
+
65
+ **Priority:** P0 — This is a critical gap in the execution pipeline.
66
+
67
+ ---
68
+
69
+ #### ENH-6: Pipeline Stages Have Inconsistent Error Handling
70
+ **Severity:** HIGH | **Category:** Enhancement
71
+ **File:** Multiple pipeline stages
72
+
73
+ ```typescript
74
+ // Constitution stage: returns continue even if loading fails silently
75
+ if (result) {
76
+ ctx.constitution = result.content;
77
+ // ...logs...
78
+ }
79
+ // No else — just continues without constitution
80
+
81
+ // Execution stage: returns fail with clear reason
82
+ if (!ctx.prompt) {
83
+ return { action: "fail", reason: "Prompt not built (prompt stage skipped?)" };
84
+ }
85
+ ```
86
+
87
+ **Risk:** Inconsistent error handling makes it hard to debug pipeline failures. Some stages silently continue on errors, others fail explicitly. This can lead to confusing behavior where a story fails for unclear reasons.
88
+
89
+ **Fix:** Establish consistent patterns:
90
+ 1. **Soft failures** (constitution missing, context empty) → continue with warning log
91
+ 2. **Hard failures** (no agent, invalid config) → return `{ action: "fail", reason: "..." }`
92
+ 3. Document these patterns in a `PIPELINE.md` guide
93
+
94
+ **Priority:** P1 — Affects debugging experience and maintainability.
95
+
96
+ ---
97
+
98
+ ### 🟡 MEDIUM
99
+
100
+ #### ENH-7: Missing JSDoc on Pipeline Stages (~40% coverage)
101
+ **Severity:** MEDIUM | **Category:** Enhancement
102
+ **File:** `src/pipeline/stages/*.ts`
103
+
104
+ ```typescript
105
+ // ✗ No JSDoc
106
+ export const queueCheckStage: PipelineStage = {
107
+ name: "queue-check",
108
+ enabled: () => true,
109
+ async execute(ctx: PipelineContext): Promise<StageResult> {
110
+ // ...
111
+ },
112
+ };
113
+
114
+ // ✓ Should have JSDoc
115
+ /**
116
+ * Queue Check Stage
117
+ *
118
+ * Checks for queue commands (PAUSE/ABORT/SKIP) before executing a story.
119
+ * Processes commands atomically and updates PRD accordingly.
120
+ *
121
+ * @returns
122
+ * - `continue`: No queue commands, proceed
123
+ * - `pause`: PAUSE/ABORT command found, stop execution
124
+ * - `skip`: SKIP command removed all stories from batch
125
+ *
126
+ * @example
127
+ * ```ts
128
+ * // User writes: echo "PAUSE" > .queue.txt
129
+ * const result = await queueCheckStage.execute(ctx);
130
+ * // result: { action: "pause", reason: "User requested pause via .queue.txt" }
131
+ * ```
132
+ */
133
+ ```
134
+
135
+ **Impact:** New contributors need to read implementation code to understand stage behavior. Missing examples make it hard to understand stage interactions.
136
+
137
+ **Fix:** Add JSDoc to all 9 pipeline stages with:
138
+ - Brief description (1-2 sentences)
139
+ - Return value documentation (all possible actions)
140
+ - Example showing stage behavior in context
141
+
142
+ **Priority:** P2 — Documentation gap, but code is readable.
143
+
144
+ ---
145
+
146
+ #### TYPE-3: Constitution Stage Uses Loose Type Conversion
147
+ **Severity:** MEDIUM | **Category:** Type Safety
148
+ **File:** `src/pipeline/stages/prompt.ts:22-30`
149
+
150
+ ```typescript
151
+ // Convert constitution string to ConstitutionResult if present
152
+ const constitution: ConstitutionResult | undefined = ctx.constitution
153
+ ? {
154
+ content: ctx.constitution,
155
+ tokens: Math.ceil(ctx.constitution.length / 4), // ⚠️ Duplicates estimation logic
156
+ originalTokens: Math.ceil(ctx.constitution.length / 4),
157
+ truncated: false,
158
+ }
159
+ : undefined;
160
+ ```
161
+
162
+ **Risk:**
163
+ 1. Duplicates token estimation logic (should use `estimateTokens()` from constitution module)
164
+ 2. Uses 1 token ≈ 4 chars, but constitution loader uses 1 token ≈ 3 chars (inconsistent)
165
+ 3. If context stores `ConstitutionResult` instead of `string`, this conversion is unnecessary
166
+
167
+ **Fix:**
168
+ 1. Store `ConstitutionResult | undefined` in `PipelineContext.constitution` instead of `string | undefined`
169
+ 2. Update constitution stage to assign the full result object
170
+ 3. Remove conversion logic from prompt stage
171
+
172
+ **Priority:** P2 — Type inconsistency, but functionally correct.
173
+
174
+ ---
175
+
176
+ #### BUG-8: Pipeline Runner Doesn't Preserve Context Mutations Across Stages
177
+ **Severity:** MEDIUM | **Category:** Bug
178
+ **File:** `src/pipeline/runner.ts:48-127`
179
+
180
+ ```typescript
181
+ export async function runPipeline(
182
+ stages: PipelineStage[],
183
+ context: PipelineContext,
184
+ ): Promise<PipelineRunResult> {
185
+ for (const stage of stages) {
186
+ // ...
187
+ result = await stage.execute(context); // ⚠️ Stages mutate context in-place
188
+ }
189
+ // ...
190
+ return {
191
+ success: true,
192
+ finalAction: "complete",
193
+ context, // ⚠️ Returns mutated context, but contract is unclear
194
+ };
195
+ }
196
+ ```
197
+
198
+ **Risk:** Stages mutate the context object in-place. The function signature doesn't make it clear whether the input `context` is mutated or a new context is returned. This could cause subtle bugs if callers expect immutability.
199
+
200
+ **Fix:**
201
+ 1. Document mutation contract in JSDoc: "Stages mutate the context in-place. The returned context is the same object, mutated."
202
+ 2. Consider cloning context before pipeline execution for safer API (if mutation is unintended)
203
+ 3. Add integration test verifying context mutations are preserved
204
+
205
+ **Priority:** P2 — Potential footgun, but current usage is correct.
206
+
207
+ ---
208
+
209
+ #### PERF-4: Prompt Stage Recreates ConstitutionResult on Every Execution
210
+ **Severity:** MEDIUM | **Category:** Performance
211
+ **File:** `src/pipeline/stages/prompt.ts:22-30`
212
+
213
+ ```typescript
214
+ async execute(ctx: PipelineContext): Promise<StageResult> {
215
+ // ⚠️ Re-creates ConstitutionResult every time even though content is static
216
+ const constitution: ConstitutionResult | undefined = ctx.constitution
217
+ ? {
218
+ content: ctx.constitution,
219
+ tokens: Math.ceil(ctx.constitution.length / 4),
220
+ originalTokens: Math.ceil(ctx.constitution.length / 4),
221
+ truncated: false,
222
+ }
223
+ : undefined;
224
+ // ...
225
+ }
226
+ ```
227
+
228
+ **Impact:** Constitution is loaded once per feature, but prompt stage recreates the result object on every story. For a 100-story feature, this wastes allocation cycles.
229
+
230
+ **Fix:** Store `ConstitutionResult` in context (see TYPE-3) so prompt stage can use it directly without reconstruction.
231
+
232
+ **Priority:** P3 — Micro-optimization, but aligns with TYPE-3 fix.
233
+
234
+ ---
235
+
236
+ #### ENH-8: No Integration Test for Full Pipeline with All Stages
237
+ **Severity:** MEDIUM | **Category:** Enhancement
238
+ **File:** `test/pipeline.test.ts`
239
+
240
+ **Current coverage:**
241
+ - ✓ Pipeline runner logic (continue/skip/fail/escalate/pause)
242
+ - ✓ Individual stage unit tests (constitution, review)
243
+ - ✗ Full pipeline execution with all 9 stages
244
+
245
+ **Missing:** An integration test that:
246
+ 1. Sets up a real workdir with package.json, src/, test/
247
+ 2. Runs `runPipeline(defaultPipeline, realContext)`
248
+ 3. Verifies all stages execute in order
249
+ 4. Checks context accumulation (constitution → context → prompt → agentResult → reviewResult)
250
+
251
+ **Fix:** Add `test/pipeline-integration.test.ts`:
252
+ ```typescript
253
+ test("full pipeline execution with all stages", async () => {
254
+ const ctx = createRealTestContext(); // Real files, not mocks
255
+ const result = await runPipeline(defaultPipeline, ctx);
256
+
257
+ expect(result.success).toBe(true);
258
+ expect(result.context.constitution).toBeDefined();
259
+ expect(result.context.prompt).toBeDefined();
260
+ expect(result.context.agentResult).toBeDefined();
261
+ // etc.
262
+ });
263
+ ```
264
+
265
+ **Priority:** P2 — Increases confidence in pipeline integration.
266
+
267
+ ---
268
+
269
+ #### STYLE-4: Magic Number for Constitution Token Estimation Inconsistency
270
+ **Severity:** MEDIUM | **Category:** Style
271
+ **File:** `src/pipeline/stages/prompt.ts:26` vs `src/constitution/loader.ts:21`
272
+
273
+ ```typescript
274
+ // constitution/loader.ts
275
+ export function estimateTokens(text: string): number {
276
+ return Math.ceil(text.length / 3); // 1 token ≈ 3 chars
277
+ }
278
+
279
+ // pipeline/stages/prompt.ts
280
+ tokens: Math.ceil(ctx.constitution.length / 4), // ⚠️ 1 token ≈ 4 chars
281
+ ```
282
+
283
+ **Risk:** Inconsistent token estimation can lead to underestimation in prompt stage, potentially hitting model context limits unexpectedly.
284
+
285
+ **Fix:** Always use `estimateTokens()` from constitution module. Extract as named constant if different heuristic is intentional:
286
+ ```typescript
287
+ const CONSERVATIVE_TOKEN_ESTIMATE = 4; // chars per token (more conservative than 3)
288
+ ```
289
+
290
+ **Priority:** P2 — Consistency issue with functional impact.
291
+
292
+ ---
293
+
294
+ ### 🟢 LOW
295
+
296
+ #### ENH-9: Plan Command Doesn't Validate Spec Template Output
297
+ **Severity:** LOW | **Category:** Enhancement
298
+ **File:** `src/cli/plan.ts:50-132`
299
+
300
+ ```typescript
301
+ // In interactive mode, assume agent wrote the spec
302
+ if (interactive) {
303
+ if (result.specContent) {
304
+ await Bun.write(outputPath, result.specContent);
305
+ } else {
306
+ // If agent wrote directly, verify it exists
307
+ if (!existsSync(outputPath)) { // ⚠️ No format validation
308
+ throw new Error(`Interactive planning completed but spec not found at ${outputPath}`);
309
+ }
310
+ }
311
+ }
312
+ ```
313
+
314
+ **Impact:** Plan mode checks if spec file exists but doesn't validate it follows the template format. Agent could write invalid markdown or skip required sections (Problem, Requirements, Acceptance Criteria).
315
+
316
+ **Fix:** Add optional spec validation:
317
+ 1. Parse output markdown
318
+ 2. Check for required sections: `# Feature:`, `## Problem`, `## Requirements`, `## Acceptance Criteria`
319
+ 3. Warn if sections are missing (don't fail, since agent may use different structure)
320
+
321
+ **Priority:** P3 — Nice-to-have validation, but agent output is typically well-structured.
322
+
323
+ ---
324
+
325
+ #### STYLE-5: Analyze Classifier Uses `any` for LLM Response Parsing
326
+ **Severity:** LOW | **Category:** Type Safety
327
+ **File:** `src/analyze/classifier.ts:105-127`
328
+
329
+ ```typescript
330
+ // Extract text from response
331
+ const textContent = response.content.find((c: any) => c.type === "text"); // ⚠️ any
332
+ if (!textContent || textContent.type !== "text") {
333
+ throw new Error("No text response from LLM");
334
+ }
335
+
336
+ // Map to StoryClassification[]
337
+ const classifications: StoryClassification[] = parsed.map((item: any) => ({ // ⚠️ any
338
+ storyId: item.storyId,
339
+ complexity: validateComplexity(item.complexity),
340
+ // ...
341
+ }));
342
+ ```
343
+
344
+ **Risk:** Using `any` bypasses type checking. If Anthropic SDK changes response structure, this code could fail at runtime without TypeScript catching it.
345
+
346
+ **Fix:** Define proper types:
347
+ ```typescript
348
+ interface AnthropicTextContent {
349
+ type: "text";
350
+ text: string;
351
+ }
352
+
353
+ interface LLMClassificationItem {
354
+ storyId: string;
355
+ complexity: string;
356
+ relevantFiles: unknown;
357
+ reasoning: unknown;
358
+ estimatedLOC: unknown;
359
+ risks: unknown;
360
+ }
361
+ ```
362
+
363
+ **Priority:** P3 — Low risk since Anthropic SDK is stable, but better type safety is always preferred.
364
+
365
+ ---
366
+
367
+ #### ENH-10: Pipeline Doesn't Log Which Stages Were Skipped
368
+ **Severity:** LOW | **Category:** Enhancement
369
+ **File:** `src/pipeline/runner.ts:52-56`
370
+
371
+ ```typescript
372
+ for (const stage of stages) {
373
+ // Skip disabled stages
374
+ if (!stage.enabled(context)) {
375
+ continue; // ⚠️ Silent skip — user doesn't know why stage didn't run
376
+ }
377
+ // ...
378
+ }
379
+ ```
380
+
381
+ **Impact:** If a stage is disabled (e.g., `reviewStage` when `config.review.enabled = false`), the pipeline silently skips it. Users may be confused why review didn't run.
382
+
383
+ **Fix:** Add debug logging for skipped stages:
384
+ ```typescript
385
+ if (!stage.enabled(context)) {
386
+ console.log(chalk.dim(` → Stage "${stage.name}" skipped (disabled)`));
387
+ continue;
388
+ }
389
+ ```
390
+
391
+ **Priority:** P3 — Improves observability but not critical.
392
+
393
+ ---
394
+
395
+ #### STYLE-6: Queue Check Stage Mutates Context Stories Array
396
+ **Severity:** LOW | **Category:** Style
397
+ **File:** `src/pipeline/stages/queue-check.ts:68`
398
+
399
+ ```typescript
400
+ // Remove from batch
401
+ ctx.stories = ctx.stories.filter((s) => s.id !== cmd.storyId); // ⚠️ Mutation
402
+ ```
403
+
404
+ **Risk:** Mutating `ctx.stories` directly could cause confusion if other code expects the original batch to remain unchanged.
405
+
406
+ **Fix:** Follow immutability principles:
407
+ ```typescript
408
+ // Create new array instead of mutating
409
+ ctx.stories = ctx.stories.filter((s) => s.id !== cmd.storyId);
410
+ // ✓ Already immutable (filter returns new array), but could be clearer:
411
+ const updatedStories = ctx.stories.filter((s) => s.id !== cmd.storyId);
412
+ ctx.stories = updatedStories;
413
+ ```
414
+
415
+ **Note:** Current code is actually fine (filter returns new array), but the assignment pattern could be clearer.
416
+
417
+ **Priority:** P4 — Code works correctly, just a style preference.
418
+
419
+ ---
420
+
421
+ #### ENH-11: No Dry-Run Support for Review Stage
422
+ **Severity:** LOW | **Category:** Enhancement
423
+ **File:** `src/pipeline/stages/review.ts:16-29`
424
+
425
+ ```typescript
426
+ async execute(ctx: PipelineContext): Promise<StageResult> {
427
+ console.log(chalk.cyan("\n → Running review phase..."));
428
+
429
+ const reviewResult = await runReview(ctx.config.review, ctx.workdir); // ⚠️ Always runs, even in dry-run mode
430
+ // ...
431
+ }
432
+ ```
433
+
434
+ **Impact:** In dry-run mode, review stage still executes `bun test`, `bun run typecheck`, etc. This makes dry runs slow and may fail on incomplete code.
435
+
436
+ **Fix:** Check for dry-run flag in context:
437
+ ```typescript
438
+ if (ctx.config.execution.dryRun) {
439
+ console.log(chalk.yellow(" [DRY RUN] Would run review phase"));
440
+ return { action: "continue" };
441
+ }
442
+ ```
443
+
444
+ **Note:** PipelineContext doesn't currently have a `dryRun` flag. This would need to be added.
445
+
446
+ **Priority:** P4 — Minor UX improvement for dry runs.
447
+
448
+ ---
449
+
450
+ #### TYPE-4: Routing Stage Console Logs Duplicate Logic
451
+ **Severity:** LOW | **Category:** Style
452
+ **File:** `src/pipeline/stages/routing.ts:32-45`
453
+
454
+ ```typescript
455
+ const isBatch = ctx.stories.length > 1;
456
+
457
+ if (isBatch) {
458
+ console.log(
459
+ chalk.dim(
460
+ ` Complexity: ${routing.complexity} | Model: ${routing.modelTier} | TDD: ${routing.testStrategy}`,
461
+ ),
462
+ );
463
+ } else {
464
+ console.log(
465
+ chalk.dim(
466
+ ` Complexity: ${routing.complexity} | Model: ${routing.modelTier} | TDD: ${routing.testStrategy}`,
467
+ ),
468
+ );
469
+ console.log(chalk.dim(` Routing: ${routing.reasoning}`));
470
+ }
471
+ ```
472
+
473
+ **Issue:** Both branches log identical strings. Could be simplified:
474
+ ```typescript
475
+ console.log(
476
+ chalk.dim(
477
+ ` Complexity: ${routing.complexity} | Model: ${routing.modelTier} | TDD: ${routing.testStrategy}`,
478
+ ),
479
+ );
480
+ if (!isBatch) {
481
+ console.log(chalk.dim(` Routing: ${routing.reasoning}`));
482
+ }
483
+ ```
484
+
485
+ **Priority:** P4 — Code clarity, no functional impact.
486
+
487
+ ---
488
+
489
+ ## Priority Fix Order
490
+
491
+ | Priority | ID | Effort | Description |
492
+ |:---|:---|:---|:---|
493
+ | **P0** | BUG-7 | M | Implement verify stage logic (run tests, check build) |
494
+ | **P1** | ENH-6 | L | Document and standardize error handling patterns across pipeline stages |
495
+ | **P1** | ENH-7 | M | Add JSDoc to all 9 pipeline stages with examples |
496
+ | **P2** | TYPE-3 | S | Store ConstitutionResult in context, remove prompt stage conversion |
497
+ | **P2** | BUG-8 | S | Document context mutation contract in runPipeline JSDoc |
498
+ | **P2** | ENH-8 | M | Add full pipeline integration test with all stages |
499
+ | **P2** | STYLE-4 | S | Fix token estimation inconsistency (use estimateTokens() everywhere) |
500
+ | **P3** | ENH-9 | M | Add optional spec validation to plan command |
501
+ | **P3** | STYLE-5 | S | Replace `any` with proper types in analyze classifier |
502
+ | **P3** | ENH-10 | S | Log skipped stages for observability |
503
+ | **P4** | STYLE-6 | — | (No action needed — code is correct) |
504
+ | **P4** | ENH-11 | S | Add dry-run support to review stage |
505
+ | **P4** | TYPE-4 | S | Simplify routing stage logging |
506
+
507
+ **Effort:** S = Small (<1hr), M = Medium (1-4hrs), L = Large (>4hrs)
508
+
509
+ ---
510
+
511
+ ## Dimension Scores
512
+
513
+ ### Security: 20/20 ✓
514
+ - ✓ No hardcoded secrets or credentials
515
+ - ✓ Input validation on all boundaries (queue commands, spec parsing)
516
+ - ✓ Command injection prevention in review runner (using spawn with args array)
517
+ - ✓ Path traversal protection via config path-security module
518
+ - ✓ No eval or dynamic code execution
519
+ - ✓ Hook security validation from v0.2 still in place
520
+
521
+ **Notes:** Pipeline stages properly delegate to existing security-vetted modules (hooks, agents, prd). No new security concerns introduced.
522
+
523
+ ### Reliability: 17/20
524
+ - ✓ Comprehensive error handling in pipeline runner (try/catch, stage failures)
525
+ - ✓ Proper resource cleanup (no leaked streams, timers, or file handles)
526
+ - ✓ Atomic queue file handling from v0.2 maintained
527
+ - ✗ **BUG-7:** Verify stage is a no-op (doesn't actually verify anything)
528
+ - ✗ **ENH-6:** Inconsistent error handling patterns across stages
529
+ - ⚠️ **BUG-8:** Context mutation contract unclear
530
+
531
+ **Deductions:** -3 for verify stage gap, -0.5 for inconsistent error patterns, -0.5 for mutation documentation gap.
532
+
533
+ ### API Design: 18/20
534
+ - ✓ Clean pipeline abstraction with composable stages
535
+ - ✓ Well-defined stage interface (PipelineStage with enabled/execute)
536
+ - ✓ Discriminated union for StageResult (exhaustiveness checking)
537
+ - ✓ Consistent naming conventions (queueCheckStage, routingStage, etc.)
538
+ - ✓ Good separation of concerns (each stage has single responsibility)
539
+ - ✗ **TYPE-3:** Constitution type inconsistency (string vs ConstitutionResult)
540
+ - ✗ **ENH-7:** Missing JSDoc on 60% of pipeline stages
541
+
542
+ **Deductions:** -1 for type inconsistency, -1 for documentation gaps.
543
+
544
+ ### Code Quality: 16/20
545
+ - ✓ Excellent test coverage (constitution: 100%, review: 100%, pipeline: 90%+)
546
+ - ✓ No dead code or commented-out blocks
547
+ - ✓ Files are appropriately sized (<400 lines for all pipeline stages)
548
+ - ✓ Consistent code style (Biome formatting)
549
+ - ✗ **STYLE-4:** Magic number inconsistency (token estimation)
550
+ - ✗ **STYLE-5:** Use of `any` in classifier LLM response parsing
551
+ - ✗ **TYPE-4:** Duplicate logging logic in routing stage
552
+ - ✗ **ENH-8:** Missing integration test for full pipeline
553
+
554
+ **Deductions:** -2 for missing integration test, -1 for any usage, -1 for magic number inconsistency.
555
+
556
+ ### Best Practices: 17/20
557
+ - ✓ Follows established v0.2 patterns (hooks, routing, PRD management)
558
+ - ✓ Proper use of TypeScript features (discriminated unions, exhaustiveness checks)
559
+ - ✓ Clear module boundaries with barrel exports
560
+ - ✓ Good abstraction (pipeline runner is framework-agnostic)
561
+ - ✗ **ENH-6:** Inconsistent error handling (some stages silent fail, others don't)
562
+ - ✗ **ENH-10:** No observability for skipped stages
563
+ - ✗ **BUG-8:** Mutation contract unclear
564
+
565
+ **Deductions:** -2 for inconsistent patterns, -1 for observability gap.
566
+
567
+ ---
568
+
569
+ ## Summary
570
+
571
+ The v0.3 pipeline refactor is a **strong architectural improvement** that successfully decomposes the monolithic runner into composable, testable stages. The new modules (constitution, analyze, review) are well-designed with excellent test coverage and proper integration.
572
+
573
+ **Critical gap:** The verify stage is currently a placeholder (BUG-7). This must be implemented before v0.3 ships, as it's a core part of the quality gate.
574
+
575
+ **Recommended path forward:**
576
+ 1. **Immediate (P0):** Implement verify stage with test execution
577
+ 2. **Before v0.3 release (P1):** Add pipeline stage JSDoc and standardize error handling
578
+ 3. **Post-v0.3 (P2-P4):** Address type inconsistencies, add integration tests, improve observability
579
+
580
+ **Grade justification:**
581
+ - Security: Excellent (20/20)
582
+ - Reliability: Very good, one critical gap (17/20)
583
+ - API Design: Very good, minor documentation gap (18/20)
584
+ - Code Quality: Good, missing integration tests (16/20)
585
+ - Best Practices: Good, inconsistent patterns (17/20)
586
+
587
+ **Total: 88/100 (A-)**
588
+
589
+ With BUG-7 fixed and ENH-6/ENH-7 addressed, this would easily achieve an **A (90+)**.
@@ -0,0 +1,86 @@
1
+ # v0.4 Implementation Plan: Acceptance Validation
2
+ **Date:** 2026-02-17
3
+ **Branch:** master
4
+
5
+ ## Complexity Assessment
6
+ - **Files touched:** 8+ (new module + pipeline stage + analyze integration + config + CLI + tests)
7
+ - **LOC:** ~400-600 new
8
+ - **Architectural impact:** New pipeline stage, new analyze output, new retry loop in runner
9
+ - **Test strategy:** test-after (internal modules, not public API)
10
+
11
+ ## Phase 1: Acceptance test generator
12
+ ### 1a: Acceptance module
13
+ **File:** `src/acceptance/generator.ts` (NEW)
14
+ - Parse spec.md acceptance criteria (extract AC-N lines)
15
+ - Build LLM prompt: ACs + codebase context → test file
16
+ - Parse LLM response → write `acceptance.test.ts`
17
+ - Fallback: generate skeleton tests with TODO if LLM fails
18
+
19
+ ### 1b: Integration with analyze
20
+ **File:** `src/cli/analyze.ts`
21
+ - After decompose, call acceptance test generator
22
+ - Write tests to `ngent/features/<name>/acceptance.test.ts`
23
+ - Config check: `acceptance.generateTests`
24
+
25
+ ### 1c: Config schema update
26
+ **File:** `src/config/schema.ts`
27
+ - Add `acceptance` config block: `enabled`, `maxRetries`, `generateTests`, `testPath`
28
+
29
+ ### Tests
30
+ - AC parser extracts criteria from spec markdown
31
+ - Generator produces valid test structure
32
+ - Config validation
33
+
34
+ **Commit:** `feat(acceptance): generate acceptance tests from spec ACs`
35
+
36
+ ## Phase 2: Acceptance pipeline stage
37
+ ### 2a: Acceptance stage
38
+ **File:** `src/pipeline/stages/acceptance.ts` (NEW)
39
+ - Only runs when all stories are complete (check prd status)
40
+ - Spawns `bun test acceptance.test.ts` in workdir
41
+ - Parses test output: which ACs passed/failed
42
+ - Returns `continue` if all pass, `fail` with details if any fail
43
+
44
+ ### 2b: Register in default pipeline
45
+ **File:** `src/pipeline/stages/index.ts`
46
+ - Add `acceptanceStage` after `completionStage`
47
+
48
+ ### Tests
49
+ - Stage skips when stories still pending
50
+ - Stage runs and parses test results
51
+ - Pass/fail detection
52
+
53
+ **Commit:** `feat(acceptance): add acceptance validation pipeline stage`
54
+
55
+ ## Phase 3: Self-correcting fix loop
56
+ ### 3a: Fix story generator
57
+ **File:** `src/acceptance/fix-generator.ts` (NEW)
58
+ - Input: failed ACs + test output + related stories + source code
59
+ - LLM call: generate fix story descriptions
60
+ - Output: FixStory objects with id, title, relatedStories, description
61
+
62
+ ### 3b: Fix loop in runner
63
+ **File:** `src/execution/runner.ts`
64
+ - After acceptance stage fails: generate fix stories, append to prd
65
+ - Re-run pipeline for fix stories only
66
+ - Re-run acceptance tests
67
+ - Max `config.acceptance.maxRetries` loops
68
+ - If still failing: pause and report to human
69
+
70
+ ### 3c: Accept override command
71
+ **File:** `src/cli/accept.ts` (NEW)
72
+ - `ngent accept --override AC-2 "reason"`
73
+ - Stores in prd.json `acceptanceOverrides`
74
+ - Acceptance stage skips overridden ACs
75
+
76
+ ### Tests
77
+ - Fix story generation from failed ACs
78
+ - Retry loop respects maxRetries
79
+ - Override skips specified ACs
80
+ - Full integration: fail → fix → pass
81
+
82
+ **Commit:** `feat(acceptance): add self-correcting fix loop with human override`
83
+
84
+ ## Test Strategy
85
+ - Mode: test-after
86
+ - Run `bun test && bun run typecheck` after each phase