@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,217 @@
1
+ /**
2
+ * Auto AI Responder Plugin (v0.15.0 US-008)
3
+ *
4
+ * Automatically responds to interactions using LLM decision-making.
5
+ * Never auto-approves security-review triggers.
6
+ */
7
+
8
+ import { z } from "zod";
9
+ import type { NaxConfig } from "../../config";
10
+ import { resolveModel } from "../../config";
11
+ import type { InteractionPlugin, InteractionRequest, InteractionResponse } from "../types";
12
+
13
+ /** Auto plugin configuration */
14
+ interface AutoConfig {
15
+ /** Model tier to use for decisions (default: fast) */
16
+ model?: string;
17
+ /** Confidence threshold (0-1, default: 0.7) */
18
+ confidenceThreshold?: number;
19
+ /** Max cost per decision in USD (default: 0.01) */
20
+ maxCostPerDecision?: number;
21
+ /** Global nax config (injected by chain) */
22
+ naxConfig?: NaxConfig;
23
+ }
24
+
25
+ /** Zod schema for validating auto plugin config */
26
+ const AutoConfigSchema = z.object({
27
+ model: z.string().optional(),
28
+ confidenceThreshold: z.number().min(0).max(1).optional(),
29
+ maxCostPerDecision: z.number().positive().optional(),
30
+ naxConfig: z.any().optional(), // NaxConfig is complex, skip deep validation
31
+ });
32
+
33
+ /** LLM decision response */
34
+ interface DecisionResponse {
35
+ action: "approve" | "reject" | "choose" | "input" | "skip" | "abort";
36
+ value?: string;
37
+ confidence: number;
38
+ reasoning: string;
39
+ }
40
+
41
+ /**
42
+ * Auto plugin for AI-powered interaction responses
43
+ */
44
+ export class AutoInteractionPlugin implements InteractionPlugin {
45
+ name = "auto";
46
+ private config: AutoConfig = {};
47
+
48
+ async init(config: Record<string, unknown>): Promise<void> {
49
+ const cfg = AutoConfigSchema.parse(config);
50
+ this.config = {
51
+ model: cfg.model ?? "fast",
52
+ confidenceThreshold: cfg.confidenceThreshold ?? 0.7,
53
+ maxCostPerDecision: cfg.maxCostPerDecision ?? 0.01,
54
+ naxConfig: cfg.naxConfig,
55
+ };
56
+ }
57
+
58
+ async destroy(): Promise<void> {
59
+ // No-op
60
+ }
61
+
62
+ async send(request: InteractionRequest): Promise<void> {
63
+ // No-op — in-process plugin
64
+ }
65
+
66
+ async receive(requestId: string, timeout = 60000): Promise<InteractionResponse> {
67
+ // For auto plugin, we need to fetch the request from somewhere
68
+ // In practice, the chain should pass the request to us
69
+ // For now, throw an error since we need the full request
70
+ throw new Error("Auto plugin requires full request context (not just requestId)");
71
+ }
72
+
73
+ /**
74
+ * Decide on an interaction request using LLM
75
+ */
76
+ async decide(request: InteractionRequest): Promise<InteractionResponse | undefined> {
77
+ // SAFETY: Never auto-approve security-review
78
+ if (request.metadata?.trigger === "security-review") {
79
+ return undefined; // Escalate to human
80
+ }
81
+
82
+ try {
83
+ const decision = await this.callLlm(request);
84
+
85
+ // Check confidence threshold
86
+ if (decision.confidence < (this.config.confidenceThreshold ?? 0.7)) {
87
+ return undefined; // Escalate to human
88
+ }
89
+
90
+ return {
91
+ requestId: request.id,
92
+ action: decision.action,
93
+ value: decision.value,
94
+ respondedBy: "auto-ai",
95
+ respondedAt: Date.now(),
96
+ };
97
+ } catch (err) {
98
+ // On error, escalate to human
99
+ return undefined;
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Call LLM to make decision
105
+ */
106
+ private async callLlm(request: InteractionRequest): Promise<DecisionResponse> {
107
+ const prompt = this.buildPrompt(request);
108
+ const modelTier = this.config.model ?? "fast";
109
+
110
+ if (!this.config.naxConfig) {
111
+ throw new Error("Auto plugin requires naxConfig in init()");
112
+ }
113
+
114
+ const modelEntry = this.config.naxConfig.models[modelTier];
115
+ if (!modelEntry) {
116
+ throw new Error(`Model tier "${modelTier}" not found in config.models`);
117
+ }
118
+
119
+ const modelDef = resolveModel(modelEntry);
120
+ const modelArg = modelDef.model;
121
+
122
+ // Spawn claude CLI
123
+ const proc = Bun.spawn(["claude", "-p", prompt, "--model", modelArg], {
124
+ stdout: "pipe",
125
+ stderr: "pipe",
126
+ });
127
+
128
+ const [stdout, stderr] = await Promise.all([new Response(proc.stdout).text(), new Response(proc.stderr).text()]);
129
+
130
+ const exitCode = await proc.exited;
131
+ if (exitCode !== 0) {
132
+ throw new Error(`claude CLI failed with exit code ${exitCode}: ${stderr}`);
133
+ }
134
+
135
+ const output = stdout.trim();
136
+ return this.parseResponse(output);
137
+ }
138
+
139
+ /**
140
+ * Build LLM prompt for decision
141
+ */
142
+ private buildPrompt(request: InteractionRequest): string {
143
+ let prompt = `You are an AI decision assistant for a code orchestration system. Given an interaction request, decide the best action.
144
+
145
+ ## Interaction Request
146
+ Type: ${request.type}
147
+ Stage: ${request.stage}
148
+ Feature: ${request.featureName}
149
+ ${request.storyId ? `Story: ${request.storyId}` : ""}
150
+
151
+ Summary: ${request.summary}
152
+ ${request.detail ? `\nDetail: ${request.detail}` : ""}
153
+ `;
154
+
155
+ if (request.options && request.options.length > 0) {
156
+ prompt += "\nOptions:\n";
157
+ for (const opt of request.options) {
158
+ const desc = opt.description ? ` — ${opt.description}` : "";
159
+ prompt += ` [${opt.key}] ${opt.label}${desc}\n`;
160
+ }
161
+ }
162
+
163
+ prompt += `\nFallback behavior on timeout: ${request.fallback}
164
+ Safety tier: ${request.metadata?.safety ?? "unknown"}
165
+
166
+ ## Available Actions
167
+ - approve: Proceed with the operation
168
+ - reject: Deny the operation
169
+ - choose: Select an option (requires value field)
170
+ - input: Provide text input (requires value field)
171
+ - skip: Skip this interaction
172
+ - abort: Abort execution
173
+
174
+ ## Rules
175
+ 1. For "red" safety tier (security-review, cost-exceeded, merge-conflict): ALWAYS return confidence 0 to escalate to human
176
+ 2. For "yellow" safety tier (cost-warning, max-retries, pre-merge): High confidence (0.8+) ONLY if clearly safe
177
+ 3. For "green" safety tier (story-ambiguity, review-gate): Can approve with moderate confidence (0.6+)
178
+ 4. Default to the fallback behavior if unsure
179
+ 5. Never auto-approve security issues
180
+ 6. If the summary mentions "critical" or "security", confidence MUST be < 0.5
181
+
182
+ Respond with ONLY this JSON (no markdown, no explanation):
183
+ {"action":"approve|reject|choose|input|skip|abort","value":"<optional>","confidence":0.0-1.0,"reasoning":"<one line>"}`;
184
+
185
+ return prompt;
186
+ }
187
+
188
+ /**
189
+ * Parse LLM response
190
+ */
191
+ private parseResponse(output: string): DecisionResponse {
192
+ let jsonText = output.trim();
193
+
194
+ // Strip markdown code fences
195
+ if (jsonText.startsWith("```")) {
196
+ const lines = jsonText.split("\n");
197
+ jsonText = lines.slice(1, -1).join("\n").trim();
198
+ }
199
+ if (jsonText.startsWith("json")) {
200
+ jsonText = jsonText.slice(4).trim();
201
+ }
202
+
203
+ const parsed = JSON.parse(jsonText) as DecisionResponse;
204
+
205
+ // Validate
206
+ if (!parsed.action || parsed.confidence === undefined || !parsed.reasoning) {
207
+ throw new Error(`Invalid LLM response: ${jsonText}`);
208
+ }
209
+
210
+ // Validate confidence is 0-1
211
+ if (parsed.confidence < 0 || parsed.confidence > 1) {
212
+ throw new Error(`Invalid confidence: ${parsed.confidence} (must be 0-1)`);
213
+ }
214
+
215
+ return parsed;
216
+ }
217
+ }
@@ -0,0 +1,300 @@
1
+ /**
2
+ * CLI Interaction Plugin (v0.15.0 US-002)
3
+ *
4
+ * Default plugin for stdin/stdout interaction in non-headless mode.
5
+ */
6
+
7
+ import * as readline from "node:readline";
8
+ import { z } from "zod";
9
+ import type { InteractionPlugin, InteractionRequest, InteractionResponse } from "../types";
10
+
11
+ /** Zod schema for validating CLI plugin config */
12
+ const CLIConfigSchema = z.object({}).passthrough();
13
+
14
+ /**
15
+ * CLI plugin for interactive prompts via stdin/stdout
16
+ */
17
+ export class CLIInteractionPlugin implements InteractionPlugin {
18
+ name = "cli";
19
+ private pendingRequests = new Map<string, InteractionRequest>();
20
+ private rl: readline.Interface | null = null;
21
+
22
+ async init(config: Record<string, unknown> = {}): Promise<void> {
23
+ CLIConfigSchema.parse(config);
24
+ // Initialize readline interface
25
+ this.rl = readline.createInterface({
26
+ input: process.stdin,
27
+ output: process.stdout,
28
+ });
29
+ }
30
+
31
+ async destroy(): Promise<void> {
32
+ if (this.rl) {
33
+ this.rl.close();
34
+ this.rl = null;
35
+ }
36
+ }
37
+
38
+ async send(request: InteractionRequest): Promise<void> {
39
+ this.pendingRequests.set(request.id, request);
40
+
41
+ // Format and print the request
42
+ console.log(`\n${"=".repeat(80)}`);
43
+ console.log(`[INTERACTION] ${request.stage.toUpperCase()} — ${request.type.toUpperCase()}`);
44
+ console.log("=".repeat(80));
45
+ console.log(`\n${request.summary}\n`);
46
+
47
+ if (request.detail) {
48
+ console.log(request.detail);
49
+ console.log("");
50
+ }
51
+
52
+ if (request.options && request.options.length > 0) {
53
+ console.log("Options:");
54
+ for (const opt of request.options) {
55
+ const desc = opt.description ? ` — ${opt.description}` : "";
56
+ console.log(` [${opt.key}] ${opt.label}${desc}`);
57
+ }
58
+ console.log("");
59
+ }
60
+
61
+ if (request.timeout) {
62
+ const timeoutSec = Math.floor(request.timeout / 1000);
63
+ console.log(`[Timeout: ${timeoutSec}s | Fallback: ${request.fallback}]`);
64
+ }
65
+
66
+ console.log(`${"=".repeat(80)}\n`);
67
+ }
68
+
69
+ async receive(requestId: string, timeout = 60000): Promise<InteractionResponse> {
70
+ const request = this.pendingRequests.get(requestId);
71
+ if (!request) {
72
+ throw new Error(`No pending request with ID: ${requestId}`);
73
+ }
74
+
75
+ if (!this.rl) {
76
+ throw new Error("CLI plugin not initialized");
77
+ }
78
+
79
+ const response = await this.promptUser(request, timeout);
80
+ this.pendingRequests.delete(requestId);
81
+ return response;
82
+ }
83
+
84
+ async cancel(requestId: string): Promise<void> {
85
+ this.pendingRequests.delete(requestId);
86
+ }
87
+
88
+ /**
89
+ * Prompt user for response with timeout
90
+ */
91
+ private async promptUser(request: InteractionRequest, timeout: number): Promise<InteractionResponse> {
92
+ if (!this.rl) {
93
+ throw new Error("CLI plugin not initialized");
94
+ }
95
+
96
+ const timeoutPromise = new Promise<InteractionResponse>((resolve) => {
97
+ setTimeout(() => {
98
+ resolve({
99
+ requestId: request.id,
100
+ action: "skip",
101
+ respondedBy: "timeout",
102
+ respondedAt: Date.now(),
103
+ });
104
+ }, timeout);
105
+ });
106
+
107
+ const userPromise = this.getUserInput(request);
108
+
109
+ const response = await Promise.race([userPromise, timeoutPromise]);
110
+ return response;
111
+ }
112
+
113
+ /**
114
+ * Get user input based on interaction type
115
+ */
116
+ private async getUserInput(request: InteractionRequest): Promise<InteractionResponse> {
117
+ if (!this.rl) {
118
+ throw new Error("CLI plugin not initialized");
119
+ }
120
+
121
+ switch (request.type) {
122
+ case "confirm":
123
+ return this.promptConfirm(request);
124
+ case "choose":
125
+ return this.promptChoose(request);
126
+ case "input":
127
+ return this.promptInput(request);
128
+ case "review":
129
+ return this.promptReview(request);
130
+ case "notify":
131
+ // Notify doesn't require input
132
+ return {
133
+ requestId: request.id,
134
+ action: "approve",
135
+ respondedBy: "system",
136
+ respondedAt: Date.now(),
137
+ };
138
+ case "webhook":
139
+ // Webhook is handled externally
140
+ return {
141
+ requestId: request.id,
142
+ action: "approve",
143
+ respondedBy: "system",
144
+ respondedAt: Date.now(),
145
+ };
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Prompt for confirmation (yes/no)
151
+ */
152
+ private async promptConfirm(request: InteractionRequest): Promise<InteractionResponse> {
153
+ const answer = await this.question("Approve? [y/n/skip/abort]: ");
154
+ const normalized = answer.toLowerCase().trim();
155
+
156
+ let action: InteractionResponse["action"];
157
+ if (normalized === "y" || normalized === "yes") {
158
+ action = "approve";
159
+ } else if (normalized === "n" || normalized === "no") {
160
+ action = "reject";
161
+ } else if (normalized === "skip") {
162
+ action = "skip";
163
+ } else if (normalized === "abort") {
164
+ action = "abort";
165
+ } else {
166
+ // Invalid input, default to skip
167
+ action = "skip";
168
+ }
169
+
170
+ return {
171
+ requestId: request.id,
172
+ action,
173
+ respondedBy: "user",
174
+ respondedAt: Date.now(),
175
+ };
176
+ }
177
+
178
+ /**
179
+ * Prompt for choice from options
180
+ */
181
+ private async promptChoose(request: InteractionRequest): Promise<InteractionResponse> {
182
+ const answer = await this.question("Choose [key or skip/abort]: ");
183
+ const normalized = answer.toLowerCase().trim();
184
+
185
+ if (normalized === "skip") {
186
+ return {
187
+ requestId: request.id,
188
+ action: "skip",
189
+ respondedBy: "user",
190
+ respondedAt: Date.now(),
191
+ };
192
+ }
193
+
194
+ if (normalized === "abort") {
195
+ return {
196
+ requestId: request.id,
197
+ action: "abort",
198
+ respondedBy: "user",
199
+ respondedAt: Date.now(),
200
+ };
201
+ }
202
+
203
+ // Check if answer matches an option key
204
+ const option = request.options?.find((opt) => opt.key === normalized);
205
+ if (option) {
206
+ return {
207
+ requestId: request.id,
208
+ action: "choose",
209
+ value: option.key,
210
+ respondedBy: "user",
211
+ respondedAt: Date.now(),
212
+ };
213
+ }
214
+
215
+ // Invalid choice, default to skip
216
+ return {
217
+ requestId: request.id,
218
+ action: "skip",
219
+ respondedBy: "user",
220
+ respondedAt: Date.now(),
221
+ };
222
+ }
223
+
224
+ /**
225
+ * Prompt for text input
226
+ */
227
+ private async promptInput(request: InteractionRequest): Promise<InteractionResponse> {
228
+ const answer = await this.question("Input [or skip/abort]: ");
229
+ const normalized = answer.trim();
230
+
231
+ if (normalized.toLowerCase() === "skip") {
232
+ return {
233
+ requestId: request.id,
234
+ action: "skip",
235
+ respondedBy: "user",
236
+ respondedAt: Date.now(),
237
+ };
238
+ }
239
+
240
+ if (normalized.toLowerCase() === "abort") {
241
+ return {
242
+ requestId: request.id,
243
+ action: "abort",
244
+ respondedBy: "user",
245
+ respondedAt: Date.now(),
246
+ };
247
+ }
248
+
249
+ return {
250
+ requestId: request.id,
251
+ action: "input",
252
+ value: normalized,
253
+ respondedBy: "user",
254
+ respondedAt: Date.now(),
255
+ };
256
+ }
257
+
258
+ /**
259
+ * Prompt for review (detailed approval)
260
+ */
261
+ private async promptReview(request: InteractionRequest): Promise<InteractionResponse> {
262
+ const answer = await this.question("Review complete? [approve/reject/skip/abort]: ");
263
+ const normalized = answer.toLowerCase().trim();
264
+
265
+ let action: InteractionResponse["action"];
266
+ if (normalized === "approve") {
267
+ action = "approve";
268
+ } else if (normalized === "reject") {
269
+ action = "reject";
270
+ } else if (normalized === "skip") {
271
+ action = "skip";
272
+ } else if (normalized === "abort") {
273
+ action = "abort";
274
+ } else {
275
+ action = "skip";
276
+ }
277
+
278
+ return {
279
+ requestId: request.id,
280
+ action,
281
+ respondedBy: "user",
282
+ respondedAt: Date.now(),
283
+ };
284
+ }
285
+
286
+ /**
287
+ * Async wrapper for readline.question
288
+ */
289
+ private async question(prompt: string): Promise<string> {
290
+ if (!this.rl) {
291
+ throw new Error("CLI plugin not initialized");
292
+ }
293
+
294
+ return new Promise((resolve) => {
295
+ this.rl?.question(prompt, (answer) => {
296
+ resolve(answer);
297
+ });
298
+ });
299
+ }
300
+ }