@nathapp/nax 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (459) hide show
  1. package/.gitlab-ci.yml +96 -0
  2. package/BRIEF.md +140 -0
  3. package/CHANGELOG.md +60 -0
  4. package/CLAUDE.md +159 -0
  5. package/README.md +373 -0
  6. package/US-007-IMPLEMENTATION.md +139 -0
  7. package/bin/nax.ts +930 -0
  8. package/biome.json +14 -0
  9. package/bun.lock +168 -0
  10. package/bunfig.toml +11 -0
  11. package/docs/20260216-fix-plan-context-review.md +56 -0
  12. package/docs/20260216-relentless-vs-ngent-comparison.md +208 -0
  13. package/docs/20260216-v02-plan.md +136 -0
  14. package/docs/20260216-v02-review.md +685 -0
  15. package/docs/20260217-dogfood-findings.md +56 -0
  16. package/docs/20260217-p2-plus-plan.md +117 -0
  17. package/docs/20260217-partial-fixes-plan.md +62 -0
  18. package/docs/20260217-plan-analyze-spec.md +117 -0
  19. package/docs/20260217-post-impl-review.md +1137 -0
  20. package/docs/20260217-quick-wins-plan.md +66 -0
  21. package/docs/20260217-split-runner-plan.md +75 -0
  22. package/docs/20260217-v03-impl-plan.md +80 -0
  23. package/docs/20260217-v03-post-impl-review.md +589 -0
  24. package/docs/20260217-v04-impl-plan.md +86 -0
  25. package/docs/20260217-v05-post-impl-review.md +850 -0
  26. package/docs/20260217-v06-post-impl-review.md +817 -0
  27. package/docs/20260218-adr003-port-plan.md +151 -0
  28. package/docs/20260218-review-adr003-verification.md +175 -0
  29. package/docs/20260219-fix-plan-bug16-19.md +79 -0
  30. package/docs/20260219-fix-plan-bug20-22.md +114 -0
  31. package/docs/20260219-plan-llm-routing.md +116 -0
  32. package/docs/20260219-review-bug20-22-fixes.md +135 -0
  33. package/docs/20260219-routing-baseline-keyword.md +63 -0
  34. package/docs/20260220-plan-structured-logging-p1.md +80 -0
  35. package/docs/20260220-plan-structured-logging-p2.md +37 -0
  36. package/docs/20260220-review-llm-routing.md +180 -0
  37. package/docs/20260220-review-post-fix-llm-routing.md +70 -0
  38. package/docs/20260221-fix-plan-relevantfiles-split.md +101 -0
  39. package/docs/20260221-fix-plan-routing-mode.md +125 -0
  40. package/docs/20260221-review-v0.9-implementation.md +379 -0
  41. package/docs/20260222-fix-plan-v091-routing-isolation.md +197 -0
  42. package/docs/20260223-fix-plan-prompt-audit.md +62 -0
  43. package/docs/20260224-nax-roadmap-phases.md +189 -0
  44. package/docs/20260225-phase2-llm-service-layer.md +401 -0
  45. package/docs/20260225-review-v0.10.1.md +187 -0
  46. package/docs/20260303-v010-implementation-plan.md +165 -0
  47. package/docs/CLAUDE.md.bak +191 -0
  48. package/docs/ROADMAP.md +165 -0
  49. package/docs/SPEC-rectification.md +0 -0
  50. package/docs/SPEC.md +324 -0
  51. package/docs/US-001-plugin-loading-verification.md +152 -0
  52. package/docs/architecture-analysis.md +1076 -0
  53. package/docs/bugs/BUG-21-escalation-null-attempts.md +48 -0
  54. package/docs/bugs-from-dogfood-run-c.md +243 -0
  55. package/docs/code-review-20260228.md +612 -0
  56. package/docs/code-review-v0.15.0.md +629 -0
  57. package/docs/hook-lifecycle-test-plan.md +149 -0
  58. package/docs/releases/v0.11.0-and-earlier.md +20 -0
  59. package/docs/releases/v0.12.0.md +15 -0
  60. package/docs/releases/v0.13.0.md +14 -0
  61. package/docs/releases/v0.14.0.md +20 -0
  62. package/docs/releases/v0.14.1.md +36 -0
  63. package/docs/releases/v0.14.2.md +51 -0
  64. package/docs/releases/v0.14.3.md +174 -0
  65. package/docs/releases/v0.14.4.md +94 -0
  66. package/docs/releases/v0.15.0.md +502 -0
  67. package/docs/releases/v0.15.1.md +170 -0
  68. package/docs/releases/v0.15.3.md +193 -0
  69. package/docs/specs/status-file-v0.10.1.md +812 -0
  70. package/docs/v0.10-global-config.md +206 -0
  71. package/docs/v0.10-plugin-system.md +415 -0
  72. package/docs/v0.10-prompt-optimizer.md +234 -0
  73. package/docs/v0.3-spec.md +244 -0
  74. package/docs/v0.4-spec.md +140 -0
  75. package/docs/v0.5-spec.md +237 -0
  76. package/docs/v0.6-spec.md +371 -0
  77. package/docs/v0.7-spec.md +177 -0
  78. package/docs/v0.8-llm-routing.md +206 -0
  79. package/docs/v0.8-structured-logging.md +132 -0
  80. package/docs/v0.9.3-prompt-audit.md +112 -0
  81. package/examples/plugins/console-reporter/index.test.ts +207 -0
  82. package/examples/plugins/console-reporter/index.ts +110 -0
  83. package/nax/config.json +147 -0
  84. package/nax/features/bugfix-v0171/prd.json +52 -0
  85. package/nax/features/config-management/prd.json +108 -0
  86. package/nax/features/config-management/progress.txt +5 -0
  87. package/nax/features/diagnose/acceptance.test.ts +412 -0
  88. package/nax/features/diagnose/prd.json +41 -0
  89. package/nax/features/orchestration-fixes/prd.json +89 -0
  90. package/nax/features/orchestration-fixes/progress.txt +1 -0
  91. package/nax/features/plugin-integration/US-007-VERIFICATION.md +259 -0
  92. package/nax/features/plugin-integration/prd.json +208 -0
  93. package/nax/features/plugin-integration/progress.txt +5 -0
  94. package/nax/features/precheck/prd.json +205 -0
  95. package/nax/features/precheck/progress.txt +15 -0
  96. package/nax/features/structured-logging/prd.json +199 -0
  97. package/nax/features/unlock/prd.json +36 -0
  98. package/package.json +47 -0
  99. package/src/acceptance/fix-generator.ts +348 -0
  100. package/src/acceptance/generator.ts +282 -0
  101. package/src/acceptance/index.ts +30 -0
  102. package/src/acceptance/types.ts +79 -0
  103. package/src/agents/claude-decompose.ts +169 -0
  104. package/src/agents/claude-plan.ts +139 -0
  105. package/src/agents/claude.ts +324 -0
  106. package/src/agents/cost.ts +268 -0
  107. package/src/agents/index.ts +13 -0
  108. package/src/agents/registry.ts +48 -0
  109. package/src/agents/types-extended.ts +133 -0
  110. package/src/agents/types.ts +113 -0
  111. package/src/agents/validation.ts +69 -0
  112. package/src/analyze/classifier.ts +305 -0
  113. package/src/analyze/index.ts +16 -0
  114. package/src/analyze/scanner.ts +175 -0
  115. package/src/analyze/types.ts +51 -0
  116. package/src/cli/accept.ts +108 -0
  117. package/src/cli/analyze-parser.ts +284 -0
  118. package/src/cli/analyze.ts +207 -0
  119. package/src/cli/config.ts +561 -0
  120. package/src/cli/constitution.ts +109 -0
  121. package/src/cli/diagnose-analysis.ts +159 -0
  122. package/src/cli/diagnose-formatter.ts +87 -0
  123. package/src/cli/diagnose.ts +203 -0
  124. package/src/cli/generate.ts +127 -0
  125. package/src/cli/index.ts +37 -0
  126. package/src/cli/init.ts +188 -0
  127. package/src/cli/interact.ts +295 -0
  128. package/src/cli/plan.ts +198 -0
  129. package/src/cli/plugins.ts +111 -0
  130. package/src/cli/prompts.ts +295 -0
  131. package/src/cli/runs.ts +174 -0
  132. package/src/cli/status-cost.ts +151 -0
  133. package/src/cli/status-features.ts +338 -0
  134. package/src/cli/status.ts +13 -0
  135. package/src/commands/common.ts +171 -0
  136. package/src/commands/diagnose.ts +17 -0
  137. package/src/commands/index.ts +8 -0
  138. package/src/commands/logs.ts +384 -0
  139. package/src/commands/precheck.ts +86 -0
  140. package/src/commands/unlock.ts +96 -0
  141. package/src/config/defaults.ts +160 -0
  142. package/src/config/index.ts +22 -0
  143. package/src/config/loader.ts +121 -0
  144. package/src/config/merger.ts +147 -0
  145. package/src/config/path-security.ts +121 -0
  146. package/src/config/paths.ts +27 -0
  147. package/src/config/schema.ts +56 -0
  148. package/src/config/schemas.ts +286 -0
  149. package/src/config/types.ts +423 -0
  150. package/src/config/validate.ts +103 -0
  151. package/src/constitution/generator.ts +191 -0
  152. package/src/constitution/generators/aider.ts +41 -0
  153. package/src/constitution/generators/claude.ts +35 -0
  154. package/src/constitution/generators/cursor.ts +36 -0
  155. package/src/constitution/generators/opencode.ts +38 -0
  156. package/src/constitution/generators/types.ts +33 -0
  157. package/src/constitution/generators/windsurf.ts +36 -0
  158. package/src/constitution/index.ts +10 -0
  159. package/src/constitution/loader.ts +133 -0
  160. package/src/constitution/types.ts +31 -0
  161. package/src/context/auto-detect.ts +227 -0
  162. package/src/context/builder.ts +246 -0
  163. package/src/context/elements.ts +83 -0
  164. package/src/context/formatter.ts +107 -0
  165. package/src/context/generator.ts +129 -0
  166. package/src/context/generators/aider.ts +34 -0
  167. package/src/context/generators/claude.ts +28 -0
  168. package/src/context/generators/cursor.ts +28 -0
  169. package/src/context/generators/opencode.ts +30 -0
  170. package/src/context/generators/windsurf.ts +28 -0
  171. package/src/context/greenfield.ts +114 -0
  172. package/src/context/index.ts +33 -0
  173. package/src/context/injector.ts +279 -0
  174. package/src/context/test-scanner.ts +370 -0
  175. package/src/context/types.ts +98 -0
  176. package/src/errors.ts +67 -0
  177. package/src/execution/batching.ts +157 -0
  178. package/src/execution/crash-recovery.ts +373 -0
  179. package/src/execution/escalation/escalation.ts +44 -0
  180. package/src/execution/escalation/index.ts +13 -0
  181. package/src/execution/escalation/tier-escalation.ts +295 -0
  182. package/src/execution/escalation/tier-outcome.ts +158 -0
  183. package/src/execution/helpers.ts +38 -0
  184. package/src/execution/index.ts +45 -0
  185. package/src/execution/lifecycle/acceptance-loop.ts +272 -0
  186. package/src/execution/lifecycle/headless-formatter.ts +85 -0
  187. package/src/execution/lifecycle/index.ts +12 -0
  188. package/src/execution/lifecycle/parallel-lifecycle.ts +101 -0
  189. package/src/execution/lifecycle/precheck-runner.ts +140 -0
  190. package/src/execution/lifecycle/run-cleanup.ts +81 -0
  191. package/src/execution/lifecycle/run-completion.ts +129 -0
  192. package/src/execution/lifecycle/run-initialization.ts +141 -0
  193. package/src/execution/lifecycle/run-lifecycle.ts +312 -0
  194. package/src/execution/lifecycle/run-setup.ts +204 -0
  195. package/src/execution/lifecycle/story-hooks.ts +38 -0
  196. package/src/execution/lifecycle/story-size-prompts.ts +123 -0
  197. package/src/execution/lock.ts +115 -0
  198. package/src/execution/parallel-executor.ts +216 -0
  199. package/src/execution/parallel.ts +400 -0
  200. package/src/execution/pid-registry.ts +280 -0
  201. package/src/execution/pipeline-result-handler.ts +388 -0
  202. package/src/execution/post-verify-rectification.ts +188 -0
  203. package/src/execution/post-verify.ts +274 -0
  204. package/src/execution/progress.ts +25 -0
  205. package/src/execution/prompts.ts +127 -0
  206. package/src/execution/queue-handler.ts +109 -0
  207. package/src/execution/rectification.ts +13 -0
  208. package/src/execution/runner.ts +377 -0
  209. package/src/execution/sequential-executor.ts +388 -0
  210. package/src/execution/status-file.ts +264 -0
  211. package/src/execution/status-writer.ts +139 -0
  212. package/src/execution/story-context.ts +229 -0
  213. package/src/execution/test-output-parser.ts +14 -0
  214. package/src/execution/verification.ts +72 -0
  215. package/src/hooks/index.ts +2 -0
  216. package/src/hooks/runner.ts +286 -0
  217. package/src/hooks/types.ts +67 -0
  218. package/src/interaction/chain.ts +154 -0
  219. package/src/interaction/index.ts +60 -0
  220. package/src/interaction/init.ts +83 -0
  221. package/src/interaction/plugins/auto.ts +217 -0
  222. package/src/interaction/plugins/cli.ts +300 -0
  223. package/src/interaction/plugins/telegram.ts +384 -0
  224. package/src/interaction/plugins/webhook.ts +258 -0
  225. package/src/interaction/state.ts +171 -0
  226. package/src/interaction/triggers.ts +229 -0
  227. package/src/interaction/types.ts +163 -0
  228. package/src/logger/formatters.ts +84 -0
  229. package/src/logger/index.ts +16 -0
  230. package/src/logger/logger.ts +298 -0
  231. package/src/logger/types.ts +48 -0
  232. package/src/logging/formatter.ts +355 -0
  233. package/src/logging/index.ts +22 -0
  234. package/src/logging/types.ts +93 -0
  235. package/src/metrics/aggregator.ts +190 -0
  236. package/src/metrics/index.ts +14 -0
  237. package/src/metrics/tracker.ts +200 -0
  238. package/src/metrics/types.ts +109 -0
  239. package/src/optimizer/index.ts +62 -0
  240. package/src/optimizer/noop.optimizer.ts +24 -0
  241. package/src/optimizer/rule-based.optimizer.ts +248 -0
  242. package/src/optimizer/types.ts +53 -0
  243. package/src/pipeline/events.ts +130 -0
  244. package/src/pipeline/index.ts +19 -0
  245. package/src/pipeline/runner.ts +161 -0
  246. package/src/pipeline/stages/acceptance.ts +197 -0
  247. package/src/pipeline/stages/completion.ts +99 -0
  248. package/src/pipeline/stages/constitution.ts +63 -0
  249. package/src/pipeline/stages/context.ts +117 -0
  250. package/src/pipeline/stages/execution.ts +194 -0
  251. package/src/pipeline/stages/index.ts +62 -0
  252. package/src/pipeline/stages/optimizer.ts +74 -0
  253. package/src/pipeline/stages/prompt.ts +57 -0
  254. package/src/pipeline/stages/queue-check.ts +103 -0
  255. package/src/pipeline/stages/review.ts +181 -0
  256. package/src/pipeline/stages/routing.ts +81 -0
  257. package/src/pipeline/stages/verify.ts +100 -0
  258. package/src/pipeline/types.ts +167 -0
  259. package/src/plugins/index.ts +31 -0
  260. package/src/plugins/loader.ts +287 -0
  261. package/src/plugins/registry.ts +168 -0
  262. package/src/plugins/types.ts +327 -0
  263. package/src/plugins/validator.ts +352 -0
  264. package/src/prd/index.ts +172 -0
  265. package/src/prd/types.ts +202 -0
  266. package/src/precheck/checks-blockers.ts +391 -0
  267. package/src/precheck/checks-warnings.ts +142 -0
  268. package/src/precheck/checks.ts +30 -0
  269. package/src/precheck/index.ts +247 -0
  270. package/src/precheck/story-size-gate.ts +144 -0
  271. package/src/precheck/types.ts +31 -0
  272. package/src/queue/index.ts +2 -0
  273. package/src/queue/manager.ts +254 -0
  274. package/src/queue/types.ts +54 -0
  275. package/src/review/index.ts +8 -0
  276. package/src/review/runner.ts +172 -0
  277. package/src/review/types.ts +66 -0
  278. package/src/routing/builder.ts +81 -0
  279. package/src/routing/chain.ts +74 -0
  280. package/src/routing/index.ts +16 -0
  281. package/src/routing/loader.ts +58 -0
  282. package/src/routing/router.ts +303 -0
  283. package/src/routing/strategies/adaptive.ts +215 -0
  284. package/src/routing/strategies/index.ts +8 -0
  285. package/src/routing/strategies/keyword.ts +163 -0
  286. package/src/routing/strategies/llm-prompts.ts +209 -0
  287. package/src/routing/strategies/llm.ts +235 -0
  288. package/src/routing/strategies/manual.ts +50 -0
  289. package/src/routing/strategy.ts +99 -0
  290. package/src/tdd/cleanup.ts +111 -0
  291. package/src/tdd/index.ts +23 -0
  292. package/src/tdd/isolation.ts +123 -0
  293. package/src/tdd/orchestrator.ts +383 -0
  294. package/src/tdd/prompts.ts +270 -0
  295. package/src/tdd/rectification-gate.ts +183 -0
  296. package/src/tdd/session-runner.ts +179 -0
  297. package/src/tdd/types.ts +81 -0
  298. package/src/tdd/verdict.ts +271 -0
  299. package/src/tui/App.tsx +265 -0
  300. package/src/tui/components/AgentPanel.tsx +75 -0
  301. package/src/tui/components/CostOverlay.tsx +118 -0
  302. package/src/tui/components/HelpOverlay.tsx +107 -0
  303. package/src/tui/components/StatusBar.tsx +63 -0
  304. package/src/tui/components/StoriesPanel.tsx +177 -0
  305. package/src/tui/hooks/useKeyboard.ts +142 -0
  306. package/src/tui/hooks/useLayout.ts +137 -0
  307. package/src/tui/hooks/usePipelineEvents.ts +183 -0
  308. package/src/tui/hooks/usePty.ts +194 -0
  309. package/src/tui/index.tsx +38 -0
  310. package/src/tui/types.ts +76 -0
  311. package/src/utils/git.ts +83 -0
  312. package/src/utils/queue-writer.ts +54 -0
  313. package/src/verification/executor.ts +235 -0
  314. package/src/verification/gate.ts +207 -0
  315. package/src/verification/index.ts +12 -0
  316. package/src/verification/parser.ts +230 -0
  317. package/src/verification/rectification.ts +108 -0
  318. package/src/verification/types.ts +113 -0
  319. package/src/worktree/dispatcher.ts +65 -0
  320. package/src/worktree/index.ts +2 -0
  321. package/src/worktree/manager.ts +187 -0
  322. package/src/worktree/merge.ts +301 -0
  323. package/src/worktree/types.ts +4 -0
  324. package/test/TEST_COVERAGE_US001.md +217 -0
  325. package/test/TEST_COVERAGE_US003.md +84 -0
  326. package/test/TEST_COVERAGE_US005.md +86 -0
  327. package/test/US-002-orchestrator.test.ts +246 -0
  328. package/test/acceptance/cm-003-default-view.test.ts +194 -0
  329. package/test/execution/pid-registry.test.ts +240 -0
  330. package/test/execution/post-verify.test.ts +224 -0
  331. package/test/helpers/timeout.ts +42 -0
  332. package/test/integration/US-002-TEST-SUMMARY.md +107 -0
  333. package/test/integration/US-003-TEST-SUMMARY.md +149 -0
  334. package/test/integration/US-004-TEST-SUMMARY.md +106 -0
  335. package/test/integration/US-005-TEST-SUMMARY.md +138 -0
  336. package/test/integration/US-007-TEST-SUMMARY.md +100 -0
  337. package/test/integration/agent-validation.test.ts +439 -0
  338. package/test/integration/analyze-integration.test.ts +261 -0
  339. package/test/integration/analyze-scanner.test.ts +131 -0
  340. package/test/integration/cli-config-default-edge-cases.test.ts +222 -0
  341. package/test/integration/cli-config-default-view.test.ts +229 -0
  342. package/test/integration/cli-config-diff.test.ts +460 -0
  343. package/test/integration/cli-config.test.ts +736 -0
  344. package/test/integration/cli-diagnose.test.ts +592 -0
  345. package/test/integration/cli-logs.test.ts +314 -0
  346. package/test/integration/cli-plugins.test.ts +678 -0
  347. package/test/integration/cli-precheck.test.ts +371 -0
  348. package/test/integration/cli-run-headless.test.ts +173 -0
  349. package/test/integration/cli.test.ts +75 -0
  350. package/test/integration/config/merger.test.ts +465 -0
  351. package/test/integration/config/paths.test.ts +51 -0
  352. package/test/integration/config-loader.test.ts +265 -0
  353. package/test/integration/config.test.ts +444 -0
  354. package/test/integration/context-integration.test.ts +702 -0
  355. package/test/integration/context-provider-injection.test.ts +506 -0
  356. package/test/integration/context-verification-integration.test.ts +295 -0
  357. package/test/integration/e2e.test.ts +896 -0
  358. package/test/integration/execution.test.ts +625 -0
  359. package/test/integration/helpers.test.ts +295 -0
  360. package/test/integration/hooks.test.ts +361 -0
  361. package/test/integration/interaction-chain-pipeline.test.ts +464 -0
  362. package/test/integration/isolation.test.ts +143 -0
  363. package/test/integration/logger.test.ts +461 -0
  364. package/test/integration/parallel.test.ts +250 -0
  365. package/test/integration/path-security.test.ts +173 -0
  366. package/test/integration/pipeline-acceptance.test.ts +302 -0
  367. package/test/integration/pipeline-events.test.ts +475 -0
  368. package/test/integration/pipeline.test.ts +658 -0
  369. package/test/integration/plan.test.ts +157 -0
  370. package/test/integration/plugin-routing.test.ts +921 -0
  371. package/test/integration/plugins/config-integration.test.ts +172 -0
  372. package/test/integration/plugins/config-resolution.test.ts +522 -0
  373. package/test/integration/plugins/loader.test.ts +641 -0
  374. package/test/integration/plugins/registry.test.ts +746 -0
  375. package/test/integration/plugins/validator.test.ts +563 -0
  376. package/test/integration/prd-pause.test.ts +205 -0
  377. package/test/integration/prd-resolvers.test.ts +185 -0
  378. package/test/integration/precheck-integration.test.ts +468 -0
  379. package/test/integration/precheck.test.ts +805 -0
  380. package/test/integration/progress.test.ts +34 -0
  381. package/test/integration/rectification-flow.test.ts +512 -0
  382. package/test/integration/reporter-lifecycle.test.ts +860 -0
  383. package/test/integration/review-config-commands.test.ts +319 -0
  384. package/test/integration/review-config-schema.test.ts +116 -0
  385. package/test/integration/review-plugin-integration.test.ts +722 -0
  386. package/test/integration/review.test.ts +149 -0
  387. package/test/integration/routing-stage-bug-021.test.ts +274 -0
  388. package/test/integration/routing-stage-greenfield.test.ts +286 -0
  389. package/test/integration/runner-config-plugins.test.ts +461 -0
  390. package/test/integration/runner-fixes.test.ts +399 -0
  391. package/test/integration/runner-plugin-integration.test.ts +543 -0
  392. package/test/integration/runner.test.ts +1679 -0
  393. package/test/integration/s5-greenfield-fallback.test.ts +297 -0
  394. package/test/integration/status-file-integration.test.ts +325 -0
  395. package/test/integration/status-file.test.ts +379 -0
  396. package/test/integration/status-writer.test.ts +345 -0
  397. package/test/integration/story-id-in-events.test.ts +273 -0
  398. package/test/integration/tdd-cleanup.test.ts +246 -0
  399. package/test/integration/tdd-orchestrator.test.ts +1762 -0
  400. package/test/integration/test-scanner.test.ts +403 -0
  401. package/test/integration/verification-asset-check.test.ts +142 -0
  402. package/test/integration/verify-stage.test.ts +275 -0
  403. package/test/integration/worktree/manager.test.ts +218 -0
  404. package/test/integration/worktree/merge.test.ts +341 -0
  405. package/test/manual/logging-formatter-demo.ts +158 -0
  406. package/test/ui/tui-agent-panel.test.tsx +99 -0
  407. package/test/ui/tui-controls.test.ts +334 -0
  408. package/test/ui/tui-cost-and-pty.test.ts +189 -0
  409. package/test/ui/tui-layout.test.ts +378 -0
  410. package/test/ui/tui-pty-integration.test.tsx +159 -0
  411. package/test/ui/tui-stories.test.ts +332 -0
  412. package/test/unit/acceptance.test.ts +186 -0
  413. package/test/unit/agent-stderr-capture.test.ts +146 -0
  414. package/test/unit/analyze-classifier.test.ts +215 -0
  415. package/test/unit/analyze.test.ts +224 -0
  416. package/test/unit/auto-detect.test.ts +249 -0
  417. package/test/unit/cli-status.test.ts +417 -0
  418. package/test/unit/commands/common.test.ts +320 -0
  419. package/test/unit/commands/logs.test.ts +416 -0
  420. package/test/unit/commands/unlock.test.ts +319 -0
  421. package/test/unit/constitution-generators.test.ts +160 -0
  422. package/test/unit/constitution.test.ts +209 -0
  423. package/test/unit/context.test.ts +1722 -0
  424. package/test/unit/cost.test.ts +231 -0
  425. package/test/unit/crash-recovery.test.ts +308 -0
  426. package/test/unit/escalation.test.ts +126 -0
  427. package/test/unit/execution-logging-stderr.test.ts +156 -0
  428. package/test/unit/execution-stage.test.ts +122 -0
  429. package/test/unit/fix-generator.test.ts +275 -0
  430. package/test/unit/formatters.test.ts +469 -0
  431. package/test/unit/greenfield.test.ts +179 -0
  432. package/test/unit/helpers.test.ts +317 -0
  433. package/test/unit/interaction/human-review-trigger.test.ts +164 -0
  434. package/test/unit/interaction-network-failures.test.ts +389 -0
  435. package/test/unit/interaction-plugins.test.ts +164 -0
  436. package/test/unit/isolation.test.ts +134 -0
  437. package/test/unit/logging/formatter.test.ts +455 -0
  438. package/test/unit/merge.test.ts +268 -0
  439. package/test/unit/metrics.test.ts +276 -0
  440. package/test/unit/optimizer/noop.optimizer.test.ts +125 -0
  441. package/test/unit/optimizer/rule-based.optimizer.test.ts +358 -0
  442. package/test/unit/prd-auto-default.test.ts +290 -0
  443. package/test/unit/prd-failure-category.test.ts +176 -0
  444. package/test/unit/prd-get-next-story.test.ts +186 -0
  445. package/test/unit/precheck-checks.test.ts +840 -0
  446. package/test/unit/precheck-story-size-gate.test.ts +287 -0
  447. package/test/unit/precheck-types.test.ts +142 -0
  448. package/test/unit/prompts.test.ts +475 -0
  449. package/test/unit/queue.test.ts +237 -0
  450. package/test/unit/rectification.test.ts +284 -0
  451. package/test/unit/registry.test.ts +287 -0
  452. package/test/unit/routing.test.ts +937 -0
  453. package/test/unit/run-lifecycle.test.ts +140 -0
  454. package/test/unit/storyid-events.test.ts +224 -0
  455. package/test/unit/tdd-verdict.test.ts +492 -0
  456. package/test/unit/test-output-parser.test.ts +377 -0
  457. package/test/unit/verdict.test.ts +324 -0
  458. package/test/unit/worktree-manager.test.ts +158 -0
  459. package/tsconfig.json +27 -0
