@nathapp/nax 0.28.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. package/CHANGELOG.md +13 -2
  2. package/dist/nax.js +72691 -0
  3. package/package.json +12 -4
  4. package/src/cli/config.ts +3 -1
  5. package/src/config/defaults.ts +1 -0
  6. package/src/config/schemas.ts +1 -0
  7. package/src/config/types.ts +1 -0
  8. package/src/context/builder.ts +10 -1
  9. package/src/prompts/sections/role-task.ts +4 -2
  10. package/src/review/runner.ts +6 -1
  11. package/src/version.ts +2 -1
  12. package/.claude/rules/01-project-conventions.md +0 -34
  13. package/.claude/rules/02-test-architecture.md +0 -39
  14. package/.claude/rules/03-test-writing.md +0 -58
  15. package/.claude/rules/04-forbidden-patterns.md +0 -29
  16. package/.claude/settings.json +0 -15
  17. package/.githooks/pre-commit +0 -16
  18. package/.gitlab-ci.yml +0 -103
  19. package/.mcp.json +0 -8
  20. package/BRIEF.md +0 -140
  21. package/CLAUDE.md +0 -143
  22. package/US-007-IMPLEMENTATION.md +0 -139
  23. package/biome.json +0 -14
  24. package/bun.lock +0 -163
  25. package/bunfig.toml +0 -12
  26. package/docker-compose.test.yml +0 -15
  27. package/docs/20260216-fix-plan-context-review.md +0 -56
  28. package/docs/20260216-relentless-vs-ngent-comparison.md +0 -208
  29. package/docs/20260216-v02-plan.md +0 -136
  30. package/docs/20260216-v02-review.md +0 -685
  31. package/docs/20260217-dogfood-findings.md +0 -56
  32. package/docs/20260217-p2-plus-plan.md +0 -117
  33. package/docs/20260217-partial-fixes-plan.md +0 -62
  34. package/docs/20260217-plan-analyze-spec.md +0 -117
  35. package/docs/20260217-post-impl-review.md +0 -1137
  36. package/docs/20260217-quick-wins-plan.md +0 -66
  37. package/docs/20260217-split-runner-plan.md +0 -75
  38. package/docs/20260217-v03-impl-plan.md +0 -80
  39. package/docs/20260217-v03-post-impl-review.md +0 -589
  40. package/docs/20260217-v04-impl-plan.md +0 -86
  41. package/docs/20260217-v05-post-impl-review.md +0 -850
  42. package/docs/20260217-v06-post-impl-review.md +0 -817
  43. package/docs/20260218-adr003-port-plan.md +0 -151
  44. package/docs/20260218-review-adr003-verification.md +0 -175
  45. package/docs/20260219-fix-plan-bug16-19.md +0 -79
  46. package/docs/20260219-fix-plan-bug20-22.md +0 -114
  47. package/docs/20260219-plan-llm-routing.md +0 -116
  48. package/docs/20260219-review-bug20-22-fixes.md +0 -135
  49. package/docs/20260219-routing-baseline-keyword.md +0 -63
  50. package/docs/20260220-plan-structured-logging-p1.md +0 -80
  51. package/docs/20260220-plan-structured-logging-p2.md +0 -37
  52. package/docs/20260220-review-llm-routing.md +0 -180
  53. package/docs/20260220-review-post-fix-llm-routing.md +0 -70
  54. package/docs/20260221-fix-plan-relevantfiles-split.md +0 -101
  55. package/docs/20260221-fix-plan-routing-mode.md +0 -125
  56. package/docs/20260221-review-v0.9-implementation.md +0 -379
  57. package/docs/20260222-fix-plan-v091-routing-isolation.md +0 -197
  58. package/docs/20260223-fix-plan-prompt-audit.md +0 -62
  59. package/docs/20260224-nax-roadmap-phases.md +0 -189
  60. package/docs/20260225-phase2-llm-service-layer.md +0 -401
  61. package/docs/20260225-review-v0.10.1.md +0 -187
  62. package/docs/20260303-v010-implementation-plan.md +0 -165
  63. package/docs/20260304-review-nax.md +0 -492
  64. package/docs/CLAUDE.md.bak +0 -191
  65. package/docs/ROADMAP.md +0 -390
  66. package/docs/SPEC-rectification.md +0 -0
  67. package/docs/SPEC.md +0 -324
  68. package/docs/US-001-plugin-loading-verification.md +0 -152
  69. package/docs/adr/ADR-005-implementation-plan.md +0 -655
  70. package/docs/adr/ADR-005-pipeline-re-architecture.md +0 -464
  71. package/docs/architecture-analysis.md +0 -1076
  72. package/docs/bugs/BUG-21-escalation-null-attempts.md +0 -48
  73. package/docs/bugs-from-dogfood-run-c.md +0 -243
  74. package/docs/code-review-20260228.md +0 -612
  75. package/docs/code-review-v0.15.0.md +0 -629
  76. package/docs/hook-lifecycle-test-plan.md +0 -149
  77. package/docs/releases/v0.11.0-and-earlier.md +0 -20
  78. package/docs/releases/v0.12.0.md +0 -15
  79. package/docs/releases/v0.13.0.md +0 -14
  80. package/docs/releases/v0.14.0.md +0 -20
  81. package/docs/releases/v0.14.1.md +0 -36
  82. package/docs/releases/v0.14.2.md +0 -51
  83. package/docs/releases/v0.14.3.md +0 -174
  84. package/docs/releases/v0.14.4.md +0 -94
  85. package/docs/releases/v0.15.0.md +0 -502
  86. package/docs/releases/v0.15.1.md +0 -170
  87. package/docs/releases/v0.15.3.md +0 -193
  88. package/docs/specs/bug-039-orphan-processes.md +0 -131
  89. package/docs/specs/bug-040-review-rectification.md +0 -82
  90. package/docs/specs/bug-041-cross-story-test-isolation.md +0 -88
  91. package/docs/specs/bug-042-verifier-failure-capture.md +0 -117
  92. package/docs/specs/bun-pty-migration.md +0 -171
  93. package/docs/specs/central-run-registry.md +0 -116
  94. package/docs/specs/feat-010-smart-runner-git-history.md +0 -96
  95. package/docs/specs/feat-011-file-context-strategy.md +0 -73
  96. package/docs/specs/feat-012-tdd-writer-tier.md +0 -79
  97. package/docs/specs/feat-013-test-after-review.md +0 -89
  98. package/docs/specs/feat-014-heartbeat-observability.md +0 -127
  99. package/docs/specs/status-file-consolidation.md +0 -93
  100. package/docs/specs/status-file-v0.10.1.md +0 -812
  101. package/docs/specs/trigger-completion.md +0 -145
  102. package/docs/specs/verification-architecture-v2.md +0 -343
  103. package/docs/tdd/strategies.md +0 -97
  104. package/docs/v0.10-global-config.md +0 -206
  105. package/docs/v0.10-plugin-system.md +0 -415
  106. package/docs/v0.10-prompt-optimizer.md +0 -234
  107. package/docs/v0.3-spec.md +0 -244
  108. package/docs/v0.4-spec.md +0 -140
  109. package/docs/v0.5-spec.md +0 -237
  110. package/docs/v0.6-spec.md +0 -371
  111. package/docs/v0.7-spec.md +0 -177
  112. package/docs/v0.8-llm-routing.md +0 -206
  113. package/docs/v0.8-structured-logging.md +0 -132
  114. package/docs/v0.9.3-prompt-audit.md +0 -112
  115. package/examples/plugins/console-reporter/index.test.ts +0 -207
  116. package/examples/plugins/console-reporter/index.ts +0 -110
  117. package/memory/topic/feat-010-baseref.md +0 -28
  118. package/memory/topic/feat-013-test-after-deprecation.md +0 -22
  119. package/nax/config.json +0 -154
  120. package/nax/features/bug-039-medium/prd.json +0 -45
  121. package/nax/features/bugfix-v0171/prd.json +0 -52
  122. package/nax/features/central-run-registry/prd.json +0 -105
  123. package/nax/features/config-management/prd.json +0 -108
  124. package/nax/features/config-management/progress.txt +0 -5
  125. package/nax/features/diagnose/acceptance.test.ts +0 -414
  126. package/nax/features/diagnose/prd.json +0 -41
  127. package/nax/features/nax-compliance/prd.json +0 -52
  128. package/nax/features/nax-compliance/progress.txt +0 -1
  129. package/nax/features/orchestration-fixes/prd.json +0 -89
  130. package/nax/features/orchestration-fixes/progress.txt +0 -1
  131. package/nax/features/plugin-integration/US-007-VERIFICATION.md +0 -259
  132. package/nax/features/plugin-integration/prd.json +0 -208
  133. package/nax/features/plugin-integration/progress.txt +0 -5
  134. package/nax/features/post-rearch-bugfix/prd.json +0 -137
  135. package/nax/features/precheck/prd.json +0 -205
  136. package/nax/features/precheck/progress.txt +0 -15
  137. package/nax/features/prompt-builder/prd.json +0 -152
  138. package/nax/features/prompt-builder/progress.txt +0 -3
  139. package/nax/features/review-quality/prd.json +0 -55
  140. package/nax/features/routing-persistence/prd.json +0 -104
  141. package/nax/features/routing-persistence/progress.txt +0 -1
  142. package/nax/features/smart-test-runner/plan.md +0 -7
  143. package/nax/features/smart-test-runner/prd.json +0 -203
  144. package/nax/features/smart-test-runner/progress.txt +0 -13
  145. package/nax/features/smart-test-runner/spec.md +0 -7
  146. package/nax/features/smart-test-runner/tasks.md +0 -8
  147. package/nax/features/status-file-consolidation/prd.json +0 -106
  148. package/nax/features/structured-logging/prd.json +0 -199
  149. package/nax/features/trigger-completion/prd.json +0 -150
  150. package/nax/features/trigger-completion/progress.txt +0 -7
  151. package/nax/features/unlock/prd.json +0 -36
  152. package/nax/features/v0.18.3-execution-reliability/prd.json +0 -80
  153. package/nax/features/v0.18.3-execution-reliability/progress.txt +0 -3
  154. package/nax/features/v0.19.0-hardening/plan.md +0 -7
  155. package/nax/features/v0.19.0-hardening/prd.json +0 -84
  156. package/nax/features/v0.19.0-hardening/progress.txt +0 -7
  157. package/nax/features/v0.19.0-hardening/spec.md +0 -18
  158. package/nax/features/v0.19.0-hardening/tasks.md +0 -8
  159. package/nax/features/verify-v2/prd.json +0 -79
  160. package/nax/features/verify-v2/progress.txt +0 -3
  161. package/nax/status.json +0 -36
  162. package/test/COVERAGE-GAPS.md +0 -333
  163. package/test/e2e/cm-003-default-view.test.ts +0 -195
  164. package/test/e2e/plan-analyze-run.test.ts +0 -902
  165. package/test/helpers/helpers.test.ts +0 -295
  166. package/test/helpers/timeout.ts +0 -42
  167. package/test/integration/US-002-TEST-SUMMARY.md +0 -107
  168. package/test/integration/US-003-TEST-SUMMARY.md +0 -149
  169. package/test/integration/US-004-TEST-SUMMARY.md +0 -106
  170. package/test/integration/US-005-TEST-SUMMARY.md +0 -138
  171. package/test/integration/US-007-TEST-SUMMARY.md +0 -100
  172. package/test/integration/cli/agent-validation.test.ts +0 -439
  173. package/test/integration/cli/cli-config-default-edge-cases.test.ts +0 -223
  174. package/test/integration/cli/cli-config-default-view.test.ts +0 -230
  175. package/test/integration/cli/cli-config-diff.test.ts +0 -461
  176. package/test/integration/cli/cli-config-prompts-explain.test.ts +0 -74
  177. package/test/integration/cli/cli-config.test.ts +0 -737
  178. package/test/integration/cli/cli-diagnose.test.ts +0 -595
  179. package/test/integration/cli/cli-logs.test.ts +0 -346
  180. package/test/integration/cli/cli-plugins.test.ts +0 -679
  181. package/test/integration/cli/cli-precheck.test.ts +0 -372
  182. package/test/integration/cli/cli-run-headless.test.ts +0 -174
  183. package/test/integration/cli/cli.test.ts +0 -76
  184. package/test/integration/cli/precheck-integration.test.ts +0 -476
  185. package/test/integration/cli/precheck-orchestrator.test.ts +0 -247
  186. package/test/integration/cli/precheck.test.ts +0 -806
  187. package/test/integration/config/config-loader.test.ts +0 -266
  188. package/test/integration/config/config.test.ts +0 -444
  189. package/test/integration/config/merger.test.ts +0 -466
  190. package/test/integration/config/paths.test.ts +0 -52
  191. package/test/integration/config/security-loader.test.ts +0 -83
  192. package/test/integration/context/context-integration.test.ts +0 -703
  193. package/test/integration/context/context-path-security.test.ts +0 -173
  194. package/test/integration/context/context-provider-injection.test.ts +0 -507
  195. package/test/integration/context/context-verification-integration.test.ts +0 -296
  196. package/test/integration/context/s5-greenfield-fallback.test.ts +0 -298
  197. package/test/integration/execution/execution-isolation.test.ts +0 -143
  198. package/test/integration/execution/execution.test.ts +0 -634
  199. package/test/integration/execution/feature-status-write.test.ts +0 -302
  200. package/test/integration/execution/parallel.test.ts +0 -251
  201. package/test/integration/execution/prd-pause.test.ts +0 -205
  202. package/test/integration/execution/prd-resolvers.test.ts +0 -186
  203. package/test/integration/execution/progress.test.ts +0 -34
  204. package/test/integration/execution/runner-batching.test.ts +0 -682
  205. package/test/integration/execution/runner-config-plugins.test.ts +0 -462
  206. package/test/integration/execution/runner-escalation.test.ts +0 -561
  207. package/test/integration/execution/runner-fixes.test.ts +0 -400
  208. package/test/integration/execution/runner-plugin-integration.test.ts +0 -544
  209. package/test/integration/execution/runner-queue-and-attempts.test.ts +0 -476
  210. package/test/integration/execution/status-file-integration.test.ts +0 -289
  211. package/test/integration/execution/status-file.test.ts +0 -380
  212. package/test/integration/execution/status-writer.test.ts +0 -447
  213. package/test/integration/execution/story-id-in-events.test.ts +0 -274
  214. package/test/integration/interaction/interaction-chain-pipeline.test.ts +0 -476
  215. package/test/integration/pipeline/hooks.test.ts +0 -363
  216. package/test/integration/pipeline/pipeline-acceptance.test.ts +0 -303
  217. package/test/integration/pipeline/pipeline-events.test.ts +0 -476
  218. package/test/integration/pipeline/pipeline.test.ts +0 -660
  219. package/test/integration/pipeline/reporter-lifecycle.test.ts +0 -862
  220. package/test/integration/pipeline/verify-stage.test.ts +0 -286
  221. package/test/integration/plan/analyze-integration.test.ts +0 -262
  222. package/test/integration/plan/analyze-scanner.test.ts +0 -132
  223. package/test/integration/plan/logger.test.ts +0 -461
  224. package/test/integration/plan/plan.test.ts +0 -157
  225. package/test/integration/plugins/config-integration.test.ts +0 -173
  226. package/test/integration/plugins/config-resolution.test.ts +0 -523
  227. package/test/integration/plugins/loader.test.ts +0 -644
  228. package/test/integration/plugins/plugins-registry.test.ts +0 -747
  229. package/test/integration/plugins/validator.test.ts +0 -564
  230. package/test/integration/prompts/pb-004-migration.test.ts +0 -523
  231. package/test/integration/review/review-config-commands.test.ts +0 -320
  232. package/test/integration/review/review-config-schema.test.ts +0 -117
  233. package/test/integration/review/review-plugin-integration.test.ts +0 -729
  234. package/test/integration/review/review.test.ts +0 -150
  235. package/test/integration/routing/plugin-routing-advanced.test.ts +0 -461
  236. package/test/integration/routing/plugin-routing-core.test.ts +0 -527
  237. package/test/integration/routing/routing-stage-bug-021.test.ts +0 -275
  238. package/test/integration/routing/routing-stage-greenfield.test.ts +0 -287
  239. package/test/integration/tdd/tdd-cleanup.test.ts +0 -246
  240. package/test/integration/tdd/tdd-orchestrator-core.test.ts +0 -565
  241. package/test/integration/tdd/tdd-orchestrator-failureCategory.test.ts +0 -355
  242. package/test/integration/tdd/tdd-orchestrator-fallback.test.ts +0 -311
  243. package/test/integration/tdd/tdd-orchestrator-lite.test.ts +0 -289
  244. package/test/integration/tdd/tdd-orchestrator-prompts.test.ts +0 -260
  245. package/test/integration/tdd/tdd-orchestrator-verdict.test.ts +0 -536
  246. package/test/integration/tmp/headless-test/test.jsonl +0 -30
  247. package/test/integration/verification/test-scanner.test.ts +0 -403
  248. package/test/integration/verification/verification-asset-check.test.ts +0 -143
  249. package/test/integration/worktree/manager.test.ts +0 -218
  250. package/test/integration/worktree/worktree-merge.test.ts +0 -341
  251. package/test/manual/logging-formatter-demo.ts +0 -158
  252. package/test/ui/tui-agent-panel.test.tsx +0 -99
  253. package/test/ui/tui-pty-integration.test.tsx +0 -146
  254. package/test/unit/acceptance.test.ts +0 -187
  255. package/test/unit/agent-stderr-capture.test.ts +0 -147
  256. package/test/unit/agents/claude.test.ts +0 -107
  257. package/test/unit/analyze-classifier.test.ts +0 -216
  258. package/test/unit/analyze.test.ts +0 -224
  259. package/test/unit/auto-detect.test.ts +0 -250
  260. package/test/unit/cli-status-project-level.test.ts +0 -283
  261. package/test/unit/cli-status.test.ts +0 -418
  262. package/test/unit/commands/common.test.ts +0 -321
  263. package/test/unit/commands/logs.test.ts +0 -458
  264. package/test/unit/commands/runs.test.ts +0 -303
  265. package/test/unit/commands/unlock.test.ts +0 -320
  266. package/test/unit/config/defaults.test.ts +0 -70
  267. package/test/unit/config/quality-commands-schema.test.ts +0 -72
  268. package/test/unit/config/regression-gate-schema.test.ts +0 -160
  269. package/test/unit/config/smart-runner-flag.test.ts +0 -250
  270. package/test/unit/constitution-generators.test.ts +0 -161
  271. package/test/unit/constitution.test.ts +0 -210
  272. package/test/unit/context/context-autodetect.test.ts +0 -297
  273. package/test/unit/context/context-build.test.ts +0 -575
  274. package/test/unit/context/context-coverage.test.ts +0 -236
  275. package/test/unit/context/context-error.test.ts +0 -93
  276. package/test/unit/context/context-estimate-tokens.test.ts +0 -201
  277. package/test/unit/context/context-format.test.ts +0 -302
  278. package/test/unit/context/context-isolation.test.ts +0 -267
  279. package/test/unit/context/context-sort.test.ts +0 -93
  280. package/test/unit/context/context-story.test.ts +0 -108
  281. package/test/unit/context/prior-failures.test.ts +0 -463
  282. package/test/unit/context.test.ts +0 -1726
  283. package/test/unit/cost.test.ts +0 -231
  284. package/test/unit/crash-recovery.test.ts +0 -309
  285. package/test/unit/escalation.test.ts +0 -127
  286. package/test/unit/execution/lifecycle/run-completion.test.ts +0 -240
  287. package/test/unit/execution/lifecycle/run-regression.test.ts +0 -420
  288. package/test/unit/execution/pid-registry.test.ts +0 -241
  289. package/test/unit/execution/sequential-executor.test.ts +0 -235
  290. package/test/unit/execution/sfc-004-dead-code-cleanup.test.ts +0 -89
  291. package/test/unit/execution/structured-failure.test.ts +0 -415
  292. package/test/unit/execution-logging-stderr.test.ts +0 -157
  293. package/test/unit/execution-stage.test.ts +0 -123
  294. package/test/unit/fix-generator.test.ts +0 -276
  295. package/test/unit/formatters.test.ts +0 -468
  296. package/test/unit/greenfield.test.ts +0 -180
  297. package/test/unit/hooks/shell-security.test.ts +0 -40
  298. package/test/unit/interaction/auto-plugin.test.ts +0 -162
  299. package/test/unit/interaction/human-review-trigger.test.ts +0 -165
  300. package/test/unit/interaction-network-failures.test.ts +0 -390
  301. package/test/unit/interaction-plugins.test.ts +0 -472
  302. package/test/unit/logging/formatter.test.ts +0 -456
  303. package/test/unit/merge.test.ts +0 -269
  304. package/test/unit/metrics/aggregator.test.ts +0 -164
  305. package/test/unit/metrics/tracker.test.ts +0 -186
  306. package/test/unit/metrics.test.ts +0 -276
  307. package/test/unit/optimizer/noop.optimizer.test.ts +0 -125
  308. package/test/unit/optimizer/rule-based.optimizer.test.ts +0 -358
  309. package/test/unit/pipeline/event-bus.test.ts +0 -105
  310. package/test/unit/pipeline/routing-partial-override.test.ts +0 -121
  311. package/test/unit/pipeline/runner-retry.test.ts +0 -89
  312. package/test/unit/pipeline/stages/autofix.test.ts +0 -97
  313. package/test/unit/pipeline/stages/completion-review-gate.test.ts +0 -218
  314. package/test/unit/pipeline/stages/execution-ambiguity.test.ts +0 -311
  315. package/test/unit/pipeline/stages/execution-merge-conflict.test.ts +0 -218
  316. package/test/unit/pipeline/stages/rectify.test.ts +0 -101
  317. package/test/unit/pipeline/stages/regression-stage.test.ts +0 -69
  318. package/test/unit/pipeline/stages/review.test.ts +0 -201
  319. package/test/unit/pipeline/stages/routing-idempotence.test.ts +0 -139
  320. package/test/unit/pipeline/stages/routing-initial-complexity.test.ts +0 -321
  321. package/test/unit/pipeline/stages/routing-persistence.test.ts +0 -380
  322. package/test/unit/pipeline/stages/verify.test.ts +0 -267
  323. package/test/unit/pipeline/subscribers/events-writer.test.ts +0 -227
  324. package/test/unit/pipeline/subscribers/hooks.test.ts +0 -84
  325. package/test/unit/pipeline/subscribers/interaction.test.ts +0 -313
  326. package/test/unit/pipeline/subscribers/registry.test.ts +0 -149
  327. package/test/unit/pipeline/subscribers/reporters.test.ts +0 -90
  328. package/test/unit/pipeline/verify-smart-runner.test.ts +0 -345
  329. package/test/unit/prd-auto-default.test.ts +0 -291
  330. package/test/unit/prd-failure-category.test.ts +0 -177
  331. package/test/unit/prd-get-next-story.test.ts +0 -215
  332. package/test/unit/precheck/checks-warnings.test.ts +0 -114
  333. package/test/unit/precheck-checks.test.ts +0 -841
  334. package/test/unit/precheck-story-size-gate.test.ts +0 -288
  335. package/test/unit/precheck-types.test.ts +0 -143
  336. package/test/unit/prompts/builder.test.ts +0 -258
  337. package/test/unit/prompts/loader.test.ts +0 -355
  338. package/test/unit/prompts/sections/conventions.test.ts +0 -30
  339. package/test/unit/prompts/sections/isolation.test.ts +0 -35
  340. package/test/unit/prompts/sections/role-task.test.ts +0 -40
  341. package/test/unit/prompts/sections/sections.test.ts +0 -238
  342. package/test/unit/prompts/sections/story.test.ts +0 -45
  343. package/test/unit/prompts/sections/verdict.test.ts +0 -58
  344. package/test/unit/prompts.test.ts +0 -476
  345. package/test/unit/queue.test.ts +0 -237
  346. package/test/unit/rectification.test.ts +0 -285
  347. package/test/unit/registry.test.ts +0 -288
  348. package/test/unit/review/runner.test.ts +0 -117
  349. package/test/unit/routing/content-hash.test.ts +0 -99
  350. package/test/unit/routing/routing-stability.test.ts +0 -208
  351. package/test/unit/routing/strategies/llm.test.ts +0 -306
  352. package/test/unit/routing-advanced.test.ts +0 -313
  353. package/test/unit/routing-core.test.ts +0 -341
  354. package/test/unit/routing-strategies.test.ts +0 -440
  355. package/test/unit/storyid-events.test.ts +0 -213
  356. package/test/unit/tdd-verdict.test.ts +0 -492
  357. package/test/unit/test-output-parser.test.ts +0 -377
  358. package/test/unit/ui/tui-controls.test.ts +0 -335
  359. package/test/unit/ui/tui-cost-and-pty.test.ts +0 -190
  360. package/test/unit/ui/tui-layout.test.ts +0 -379
  361. package/test/unit/ui/tui-stories.test.ts +0 -333
  362. package/test/unit/unit-isolation.test.ts +0 -135
  363. package/test/unit/utils/git.test.ts +0 -50
  364. package/test/unit/utils/path-security.test.ts +0 -47
  365. package/test/unit/utils-helpers.test.ts +0 -318
  366. package/test/unit/verdict.test.ts +0 -325
  367. package/test/unit/verification/orchestrator-types.test.ts +0 -54
  368. package/test/unit/verification/orchestrator.test.ts +0 -66
  369. package/test/unit/verification/smart-runner-config.test.ts +0 -163
  370. package/test/unit/verification/smart-runner-discovery.test.ts +0 -354
  371. package/test/unit/verification/smart-runner.test.ts +0 -262
  372. package/test/unit/verification/strategies/acceptance.test.ts +0 -33
  373. package/test/unit/verification/strategies/regression.test.ts +0 -87
  374. package/test/unit/verification/strategies/scoped.test.ts +0 -100
  375. package/test/unit/worktree-manager.test.ts +0 -159
  376. package/tsconfig.json +0 -27
