@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,416 @@
1
+ /**
2
+ * Unit tests for nax logs command
3
+ *
4
+ * Tests the logs command implementation including:
5
+ * - Latest run log display
6
+ * - --follow mode (real-time streaming)
7
+ * - --story filter
8
+ * - --level filter
9
+ * - --list (runs table)
10
+ * - --run (specific run selection)
11
+ * - --json (raw JSONL output)
12
+ * - Combined filters
13
+ */
14
+
15
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
16
+ import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
17
+ import { join } from "node:path";
18
+ import { type LogsOptions, logsCommand } from "../../../src/commands/logs";
19
+
20
+ const TEST_WORKSPACE = join(import.meta.dir, "..", "..", "tmp", "logs-test");
21
+
22
+ function setupTestProject(featureName: string): string {
23
+ const projectDir = join(TEST_WORKSPACE, `project-${Date.now()}`);
24
+ const naxDir = join(projectDir, "nax");
25
+ const featureDir = join(naxDir, "features", featureName);
26
+ const runsDir = join(featureDir, "runs");
27
+
28
+ mkdirSync(runsDir, { recursive: true });
29
+
30
+ // Create minimal config.json
31
+ writeFileSync(join(naxDir, "config.json"), JSON.stringify({ feature: featureName }));
32
+
33
+ // Create sample JSONL log files
34
+ const sampleLogs = [
35
+ {
36
+ timestamp: "2026-02-27T10:00:00.000Z",
37
+ level: "info",
38
+ stage: "run.start",
39
+ message: "Starting feature",
40
+ data: { runId: "run-001", feature: featureName },
41
+ },
42
+ {
43
+ timestamp: "2026-02-27T10:00:01.000Z",
44
+ level: "info",
45
+ stage: "story.start",
46
+ storyId: "US-001",
47
+ message: "Starting story",
48
+ data: { storyId: "US-001", title: "Test Story" },
49
+ },
50
+ {
51
+ timestamp: "2026-02-27T10:00:02.000Z",
52
+ level: "debug",
53
+ stage: "routing",
54
+ storyId: "US-001",
55
+ message: "Routing decision",
56
+ data: { tier: "haiku" },
57
+ },
58
+ {
59
+ timestamp: "2026-02-27T10:00:03.000Z",
60
+ level: "info",
61
+ stage: "story.complete",
62
+ storyId: "US-001",
63
+ message: "Story passed",
64
+ data: { success: true, cost: 0.0023 },
65
+ },
66
+ {
67
+ timestamp: "2026-02-27T10:00:04.000Z",
68
+ level: "error",
69
+ stage: "story.start",
70
+ storyId: "US-002",
71
+ message: "Story failed",
72
+ data: { storyId: "US-002", title: "Failed Story" },
73
+ },
74
+ ];
75
+
76
+ // Write latest run log
77
+ const latestRunPath = join(runsDir, "2026-02-27T10-00-00.jsonl");
78
+ writeFileSync(latestRunPath, sampleLogs.map((log) => JSON.stringify(log)).join("\n"));
79
+
80
+ // Write older run log
81
+ const olderLogs = [
82
+ {
83
+ timestamp: "2026-02-26T09:00:00.000Z",
84
+ level: "info",
85
+ stage: "run.start",
86
+ message: "Starting feature",
87
+ data: { runId: "run-000", feature: featureName },
88
+ },
89
+ {
90
+ timestamp: "2026-02-26T09:00:01.000Z",
91
+ level: "info",
92
+ stage: "story.start",
93
+ storyId: "US-001",
94
+ message: "Old run",
95
+ data: { storyId: "US-001", title: "Old Story" },
96
+ },
97
+ ];
98
+ const olderRunPath = join(runsDir, "2026-02-26T09-00-00.jsonl");
99
+ writeFileSync(olderRunPath, olderLogs.map((log) => JSON.stringify(log)).join("\n"));
100
+
101
+ return projectDir;
102
+ }
103
+
104
+ function cleanup(projectDir: string) {
105
+ if (existsSync(projectDir)) {
106
+ rmSync(projectDir, { recursive: true, force: true });
107
+ }
108
+ }
109
+
110
+ describe("logsCommand", () => {
111
+ let projectDir: string;
112
+
113
+ beforeEach(() => {
114
+ projectDir = setupTestProject("test-feature");
115
+ });
116
+
117
+ afterEach(() => {
118
+ cleanup(projectDir);
119
+ });
120
+
121
+ describe("default behavior (latest run formatted)", () => {
122
+ test("displays latest run logs with formatting", async () => {
123
+ const options: LogsOptions = { dir: projectDir };
124
+
125
+ // This should format and display the latest run
126
+ await expect(logsCommand(options)).resolves.toBeUndefined();
127
+ });
128
+
129
+ test("uses resolveProject() to find project directory", async () => {
130
+ // Change to project directory
131
+ const originalCwd = process.cwd();
132
+ process.chdir(projectDir);
133
+
134
+ try {
135
+ const options: LogsOptions = {};
136
+ await expect(logsCommand(options)).resolves.toBeUndefined();
137
+ } finally {
138
+ process.chdir(originalCwd);
139
+ }
140
+ });
141
+
142
+ test("throws when no nax directory found", async () => {
143
+ const options: LogsOptions = { dir: "/nonexistent/path" };
144
+
145
+ await expect(logsCommand(options)).rejects.toThrow();
146
+ });
147
+
148
+ test("displays error when no runs exist", async () => {
149
+ // Create fresh project with no runs
150
+ const emptyProject = setupTestProject("empty-feature");
151
+ const runsDir = join(emptyProject, "nax", "features", "empty-feature", "runs");
152
+ rmSync(join(runsDir, "2026-02-27T10-00-00.jsonl"));
153
+ rmSync(join(runsDir, "2026-02-26T09-00-00.jsonl"));
154
+
155
+ const options: LogsOptions = { dir: emptyProject };
156
+
157
+ await expect(logsCommand(options)).rejects.toThrow(/no runs found/i);
158
+
159
+ cleanup(emptyProject);
160
+ });
161
+ });
162
+
163
+ describe("--follow mode (real-time streaming)", () => {
164
+ // Note: Follow mode tests are skipped in unit tests because they run indefinitely.
165
+ // They are tested in integration tests (test/integration/cli-logs.test.ts) where we can spawn and kill processes.
166
+ test.skip("streams new log entries in real-time", async () => {
167
+ // Skipped: tested in integration tests
168
+ });
169
+
170
+ test.skip("follows the latest run by default", async () => {
171
+ // Skipped: tested in integration tests
172
+ });
173
+
174
+ test.skip("can follow a specific run with --run flag", async () => {
175
+ // Skipped: tested in integration tests
176
+ });
177
+ });
178
+
179
+ describe("--story filter", () => {
180
+ test("filters logs to specific story", async () => {
181
+ const options: LogsOptions = { dir: projectDir, story: "US-001" };
182
+
183
+ // Should only show logs with storyId: "US-001"
184
+ await expect(logsCommand(options)).resolves.toBeUndefined();
185
+ });
186
+
187
+ test.skip("filters work with --follow mode", async () => {
188
+ // Skipped: tested in integration tests
189
+ });
190
+
191
+ test("shows empty result when story not found", async () => {
192
+ const options: LogsOptions = { dir: projectDir, story: "US-999" };
193
+
194
+ // No logs match this story
195
+ await expect(logsCommand(options)).resolves.toBeUndefined();
196
+ });
197
+ });
198
+
199
+ describe("--level filter", () => {
200
+ test("filters logs by error level", async () => {
201
+ const options: LogsOptions = { dir: projectDir, level: "error" };
202
+
203
+ // Should only show error-level logs
204
+ await expect(logsCommand(options)).resolves.toBeUndefined();
205
+ });
206
+
207
+ test("filters logs by info level", async () => {
208
+ const options: LogsOptions = { dir: projectDir, level: "info" };
209
+
210
+ // Should show info, warn, error (all >= info)
211
+ await expect(logsCommand(options)).resolves.toBeUndefined();
212
+ });
213
+
214
+ test("filters logs by debug level", async () => {
215
+ const options: LogsOptions = { dir: projectDir, level: "debug" };
216
+
217
+ // Should show all logs (debug is lowest level)
218
+ await expect(logsCommand(options)).resolves.toBeUndefined();
219
+ });
220
+
221
+ test.skip("filters work with --follow mode", async () => {
222
+ // Skipped: tested in integration tests
223
+ });
224
+ });
225
+
226
+ describe("--list (runs table)", () => {
227
+ test("displays table of all runs", async () => {
228
+ const options: LogsOptions = { dir: projectDir, list: true };
229
+
230
+ // Should display a table of runs with timestamps, status, duration
231
+ await expect(logsCommand(options)).resolves.toBeUndefined();
232
+ });
233
+
234
+ test("includes run metadata in table", async () => {
235
+ const options: LogsOptions = { dir: projectDir, list: true };
236
+
237
+ // Table should include: timestamp, stories count, cost, duration
238
+ await expect(logsCommand(options)).resolves.toBeUndefined();
239
+ });
240
+
241
+ test("sorts runs by timestamp descending (newest first)", async () => {
242
+ const options: LogsOptions = { dir: projectDir, list: true };
243
+
244
+ await expect(logsCommand(options)).resolves.toBeUndefined();
245
+ });
246
+
247
+ test("shows empty message when no runs exist", async () => {
248
+ const emptyProject = setupTestProject("empty-feature");
249
+ const runsDir = join(emptyProject, "nax", "features", "empty-feature", "runs");
250
+ rmSync(join(runsDir, "2026-02-27T10-00-00.jsonl"));
251
+ rmSync(join(runsDir, "2026-02-26T09-00-00.jsonl"));
252
+
253
+ const options: LogsOptions = { dir: emptyProject, list: true };
254
+
255
+ await expect(logsCommand(options)).resolves.toBeUndefined();
256
+
257
+ cleanup(emptyProject);
258
+ });
259
+ });
260
+
261
+ describe("--run (specific run selection)", () => {
262
+ test("displays specific run by timestamp", async () => {
263
+ const options: LogsOptions = {
264
+ dir: projectDir,
265
+ run: "2026-02-26T09-00-00",
266
+ };
267
+
268
+ // Should display the older run
269
+ await expect(logsCommand(options)).resolves.toBeUndefined();
270
+ });
271
+
272
+ test("throws when specified run does not exist", async () => {
273
+ const options: LogsOptions = {
274
+ dir: projectDir,
275
+ run: "2026-01-01T00-00-00",
276
+ };
277
+
278
+ await expect(logsCommand(options)).rejects.toThrow(/run not found/i);
279
+ });
280
+
281
+ test("works with partial timestamp matching", async () => {
282
+ const options: LogsOptions = {
283
+ dir: projectDir,
284
+ run: "2026-02-26",
285
+ };
286
+
287
+ // Should match "2026-02-26T09-00-00"
288
+ await expect(logsCommand(options)).resolves.toBeUndefined();
289
+ });
290
+ });
291
+
292
+ describe("--json (raw JSONL output)", () => {
293
+ test("outputs raw JSONL without formatting", async () => {
294
+ const options: LogsOptions = { dir: projectDir, json: true };
295
+
296
+ // Should output raw JSONL lines
297
+ await expect(logsCommand(options)).resolves.toBeUndefined();
298
+ });
299
+
300
+ test("combines with --story filter", async () => {
301
+ const options: LogsOptions = {
302
+ dir: projectDir,
303
+ story: "US-001",
304
+ json: true,
305
+ };
306
+
307
+ // Raw JSONL output but only for US-001
308
+ await expect(logsCommand(options)).resolves.toBeUndefined();
309
+ });
310
+
311
+ test("combines with --level filter", async () => {
312
+ const options: LogsOptions = {
313
+ dir: projectDir,
314
+ level: "error",
315
+ json: true,
316
+ };
317
+
318
+ // Raw JSONL output but only error level
319
+ await expect(logsCommand(options)).resolves.toBeUndefined();
320
+ });
321
+
322
+ test.skip("works with --follow mode", async () => {
323
+ // Skipped: tested in integration tests
324
+ });
325
+ });
326
+
327
+ describe("combined filters", () => {
328
+ test("--story + --level filters", async () => {
329
+ const options: LogsOptions = {
330
+ dir: projectDir,
331
+ story: "US-001",
332
+ level: "info",
333
+ };
334
+
335
+ // Only US-001 logs with info level or higher
336
+ await expect(logsCommand(options)).resolves.toBeUndefined();
337
+ });
338
+
339
+ test("--story + --level + --json", async () => {
340
+ const options: LogsOptions = {
341
+ dir: projectDir,
342
+ story: "US-001",
343
+ level: "debug",
344
+ json: true,
345
+ };
346
+
347
+ await expect(logsCommand(options)).resolves.toBeUndefined();
348
+ });
349
+
350
+ test("--run + --story + --level", async () => {
351
+ const options: LogsOptions = {
352
+ dir: projectDir,
353
+ run: "2026-02-27T10-00-00",
354
+ story: "US-001",
355
+ level: "info",
356
+ };
357
+
358
+ await expect(logsCommand(options)).resolves.toBeUndefined();
359
+ });
360
+
361
+ test("all filters combined", async () => {
362
+ const options: LogsOptions = {
363
+ dir: projectDir,
364
+ run: "2026-02-27T10-00-00",
365
+ story: "US-001",
366
+ level: "info",
367
+ json: true,
368
+ };
369
+
370
+ await expect(logsCommand(options)).resolves.toBeUndefined();
371
+ });
372
+
373
+ test("--list ignores other filters", async () => {
374
+ const options: LogsOptions = {
375
+ dir: projectDir,
376
+ list: true,
377
+ story: "US-001", // Should be ignored
378
+ level: "error", // Should be ignored
379
+ };
380
+
381
+ // --list takes precedence, others ignored
382
+ await expect(logsCommand(options)).resolves.toBeUndefined();
383
+ });
384
+ });
385
+
386
+ describe("resolveProject integration", () => {
387
+ test("resolves project from -d flag", async () => {
388
+ const options: LogsOptions = { dir: projectDir };
389
+
390
+ await expect(logsCommand(options)).resolves.toBeUndefined();
391
+ });
392
+
393
+ test("resolves project from CWD", async () => {
394
+ const originalCwd = process.cwd();
395
+ process.chdir(projectDir);
396
+
397
+ try {
398
+ const options: LogsOptions = {};
399
+ await expect(logsCommand(options)).resolves.toBeUndefined();
400
+ } finally {
401
+ process.chdir(originalCwd);
402
+ }
403
+ });
404
+
405
+ test("validates nax/config.json exists", async () => {
406
+ const invalidProject = join(TEST_WORKSPACE, "invalid");
407
+ mkdirSync(join(invalidProject, "nax"), { recursive: true });
408
+
409
+ const options: LogsOptions = { dir: invalidProject };
410
+
411
+ await expect(logsCommand(options)).rejects.toThrow(/config.json/i);
412
+
413
+ cleanup(invalidProject);
414
+ });
415
+ });
416
+ });