@@ -0,0 +1,629 @@
1
+ # Code Review: v0.15.0 Interactive Pipeline
2
+
3
+ **Review Date:** 2026-02-28
4
+ **Reviewed By:** Claude Code (Sonnet 4.5)
5
+ **Scope:** All files changed between v0.14.4 (6d27bd7) and HEAD (6fe168a)
6
+
7
+ ---
8
+
9
+ ## Overall Grade: B+
10
+
11
+ **Summary:** The v0.15.0 Interactive Pipeline implementation is well-structured with good separation of concerns. The interaction module follows clean architecture principles with a plugin-based design. However, there are several CRITICAL security and reliability issues that must be fixed immediately, plus architectural violations (files over 400 lines) that need addressing.
12
+
13
+ **Strengths:**
14
+ - Clean plugin architecture for interaction system
15
+ - Good type safety throughout interaction module
16
+ - Proper separation between CLI, Telegram, Webhook, and Auto plugins
17
+ - Unified verification layer eliminates duplication
18
+ - Test coverage for critical paths
19
+
20
+ **Weaknesses:**
21
+ - Multiple files exceed 400-line limit (violates CLAUDE.md)
22
+ - Missing error handling for network failures in Telegram/Webhook plugins
23
+ - No input validation for malformed webhook callbacks
24
+ - JSON.parse without try-catch in several locations
25
+ - Auto plugin security rule not enforced via config validation
26
+ - Missing tests for edge cases (network failures, malformed input, race conditions)
27
+
28
+ ---
29
+
30
+ ## Critical Findings
31
+
32
+ | ID | Severity | File | Line | Description | Fix |
33
+ |:---|:---|:---|:---|:---|:---|
34
+ | SEC-001 | CRITICAL | `src/interaction/plugins/webhook.ts` | 158 | JSON.parse without try-catch when handling webhook callbacks. Malformed JSON can crash the server. | Wrap in try-catch, return 400 Bad Request on parse error |
35
+ | SEC-002 | CRITICAL | `src/interaction/plugins/telegram.ts` | 79 | No error handling for fetch failure when sending messages. Network errors can crash the plugin. | Add try-catch, throw descriptive error |
36
+ | SEC-003 | CRITICAL | `src/interaction/plugins/telegram.ts` | 244 | No error handling for getUpdates fetch failure. Can cause infinite loop on network errors. | Add try-catch with exponential backoff |
37
+ | SEC-004 | CRITICAL | `src/interaction/plugins/auto.ts` | 72-73 | Security-review never-auto-approve rule is code-based, not config-enforced. Can be accidentally removed. | Add to config schema validation, enforce at chain level |
38
+ | REL-001 | CRITICAL | `src/interaction/chain.ts` | 74-82 | Catch block swallows ALL errors (not just timeout). Plugin crashes are silently converted to timeout responses. | Only catch timeout-specific errors, re-throw others |
39
+ | REL-002 | HIGH | `src/interaction/plugins/webhook.ts` | 80-90 | Polling loop has no exponential backoff. Can cause high CPU usage on stuck requests. | Add exponential backoff with max delay |
40
+ | REL-003 | HIGH | `src/interaction/plugins/telegram.ts` | 96-111 | Polling loop has no exponential backoff. Can hammer Telegram API and get rate limited. | Add exponential backoff (start 1s, max 5s) |
41
+ | TYPE-001 | HIGH | `src/interaction/plugins/webhook.ts` | 117, 127 | Double `as unknown as` casts to work around Bun.serve typing. Loses type safety. | Add proper type definitions for Bun.serve return type |
42
+ | ARCH-001 | HIGH | Multiple files | - | 15 files exceed 400-line limit, violating CLAUDE.md hard requirement. | Split files as documented below |
43
+ | LOG-001 | MEDIUM | `src/interaction/plugins/telegram.ts` | 79-82 | Telegram API error response not logged. Silent failures are hard to debug. | Log error response body before throwing |
44
+ | LOG-002 | MEDIUM | `src/interaction/plugins/webhook.ts` | 72-74 | Webhook POST failure not logged with response body. | Log response body before throwing |
45
+ | TEST-001 | MEDIUM | `test/unit/interaction-plugins.test.ts` | - | No tests for network failures, malformed input, or timeout edge cases. | Add failure scenario tests |
46
+ | TEST-002 | MEDIUM | `test/unit/interaction-plugins.test.ts` | - | Auto plugin LLM call not mocked. Real LLM calls in tests are slow and flaky. | Mock Bun.spawn for LLM calls |
47
+ | MEM-001 | LOW | `src/interaction/plugins/telegram.ts` | 43 | `pendingMessages` Map grows unbounded. Never cleaned up on timeout. | Add cleanup in sendTimeoutMessage |
48
+ | MEM-002 | LOW | `src/interaction/plugins/webhook.ts` | 29 | `pendingResponses` Map grows unbounded. | Add cleanup in cancel() method |
49
+
50
+ ---
51
+
52
+ ## Files Exceeding 400-Line Limit (ARCH-001)
53
+
54
+ **CRITICAL:** CLAUDE.md mandates **400 lines maximum** per file. The following files violate this:
55
+
56
+ | File | Lines | Recommended Split |
57
+ |:---|---:|:---|
58
+ | `src/config/schema.ts` | 853 | Split into: `schema-core.ts` (types), `schema-routing.ts`, `schema-interaction.ts`, `schema-validation.ts` |
59
+ | `src/agents/claude.ts` | 820 | Split into: `claude-adapter.ts`, `claude-session.ts`, `claude-parser.ts` |
60
+ | `src/tdd/orchestrator.ts` | 743 | Split into: `orchestrator.ts` (main loop), `session-manager.ts`, `verdict-handler.ts` |
61
+ | `src/execution/sequential-executor.ts` | 648 | Split into: `executor.ts`, `story-runner.ts`, `retry-handler.ts` |
62
+ | `src/cli/diagnose.ts` | 638 | Split into: `diagnose.ts`, `checks.ts`, `formatters.ts` |
63
+ | `src/execution/post-verify.ts` | 584 | Split into: `post-verify.ts`, `rectification.ts`, `escalation-decision.ts` |
64
+ | `src/context/builder.ts` | 576 | Split into: `builder.ts`, `providers.ts`, `test-coverage.ts` |
65
+ | `src/cli/analyze.ts` | 568 | Split into: `analyze.ts`, `metrics.ts`, `reports.ts` |
66
+ | `src/precheck/checks.ts` | 548 | Split into: `checks.ts`, `validators.ts`, `git-checks.ts` |
67
+ | `src/cli/status.ts` | 519 | Split into: `status.ts`, `formatters.ts`, `progress.ts` |
68
+ | `src/execution/helpers.ts` | 450 | Split into: `story-filters.ts`, `batch-helpers.ts`, `status-helpers.ts` |
69
+ | `src/execution/escalation/tier-escalation.ts` | 439 | Split into: `tier-escalation.ts`, `cost-calculator.ts` |
70
+ | `src/routing/strategies/llm.ts` | 432 | Split into: `llm-router.ts`, `batch-router.ts`, `cache.ts` |
71
+ | `src/agents/types.ts` | 430 | Split into: `agent-types.ts`, `session-types.ts`, `result-types.ts` |
72
+ | `src/execution/parallel.ts` | 404 | OK (close to limit, watch carefully) |
73
+
74
+ **Action Required:** These files MUST be split before v0.15.0 release. This is a blocking requirement per CLAUDE.md.
75
+
76
+ ---
77
+
78
+ ## Security Analysis
79
+
80
+ ### Input Validation
81
+
82
+ **FAIL:** Webhook plugin does not validate incoming callback structure.
83
+
84
+ ```typescript
85
+ // src/interaction/plugins/webhook.ts:158 (VULNERABLE)
86
+ const response = JSON.parse(body) as InteractionResponse;
87
+ this.pendingResponses.set(requestId, response);
88
+ ```
89
+
90
+ **Attack Vector:**
91
+ - Attacker sends `{"malicious": "payload"}` to webhook callback
92
+ - JSON.parse succeeds but object doesn't match InteractionResponse
93
+ - Type assertion `as InteractionResponse` bypasses type checking
94
+ - Invalid response stored in Map, causes undefined behavior later
95
+
96
+ **Fix:** Add Zod schema validation:
97
+
98
+ ```typescript
99
+ import { z } from "zod";
100
+
101
+ const InteractionResponseSchema = z.object({
102
+ requestId: z.string(),
103
+ action: z.enum(["approve", "reject", "choose", "input", "skip", "abort"]),
104
+ value: z.string().optional(),
105
+ respondedBy: z.string().optional(),
106
+ respondedAt: z.number(),
107
+ });
108
+
109
+ // In handleRequest():
110
+ try {
111
+ const parsed = JSON.parse(body);
112
+ const response = InteractionResponseSchema.parse(parsed);
113
+ this.pendingResponses.set(requestId, response);
114
+ } catch (err) {
115
+ return new Response("Bad Request: Invalid response format", { status: 400 });
116
+ }
117
+ ```
118
+
119
+ ### Credential Handling
120
+
121
+ **PASS:** Telegram bot token and webhook secrets are stored correctly:
122
+ - Read from env vars or config (never hardcoded)
123
+ - HMAC verification uses timing-safe comparison
124
+ - Secrets not logged
125
+
126
+ **Recommendation:** Add config validation to reject empty secrets:
127
+
128
+ ```typescript
129
+ // src/config/schema.ts
130
+ interaction: {
131
+ config: {
132
+ secret: z.string().min(32).optional(), // Enforce minimum secret length
133
+ }
134
+ }
135
+ ```
136
+
137
+ ### SSRF Protection
138
+
139
+ **N/A:** Webhook URL is user-configured (not from untrusted input). No SSRF risk.
140
+
141
+ ### Auto Plugin Security Rule
142
+
143
+ **FAIL:** Security-review never-auto-approve rule is enforced in code only:
144
+
145
+ ```typescript
146
+ // src/interaction/plugins/auto.ts:72-74
147
+ if (request.metadata?.trigger === "security-review") {
148
+ return undefined; // Escalate to human
149
+ }
150
+ ```
151
+
152
+ **Issue:** This can be accidentally removed during refactoring.
153
+
154
+ **Fix:** Enforce at config schema level:
155
+
156
+ ```typescript
157
+ // src/config/schema.ts
158
+ triggers: {
159
+ "security-review": z.object({
160
+ enabled: z.boolean(),
161
+ autoApprove: z.literal(false), // NEVER allow auto-approve for security
162
+ })
163
+ }
164
+ ```
165
+
166
+ ---
167
+
168
+ ## Reliability Analysis
169
+
170
+ ### Error Handling
171
+
172
+ **FAIL:** Network errors are not handled properly.
173
+
174
+ **Telegram Plugin (Critical):**
175
+
176
+ ```typescript
177
+ // src/interaction/plugins/telegram.ts:68 (VULNERABLE)
178
+ const response = await fetch(`https://api.telegram.org/bot${this.botToken}/sendMessage`, {
179
+ method: "POST",
180
+ headers: { "Content-Type": "application/json" },
181
+ body: JSON.stringify({...}),
182
+ });
183
+
184
+ const data = (await response.json()) as { ok: boolean; result: TelegramMessage };
185
+ if (!data.ok) {
186
+ throw new Error("Failed to send Telegram message");
187
+ }
188
+ ```
189
+
190
+ **Issues:**
191
+ 1. `fetch()` can throw on network errors (connection refused, DNS failure, timeout)
192
+ 2. `response.json()` can throw on malformed JSON
193
+ 3. `data.ok` check assumes `data` is defined
194
+ 4. No retry logic for transient failures
195
+
196
+ **Fix:**
197
+
198
+ ```typescript
199
+ try {
200
+ const response = await fetch(`https://api.telegram.org/bot${this.botToken}/sendMessage`, {
201
+ method: "POST",
202
+ headers: { "Content-Type": "application/json" },
203
+ body: JSON.stringify({...}),
204
+ });
205
+
206
+ if (!response.ok) {
207
+ const errorBody = await response.text();
208
+ throw new Error(`Telegram API error (${response.status}): ${errorBody}`);
209
+ }
210
+
211
+ const data = await response.json();
212
+ if (!data.ok) {
213
+ throw new Error(`Telegram API returned ok=false: ${JSON.stringify(data)}`);
214
+ }
215
+
216
+ this.pendingMessages.set(request.id, data.result.message_id);
217
+ } catch (err) {
218
+ const msg = err instanceof Error ? err.message : String(err);
219
+ throw new Error(`Failed to send Telegram message: ${msg}`);
220
+ }
221
+ ```
222
+
223
+ **Webhook Plugin (Critical):**
224
+
225
+ Same issues as Telegram. Apply similar fix pattern.
226
+
227
+ ### Race Conditions
228
+
229
+ **PASS:** No obvious race conditions found. Interaction chain is single-threaded per request.
230
+
231
+ **Potential Issue:** Webhook server starts on first `receive()` call, but multiple concurrent calls could race:
232
+
233
+ ```typescript
234
+ // src/interaction/plugins/webhook.ts:109
235
+ private async startServer(): Promise<void> {
236
+ if (this.server) return; // Already running
237
+
238
+ const port = this.config.callbackPort ?? 8765;
239
+ this.server = Bun.serve({...}) as unknown as Server;
240
+ }
241
+ ```
242
+
243
+ **Race:** Two concurrent `receive()` calls could both check `if (this.server)` before either sets it.
244
+
245
+ **Fix:** Use a mutex or Promise-based lock:
246
+
247
+ ```typescript
248
+ private serverStartPromise: Promise<void> | null = null;
249
+
250
+ private async startServer(): Promise<void> {
251
+ if (this.server) return;
252
+ if (this.serverStartPromise) {
253
+ await this.serverStartPromise;
254
+ return;
255
+ }
256
+
257
+ this.serverStartPromise = (async () => {
258
+ const port = this.config.callbackPort ?? 8765;
259
+ this.server = Bun.serve({...}) as unknown as Server;
260
+ })();
261
+
262
+ await this.serverStartPromise;
263
+ this.serverStartPromise = null;
264
+ }
265
+ ```
266
+
267
+ ### Memory Leaks
268
+
269
+ **MEDIUM:** Two Maps grow unbounded:
270
+ - `TelegramInteractionPlugin.pendingMessages` (Line 42)
271
+ - `WebhookInteractionPlugin.pendingResponses` (Line 29)
272
+
273
+ **Issue:** When a request times out, the entry is never removed from the Map.
274
+
275
+ **Fix:**
276
+
277
+ ```typescript
278
+ // In sendTimeoutMessage() / cancel():
279
+ this.pendingMessages.delete(requestId);
280
+ this.pendingResponses.delete(requestId);
281
+ ```
282
+
283
+ Already implemented in `sendTimeoutMessage()` for Telegram (line 331), but not in `cancel()` for Webhook.
284
+
285
+ ---
286
+
287
+ ## Test Coverage Gaps
288
+
289
+ ### Current Coverage
290
+
291
+ **Good:**
292
+ - ✅ Plugin initialization (with/without config, env vars)
293
+ - ✅ Config validation (missing required fields)
294
+ - ✅ Auto plugin security-review rejection
295
+
296
+ **Missing:**
297
+ - ❌ Network failure scenarios (Telegram API down, webhook unreachable)
298
+ - ❌ Malformed responses (invalid JSON, wrong structure)
299
+ - ❌ Timeout edge cases (request expires during polling)
300
+ - ❌ Concurrent request handling
301
+ - ❌ Memory leak verification (Map cleanup)
302
+ - ❌ Auto plugin LLM call (currently untested, would make real API calls)
303
+
304
+ ### Recommended Additional Tests
305
+
306
+ ```typescript
307
+ describe("TelegramInteractionPlugin - Error Handling", () => {
308
+ test("should handle network failure gracefully", async () => {
309
+ const plugin = new TelegramInteractionPlugin();
310
+ await plugin.init({ botToken: "token", chatId: "123" });
311
+
312
+ // Mock fetch to throw network error
313
+ global.fetch = async () => { throw new Error("ECONNREFUSED") };
314
+
315
+ const request = { /* ... */ };
316
+ await expect(plugin.send(request)).rejects.toThrow("Failed to send Telegram message");
317
+ });
318
+
319
+ test("should handle malformed API response", async () => {
320
+ // Mock fetch to return invalid JSON
321
+ global.fetch = async () => new Response("not json");
322
+ // ... test
323
+ });
324
+
325
+ test("should clean up pendingMessages on timeout", async () => {
326
+ // ... verify Map is empty after timeout
327
+ });
328
+ });
329
+
330
+ describe("WebhookInteractionPlugin - Security", () => {
331
+ test("should reject malformed callback payload", async () => {
332
+ const plugin = new WebhookInteractionPlugin();
333
+ await plugin.init({ url: "http://example.com" });
334
+
335
+ const malformed = { malicious: "payload" };
336
+ const response = await plugin.handleRequest(
337
+ new Request("http://localhost:8765/nax/interact/test-id", {
338
+ method: "POST",
339
+ body: JSON.stringify(malformed),
340
+ })
341
+ );
342
+
343
+ expect(response.status).toBe(400);
344
+ });
345
+
346
+ test("should reject callback without HMAC when secret configured", async () => {
347
+ // ... test
348
+ });
349
+ });
350
+
351
+ describe("AutoInteractionPlugin - LLM", () => {
352
+ test("should make correct LLM decision (mocked)", async () => {
353
+ // Mock Bun.spawn to return fake LLM response
354
+ const originalSpawn = Bun.spawn;
355
+ Bun.spawn = (cmd, opts) => {
356
+ const mockStdout = new ReadableStream({
357
+ start(controller) {
358
+ controller.enqueue(new TextEncoder().encode(
359
+ JSON.stringify({
360
+ action: "approve",
361
+ confidence: 0.8,
362
+ reasoning: "test"
363
+ })
364
+ ));
365
+ controller.close();
366
+ }
367
+ });
368
+ return { stdout: mockStdout, stderr: new ReadableStream(), exited: Promise.resolve(0) };
369
+ };
370
+
371
+ // ... test decision logic
372
+
373
+ Bun.spawn = originalSpawn; // Restore
374
+ });
375
+ });
376
+ ```
377
+
378
+ ---
379
+
380
+ ## Architecture Compliance
381
+
382
+ ### Plugin Chain Escalation
383
+
384
+ **Question:** Does the plugin chain correctly handle escalation when all plugins fail?
385
+
386
+ **Answer:** **PARTIAL FAIL**
387
+
388
+ Current behavior:
389
+ - `InteractionChain.receive()` catches ALL errors and returns timeout response
390
+ - If primary plugin throws, it's converted to timeout (action: "skip")
391
+ - No escalation to secondary plugins
392
+
393
+ **Expected behavior:**
394
+ - Try primary plugin
395
+ - On failure, try next plugin in chain (by priority)
396
+ - Only return timeout if all plugins fail OR timeout reached
397
+
398
+ **Current code:**
399
+ ```typescript
400
+ // src/interaction/chain.ts:63-82
401
+ async receive(requestId: string, timeout?: number): Promise<InteractionResponse> {
402
+ const plugin = this.getPrimary();
403
+ if (!plugin) {
404
+ throw new Error("No interaction plugin registered");
405
+ }
406
+
407
+ const timeoutMs = timeout ?? this.config.defaultTimeout;
408
+
409
+ try {
410
+ const response = await plugin.receive(requestId, timeoutMs);
411
+ return response;
412
+ } catch (err) {
413
+ // BUG: All errors converted to timeout, no fallback to other plugins
414
+ return {
415
+ requestId,
416
+ action: "skip",
417
+ respondedBy: "timeout",
418
+ respondedAt: Date.now(),
419
+ };
420
+ }
421
+ }
422
+ ```
423
+
424
+ **Fix:** Implement plugin fallback cascade:
425
+
426
+ ```typescript
427
+ async receive(requestId: string, timeout?: number): Promise<InteractionResponse> {
428
+ const timeoutMs = timeout ?? this.config.defaultTimeout;
429
+ const errors: Error[] = [];
430
+
431
+ // Try each plugin in priority order
432
+ for (const entry of this.plugins) {
433
+ try {
434
+ const response = await entry.plugin.receive(requestId, timeoutMs);
435
+ return response;
436
+ } catch (err) {
437
+ errors.push(err instanceof Error ? err : new Error(String(err)));
438
+ // Continue to next plugin
439
+ }
440
+ }
441
+
442
+ // All plugins failed
443
+ throw new Error(
444
+ `All interaction plugins failed: ${errors.map(e => e.message).join("; ")}`
445
+ );
446
+ }
447
+ ```
448
+
449
+ ### State Persistence
450
+
451
+ **Question:** Does state persistence correctly serialize/deserialize all runner state?
452
+
453
+ **Answer:** **PASS**
454
+
455
+ - `RunState` interface covers all necessary fields (line 11-41)
456
+ - Serialization uses JSON.stringify with pretty-printing (line 48)
457
+ - Deserialization has error handling for corrupted files (line 68-70)
458
+ - File operations use Bun-native APIs correctly
459
+
460
+ **Recommendation:** Add Zod schema validation for loaded state:
461
+
462
+ ```typescript
463
+ import { z } from "zod";
464
+
465
+ const RunStateSchema = z.object({
466
+ feature: z.string(),
467
+ prdPath: z.string(),
468
+ iteration: z.number(),
469
+ totalCost: z.number(),
470
+ storiesCompleted: z.number(),
471
+ pendingInteractions: z.array(z.any()), // Use InteractionRequestSchema
472
+ completedInteractions: z.array(z.any()),
473
+ pausedAt: z.number(),
474
+ pauseReason: z.string(),
475
+ currentStoryId: z.string().optional(),
476
+ currentTier: z.string().optional(),
477
+ currentModel: z.string().optional(),
478
+ metadata: z.record(z.unknown()).optional(),
479
+ });
480
+
481
+ export async function deserializeRunState(featureDir: string): Promise<RunState | null> {
482
+ try {
483
+ const file = Bun.file(stateFile);
484
+ const exists = await file.exists();
485
+ if (!exists) return null;
486
+
487
+ const json = await file.text();
488
+ const parsed = JSON.parse(json);
489
+ const state = RunStateSchema.parse(parsed); // Validate before returning
490
+ return state as RunState;
491
+ } catch (err) {
492
+ // Log validation error for debugging
493
+ console.error("Invalid run state file:", err);
494
+ return null;
495
+ }
496
+ }
497
+ ```
498
+
499
+ ### Config Schema Validation
500
+
501
+ **Question:** Are all config schema additions validated with Zod?
502
+
503
+ **Answer:** **PARTIAL PASS**
504
+
505
+ New `InteractionConfig` interface exists (line 289-304) but NOT in Zod schema.
506
+
507
+ **Current issue:**
508
+ ```typescript
509
+ // src/config/schema.ts:289-304
510
+ export interface InteractionConfig {
511
+ plugin: string;
512
+ config?: Record<string, unknown>;
513
+ defaults: { timeout: number; fallback: string };
514
+ triggers: Partial<Record<string, boolean | { enabled: boolean; fallback?: string; timeout?: number }>>;
515
+ }
516
+ ```
517
+
518
+ This is a **TypeScript interface only** — no runtime validation!
519
+
520
+ **Fix:** Add Zod schema:
521
+
522
+ ```typescript
523
+ const InteractionConfigSchema = z.object({
524
+ plugin: z.enum(["cli", "telegram", "webhook", "auto"]),
525
+ config: z.record(z.unknown()).optional(),
526
+ defaults: z.object({
527
+ timeout: z.number().min(1000).max(3600000), // 1s to 1hr
528
+ fallback: z.enum(["continue", "skip", "escalate", "abort"]),
529
+ }),
530
+ triggers: z.record(
531
+ z.union([
532
+ z.boolean(),
533
+ z.object({
534
+ enabled: z.boolean(),
535
+ fallback: z.enum(["continue", "skip", "escalate", "abort"]).optional(),
536
+ timeout: z.number().min(1000).optional(),
537
+ }),
538
+ ])
539
+ ).partial(),
540
+ });
541
+
542
+ // In main config schema:
543
+ export const NaxConfigSchema = z.object({
544
+ // ... existing fields
545
+ interaction: InteractionConfigSchema.optional(),
546
+ });
547
+ ```
548
+
549
+ ---
550
+
551
+ ## Top 5 Fixes (Priority Order)
552
+
553
+ ### 1. Fix Webhook JSON.parse Vulnerability (SEC-001)
554
+ **File:** `src/interaction/plugins/webhook.ts:158`
555
+ **Impact:** CRITICAL — Can crash server on malformed input
556
+ **Effort:** 15 minutes
557
+
558
+ Add try-catch + Zod validation:
559
+ ```typescript
560
+ try {
561
+ const parsed = JSON.parse(body);
562
+ const response = InteractionResponseSchema.parse(parsed);
563
+ this.pendingResponses.set(requestId, response);
564
+ } catch (err) {
565
+ return new Response("Bad Request", { status: 400 });
566
+ }
567
+ ```
568
+
569
+ ### 2. Add Network Error Handling to Telegram Plugin (SEC-002, SEC-003)
570
+ **File:** `src/interaction/plugins/telegram.ts:68, 235`
571
+ **Impact:** CRITICAL — Can crash plugin on network failures
572
+ **Effort:** 30 minutes
573
+
574
+ Wrap all fetch() calls in try-catch with descriptive errors.
575
+
576
+ ### 3. Fix InteractionChain Error Swallowing (REL-001)
577
+ **File:** `src/interaction/chain.ts:74-82`
578
+ **Impact:** CRITICAL — Masks real errors as timeouts
579
+ **Effort:** 20 minutes
580
+
581
+ Implement plugin fallback cascade (see Architecture section).
582
+
583
+ ### 4. Add Config Schema Validation for Interaction (SEC-004)
584
+ **File:** `src/config/schema.ts`
585
+ **Impact:** HIGH — Runtime validation missing
586
+ **Effort:** 30 minutes
587
+
588
+ Add Zod schemas for InteractionConfig and all trigger configs.
589
+
590
+ ### 5. Split Files Over 400 Lines (ARCH-001)
591
+ **Files:** 14 files (see table above)
592
+ **Impact:** HIGH — Violates CLAUDE.md hard requirement
593
+ **Effort:** 4-6 hours
594
+
595
+ Start with largest offenders:
596
+ 1. `config/schema.ts` (853 lines) → 4 files
597
+ 2. `agents/claude.ts` (820 lines) → 3 files
598
+ 3. `tdd/orchestrator.ts` (743 lines) → 3 files
599
+
600
+ ---
601
+
602
+ ## Conclusion
603
+
604
+ The v0.15.0 Interactive Pipeline implementation demonstrates solid engineering with clean separation of concerns and a well-designed plugin architecture. However, **several CRITICAL security and reliability issues must be fixed before release**.
605
+
606
+ **Blocking Issues for Release:**
607
+ 1. ✅ Test coverage is adequate (10/10 tests pass)
608
+ 2. ❌ **SEC-001, SEC-002, SEC-003** — Network error handling (CRITICAL)
609
+ 3. ❌ **REL-001** — Error swallowing in chain (CRITICAL)
610
+ 4. ❌ **ARCH-001** — 14 files exceed 400 lines (CRITICAL per CLAUDE.md)
611
+
612
+ **Recommended Release Plan:**
613
+ 1. Fix all CRITICAL findings (1-3 above) — **2 hours**
614
+ 2. Fix HIGH findings (config validation, type casts) — **1 hour**
615
+ 3. Split 3 largest files (config, agents, tdd) — **3 hours**
616
+ 4. Add missing tests for network failures — **2 hours**
617
+ 5. Re-run full test suite + typecheck — **30 minutes**
618
+ 6. **Total:** ~8-9 hours to production-ready
619
+
620
+ **Post-Release Backlog:**
621
+ - Split remaining 11 files over 400 lines
622
+ - Add comprehensive integration tests
623
+ - Implement exponential backoff for polling loops
624
+ - Add Prometheus metrics for interaction success/failure rates
625
+
626
+ ---
627
+
628
+ **Reviewer Signature:** Claude Sonnet 4.5
629
+ **Review Completed:** 2026-02-28