@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,237 @@
1
+ # ngent v0.5 Specification
2
+ **Date:** 2026-02-17
3
+ **Status:** Approved
4
+
5
+ ## Theme: Cost Intelligence
6
+
7
+ v0.5 makes ngent cost-aware — track spending, control routing, and auto-optimize model selection based on observed data.
8
+
9
+ ## Feature 1: Metrics Tracking
10
+
11
+ ### Problem
12
+ No visibility into where money goes. Users can't answer: "Which stories cost the most?", "What's my haiku pass rate?", "Am I wasting money on sonnet for simple tasks?"
13
+
14
+ ### Solution
15
+ Log structured metrics per run and per story. Persist to `ngent/metrics.json`.
16
+
17
+ ### Data Model
18
+ ```typescript
19
+ interface RunMetrics {
20
+ runId: string;
21
+ feature: string;
22
+ startedAt: string;
23
+ completedAt: string;
24
+ totalCost: number;
25
+ totalStories: number;
26
+ storiesCompleted: number;
27
+ storiesFailed: number;
28
+ totalDurationMs: number;
29
+ stories: StoryMetrics[];
30
+ }
31
+
32
+ interface StoryMetrics {
33
+ storyId: string;
34
+ complexity: string;
35
+ modelTier: string;
36
+ modelUsed: string;
37
+ attempts: number; // how many tries (escalations)
38
+ finalTier: string; // tier that succeeded
39
+ success: boolean;
40
+ cost: number;
41
+ durationMs: number;
42
+ firstPassSuccess: boolean; // passed on first attempt?
43
+ }
44
+
45
+ interface AggregateMetrics {
46
+ totalRuns: number;
47
+ totalCost: number;
48
+ totalStories: number;
49
+ firstPassRate: number; // % passing on first attempt
50
+ escalationRate: number; // % needing model upgrade
51
+ avgCostPerStory: number;
52
+ avgCostPerFeature: number;
53
+ modelEfficiency: Record<string, {
54
+ attempts: number;
55
+ successes: number;
56
+ passRate: number;
57
+ avgCost: number;
58
+ totalCost: number;
59
+ }>;
60
+ complexityAccuracy: Record<string, {
61
+ predicted: number;
62
+ actualTierUsed: string; // most common final tier
63
+ mismatchRate: number; // predicted simple but needed sonnet
64
+ }>;
65
+ }
66
+ ```
67
+
68
+ ### CLI
69
+ ```bash
70
+ ngent status --cost # show aggregate metrics
71
+ ngent status --cost --last # show last run metrics
72
+ ngent status --cost --model # show per-model efficiency
73
+ ```
74
+
75
+ ### Acceptance Criteria
76
+ - [ ] Per-story metrics logged during run
77
+ - [ ] Per-run summary persisted to metrics.json
78
+ - [ ] Aggregate metrics calculated across all runs
79
+ - [ ] `ngent status --cost` displays formatted report
80
+ - [ ] Metrics survive across runs (append, not overwrite)
81
+
82
+ ---
83
+
84
+ ## Feature 2: Pluggable Routing
85
+
86
+ ### Problem
87
+ Routing is hardcoded — keyword matching or LLM classification. Developers can't inject domain knowledge like "always use opus for database migrations" or "use haiku for all docs tasks".
88
+
89
+ ### Solution
90
+ `RoutingStrategy` interface. Built-in strategies + custom strategy loading.
91
+
92
+ ### Interface
93
+ ```typescript
94
+ interface RoutingStrategy {
95
+ readonly name: string;
96
+ route(story: UserStory, context: RoutingContext): RoutingDecision;
97
+ }
98
+
99
+ interface RoutingContext {
100
+ config: NgentConfig;
101
+ codebaseContext?: string;
102
+ metrics?: AggregateMetrics;
103
+ }
104
+
105
+ interface RoutingDecision {
106
+ complexity: string;
107
+ modelTier: ModelTier;
108
+ testStrategy: string;
109
+ reasoning: string;
110
+ }
111
+ ```
112
+
113
+ ### Built-in Strategies
114
+ - `keyword` — current keyword matching (default fallback)
115
+ - `llm` — LLM classification (v0.3)
116
+ - `adaptive` — metrics-driven (v0.5, see Feature 3)
117
+ - `manual` — user specifies tier per story in prd.json
118
+
119
+ ### Custom Strategy
120
+ ```json
121
+ {
122
+ "routing": {
123
+ "strategy": "custom",
124
+ "customStrategyPath": "./my-router.ts"
125
+ }
126
+ }
127
+ ```
128
+
129
+ ```typescript
130
+ // my-router.ts
131
+ import type { RoutingStrategy } from "ngent";
132
+
133
+ export default {
134
+ name: "my-project-router",
135
+ route(story, context) {
136
+ if (story.tags.includes("migration")) return { modelTier: "powerful", ... };
137
+ if (story.tags.includes("docs")) return { modelTier: "fast", ... };
138
+ // fallback to keyword
139
+ return null; // null = use fallback strategy
140
+ },
141
+ } satisfies RoutingStrategy;
142
+ ```
143
+
144
+ ### Strategy Chain
145
+ Custom strategy can return `null` to delegate to next strategy:
146
+ ```
147
+ custom → adaptive → llm → keyword
148
+ ```
149
+
150
+ ### Acceptance Criteria
151
+ - [ ] RoutingStrategy interface exported
152
+ - [ ] Custom strategy loaded from config path
153
+ - [ ] Strategy chain with null-delegation fallback
154
+ - [ ] Built-in strategies: keyword, llm, manual
155
+ - [ ] Config validation for strategy selection
156
+
157
+ ---
158
+
159
+ ## Feature 3: Adaptive Routing
160
+
161
+ ### Problem
162
+ Static routing wastes money. Haiku might handle 90% of "medium" stories, but routing always sends them to sonnet.
163
+
164
+ ### Solution
165
+ Use historical metrics to auto-adjust routing thresholds.
166
+
167
+ ### Algorithm
168
+ ```
169
+ For each complexity level:
170
+ 1. Check metrics: what's haiku's pass rate for this complexity?
171
+ 2. Calculate: effectiveCost = haikuCost + (failRate × escalationCost)
172
+ 3. Compare: is effectiveCost < sonnetCost?
173
+ 4. If yes → route to haiku (escalation handles failures)
174
+ 5. If no → route to sonnet (haiku wastes more than it saves)
175
+ ```
176
+
177
+ ### Thresholds
178
+ ```json
179
+ {
180
+ "routing": {
181
+ "strategy": "adaptive",
182
+ "adaptive": {
183
+ "minSamples": 10, // need 10 stories before adapting
184
+ "costThreshold": 0.8, // switch when effectiveCost > 80% of next tier
185
+ "fallbackStrategy": "llm" // use before enough data collected
186
+ }
187
+ }
188
+ }
189
+ ```
190
+
191
+ ### Acceptance Criteria
192
+ - [ ] Reads historical metrics for routing decisions
193
+ - [ ] Falls back to configured strategy when insufficient data
194
+ - [ ] Respects minSamples threshold
195
+ - [ ] Calculates effective cost including escalation
196
+ - [ ] Auto-adjusts routing per complexity level
197
+ - [ ] Logs reasoning for adaptive decisions
198
+
199
+ ---
200
+
201
+ ## Implementation Plan
202
+
203
+ ### Phase 1: Metrics Tracking
204
+ **Files:** `src/metrics/tracker.ts`, `src/metrics/aggregator.ts`, `src/metrics/index.ts`
205
+ - StoryMetrics collection during pipeline execution
206
+ - RunMetrics summary on completion
207
+ - AggregateMetrics calculation
208
+ - Persistence to `ngent/metrics.json`
209
+ - `ngent status --cost` display
210
+
211
+ **Commit:** `feat(metrics): add per-story and per-run cost tracking`
212
+
213
+ ### Phase 2: Pluggable Routing
214
+ **Files:** `src/routing/strategy.ts`, `src/routing/chain.ts`, `src/routing/strategies/`
215
+ - RoutingStrategy interface
216
+ - Strategy chain with fallback
217
+ - Custom strategy loader (dynamic import)
218
+ - Manual strategy (read from prd.json)
219
+ - Config schema update
220
+
221
+ **Commit:** `feat(routing): add pluggable routing strategy system`
222
+
223
+ ### Phase 3: Adaptive Routing
224
+ **Files:** `src/routing/strategies/adaptive.ts`
225
+ - Read AggregateMetrics
226
+ - Calculate effective cost per complexity
227
+ - Route based on cost optimization
228
+ - Fallback when insufficient data
229
+
230
+ **Commit:** `feat(routing): add adaptive metrics-driven routing strategy`
231
+
232
+ ## Test Strategy
233
+ - Mode: test-after
234
+ - Run `bun test && bun run typecheck` after each phase
235
+
236
+ ## Estimated Effort
237
+ ~500-700 LOC across 3 phases.
@@ -0,0 +1,371 @@
1
+ # nax v0.6 Specification
2
+ **Date:** 2026-02-17
3
+ **Status:** Draft
4
+
5
+ ## Theme: Terminal User Interface
6
+
7
+ v0.6 adds an interactive TUI that wraps the orchestration loop, giving developers real-time visibility and control over agent execution — without leaving the terminal.
8
+
9
+ ### Core Insight
10
+
11
+ **Relentless TUI = monitoring dashboard. nax TUI = interactive co-pilot.**
12
+
13
+ Relentless streams piped text into a read-only panel. nax embeds the actual Claude Code session in a PTY — the developer can **approve permission prompts, intervene mid-execution, and steer** while nax handles the orchestration loop around it.
14
+
15
+ ---
16
+
17
+ ## Feature 1: PTY-Embedded Agent Sessions
18
+
19
+ ### Problem
20
+ `nax run` currently spawns Claude Code with `-p` (print mode) — fully non-interactive. The developer has no visibility into what the agent is doing or ability to intervene. For `--dangerously-skip-permissions` this is fine, but for interactive use (where the developer approves each tool call), there's no way to see/interact with the agent.
21
+
22
+ ### Solution
23
+ Embed the agent session in a PTY panel within the TUI. Agent output streams in real-time. Keyboard input routes to the agent's stdin when the agent panel is focused.
24
+
25
+ ### Design
26
+ ```
27
+ ┌─ nax run ─────────────────────────────────────────────────────┐
28
+ │ ┌─ Stories ──────────┐ ┌─ Agent ────────────────────────────┐ │
29
+ │ │ ✅ US-001 setup │ │ $ claude │ │
30
+ │ │ ✅ US-002 models │ │ │ │
31
+ │ │ 🔄 US-003 api │ │ I'll implement the API routes... │ │
32
+ │ │ ⬚ US-004 tests │ │ │ │
33
+ │ │ ⬚ US-005 docs │ │ > Allow: Write src/routes/api.ts? │ │
34
+ │ │ │ │ [Y/n] _ │ │
35
+ │ │ Cost: $0.42 │ │ │ │
36
+ │ │ Time: 4m 23s │ │ │ │
37
+ │ └────────────────────┘ └────────────────────────────────────┘ │
38
+ │ ┌─ Status ──────────────────────────────────────────────────┐ │
39
+ │ │ Story 3/5 · US-003 · medium · sonnet · single-session │ │
40
+ │ └───────────────────────────────────────────────────────────┘ │
41
+ └───────────────────────────────────────────────────────────────┘
42
+ ```
43
+
44
+ ### PTY Architecture (Agent-Agnostic)
45
+
46
+ The PTY embedding is **agent-agnostic by design**. The agent panel is a terminal emulator widget — it doesn't parse or understand agent-specific output. Whatever the agent prints, we display. Whatever the user types, we forward. This means any coding agent that runs in a terminal works automatically:
47
+
48
+ | Agent | Interactive PTY? | Notes |
49
+ |:---|:---|:---|
50
+ | Claude Code | ✅ | Permission prompts, rich ANSI output |
51
+ | Codex CLI | ✅ | Similar interactive flow |
52
+ | Aider | ✅ | Chat-style terminal UI |
53
+ | OpenCode | ✅ | Terminal-based |
54
+ | Any CLI tool | ✅ | If it runs in a terminal, it works in the panel |
55
+
56
+ ```typescript
57
+ // Agent adapter spawns with PTY instead of piped stdio
58
+ interface AgentSpawnOptions {
59
+ mode: 'pty' | 'pipe'; // pty = interactive TUI, pipe = headless (-p mode)
60
+ onOutput?: (data: string) => void; // stream to TUI panel
61
+ onInput?: () => ReadableStream; // keyboard from TUI
62
+ }
63
+ ```
64
+
65
+ - **`node-pty`** for PTY allocation (battle-tested, used by VS Code)
66
+ - Agent panel captures all PTY output (ANSI codes preserved)
67
+ - Focused panel routes keystrokes to PTY stdin
68
+ - When not in TUI mode, behavior is unchanged (pipe mode, `-p`)
69
+ - Adding a new agent to the TUI requires only implementing `runInteractive()` on the adapter — zero TUI code changes
70
+
71
+ ### Acceptance Criteria
72
+ - [ ] Agent session runs in embedded PTY
73
+ - [ ] Real-time output streaming to TUI panel
74
+ - [ ] Keyboard input routes to agent when panel focused
75
+ - [ ] Permission prompts visible and answerable
76
+ - [ ] Falls back to pipe mode when `--headless` flag or no TTY
77
+
78
+ ---
79
+
80
+ ## Feature 2: Story Progress Panel
81
+
82
+ ### Problem
83
+ During a run, the developer has no idea which stories are done, which failed, or what's currently executing without reading log output.
84
+
85
+ ### Solution
86
+ Left sidebar showing all stories with live status icons, cost accumulator, and elapsed time.
87
+
88
+ ### Story States
89
+ ```
90
+ ⬚ pending — not started
91
+ 🔄 running — agent working on it
92
+ ✅ passed — completed successfully
93
+ ❌ failed — all attempts exhausted
94
+ ⏭️ skipped — skipped by queue command or dependency failure
95
+ 🔁 retrying — escalating to higher tier
96
+ ⏸️ paused — queue PAUSE received
97
+ ```
98
+
99
+ ### Data Source
100
+ Pipeline context already tracks story status. The TUI subscribes to pipeline events:
101
+
102
+ ```typescript
103
+ interface PipelineEvents {
104
+ 'story:start': (story: UserStory, routing: RoutingResult) => void;
105
+ 'story:complete': (story: UserStory, result: StageResult) => void;
106
+ 'story:escalate': (story: UserStory, fromTier: string, toTier: string) => void;
107
+ 'stage:enter': (stage: string, story: UserStory) => void;
108
+ 'stage:exit': (stage: string, result: StageResult) => void;
109
+ 'run:complete': (summary: RunSummary) => void;
110
+ }
111
+ ```
112
+
113
+ ### Cost Display
114
+ - Per-story cost (from metrics tracker, v0.5)
115
+ - Running total
116
+ - Projected total (based on avg cost × remaining stories)
117
+
118
+ ### Acceptance Criteria
119
+ - [ ] All stories listed with real-time status icons
120
+ - [ ] Cost accumulator updates per story completion
121
+ - [ ] Elapsed time displayed
122
+ - [ ] Current stage shown in status bar (routing → constitution → prompt → execution → verify → review)
123
+ - [ ] Pipeline events emitted from runner
124
+
125
+ ---
126
+
127
+ ## Feature 3: Interactive Controls
128
+
129
+ ### Problem
130
+ Queue commands (`PAUSE`, `ABORT`, `SKIP`) require writing to a file. Developers want keyboard shortcuts.
131
+
132
+ ### Solution
133
+ Keyboard shortcuts that write queue commands + additional TUI-only controls.
134
+
135
+ ### Keybindings
136
+ ```
137
+ p — Pause after current story (writes PAUSE to queue)
138
+ a — Abort run (writes ABORT to queue)
139
+ s — Skip current story (writes SKIP <current-story-id>)
140
+ Tab — Toggle focus between Stories panel and Agent panel
141
+ q — Quit TUI (confirms if run is active)
142
+ ? — Show help overlay
143
+ Esc — Close overlay / unfocus agent panel
144
+ r — Retry last failed story
145
+ c — Show cost breakdown overlay
146
+ ```
147
+
148
+ When the Agent panel is focused, all keys route to the PTY **except**:
149
+ - `Ctrl+]` — escape back to TUI controls (like `screen`/`tmux` prefix)
150
+
151
+ ### Acceptance Criteria
152
+ - [ ] Keyboard shortcuts trigger queue commands
153
+ - [ ] Focus mode for agent panel (keys → PTY)
154
+ - [ ] Escape sequence to return to TUI controls
155
+ - [ ] Help overlay with keybinding reference
156
+ - [ ] Confirmation prompt before abort/quit during active run
157
+
158
+ ---
159
+
160
+ ## Feature 4: Headless Mode Compatibility
161
+
162
+ ### Problem
163
+ CI/CD, cron jobs, and `nax run` via scripts need headless operation. TUI should be opt-in, not forced.
164
+
165
+ ### Solution
166
+ TUI activates only when:
167
+ 1. stdout is a TTY, AND
168
+ 2. `--headless` flag is NOT passed
169
+
170
+ ```bash
171
+ nax run # TUI mode (if TTY)
172
+ nax run --headless # pipe mode (current behavior)
173
+ nax run | tee log.txt # pipe mode (not a TTY)
174
+ NAX_HEADLESS=1 nax run # pipe mode (env override)
175
+ ```
176
+
177
+ ### Acceptance Criteria
178
+ - [ ] TUI auto-activates on TTY
179
+ - [ ] `--headless` forces pipe mode
180
+ - [ ] Non-TTY detection falls back to pipe mode
181
+ - [ ] `NAX_HEADLESS` env var override
182
+ - [ ] All existing functionality works in headless mode (no regressions)
183
+
184
+ ---
185
+
186
+ ## Feature 5: Responsive Layout
187
+
188
+ ### Problem
189
+ Terminal widths vary (80–200+ columns). The 2-panel layout needs to adapt.
190
+
191
+ ### Solution
192
+ Three layout breakpoints:
193
+
194
+ ```
195
+ < 80 cols: Single column (stories above, agent below, stacked)
196
+ 80–140 cols: 2-column (stories left, agent right)
197
+ > 140 cols: 2-column with wider agent panel + stage detail in status bar
198
+ ```
199
+
200
+ Vertical: Agent panel takes remaining height. Stories panel scrolls if >15 stories.
201
+
202
+ ### Acceptance Criteria
203
+ - [ ] Layout adapts to terminal width
204
+ - [ ] Resize events handled (SIGWINCH)
205
+ - [ ] Single-column mode functional on 80-col terminals
206
+ - [ ] Stories panel scrollable
207
+
208
+ ---
209
+
210
+ ## Non-Goals (v0.6)
211
+
212
+ - **3-column layout** — Relentless-style message queue panel. Not needed; nax doesn't have a message queue concept.
213
+ - **Animated effects** — Typing animations, pulsing cursors. Keep it clean and fast.
214
+ - **Mouse support** — Keyboard-only for v0.6. Mouse can come later.
215
+ - **Theming/colors config** — Hardcoded color scheme (chalk). Configurable themes deferred.
216
+ - **Log panel** — Agent output IS the log. No separate log panel needed.
217
+
218
+ ---
219
+
220
+ ## Technical Stack
221
+
222
+ | Component | Choice | Rationale |
223
+ |:---|:---|:---|
224
+ | **UI framework** | [Ink](https://github.com/vadimdemedes/ink) (React for terminal) | Declarative, Bun-compatible, used by Relentless |
225
+ | **PTY library** | [node-pty](https://github.com/microsoft/node-pty) | Battle-tested (VS Code), split I/O, cross-platform |
226
+ | **Terminal detection** | `process.stdout.isTTY` + `--headless` flag | Standard approach |
227
+ | **Layout** | Ink `<Box>` with flexbox | Built into Ink |
228
+
229
+ ### Component Tree
230
+ ```
231
+ <App>
232
+ <Layout cols={termWidth}>
233
+ <StoriesPanel stories={stories} costs={costs} elapsed={elapsed} />
234
+ <AgentPanel pty={ptyProcess} focused={agentFocused} />
235
+ </Layout>
236
+ <StatusBar story={current} stage={currentStage} routing={routing} />
237
+ {showHelp && <HelpOverlay />}
238
+ {showCosts && <CostOverlay metrics={metrics} />}
239
+ </App>
240
+ ```
241
+
242
+ ### File Structure
243
+ ```
244
+ src/
245
+ tui/
246
+ index.ts # TUI entry point, Ink render()
247
+ App.tsx # Root component
248
+ components/
249
+ StoriesPanel.tsx # Story list with status icons
250
+ AgentPanel.tsx # PTY output display + input routing
251
+ StatusBar.tsx # Current story/stage info
252
+ HelpOverlay.tsx # Keybinding reference
253
+ CostOverlay.tsx # Cost breakdown table
254
+ hooks/
255
+ usePty.ts # PTY lifecycle management
256
+ usePipelineEvents.ts # Subscribe to pipeline events
257
+ useKeyboard.ts # Keyboard shortcut handler
258
+ useLayout.ts # Terminal size + breakpoint detection
259
+ types.ts # TUI-specific types
260
+ ```
261
+
262
+ ### Agent Adapter Changes
263
+ ```typescript
264
+ // src/agents/types.ts — extend AgentAdapter
265
+ interface AgentAdapter {
266
+ // existing
267
+ run(command: string[], options: RunOptions): Promise<AgentResult>;
268
+
269
+ // new: PTY mode for TUI
270
+ runInteractive?(
271
+ command: string[],
272
+ options: RunOptions & {
273
+ onOutput: (data: Buffer) => void;
274
+ onExit: (code: number) => void;
275
+ }
276
+ ): PtyHandle;
277
+ }
278
+
279
+ interface PtyHandle {
280
+ write(data: string): void; // send input to agent
281
+ resize(cols: number, rows: number): void;
282
+ kill(): void;
283
+ pid: number;
284
+ }
285
+ ```
286
+
287
+ ---
288
+
289
+ ## Implementation Plan
290
+
291
+ ### Phase 1: Pipeline Events + Headless Flag
292
+ **Files:** `src/pipeline/runner.ts`, `src/pipeline/events.ts`, `src/cli/run.ts`
293
+ - Add EventEmitter to pipeline runner
294
+ - Emit story/stage lifecycle events
295
+ - Add `--headless` flag and TTY detection
296
+ - No visual changes — just the event plumbing
297
+
298
+ **Commit:** `feat(pipeline): add event emitter for TUI integration`
299
+
300
+ ### Phase 2: Ink Scaffolding + Stories Panel
301
+ **Files:** `src/tui/`, `package.json` (add ink, react, node-pty deps)
302
+ - Ink app bootstrap
303
+ - StoriesPanel with mock data
304
+ - StatusBar
305
+ - Layout with breakpoints
306
+ - Wire to pipeline events (stories update live)
307
+
308
+ **Commit:** `feat(tui): add Ink-based TUI with stories panel`
309
+
310
+ ### Phase 3: PTY Agent Panel
311
+ **Files:** `src/tui/components/AgentPanel.tsx`, `src/tui/hooks/usePty.ts`, `src/agents/claude.ts`
312
+ - node-pty integration in Claude adapter
313
+ - AgentPanel rendering PTY output
314
+ - Focus management (Tab to switch, Ctrl+] to escape)
315
+ - Input routing to PTY stdin
316
+
317
+ **Commit:** `feat(tui): embed agent PTY session in TUI`
318
+
319
+ ### Phase 4: Interactive Controls + Overlays
320
+ **Files:** `src/tui/hooks/useKeyboard.ts`, `src/tui/components/HelpOverlay.tsx`, `src/tui/components/CostOverlay.tsx`
321
+ - Keyboard shortcuts (p/a/s/q/?)
322
+ - Help overlay
323
+ - Cost breakdown overlay
324
+ - Confirmation prompts
325
+
326
+ **Commit:** `feat(tui): add keyboard controls and overlays`
327
+
328
+ ### Phase 5: Responsive Layout + Polish
329
+ **Files:** `src/tui/hooks/useLayout.ts`, `src/tui/App.tsx`
330
+ - SIGWINCH handling
331
+ - Single-column breakpoint
332
+ - Scrollable stories panel
333
+ - Edge cases (tiny terminals, rapid resize)
334
+
335
+ **Commit:** `feat(tui): responsive layout and polish`
336
+
337
+ ## Test Strategy
338
+ - **Unit tests:** Pipeline events, layout breakpoint logic, keybinding handler
339
+ - **Snapshot tests:** Ink component rendering (ink-testing-library)
340
+ - **Integration:** Full TUI with mock agent adapter (no real Claude Code)
341
+ - Mode: test-after per phase
342
+
343
+ ## Dependencies (new)
344
+ ```json
345
+ {
346
+ "ink": "^5.0.0",
347
+ "react": "^18.3.0",
348
+ "node-pty": "^1.0.0"
349
+ }
350
+ ```
351
+
352
+ DevDependencies:
353
+ ```json
354
+ {
355
+ "ink-testing-library": "^4.0.0",
356
+ "@types/react": "^18.3.0"
357
+ }
358
+ ```
359
+
360
+ ## Estimated Effort
361
+ ~1,200–1,500 LOC across 5 phases. Largest phase is Phase 3 (PTY integration).
362
+
363
+ ## Risk Assessment
364
+
365
+ | Risk | Mitigation |
366
+ |:---|:---|
367
+ | `node-pty` native compilation on different platforms | Provide fallback to pipe mode; node-pty is well-maintained |
368
+ | Ink + Bun compatibility | Ink 5.x works with Bun; verify in Phase 2 before investing in Phase 3 |
369
+ | PTY output flooding (fast agent output) | Buffer/throttle rendering to 30fps; Ink handles this natively |
370
+ | ANSI escape code rendering in Ink | Use `<Static>` or raw output mode for agent panel |
371
+ | node-pty adds ~5MB to install size | Acceptable tradeoff; it's optional (headless mode works without it) |