@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,54 @@
1
+ /**
2
+ * Queue Types
3
+ *
4
+ * Priority queue for scheduling user stories across agents.
5
+ * Enables future parallel agent execution.
6
+ */
7
+
8
+ /** Queue item status */
9
+ export type QueueItemStatus = "pending" | "in-progress" | "completed" | "failed" | "skipped";
10
+
11
+ /** Queue item representing a user story to be executed */
12
+ export interface QueueItem {
13
+ /** Unique story ID */
14
+ storyId: string;
15
+ /** Display title */
16
+ title: string;
17
+ /** Priority score (higher = more urgent) */
18
+ priority: number;
19
+ /** Current status */
20
+ status: QueueItemStatus;
21
+ /** Assigned agent (if any) */
22
+ assignedAgent?: string;
23
+ /** Number of retry attempts */
24
+ attempts: number;
25
+ /** Timestamp when added to queue */
26
+ addedAt: Date;
27
+ /** Timestamp when started (if in-progress) */
28
+ startedAt?: Date;
29
+ /** Timestamp when completed/failed */
30
+ completedAt?: Date;
31
+ /** Error message (if failed) */
32
+ error?: string;
33
+ }
34
+
35
+ /** Queue statistics */
36
+ export interface QueueStats {
37
+ total: number;
38
+ pending: number;
39
+ inProgress: number;
40
+ completed: number;
41
+ failed: number;
42
+ skipped: number;
43
+ }
44
+
45
+ /** Queue command for mid-run control */
46
+ export type QueueCommand = { type: "PAUSE" } | { type: "ABORT" } | { type: "SKIP"; storyId: string };
47
+
48
+ /** Result of parsing a queue file */
49
+ export interface QueueFileResult {
50
+ /** Parsed commands from the queue file */
51
+ commands: QueueCommand[];
52
+ /** Non-command lines (existing guidance behavior) */
53
+ guidance: string[];
54
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Review Module
3
+ *
4
+ * Post-implementation quality verification
5
+ */
6
+
7
+ export * from "./types";
8
+ export * from "./runner";
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Review Runner
3
+ *
4
+ * Runs configurable quality checks after story implementation
5
+ */
6
+
7
+ import { spawn } from "bun";
8
+ import type { ExecutionConfig } from "../config/schema";
9
+ import type { ReviewCheckName, ReviewCheckResult, ReviewConfig, ReviewResult } from "./types";
10
+
11
+ /** Default commands for each check type */
12
+ const DEFAULT_COMMANDS: Record<ReviewCheckName, string> = {
13
+ typecheck: "bun run typecheck",
14
+ lint: "bun run lint",
15
+ test: "bun test",
16
+ };
17
+
18
+ /**
19
+ * Load package.json from workdir
20
+ */
21
+ async function loadPackageJson(workdir: string): Promise<Record<string, unknown> | null> {
22
+ try {
23
+ const file = Bun.file(`${workdir}/package.json`);
24
+ const content = await file.text();
25
+ return JSON.parse(content);
26
+ } catch {
27
+ return null;
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Check if package.json has a script
33
+ */
34
+ function hasScript(packageJson: Record<string, unknown> | null, scriptName: string): boolean {
35
+ if (!packageJson) return false;
36
+ const scripts = packageJson.scripts;
37
+ if (typeof scripts !== "object" || scripts === null) return false;
38
+ return scriptName in scripts;
39
+ }
40
+
41
+ /**
42
+ * Resolve command for a check
43
+ * Resolution order:
44
+ * 1. Explicit executionConfig field (lintCommand/typecheckCommand) - null = disabled
45
+ * 2. package.json has script -> use 'bun run <script>'
46
+ * 3. Not found -> return null (skip)
47
+ */
48
+ async function resolveCommand(
49
+ check: ReviewCheckName,
50
+ config: ReviewConfig,
51
+ executionConfig: ExecutionConfig | undefined,
52
+ workdir: string,
53
+ ): Promise<string | null> {
54
+ // 1. Check explicit config.execution commands (v0.13 story)
55
+ if (executionConfig) {
56
+ if (check === "lint" && executionConfig.lintCommand !== undefined) {
57
+ return executionConfig.lintCommand; // null = disabled
58
+ }
59
+ if (check === "typecheck" && executionConfig.typecheckCommand !== undefined) {
60
+ return executionConfig.typecheckCommand; // null = disabled
61
+ }
62
+ }
63
+
64
+ // 2. Check config.review.commands (legacy, backwards compat)
65
+ if (config.commands[check]) {
66
+ return config.commands[check] ?? null;
67
+ }
68
+
69
+ // 3. Check package.json
70
+ const packageJson = await loadPackageJson(workdir);
71
+ if (hasScript(packageJson, check)) {
72
+ return `bun run ${check}`;
73
+ }
74
+
75
+ // 4. Not found - return null to skip
76
+ return null;
77
+ }
78
+
79
+ /**
80
+ * Run a single review check
81
+ */
82
+ async function runCheck(check: ReviewCheckName, command: string, workdir: string): Promise<ReviewCheckResult> {
83
+ const startTime = Date.now();
84
+
85
+ try {
86
+ // Parse command into executable and args
87
+ const parts = command.split(/\s+/);
88
+ const executable = parts[0];
89
+ const args = parts.slice(1);
90
+
91
+ // Spawn the process
92
+ const proc = spawn({
93
+ cmd: [executable, ...args],
94
+ cwd: workdir,
95
+ stdout: "pipe",
96
+ stderr: "pipe",
97
+ });
98
+
99
+ // Wait for completion
100
+ const result = await proc.exited;
101
+
102
+ // Collect output
103
+ const stdout = await new Response(proc.stdout).text();
104
+ const stderr = await new Response(proc.stderr).text();
105
+ const output = [stdout, stderr].filter(Boolean).join("\n");
106
+
107
+ return {
108
+ check,
109
+ command,
110
+ success: result === 0,
111
+ exitCode: result,
112
+ output,
113
+ durationMs: Date.now() - startTime,
114
+ };
115
+ } catch (error) {
116
+ return {
117
+ check,
118
+ command,
119
+ success: false,
120
+ exitCode: -1,
121
+ output: error instanceof Error ? error.message : String(error),
122
+ durationMs: Date.now() - startTime,
123
+ };
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Run all configured review checks
129
+ */
130
+ export async function runReview(
131
+ config: ReviewConfig,
132
+ workdir: string,
133
+ executionConfig?: ExecutionConfig,
134
+ ): Promise<ReviewResult> {
135
+ const startTime = Date.now();
136
+ const checks: ReviewCheckResult[] = [];
137
+ let firstFailure: string | undefined;
138
+
139
+ for (const checkName of config.checks) {
140
+ // Resolve command using resolution strategy
141
+ const command = await resolveCommand(checkName, config, executionConfig, workdir);
142
+
143
+ // Skip if explicitly disabled or not found
144
+ if (command === null) {
145
+ console.warn(`[nax] Skipping ${checkName} check (command not configured or disabled)`);
146
+ continue;
147
+ }
148
+
149
+ // Run the check
150
+ const result = await runCheck(checkName, command, workdir);
151
+ checks.push(result);
152
+
153
+ // Track first failure
154
+ if (!result.success && !firstFailure) {
155
+ firstFailure = `${checkName} failed (exit code ${result.exitCode})`;
156
+ }
157
+
158
+ // Stop on first failure (fail-fast)
159
+ if (!result.success) {
160
+ break;
161
+ }
162
+ }
163
+
164
+ const allPassed = checks.every((c) => c.success);
165
+
166
+ return {
167
+ success: allPassed,
168
+ checks,
169
+ totalDurationMs: Date.now() - startTime,
170
+ failureReason: firstFailure,
171
+ };
172
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Review Phase Types
3
+ *
4
+ * Post-implementation quality verification
5
+ */
6
+
7
+ /** Review check name */
8
+ export type ReviewCheckName = "typecheck" | "lint" | "test";
9
+
10
+ /** Review check result */
11
+ export interface ReviewCheckResult {
12
+ /** Check name */
13
+ check: ReviewCheckName;
14
+ /** Pass or fail */
15
+ success: boolean;
16
+ /** Command that was run */
17
+ command: string;
18
+ /** Exit code */
19
+ exitCode: number;
20
+ /** Output from the command */
21
+ output: string;
22
+ /** Duration in milliseconds */
23
+ durationMs: number;
24
+ }
25
+
26
+ /** Plugin reviewer result */
27
+ export interface PluginReviewerResult {
28
+ /** Plugin reviewer name */
29
+ name: string;
30
+ /** Pass or fail */
31
+ passed: boolean;
32
+ /** Output from the reviewer */
33
+ output: string;
34
+ /** Exit code (if applicable) */
35
+ exitCode?: number;
36
+ /** Error message if reviewer threw an exception */
37
+ error?: string;
38
+ }
39
+
40
+ /** Review phase result */
41
+ export interface ReviewResult {
42
+ /** All checks passed */
43
+ success: boolean;
44
+ /** Individual check results */
45
+ checks: ReviewCheckResult[];
46
+ /** Total duration */
47
+ totalDurationMs: number;
48
+ /** First failure reason (if any) */
49
+ failureReason?: string;
50
+ /** Plugin reviewer results (if any) */
51
+ pluginReviewers?: PluginReviewerResult[];
52
+ }
53
+
54
+ /** Review configuration */
55
+ export interface ReviewConfig {
56
+ /** Enable review phase */
57
+ enabled: boolean;
58
+ /** List of checks to run */
59
+ checks: ReviewCheckName[];
60
+ /** Custom commands per check */
61
+ commands: {
62
+ typecheck?: string;
63
+ lint?: string;
64
+ test?: string;
65
+ };
66
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Routing Strategy Chain Builder
3
+ *
4
+ * Builds the strategy chain based on configuration.
5
+ */
6
+
7
+ import type { NaxConfig } from "../config";
8
+ import type { PluginRegistry } from "../plugins/registry";
9
+ import { StrategyChain } from "./chain";
10
+ import { loadCustomStrategy } from "./loader";
11
+ import { adaptiveStrategy, keywordStrategy, llmStrategy, manualStrategy } from "./strategies";
12
+ import type { RoutingStrategy } from "./strategy";
13
+
14
+ /**
15
+ * Build the routing strategy chain based on configuration.
16
+ *
17
+ * Chain order (plugin routers first, then config-based, keyword always last):
18
+ * - plugin routers (from plugin registry, in load order)
19
+ * - manual (if strategy = "manual")
20
+ * - custom (if strategy = "custom")
21
+ * - llm (if strategy = "llm")
22
+ * - adaptive (if strategy = "adaptive") [v0.5 Phase 3]
23
+ * - keyword (always last — never returns null)
24
+ *
25
+ * @param config - nax configuration
26
+ * @param workdir - Working directory for resolving custom strategy paths
27
+ * @param plugins - Optional plugin registry for plugin-provided routers
28
+ * @returns Strategy chain instance
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * const chain = await buildStrategyChain(config, "/path/to/project", plugins);
33
+ * const decision = chain.route(story, context);
34
+ * ```
35
+ */
36
+ export async function buildStrategyChain(
37
+ config: NaxConfig,
38
+ workdir: string,
39
+ plugins?: PluginRegistry,
40
+ ): Promise<StrategyChain> {
41
+ const strategies: RoutingStrategy[] = [];
42
+
43
+ // Prepend plugin routers before built-in strategies
44
+ if (plugins) {
45
+ const pluginRouters = plugins.getRouters();
46
+ strategies.push(...pluginRouters);
47
+ }
48
+
49
+ // Add strategies based on config
50
+ switch (config.routing.strategy) {
51
+ case "manual":
52
+ strategies.push(manualStrategy);
53
+ break;
54
+
55
+ case "llm":
56
+ strategies.push(llmStrategy);
57
+ break;
58
+
59
+ case "adaptive":
60
+ strategies.push(adaptiveStrategy);
61
+ break;
62
+
63
+ case "custom": {
64
+ if (!config.routing.customStrategyPath) {
65
+ throw new Error("routing.customStrategyPath is required when strategy is 'custom'");
66
+ }
67
+ const customStrategy = await loadCustomStrategy(config.routing.customStrategyPath, workdir);
68
+ strategies.push(customStrategy);
69
+ break;
70
+ }
71
+
72
+ case "keyword":
73
+ // Keyword will be added at the end anyway
74
+ break;
75
+ }
76
+
77
+ // Always add keyword strategy as final fallback
78
+ strategies.push(keywordStrategy);
79
+
80
+ return new StrategyChain(strategies);
81
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Strategy Chain
3
+ *
4
+ * Executes routing strategies in order, falling through on null returns.
5
+ * First strategy to return a non-null decision wins.
6
+ */
7
+
8
+ import { getSafeLogger } from "../logger";
9
+ import type { UserStory } from "../prd/types";
10
+ import type { RoutingContext, RoutingDecision, RoutingStrategy } from "./strategy";
11
+
12
+ /**
13
+ * Strategy chain that tries strategies in order until one returns a decision.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const chain = new StrategyChain([customStrategy, adaptiveStrategy, keywordStrategy]);
18
+ * const decision = chain.route(story, context);
19
+ * // Tries custom first, then adaptive, then keyword
20
+ * // Returns first non-null decision
21
+ * ```
22
+ */
23
+ export class StrategyChain {
24
+ constructor(private readonly strategies: RoutingStrategy[]) {}
25
+
26
+ /**
27
+ * Route a story through the strategy chain.
28
+ *
29
+ * Tries each strategy in order:
30
+ * - If strategy returns a decision → use it
31
+ * - If strategy returns null → try next strategy
32
+ * - If strategy throws an error → log it and try next strategy
33
+ * - If all strategies return null → throw error
34
+ *
35
+ * @param story - User story to route
36
+ * @param context - Routing context
37
+ * @returns Routing decision from first strategy that handles it
38
+ * @throws Error if no strategy returns a decision
39
+ */
40
+ async route(story: UserStory, context: RoutingContext): Promise<RoutingDecision> {
41
+ const logger = getSafeLogger();
42
+
43
+ for (const strategy of this.strategies) {
44
+ try {
45
+ const decision = await strategy.route(story, context);
46
+ if (decision !== null) {
47
+ return decision;
48
+ }
49
+ } catch (error) {
50
+ // Log the error and continue to next strategy
51
+ logger?.error("routing", `Plugin router "${strategy.name}" failed`, {
52
+ strategyName: strategy.name,
53
+ storyId: story.id,
54
+ error: error instanceof Error ? error.message : String(error),
55
+ });
56
+ // Continue to next strategy
57
+ }
58
+ }
59
+
60
+ // This should never happen if keyword strategy is last (it never returns null)
61
+ throw new Error(
62
+ `No routing strategy returned a decision for story ${story.id}. Ensure at least one fallback strategy (e.g., keyword) is in the chain.`,
63
+ );
64
+ }
65
+
66
+ /**
67
+ * Get the list of strategy names in this chain.
68
+ *
69
+ * @returns Array of strategy names
70
+ */
71
+ getStrategyNames(): string[] {
72
+ return this.strategies.map((s) => s.name);
73
+ }
74
+ }
@@ -0,0 +1,16 @@
1
+ // Core types and interfaces
2
+ export type { RoutingDecision } from "./router";
3
+ export type { RoutingStrategy, RoutingContext, AggregateMetrics } from "./strategy";
4
+
5
+ // Main routing functions
6
+ export { routeStory, routeTask, classifyComplexity, determineTestStrategy, complexityToModelTier } from "./router";
7
+
8
+ // Strategy chain
9
+ export { StrategyChain } from "./chain";
10
+ export { buildStrategyChain } from "./builder";
11
+
12
+ // Built-in strategies
13
+ export { keywordStrategy, llmStrategy, manualStrategy } from "./strategies";
14
+
15
+ // Custom strategy loader
16
+ export { loadCustomStrategy } from "./loader";
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Custom Strategy Loader
3
+ *
4
+ * Dynamically imports custom routing strategies from user-provided paths.
5
+ */
6
+
7
+ import { resolve } from "node:path";
8
+ import type { RoutingStrategy } from "./strategy";
9
+
10
+ /**
11
+ * Load a custom routing strategy from a file path.
12
+ *
13
+ * The custom strategy file must export a default object that satisfies
14
+ * the RoutingStrategy interface.
15
+ *
16
+ * @param strategyPath - Path to the custom strategy file (relative to project root or absolute)
17
+ * @param workdir - Working directory (project root)
18
+ * @returns Loaded routing strategy
19
+ * @throws Error if the strategy cannot be loaded or is invalid
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const strategy = await loadCustomStrategy("./my-router.ts", process.cwd());
24
+ * const decision = strategy.route(story, context);
25
+ * ```
26
+ */
27
+ export async function loadCustomStrategy(strategyPath: string, workdir: string): Promise<RoutingStrategy> {
28
+ const absolutePath = resolve(workdir, strategyPath);
29
+
30
+ try {
31
+ // Dynamic import (works with both .ts and .js files in Bun)
32
+ const module = await import(absolutePath);
33
+
34
+ // Expect default export
35
+ const strategy = module.default;
36
+
37
+ if (!strategy) {
38
+ throw new Error(`Custom strategy at ${absolutePath} does not have a default export`);
39
+ }
40
+
41
+ // Validate strategy interface
42
+ if (typeof strategy.name !== "string") {
43
+ throw new Error(`Custom strategy at ${absolutePath} is missing 'name' property`);
44
+ }
45
+
46
+ if (typeof strategy.route !== "function") {
47
+ throw new Error(`Custom strategy at ${absolutePath} is missing 'route' method`);
48
+ }
49
+
50
+ return strategy as RoutingStrategy;
51
+ } catch (error) {
52
+ throw new Error(
53
+ `Failed to load custom routing strategy from ${absolutePath}: ${
54
+ error instanceof Error ? error.message : String(error)
55
+ }`,
56
+ );
57
+ }
58
+ }