@@ -1,105 +0,0 @@
1
- {
2
- "project": "nax",
3
- "branchName": "feat/central-run-registry",
4
- "feature": "central-run-registry",
5
- "version": "0.24.0",
6
- "description": "Global run index across all projects. Events file writer for machine-readable lifecycle events, registry subscriber that indexes every run to ~/.nax/runs/, nax runs CLI for cross-project run history, and nax logs --run <runId> for global log resolution.",
7
- "userStories": [
8
- {
9
- "id": "CRR-000",
10
- "title": "Events file writer subscriber",
11
- "description": "New subscriber: src/pipeline/subscribers/events-writer.ts \u2014 wireEventsWriter(bus, project, feature, runId, workdir). Listens to run:started, story:started, story:completed, story:failed, run:completed, run:paused. Writes one JSON line per event to ~/.nax/events/<project>/events.jsonl (append mode). Each line: {\"ts\": ISO8601, \"event\": string, \"runId\": string, \"feature\": string, \"project\": string, \"storyId\"?: string, \"data\"?: object}. The run:completed event writes an 'on-complete' entry \u2014 the machine-readable signal that nax exited gracefully (fixes watchdog false crash reports). Best-effort: wrap all writes in try/catch, log warnings on failure, never throw or block the pipeline. Create ~/.nax/events/<project>/ on first write via mkdir recursive. Derive project name from path.basename(workdir). Wire in sequential-executor.ts alongside existing wireHooks/wireReporters/wireInteraction calls. Return UnsubscribeFn matching existing subscriber pattern.",
12
- "complexity": "medium",
13
- "status": "pending",
14
- "acceptanceCriteria": [
15
- "After a run, ~/.nax/events/<project>/events.jsonl exists with JSONL entries",
16
- "Each line is valid JSON with ts, event, runId, feature, project fields",
17
- "run:completed produces an entry with event=on-complete",
18
- "story:started/completed/failed events include storyId",
19
- "Write failure does not crash or block the nax run",
20
- "Directory is created automatically on first write",
21
- "wireEventsWriter is called in sequential-executor.ts",
22
- "Returns UnsubscribeFn consistent with wireHooks/wireReporters pattern"
23
- ],
24
- "attempts": 0,
25
- "priorErrors": [],
26
- "priorFailures": [],
27
- "escalations": [],
28
- "dependencies": [],
29
- "tags": [],
30
- "storyPoints": 2
31
- },
32
- {
33
- "id": "CRR-001",
34
- "title": "Registry writer subscriber",
35
- "description": "New subscriber: src/pipeline/subscribers/registry.ts \u2014 wireRegistry(bus, project, feature, runId, workdir). Listens to run:started. On event, creates ~/.nax/runs/<project>-<feature>-<runId>/meta.json with fields: {runId, project, feature, workdir, statusPath: join(workdir, 'nax/features', feature, 'status.json'), eventsDir: join(workdir, 'nax/features', feature, 'runs'), registeredAt: ISO8601}. meta.json schema exported as MetaJson interface. Written once, never updated. Best-effort: try/catch + warn log, never throw/block. Create ~/.nax/runs/ directory on first call via mkdir recursive. Derive project from path.basename(workdir). Wire in sequential-executor.ts alongside wireEventsWriter. Return UnsubscribeFn.",
36
- "complexity": "medium",
37
- "status": "pending",
38
- "acceptanceCriteria": [
39
- "After run start, ~/.nax/runs/<project>-<feature>-<runId>/meta.json exists",
40
- "meta.json contains runId, project, feature, workdir, statusPath, eventsDir, registeredAt",
41
- "statusPath points to <workdir>/nax/features/<feature>/status.json",
42
- "eventsDir points to <workdir>/nax/features/<feature>/runs",
43
- "MetaJson interface is exported from the module",
44
- "Write failure does not crash or block the nax run",
45
- "wireRegistry is called in sequential-executor.ts"
46
- ],
47
- "attempts": 0,
48
- "priorErrors": [],
49
- "priorFailures": [],
50
- "escalations": [],
51
- "dependencies": [],
52
- "tags": [],
53
- "storyPoints": 2
54
- },
55
- {
56
- "id": "CRR-002",
57
- "title": "nax runs CLI command",
58
- "description": "New command: src/commands/runs.ts \u2014 runsCommand(options). Reads all ~/.nax/runs/*/meta.json, resolves each statusPath to read the live NaxStatusFile for current state. Displays a table sorted by registeredAt desc. Columns: RUN ID, PROJECT, FEATURE, STATUS, STORIES (passed/total), DURATION, DATE. Default limit: 20. Options: --project <name> (filter), --last <N> (limit), --status <running|completed|failed|crashed> (filter). If statusPath missing, show status as '[unavailable]'. Register in src/commands/index.ts and wire in bin/nax.ts CLI arg parser (match pattern of existing diagnose/logs/status commands). Use chalk for colored output. Green for completed, red for failed, yellow for running, dim for unavailable.",
59
- "complexity": "medium",
60
- "status": "pending",
61
- "acceptanceCriteria": [
62
- "nax runs displays a table of all registered runs sorted newest-first",
63
- "nax runs --project <name> filters by project name",
64
- "nax runs --last <N> limits output to N runs",
65
- "nax runs --status <status> filters by run status",
66
- "Runs with missing statusPath show '[unavailable]' status gracefully",
67
- "Empty registry shows 'No runs found' message",
68
- "Command is registered in CLI help output and bin/nax.ts"
69
- ],
70
- "attempts": 0,
71
- "priorErrors": [],
72
- "priorFailures": [],
73
- "escalations": [],
74
- "dependencies": [
75
- "CRR-001"
76
- ],
77
- "tags": [],
78
- "storyPoints": 3
79
- },
80
- {
81
- "id": "CRR-003",
82
- "title": "nax logs --run <runId> global resolution",
83
- "description": "Enhance src/commands/logs.ts logsCommand: when --run <runId> is provided, scan ~/.nax/runs/*/meta.json for matching runId (exact or prefix match). Read eventsDir from meta.json, locate the JSONL log file in that directory (newest .jsonl file), then display using existing displayLogs/followLogs functions. Falls back to current behavior (local feature context) when --run is not specified. If runId not found in registry, throw error Run not found in registry: <runId>. If eventsDir or log file missing, show unavailable message. Update LogsOptions interface to accept run?: string. Update bin/nax.ts to pass --run option through.",
84
- "complexity": "medium",
85
- "status": "pending",
86
- "acceptanceCriteria": [
87
- "nax logs --run <runId> displays logs from the matching run regardless of cwd",
88
- "Resolution uses ~/.nax/runs/*/meta.json to find eventsDir path",
89
- "Unknown runId shows clear error message",
90
- "Missing log files show unavailable message",
91
- "Without --run flag, existing local behavior is unchanged",
92
- "Partial runId matching works (prefix match on runId field)"
93
- ],
94
- "attempts": 0,
95
- "priorErrors": [],
96
- "priorFailures": [],
97
- "escalations": [],
98
- "dependencies": [
99
- "CRR-001"
100
- ],
101
- "tags": [],
102
- "storyPoints": 2
103
- }
104
- ]
105
- }
@@ -1,108 +0,0 @@
1
- {
2
- "project": "nax",
3
- "branchName": "feat/v0.17.0-config-management",
4
- "feature": "config-management",
5
- "userStories": [
6
- {
7
- "id": "CM-001",
8
- "title": "nax config --explain",
9
- "description": "Add `nax config` CLI command with `--explain` flag that dumps the effective merged config with inline comments. Resolution order: defaults \u2192 global (~/.nax/config.json) \u2192 project (nax/config.json) \u2192 CLI overrides. Each field gets a one-line human-readable description of what it does. Fields overridden by project config are annotated with '(project override)' vs '(global)' vs '(default)'. Output format: YAML-like with # comments. Must cover all sections: models, routing, execution, tdd, quality, review, context, constitution, analyze, plan, acceptance, interaction, autoMode. Implementation: add `src/cli/config.ts` with `configCommand()`. Read merged config from loader, annotate each field using a static descriptions map (Record<string, string>). Register in `src/cli/index.ts`.",
10
- "complexity": "medium",
11
- "status": "passed",
12
- "attempts": 1,
13
- "escalations": [],
14
- "dependencies": [],
15
- "tags": [
16
- "cli",
17
- "config",
18
- "dx"
19
- ],
20
- "acceptanceCriteria": [
21
- "Running `nax config --explain` outputs all config fields with descriptions",
22
- "Each field shows its source: (default), (global), or (project override)",
23
- "Output is human-readable, not raw JSON",
24
- "Works from any directory (uses existing config loader)"
25
- ],
26
- "storyPoints": 1,
27
- "priorErrors": [
28
- "Attempt 1 failed with model tier: fast",
29
- "Attempt 1 failed with model tier: balanced"
30
- ],
31
- "passes": true,
32
- "routing": {
33
- "complexity": "simple",
34
- "modelTier": "powerful",
35
- "testStrategy": "three-session-tdd-lite",
36
- "reasoning": "three-session-tdd-lite: strategy:lite"
37
- }
38
- },
39
- {
40
- "id": "CM-002",
41
- "title": "nax config --diff",
42
- "description": "Add `--diff` flag to `nax config` that shows only fields where project config overrides the global config. Output format: table or structured list showing field path, project value, and global value. Skip fields that are identical or only set at one layer. If no project config exists, print 'No project config found \u2014 using global defaults'. Implementation: in `src/cli/config.ts`, load global and project configs separately (extend loader to expose both), deep-diff them, format as table. Use the same descriptions map from CM-001 to add context.",
43
- "complexity": "medium",
44
- "status": "passed",
45
- "attempts": 1,
46
- "escalations": [],
47
- "dependencies": [
48
- "CM-001"
49
- ],
50
- "tags": [
51
- "cli",
52
- "config",
53
- "dx"
54
- ],
55
- "acceptanceCriteria": [
56
- "Running `nax config --diff` shows only fields where project differs from global",
57
- "Each differing field shows: field path, project value, global value",
58
- "Shows 'No project config found' when no nax/config.json exists",
59
- "Works alongside --explain (mutually exclusive flags)"
60
- ],
61
- "storyPoints": 1,
62
- "priorErrors": [
63
- "Attempt 1 failed with model tier: fast",
64
- "Attempt 1 failed with model tier: balanced"
65
- ],
66
- "passes": false,
67
- "routing": {
68
- "complexity": "simple",
69
- "modelTier": "powerful",
70
- "testStrategy": "three-session-tdd-lite",
71
- "reasoning": "three-session-tdd-lite: strategy:lite"
72
- }
73
- },
74
- {
75
- "id": "CM-003",
76
- "title": "nax config (default view)",
77
- "description": "When `nax config` is run without flags, print the effective merged config as formatted JSON with a header showing the config sources found (global path, project path if exists). This is the quick 'what am I actually running with?' view. Implementation: default action in `src/cli/config.ts`. Load merged config, pretty-print with JSON.stringify(config, null, 2). Add header lines showing which config files were found and loaded.",
78
- "complexity": "simple",
79
- "status": "passed",
80
- "attempts": 1,
81
- "escalations": [],
82
- "dependencies": [],
83
- "tags": [
84
- "cli",
85
- "config",
86
- "dx"
87
- ],
88
- "acceptanceCriteria": [
89
- "Running `nax config` prints the effective merged config as formatted JSON",
90
- "Header shows paths of config files found (global, project)",
91
- "Missing config files noted in header"
92
- ],
93
- "storyPoints": 1,
94
- "priorErrors": [
95
- "Attempt 1 failed with model tier: fast",
96
- "Attempt 1 failed with model tier: balanced"
97
- ],
98
- "passes": true,
99
- "routing": {
100
- "complexity": "simple",
101
- "modelTier": "powerful",
102
- "testStrategy": "three-session-tdd-lite",
103
- "reasoning": "three-session-tdd-lite: strategy:lite"
104
- }
105
- }
106
- ],
107
- "updatedAt": "2026-03-02T07:38:25.351Z"
108
- }
@@ -1,5 +0,0 @@
1
- [2026-03-02T06:07:47.434Z] CM-001 — FAILED — nax config --explain — Execution failed
2
- [2026-03-02T08:15:00.000Z] CM-002 — PASSED — nax config --diff — All acceptance criteria met
3
- [2026-03-02T07:12:34.595Z] CM-002 — FAILED — nax config --diff — Execution failed
4
- [2026-03-02T09:30:00.000Z] CM-003 — PASSED — nax config (default view) — All acceptance criteria met
5
- [2026-03-02T07:20:20.866Z] CM-003 — FAILED — nax config (default view) — Execution failed
@@ -1,414 +0,0 @@
1
- /**
2
- * Acceptance Test: nax diagnose CLI
3
- *
4
- * Validates that the nax diagnose command meets all acceptance criteria.
5
- */
6
-
7
- import { describe, test, expect, beforeEach, afterEach } from "bun:test";
8
- import { existsSync, mkdirSync, rmSync } from "node:fs";
9
- import { join } from "node:path";
10
- import { tmpdir } from "node:os";
11
- import { diagnoseCommand } from "../../../src/cli/diagnose";
12
- import type { PRD } from "../../../src/prd";
13
- import { savePRD } from "../../../src/prd";
14
- import type { NaxStatusFile } from "../../../src/execution/status-file";
15
-
16
- // Test fixture directory
17
- let testDir: string;
18
-
19
- beforeEach(() => {
20
- // Create unique test directory
21
- testDir = join(tmpdir(), `nax-diagnose-acceptance-${Date.now()}-${Math.random().toString(36).slice(2)}`);
22
- mkdirSync(testDir, { recursive: true });
23
- mkdirSync(join(testDir, "nax", "features"), { recursive: true });
24
- });
25
-
26
- afterEach(() => {
27
- // Clean up test directory
28
- if (existsSync(testDir)) {
29
- rmSync(testDir, { recursive: true, force: true });
30
- }
31
- });
32
-
33
- /**
34
- * Create a minimal PRD fixture
35
- */
36
- function createPRD(feature: string, stories: Array<Partial<PRD["userStories"][0]>>): PRD {
37
- return {
38
- project: "test-project",
39
- feature,
40
- branchName: "feature/test",
41
- createdAt: "2026-01-01T00:00:00Z",
42
- updatedAt: "2026-01-01T00:00:00Z",
43
- userStories: stories.map((s, i) => ({
44
- id: s.id ?? `US-${String(i + 1).padStart(3, "0")}`,
45
- title: s.title ?? "Test Story",
46
- description: s.description ?? "Test description",
47
- acceptanceCriteria: s.acceptanceCriteria ?? [],
48
- tags: s.tags ?? [],
49
- dependencies: s.dependencies ?? [],
50
- status: s.status ?? "pending",
51
- passes: s.passes ?? false,
52
- escalations: s.escalations ?? [],
53
- attempts: s.attempts ?? 0,
54
- priorErrors: s.priorErrors ?? [],
55
- ...s,
56
- })),
57
- };
58
- }
59
-
60
- /**
61
- * Create a status.json fixture
62
- */
63
- async function createStatusFile(
64
- dir: string,
65
- feature: string,
66
- overrides: Partial<NaxStatusFile> = {},
67
- ): Promise<void> {
68
- const status: NaxStatusFile = {
69
- version: 1,
70
- run: {
71
- id: "run-001",
72
- feature,
73
- startedAt: "2026-01-01T10:00:00Z",
74
- status: "running",
75
- dryRun: false,
76
- pid: process.pid,
77
- ...overrides.run,
78
- },
79
- progress: {
80
- total: 3,
81
- passed: 1,
82
- failed: 1,
83
- paused: 0,
84
- blocked: 0,
85
- pending: 1,
86
- ...overrides.progress,
87
- },
88
- cost: {
89
- spent: 0.05,
90
- limit: null,
91
- ...overrides.cost,
92
- },
93
- current: null,
94
- iterations: 1,
95
- updatedAt: "2026-01-01T10:30:00Z",
96
- durationMs: 1800000,
97
- ...overrides,
98
- };
99
-
100
- // Ensure nax directory exists
101
- mkdirSync(join(dir, "nax"), { recursive: true });
102
- await Bun.write(join(dir, "nax", "status.json"), JSON.stringify(status, null, 2));
103
- }
104
-
105
- /**
106
- * Create a lock file fixture
107
- */
108
- async function createLockFile(dir: string, pid: number): Promise<void> {
109
- await Bun.write(
110
- join(dir, "nax.lock"),
111
- JSON.stringify({
112
- pid,
113
- timestamp: Date.now(),
114
- }),
115
- );
116
- }
117
-
118
- // ============================================================================
119
- // AC1: Basic diagnosis with all 5 sections
120
- // ============================================================================
121
-
122
- describe("AC1: nax diagnose reads last run and prints all 5 sections", () => {
123
- test("prints Run Summary, Story Breakdown, Failure Analysis, Lock Check, Recommendations", async () => {
124
- const feature = "test-feature";
125
- const featureDir = join(testDir, "nax", "features", feature);
126
- mkdirSync(featureDir, { recursive: true });
127
-
128
- const prd = createPRD(feature, [
129
- { id: "US-001", title: "Passed Story", status: "passed", passes: true, attempts: 1 },
130
- {
131
- id: "US-002",
132
- title: "Failed Story",
133
- status: "failed",
134
- passes: false,
135
- attempts: 3,
136
- priorErrors: ["tests-failing", "tests-failing"],
137
- },
138
- { id: "US-003", title: "Pending Story", status: "pending", passes: false, attempts: 0 },
139
- ]);
140
-
141
- await savePRD(prd, join(featureDir, "prd.json"));
142
- await createStatusFile(testDir, feature);
143
-
144
- let output = "";
145
- const originalLog = console.log;
146
- console.log = (...args: unknown[]) => {
147
- output += args.join(" ") + "\n";
148
- };
149
-
150
- try {
151
- await diagnoseCommand({ feature, workdir: testDir, verbose: true });
152
-
153
- // Verify all sections present
154
- expect(output).toContain("Diagnosis Report");
155
- expect(output).toContain("Run Summary");
156
- expect(output).toContain("Story Breakdown");
157
- expect(output).toContain("Failure Analysis");
158
- expect(output).toContain("Lock Check");
159
- expect(output).toContain("Recommendations");
160
-
161
- // Verify counts
162
- expect(output).toContain("Passed: 1");
163
- expect(output).toContain("Failed: 1");
164
- expect(output).toContain("Pending: 1");
165
- } finally {
166
- console.log = originalLog;
167
- }
168
- });
169
- });
170
-
171
- // ============================================================================
172
- // AC2: Pattern classification for failed stories
173
- // ============================================================================
174
-
175
- describe("AC2: Each failed story shows pattern classification", () => {
176
- test("classifies all failure patterns correctly", async () => {
177
- const feature = "patterns-feature";
178
- const featureDir = join(testDir, "nax", "features", feature);
179
- mkdirSync(featureDir, { recursive: true });
180
-
181
- const prd = createPRD(feature, [
182
- {
183
- id: "US-001",
184
- title: "Greenfield Story",
185
- status: "failed",
186
- failureCategory: "greenfield-no-tests",
187
- attempts: 1,
188
- },
189
- {
190
- id: "US-002",
191
- title: "Test Mismatch",
192
- status: "failed",
193
- priorErrors: ["tests-failing", "tests-failing"],
194
- attempts: 2,
195
- },
196
- {
197
- id: "US-003",
198
- title: "Isolation Violation",
199
- status: "failed",
200
- failureCategory: "isolation-violation",
201
- attempts: 1,
202
- },
203
- ]);
204
-
205
- await savePRD(prd, join(featureDir, "prd.json"));
206
-
207
- let output = "";
208
- const originalLog = console.log;
209
- console.log = (...args: unknown[]) => {
210
- output += args.join(" ") + "\n";
211
- };
212
-
213
- try {
214
- await diagnoseCommand({ feature, workdir: testDir });
215
-
216
- expect(output).toContain("GREENFIELD_TDD");
217
- expect(output).toContain("TEST_MISMATCH");
218
- expect(output).toContain("ISOLATION_VIOLATION");
219
- } finally {
220
- console.log = originalLog;
221
- }
222
- });
223
- });
224
-
225
- // ============================================================================
226
- // AC3: Stale lock detection
227
- // ============================================================================
228
-
229
- describe("AC3: Stale nax.lock detection", () => {
230
- test("detects stale lock and shows fix command", async () => {
231
- const feature = "locked-feature";
232
- const featureDir = join(testDir, "nax", "features", feature);
233
- mkdirSync(featureDir, { recursive: true });
234
-
235
- const prd = createPRD(feature, [{ id: "US-001", title: "Test Story", status: "pending" }]);
236
- await savePRD(prd, join(featureDir, "prd.json"));
237
- await createLockFile(testDir, 999999); // Dead PID
238
-
239
- let output = "";
240
- const originalLog = console.log;
241
- console.log = (...args: unknown[]) => {
242
- output += args.join(" ") + "\n";
243
- };
244
-
245
- try {
246
- await diagnoseCommand({ feature, workdir: testDir });
247
-
248
- expect(output).toContain("Stale lock detected");
249
- expect(output).toContain("rm nax.lock");
250
- } finally {
251
- console.log = originalLog;
252
- }
253
- });
254
- });
255
-
256
- // ============================================================================
257
- // AC4: JSON output mode
258
- // ============================================================================
259
-
260
- describe("AC4: --json flag outputs machine-readable JSON", () => {
261
- test("outputs valid JSON with all report fields", async () => {
262
- const feature = "json-feature";
263
- const featureDir = join(testDir, "nax", "features", feature);
264
- mkdirSync(featureDir, { recursive: true });
265
-
266
- const prd = createPRD(feature, [
267
- { id: "US-001", title: "Passed Story", status: "passed", passes: true },
268
- { id: "US-002", title: "Failed Story", status: "failed", attempts: 2 },
269
- ]);
270
-
271
- await savePRD(prd, join(featureDir, "prd.json"));
272
-
273
- let output = "";
274
- const originalLog = console.log;
275
- console.log = (...args: unknown[]) => {
276
- output += args.join(" ") + "\n";
277
- };
278
-
279
- try {
280
- await diagnoseCommand({ feature, workdir: testDir, json: true });
281
-
282
- const report = JSON.parse(output);
283
-
284
- expect(report).toHaveProperty("runSummary");
285
- expect(report).toHaveProperty("storyBreakdown");
286
- expect(report).toHaveProperty("failureAnalysis");
287
- expect(report).toHaveProperty("lockCheck");
288
- expect(report).toHaveProperty("recommendations");
289
- expect(report).toHaveProperty("dataSources");
290
-
291
- expect(report.runSummary.storiesPassed).toBe(1);
292
- expect(report.runSummary.storiesFailed).toBe(1);
293
- } finally {
294
- console.log = originalLog;
295
- }
296
- });
297
- });
298
-
299
- // ============================================================================
300
- // AC5: Graceful degradation when events.jsonl missing
301
- // ============================================================================
302
-
303
- describe("AC5: Works gracefully when events.jsonl missing", () => {
304
- test("uses PRD + git log only and prints note", async () => {
305
- const feature = "no-events-feature";
306
- const featureDir = join(testDir, "nax", "features", feature);
307
- mkdirSync(featureDir, { recursive: true });
308
-
309
- const prd = createPRD(feature, [{ id: "US-001", title: "Test Story", status: "passed", passes: true }]);
310
- await savePRD(prd, join(featureDir, "prd.json"));
311
-
312
- let output = "";
313
- const originalLog = console.log;
314
- console.log = (...args: unknown[]) => {
315
- output += args.join(" ") + "\n";
316
- };
317
-
318
- try {
319
- await diagnoseCommand({ feature, workdir: testDir });
320
-
321
- expect(output).toContain("Diagnosis Report");
322
- expect(output).toContain("events.jsonl not found");
323
- } finally {
324
- console.log = originalLog;
325
- }
326
- });
327
- });
328
-
329
- // ============================================================================
330
- // AC6: -f and -d flags for targeting
331
- // ============================================================================
332
-
333
- describe("AC6: -f <feature> and -d <workdir> flags work", () => {
334
- test("diagnoses specific feature with -f flag", async () => {
335
- const feature = "specific-feature";
336
- const featureDir = join(testDir, "nax", "features", feature);
337
- mkdirSync(featureDir, { recursive: true });
338
-
339
- const prd = createPRD(feature, [{ id: "US-001", title: "Specific Story", status: "passed", passes: true }]);
340
- await savePRD(prd, join(featureDir, "prd.json"));
341
-
342
- let output = "";
343
- const originalLog = console.log;
344
- console.log = (...args: unknown[]) => {
345
- output += args.join(" ") + "\n";
346
- };
347
-
348
- try {
349
- await diagnoseCommand({ feature, workdir: testDir, verbose: true });
350
-
351
- expect(output).toContain(feature);
352
- expect(output).toContain("Specific Story");
353
- } finally {
354
- console.log = originalLog;
355
- }
356
- });
357
- });
358
-
359
- // ============================================================================
360
- // AC7: AUTO_RECOVERED shown as INFO not ERROR
361
- // ============================================================================
362
-
363
- describe("AC7: AUTO_RECOVERED stories shown as INFO", () => {
364
- test("displays AUTO_RECOVERED with INFO level, not ERROR", async () => {
365
- const feature = "recovered-feature";
366
- const featureDir = join(testDir, "nax", "features", feature);
367
- mkdirSync(featureDir, { recursive: true });
368
-
369
- const prd = createPRD(feature, [
370
- {
371
- id: "US-001",
372
- title: "Recovered Story",
373
- status: "passed",
374
- passes: true,
375
- priorErrors: ["greenfield-no-tests"],
376
- attempts: 2,
377
- },
378
- ]);
379
-
380
- await savePRD(prd, join(featureDir, "prd.json"));
381
-
382
- let output = "";
383
- const originalLog = console.log;
384
- console.log = (...args: unknown[]) => {
385
- output += args.join(" ") + "\n";
386
- };
387
-
388
- try {
389
- await diagnoseCommand({ feature, workdir: testDir });
390
-
391
- expect(output).toContain("INFO");
392
- expect(output).toContain("AUTO_RECOVERED");
393
- expect(output).not.toContain("ERROR US-001");
394
- } finally {
395
- console.log = originalLog;
396
- }
397
- });
398
- });
399
-
400
- // ============================================================================
401
- // AC8: TypeScript compiles cleanly
402
- // ============================================================================
403
-
404
- describe("AC8: TypeScript compiles cleanly", () => {
405
- test("bun x tsc --noEmit passes", async () => {
406
- const result = Bun.spawnSync(["bun", "x", "tsc", "--noEmit"], {
407
- cwd: join(__dirname, "../../.."),
408
- stdout: "pipe",
409
- stderr: "pipe",
410
- });
411
-
412
- expect(result.exitCode).toBe(0);
413
- }, 60000);
414
- });
@@ -1,41 +0,0 @@
1
- {
2
- "project": "nax",
3
- "feature": "diagnose",
4
- "branchName": "feat/v0.14.1-diagnose-cli",
5
- "createdAt": "2026-02-28T12:00:00Z",
6
- "userStories": [
7
- {
8
- "id": "US-001",
9
- "title": "nax diagnose CLI \u2014 pure pattern-matching diagnosis",
10
- "description": "Implement the `nax diagnose` command that reads existing run artifacts (events.jsonl from ~/.nax/events/<project>/, status.json from <workdir>/.nax-status.json, PRD from nax/features/<feature>/prd.json, nax.lock from <workdir>/nax.lock, git log) and produces a structured human-readable diagnosis report. No LLM calls. No agent. Purely deterministic pattern matching.\n\nCOMMAND SIGNATURE:\n nax diagnose [-f <feature>] [-d <workdir>] [--json] [--verbose]\n\nOUTPUT SECTIONS:\n1. Run Summary \u2014 feature, last run time, status (complete/stalled/failed), stories passed/failed/pending, cost, commits produced\n2. Story Breakdown \u2014 per-story: status, attempts, tier, strategy, pattern detected\n3. Failure Analysis \u2014 for each failed story: pattern name, symptom description, fix suggestion\n4. Lock Check \u2014 is nax.lock present? Is PID alive (process.kill(pid, 0))? Show fix command if stale.\n5. Recommendations \u2014 ordered list of next actions\n\nFAILURE PATTERNS TO DETECT (match in order):\n- GREENFIELD_TDD: failureCategory === greenfield-no-tests in priorErrors or events\n- TEST_MISMATCH: 2+ consecutive tests-failing escalation events for same story\n- ENVIRONMENTAL: precheck-failed event OR blocker in status.json\n- RATE_LIMITED: rateLimited: true in agent session failure events\n- ISOLATION_VIOLATION: failureCategory === isolation-violation\n- MAX_TIERS_EXHAUSTED: story has priorErrors for all configured tiers AND status is failed/paused\n- SESSION_CRASH: session-failure category + no commits for that story in git log\n- STALLED: isStalled flag in status.json OR all pending stories blocked by dependencies\n- LOCK_STALE: nax.lock present + PID not alive\n- AUTO_RECOVERED: story had greenfield-no-tests but status is passed (S5 worked)\n- UNKNOWN: no pattern matched\n\nGRACEFUL DEGRADATION: If events.jsonl is missing, fall back to PRD priorErrors + git log only. Never crash \u2014 always produce partial output with a note about missing data.\n\nFILES TO CREATE:\n- src/cli/diagnose.ts \u2014 main implementation (read artifacts, pattern match, format output)\n- src/commands/diagnose.ts \u2014 thin commander wrapper registering the command\n- Register in bin/nax.ts \u2014 add diagnose command import\n- test/integration/cli-diagnose.test.ts \u2014 integration tests covering all ACs",
11
- "acceptanceCriteria": [
12
- "AC1: `nax diagnose` reads the last run for the current directory feature and prints human-readable output with all 5 sections (Run Summary, Story Breakdown, Failure Analysis, Lock Check, Recommendations)",
13
- "AC2: Each failed story shows a pattern classification from the known patterns list, or UNKNOWN if no match",
14
- "AC3: Stale nax.lock (lock present + PID dead) is detected and a fix command shown: rm nax.lock",
15
- "AC4: `--json` flag outputs machine-readable JSON containing the same data as human output",
16
- "AC5: Works gracefully when events.jsonl is missing \u2014 uses PRD + git log only, prints a note about missing events",
17
- "AC6: `-f <feature>` targets a specific feature; `-d <workdir>` sets working directory",
18
- "AC7: AUTO_RECOVERED stories (S5 switched strategy, story passed) are shown as INFO not ERROR",
19
- "AC8: TypeScript compiles cleanly (bun x tsc --noEmit)"
20
- ],
21
- "dependencies": [],
22
- "tags": [
23
- "cli",
24
- "medium"
25
- ],
26
- "status": "passed",
27
- "passes": true,
28
- "attempts": 1,
29
- "escalations": [],
30
- "priorErrors": [
31
- "Manual accept: verified 8/8 AC tests pass on VPS. Mac01 Bun env issue with git detection in temp dirs during verification."
32
- ],
33
- "storyPoints": 1
34
- }
35
- ],
36
- "analyzeConfig": {
37
- "maxStories": 5,
38
- "granularity": "medium"
39
- },
40
- "updatedAt": "2026-02-28T06:18:08Z"
41
- }