@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,172 @@
1
+ /**
2
+ * PRD Operations
3
+ */
4
+
5
+ import { existsSync, statSync } from "node:fs";
6
+ import type { FailureCategory } from "../tdd/types";
7
+ import type { PRD, UserStory } from "./types";
8
+
9
+ export type { PRD, UserStory, StoryRouting, StoryStatus, EscalationAttempt } from "./types";
10
+ export { isStalled, markStoryAsBlocked, generateHumanHaltSummary, getContextFiles, getExpectedFiles } from "./types";
11
+ export type { FailureCategory } from "../tdd/types";
12
+
13
+ /** Maximum PRD file size (5MB) - reject larger PRDs to prevent memory issues */
14
+ export const PRD_MAX_FILE_SIZE = 5 * 1024 * 1024;
15
+
16
+ /** Load PRD from file */
17
+ export async function loadPRD(path: string): Promise<PRD> {
18
+ if (!existsSync(path)) {
19
+ throw new Error(`PRD file not found: ${path}`);
20
+ }
21
+
22
+ // Check file size to prevent loading oversized PRDs
23
+ const stats = statSync(path);
24
+ if (stats.size > PRD_MAX_FILE_SIZE) {
25
+ const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
26
+ const limitMB = (PRD_MAX_FILE_SIZE / (1024 * 1024)).toFixed(2);
27
+ throw new Error(
28
+ `PRD file is too large (${sizeMB} MB exceeds ${limitMB} MB limit). Split this feature into smaller features or reduce story count.`,
29
+ );
30
+ }
31
+
32
+ const prd: PRD = await Bun.file(path).json();
33
+
34
+ // BUG-21: Normalize story fields to prevent null/undefined arithmetic issues
35
+ // BUG-004: Auto-default optional PRD fields in-memory (tags, status, acceptanceCriteria, storyPoints)
36
+ for (const story of prd.userStories) {
37
+ story.attempts = story.attempts ?? 0;
38
+ story.priorErrors = story.priorErrors ?? [];
39
+ story.escalations = story.escalations ?? [];
40
+ story.dependencies = story.dependencies ?? [];
41
+ story.tags = story.tags ?? [];
42
+ story.status = story.status ?? "pending";
43
+ story.acceptanceCriteria = story.acceptanceCriteria ?? [];
44
+ story.storyPoints = story.storyPoints ?? 1;
45
+ }
46
+
47
+ return prd;
48
+ }
49
+
50
+ /** Save PRD to file */
51
+ export async function savePRD(prd: PRD, path: string): Promise<void> {
52
+ prd.updatedAt = new Date().toISOString();
53
+ await Bun.write(path, JSON.stringify(prd, null, 2));
54
+ }
55
+
56
+ /**
57
+ * Get the next story to work on.
58
+ *
59
+ * Priority 1 (retry): If `currentStoryId` is provided and that story has
60
+ * `status === "failed"` with `attempts <= maxRetries`, return it immediately
61
+ * so the executor retries the same story before moving on.
62
+ *
63
+ * Priority 2 (normal): First pending story whose dependencies are satisfied.
64
+ *
65
+ * @param prd - PRD containing all stories
66
+ * @param currentStoryId - ID of the story just executed (optional)
67
+ * @param maxRetries - Max retry attempts per story before giving up (optional)
68
+ */
69
+ export function getNextStory(prd: PRD, currentStoryId?: string | null, maxRetries?: number): UserStory | null {
70
+ // Priority 1: Retry current story if failed but has attempts remaining
71
+ if (currentStoryId != null && maxRetries != null && maxRetries > 0) {
72
+ const currentStory = prd.userStories.find((s) => s.id === currentStoryId);
73
+ if (currentStory && currentStory.status === "failed" && (currentStory.attempts ?? 0) <= maxRetries) {
74
+ return currentStory;
75
+ }
76
+ }
77
+
78
+ const completedIds = new Set(
79
+ prd.userStories.filter((s) => s.passes || s.status === "passed" || s.status === "skipped").map((s) => s.id),
80
+ );
81
+
82
+ return (
83
+ prd.userStories.find(
84
+ (s) =>
85
+ !s.passes &&
86
+ s.status !== "passed" &&
87
+ s.status !== "skipped" &&
88
+ s.status !== "blocked" &&
89
+ s.status !== "failed" &&
90
+ s.status !== "paused" &&
91
+ s.dependencies.every((dep) => completedIds.has(dep)),
92
+ ) ?? null
93
+ );
94
+ }
95
+
96
+ /**
97
+ * Check if all stories are complete (passed or skipped).
98
+ *
99
+ * @design Does NOT account for blocked/failed stories — a PRD with blocked stories
100
+ * is NOT complete. Use `isStalled()` separately to detect when forward progress
101
+ * is impossible (all remaining stories blocked or depend on blocked).
102
+ */
103
+ export function isComplete(prd: PRD): boolean {
104
+ return prd.userStories.every((s) => s.passes || s.status === "passed" || s.status === "skipped");
105
+ }
106
+
107
+ /** Count stories by status */
108
+ export function countStories(prd: PRD): {
109
+ total: number;
110
+ passed: number;
111
+ failed: number;
112
+ pending: number;
113
+ skipped: number;
114
+ blocked: number;
115
+ paused: number;
116
+ } {
117
+ return {
118
+ total: prd.userStories.length,
119
+ passed: prd.userStories.filter((s) => s.passes || s.status === "passed").length,
120
+ failed: prd.userStories.filter((s) => s.status === "failed").length,
121
+ pending: prd.userStories.filter(
122
+ (s) =>
123
+ !s.passes &&
124
+ s.status !== "passed" &&
125
+ s.status !== "failed" &&
126
+ s.status !== "skipped" &&
127
+ s.status !== "blocked" &&
128
+ s.status !== "paused",
129
+ ).length,
130
+ skipped: prd.userStories.filter((s) => s.status === "skipped").length,
131
+ blocked: prd.userStories.filter((s) => s.status === "blocked").length,
132
+ paused: prd.userStories.filter((s) => s.status === "paused").length,
133
+ };
134
+ }
135
+
136
+ /** Mark a story as passed */
137
+ export function markStoryPassed(prd: PRD, storyId: string): void {
138
+ const story = prd.userStories.find((s) => s.id === storyId);
139
+ if (story) {
140
+ story.passes = true;
141
+ story.status = "passed";
142
+ }
143
+ }
144
+
145
+ /** Mark a story as failed */
146
+ export function markStoryFailed(prd: PRD, storyId: string, failureCategory?: FailureCategory): void {
147
+ const story = prd.userStories.find((s) => s.id === storyId);
148
+ if (story) {
149
+ story.status = "failed";
150
+ story.attempts += 1;
151
+ if (failureCategory !== undefined) {
152
+ story.failureCategory = failureCategory;
153
+ }
154
+ }
155
+ }
156
+
157
+ /** Mark a story as skipped */
158
+ export function markStorySkipped(prd: PRD, storyId: string): void {
159
+ const story = prd.userStories.find((s) => s.id === storyId);
160
+ if (story) {
161
+ story.status = "skipped";
162
+ }
163
+ }
164
+
165
+ /** Mark a story as paused */
166
+ export function markStoryPaused(prd: PRD, storyId: string): void {
167
+ const story = prd.userStories.find((s) => s.id === storyId);
168
+ if (story) {
169
+ story.status = "paused";
170
+ story.attempts = (story.attempts ?? 0) + 1;
171
+ }
172
+ }
@@ -0,0 +1,202 @@
1
+ /**
2
+ * PRD (Product Requirements Document) Types
3
+ *
4
+ * Machine-readable task state for orchestration.
5
+ */
6
+
7
+ import type { Complexity, TestStrategy } from "../config";
8
+ import type { ModelTier } from "../config";
9
+ import type { FailureCategory } from "../tdd/types";
10
+
11
+ /** User story status */
12
+ export type StoryStatus = "pending" | "in-progress" | "passed" | "failed" | "skipped" | "blocked" | "paused";
13
+
14
+ /** Routing metadata per story */
15
+ export interface StoryRouting {
16
+ complexity: Complexity;
17
+ /** Model tier (derived at runtime from config, not persisted) */
18
+ modelTier?: ModelTier;
19
+ testStrategy: TestStrategy;
20
+ reasoning: string;
21
+ estimatedCost?: number;
22
+ /** Estimated lines of code (from LLM classifier) */
23
+ estimatedLOC?: number;
24
+ /** Implementation risks (from LLM classifier) */
25
+ risks?: string[];
26
+ /** Classification strategy used */
27
+ strategy?: "keyword" | "llm";
28
+ /** Model used for classification (if LLM strategy) */
29
+ llmModel?: string;
30
+ }
31
+
32
+ /** Escalation attempt tracking */
33
+ export interface EscalationAttempt {
34
+ fromTier: ModelTier;
35
+ toTier: ModelTier;
36
+ reason: string;
37
+ timestamp: string;
38
+ }
39
+
40
+ /** A single user story */
41
+ export interface UserStory {
42
+ /** Story ID (e.g., "US-001") */
43
+ id: string;
44
+ /** Story title */
45
+ title: string;
46
+ /** Story description */
47
+ description: string;
48
+ /** Acceptance criteria */
49
+ acceptanceCriteria: string[];
50
+ /** Tags for routing (e.g., ["security", "public-api"]) */
51
+ tags: string[];
52
+ /** Dependencies (story IDs that must complete first) */
53
+ dependencies: string[];
54
+ /** Current status */
55
+ status: StoryStatus;
56
+ /** Whether all acceptance criteria pass */
57
+ passes: boolean;
58
+ /** Routing metadata (set during analyze phase) */
59
+ routing?: StoryRouting;
60
+ /** Escalation history */
61
+ escalations: EscalationAttempt[];
62
+ /** Number of attempts */
63
+ attempts: number;
64
+ /** Story points estimate (optional, defaults to 1) */
65
+ storyPoints?: number;
66
+ /** @deprecated Use contextFiles instead. Relevant source files for context injection */
67
+ relevantFiles?: string[];
68
+ /** Files loaded into agent prompt before execution */
69
+ contextFiles?: string[];
70
+ /** Files that must exist after execution (pre-flight gate) */
71
+ expectedFiles?: string[];
72
+ /** Prior error messages from failed attempts */
73
+ priorErrors?: string[];
74
+ /** Custom context strings */
75
+ customContext?: string[];
76
+ /** Category of the last failure (set when story is marked failed) */
77
+ failureCategory?: FailureCategory;
78
+ /** Worktree path for parallel execution (set when --parallel is used) */
79
+ worktreePath?: string;
80
+ }
81
+
82
+ // ============================================================================
83
+ // Resolver Functions
84
+ // ============================================================================
85
+
86
+ /**
87
+ * Get files to load into agent prompt before execution.
88
+ * Falls back to relevantFiles for backward compatibility.
89
+ */
90
+ export function getContextFiles(story: UserStory): string[] {
91
+ return story.contextFiles ?? story.relevantFiles ?? [];
92
+ }
93
+
94
+ /**
95
+ * Get files that must exist after execution (pre-flight gate).
96
+ * Does NOT fall back to relevantFiles. Asset check is opt-in only.
97
+ */
98
+ export function getExpectedFiles(story: UserStory): string[] {
99
+ return story.expectedFiles ?? [];
100
+ }
101
+
102
+ // ============================================================================
103
+ // ADR-003: Stall Detection Helpers
104
+ // ============================================================================
105
+
106
+ /**
107
+ * Check if a PRD run is stalled — all remaining stories are blocked, paused, or
108
+ * depend on blocked/paused stories, making forward progress impossible.
109
+ */
110
+ export function isStalled(prd: PRD): boolean {
111
+ const remaining = prd.userStories.filter((s) => s.status !== "passed" && s.status !== "skipped");
112
+ if (remaining.length === 0) return false;
113
+
114
+ const blockedIds = new Set(
115
+ prd.userStories
116
+ .filter((s) => s.status === "blocked" || s.status === "failed" || s.status === "paused")
117
+ .map((s) => s.id),
118
+ );
119
+
120
+ return remaining.every(
121
+ (s) =>
122
+ s.status === "blocked" ||
123
+ s.status === "failed" ||
124
+ s.status === "paused" ||
125
+ s.dependencies.some((dep) => blockedIds.has(dep)),
126
+ );
127
+ }
128
+
129
+ /**
130
+ * Mark a story as blocked (e.g., dependency failed, unresolvable issue).
131
+ */
132
+ export function markStoryAsBlocked(prd: PRD, storyId: string, reason: string): void {
133
+ const story = prd.userStories.find((s) => s.id === storyId);
134
+ if (story) {
135
+ story.status = "blocked";
136
+ story.priorErrors = [...(story.priorErrors || []), `BLOCKED: ${reason}`];
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Generate a human-readable summary when all progress is stalled.
142
+ */
143
+ export function generateHumanHaltSummary(prd: PRD): string {
144
+ const blocked = prd.userStories.filter((s) => s.status === "blocked");
145
+ const failed = prd.userStories.filter((s) => s.status === "failed");
146
+ const paused = prd.userStories.filter((s) => s.status === "paused");
147
+ const pending = prd.userStories.filter((s) => s.status === "pending" || s.status === "in-progress");
148
+
149
+ const lines = [
150
+ `🛑 STALLED: ${prd.feature}`,
151
+ "",
152
+ `Blocked (${blocked.length}):`,
153
+ ...blocked.map((s) => ` ${s.id}: ${s.title} — ${s.priorErrors?.slice(-1)[0] || "unknown"}`),
154
+ "",
155
+ `Failed (${failed.length}):`,
156
+ ...failed.map((s) => ` ${s.id}: ${s.title} — ${s.priorErrors?.slice(-1)[0] || "unknown"}`),
157
+ "",
158
+ `Paused (${paused.length}):`,
159
+ ...paused.map((s) => ` ${s.id}: ${s.title} — ${s.priorErrors?.slice(-1)[0] || "user paused"}`),
160
+ ];
161
+
162
+ if (pending.length > 0) {
163
+ lines.push(
164
+ "",
165
+ `Waiting on blocked/paused dependencies (${pending.length}):`,
166
+ ...pending.map((s) => ` ${s.id}: ${s.title} — depends on: ${s.dependencies.join(", ")}`),
167
+ );
168
+ }
169
+
170
+ return lines.join("\n");
171
+ }
172
+
173
+ /** The full PRD document */
174
+ export interface PRD {
175
+ /** Project name */
176
+ project: string;
177
+ /** Feature name */
178
+ feature: string;
179
+ /** Git branch name */
180
+ branchName: string;
181
+ /** Creation timestamp */
182
+ createdAt: string;
183
+ /** Last updated timestamp */
184
+ updatedAt: string;
185
+ /** All user stories */
186
+ userStories: UserStory[];
187
+ /** Configuration used during analyze phase */
188
+ analyzeConfig?: {
189
+ /** nax version that generated this PRD */
190
+ naxVersion: string;
191
+ /** Model tier used for analysis */
192
+ model: string;
193
+ /** Whether LLM-enhanced decomposition was used */
194
+ llmEnhanced: boolean;
195
+ /** Maximum stories per feature (from config) */
196
+ maxStoriesPerFeature: number;
197
+ /** Routing strategy used */
198
+ routingStrategy: "keyword" | "llm";
199
+ };
200
+ /** Acceptance test overrides (AC-N → reason for accepting despite test failure) */
201
+ acceptanceOverrides?: Record<string, string>;
202
+ }