@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,206 @@
1
+ # v0.10 — Global + Project Config Layering
2
+
3
+ **Status:** Draft
4
+ **Author:** Subrina
5
+ **Date:** 2026-03-03
6
+ **Base:** v0.9.3
7
+ **Issue:** #14
8
+
9
+ ## Overview
10
+
11
+ Introduce a global `~/.nax/` directory for user-wide defaults. Project-level `nax/` overrides global via deep merge. Hooks concatenate (global fires first, then project).
12
+
13
+ ## Motivation
14
+
15
+ - Users repeat the same config across projects (model mappings, cost limits, hooks)
16
+ - No way to set personal defaults without copy-pasting `nax/config.json`
17
+ - Notification hooks (Telegram, Slack) are user-level, not project-level
18
+ - Constitution rules often have a universal component ("always strict TypeScript") plus project-specific additions
19
+
20
+ ## Directory Structure
21
+
22
+ ```
23
+ ~/.nax/ # Global (user-wide)
24
+ config.json # Global defaults
25
+ constitution.md # Global coding standards
26
+ hooks/
27
+ on-complete.sh # Fires after every run
28
+ on-error.sh # Fires on story failure
29
+ on-pause.sh # Fires when story pauses
30
+ on-start.sh # Fires when run starts
31
+
32
+ <project>/nax/ # Project (existing, unchanged)
33
+ config.json # Project overrides
34
+ constitution.md # Project-specific rules
35
+ hooks/
36
+ on-complete.sh # Project-specific hooks
37
+ features/
38
+ <feature>/prd.json
39
+ ```
40
+
41
+ ## Merge Strategy
42
+
43
+ ### Config: Deep Merge (project wins)
44
+
45
+ ```
46
+ global config.json + project config.json = effective config
47
+ ───────────────── ──────────────────── ────────────────
48
+ { { {
49
+ "models": { "models": { "models": {
50
+ "fast": "haiku", "fast": "flash" "fast": "flash", ← project wins
51
+ "balanced": "sonnet", "balanced": "sonnet", ← from global
52
+ "powerful": "opus" "powerful": "opus" ← from global
53
+ }, }, },
54
+ "execution": { "execution": { "execution": {
55
+ "costLimit": 5.0, "costLimit": 2.0 "costLimit": 2.0, ← project wins
56
+ "sessionTimeout": 600 "sessionTimeout": 600 ← from global
57
+ } } }
58
+ } } }
59
+ ```
60
+
61
+ Rules:
62
+ - Objects are recursively merged; project values override global at the leaf level
63
+ - Arrays are **replaced** (not concatenated) — e.g., `escalation.tierOrder` from project fully replaces global
64
+ - `null` in project explicitly removes a global key
65
+ - Missing sections in project inherit from global as-is
66
+
67
+ ### Hooks: Concatenate (global first, then project)
68
+
69
+ ```
70
+ Effective hook execution order:
71
+ 1. ~/.nax/hooks/on-complete.sh (if exists)
72
+ 2. <project>/nax/hooks/on-complete.sh (if exists)
73
+ ```
74
+
75
+ - Both fire independently — global hook failure does NOT block project hook
76
+ - Each hook receives the same environment variables (run metadata, exit code, cost, etc.)
77
+ - To skip global hooks for a project, set `"hooks": { "skipGlobal": true }` in project config
78
+
79
+ ### Constitution: Concatenate (global first, then project)
80
+
81
+ ```
82
+ Effective constitution:
83
+ 1. ~/.nax/constitution.md content
84
+ 2. ---
85
+ 3. <project>/nax/constitution.md content
86
+ ```
87
+
88
+ - Global constitution prepended to project constitution with `---` separator
89
+ - To skip global constitution, set `"constitution": { "skipGlobal": true }` in project config
90
+
91
+ ## Config Resolution Order
92
+
93
+ ```
94
+ 1. Built-in defaults (hardcoded in schema.ts)
95
+ 2. ~/.nax/config.json (global)
96
+ 3. <project>/nax/config.json (project)
97
+ 4. CLI flags (--cost-limit, --model, etc.) — highest priority
98
+ ```
99
+
100
+ ## Global Config Scope
101
+
102
+ All existing config sections are valid at global level:
103
+
104
+ | Section | Global Use Case |
105
+ |:--------|:----------------|
106
+ | `models` | Default model mappings (your API keys, preferred providers) |
107
+ | `autoMode` | Default complexity→tier routing and escalation budgets |
108
+ | `routing` | Preferred routing strategy (llm vs keyword) |
109
+ | `execution` | Default cost limit, session timeout, verification timeout |
110
+ | `quality` | Default stripEnvVars, forceExit |
111
+ | `tdd` | Default session tiers, testWriterAllowedPaths |
112
+ | `constitution` | Path (always relative to `~/.nax/`) |
113
+ | `context` | Default test coverage detail level and token budget |
114
+ | `acceptance` | Default enabled/disabled |
115
+ | `hooks` | Global hook directory path |
116
+ | `analyze` | Default LLM-enhanced analysis settings |
117
+
118
+ ## New Config Fields
119
+
120
+ ```typescript
121
+ // Added to NaxConfig (or a new GlobalConfig extending it)
122
+ interface HooksConfig {
123
+ /** Skip global hooks for this project */
124
+ skipGlobal?: boolean;
125
+ /** Hook directory path (default: "hooks/" relative to config dir) */
126
+ dir?: string;
127
+ }
128
+
129
+ interface ConstitutionConfig {
130
+ /** Path to constitution file (relative to config dir) */
131
+ path?: string;
132
+ /** Skip global constitution for this project */
133
+ skipGlobal?: boolean;
134
+ }
135
+ ```
136
+
137
+ ## Implementation
138
+
139
+ ### File Structure
140
+
141
+ ```
142
+ src/config/
143
+ schema.ts # Add HooksConfig, ConstitutionConfig schemas
144
+ loader.ts # Modify: load global → project → merge
145
+ merger.ts # NEW: deep merge logic with concatenation rules
146
+ paths.ts # NEW: resolve ~/.nax/ and project nax/ paths
147
+ ```
148
+
149
+ ### Key Functions
150
+
151
+ ```typescript
152
+ // paths.ts
153
+ export function globalConfigDir(): string; // ~/.nax/
154
+ export function projectConfigDir(): string; // <cwd>/nax/
155
+
156
+ // merger.ts
157
+ export function mergeConfigs(global: Partial<NaxConfig>, project: Partial<NaxConfig>): NaxConfig;
158
+
159
+ // loader.ts (modified)
160
+ export async function loadConfig(options?: { projectDir?: string }): Promise<NaxConfig> {
161
+ const defaults = getDefaults();
162
+ const global = await loadConfigFile(globalConfigDir());
163
+ const project = await loadConfigFile(projectConfigDir(options?.projectDir));
164
+ return mergeConfigs(defaults, mergeConfigs(global, project));
165
+ }
166
+ ```
167
+
168
+ ### `nax init --global`
169
+
170
+ New flag to initialize `~/.nax/`:
171
+
172
+ ```bash
173
+ nax init --global
174
+ # Creates:
175
+ # ~/.nax/config.json (with commented examples)
176
+ # ~/.nax/constitution.md (empty template)
177
+ # ~/.nax/hooks/ (empty directory)
178
+ ```
179
+
180
+ Existing `nax init` (without `--global`) continues to initialize project-level `nax/`.
181
+
182
+ ## User Stories
183
+
184
+ | # | Title | Complexity | Est. LOC | Dependencies |
185
+ |:--|:------|:-----------|:---------|:-------------|
186
+ | US-001 | Config paths resolver (`~/.nax/` + project `nax/`) | simple | 40 | — |
187
+ | US-002 | Deep merge utility with array-replace and null-remove semantics | simple | 60 | — |
188
+ | US-003 | Update `loadConfig()` to load global → project → merge | medium | 80 | US-001, US-002 |
189
+ | US-004 | Hook concatenation (global + project, independent execution) | medium | 100 | US-001, US-003 |
190
+ | US-005 | Constitution concatenation with `skipGlobal` support | simple | 50 | US-001, US-003 |
191
+ | US-006 | `nax init --global` command | simple | 60 | US-001 |
192
+ | US-007 | Update Zod schema for HooksConfig and ConstitutionConfig | simple | 40 | — |
193
+
194
+ ## Design Decisions
195
+
196
+ 1. **Deep merge over section replace** — more intuitive; users only override what they change
197
+ 2. **Hooks concatenate, arrays replace** — hooks are additive (notification + CI); config arrays like `tierOrder` are intentional overrides
198
+ 3. **`skipGlobal` opt-out** — simple boolean rather than complex inheritance rules
199
+ 4. **Global first in concatenation** — global rules are "baseline", project adds specifics
200
+ 5. **`null` removes keys** — explicit opt-out mechanism for global defaults you don't want in a specific project
201
+ 6. **CLI flags beat everything** — one-off overrides without touching files
202
+ 7. **No `nax config show`** — defer to v0.11; users can check effective config via `nax prompts` audit
203
+
204
+ ---
205
+
206
+ *Draft — pending William's review.*
@@ -0,0 +1,415 @@
1
+ # v0.10 — Plugin System
2
+
3
+ **Status:** Draft
4
+ **Author:** Subrina
5
+ **Date:** 2026-03-03
6
+ **Base:** v0.9.3
7
+ **Issue:** #14 (bundled with global config)
8
+
9
+ ## Overview
10
+
11
+ A lightweight plugin system that lets developers extend nax with custom optimizers, routing strategies, review checks, context providers, reporters, and agent adapters. Plugins are plain JS/TS modules that export a `NaxPlugin` object.
12
+
13
+ ## Motivation
14
+
15
+ - Prompt optimization, routing, and review are already extensible in concept but hardcoded in practice
16
+ - Users want to integrate external tools (LLMLingua, Jira, security scanners) without forking nax
17
+ - nax has well-defined interfaces (`RoutingStrategy`, `AgentAdapter`, `ReviewConfig`) — plugins just need a standard way to register implementations
18
+ - Global plugins (in `~/.nax/plugins/`) apply to all projects; project plugins override or add
19
+
20
+ ## Plugin Interface
21
+
22
+ ```typescript
23
+ // src/plugins/types.ts
24
+
25
+ /**
26
+ * Extension point types that plugins can provide.
27
+ */
28
+ export type PluginType =
29
+ | "optimizer"
30
+ | "router"
31
+ | "agent"
32
+ | "reviewer"
33
+ | "context-provider"
34
+ | "reporter";
35
+
36
+ /**
37
+ * A nax plugin module.
38
+ *
39
+ * Plugins export a single NaxPlugin object (default or named export).
40
+ * Each plugin declares which extension points it provides and supplies
41
+ * the corresponding implementations.
42
+ */
43
+ export interface NaxPlugin {
44
+ /** Unique plugin name (e.g., "jira-context", "llmlingua-optimizer") */
45
+ name: string;
46
+
47
+ /** Plugin version (semver) */
48
+ version: string;
49
+
50
+ /** Which extension points this plugin provides */
51
+ provides: PluginType[];
52
+
53
+ /**
54
+ * Called once when plugin is loaded. Use for initialization,
55
+ * validating config, establishing connections, etc.
56
+ *
57
+ * @param config - Plugin-specific config from nax config.json
58
+ */
59
+ setup?(config: Record<string, unknown>): Promise<void>;
60
+
61
+ /**
62
+ * Called when the nax run ends (success or failure).
63
+ * Use for cleanup, closing connections, flushing buffers.
64
+ */
65
+ teardown?(): Promise<void>;
66
+
67
+ /**
68
+ * Extension implementations. Only the types listed in `provides`
69
+ * are required; others are ignored.
70
+ */
71
+ extensions: PluginExtensions;
72
+ }
73
+
74
+ export interface PluginExtensions {
75
+ /** Custom prompt optimizer */
76
+ optimizer?: IPromptOptimizer;
77
+
78
+ /** Custom routing strategy (inserted into the strategy chain) */
79
+ router?: RoutingStrategy;
80
+
81
+ /** Custom agent adapter (e.g., Codex, Gemini, Aider) */
82
+ agent?: AgentAdapter;
83
+
84
+ /** Custom review check (runs alongside built-in typecheck/lint/test) */
85
+ reviewer?: IReviewPlugin;
86
+
87
+ /** Custom context provider (injects external context into prompts) */
88
+ contextProvider?: IContextProvider;
89
+
90
+ /** Custom reporter (receives run events for dashboards, CI, etc.) */
91
+ reporter?: IReporter;
92
+ }
93
+ ```
94
+
95
+ ## Extension Point Interfaces
96
+
97
+ ### IPromptOptimizer (existing from optimizer spec)
98
+
99
+ ```typescript
100
+ // src/optimizer/types.ts (from v0.10-prompt-optimizer.md)
101
+ export interface IPromptOptimizer {
102
+ name: string;
103
+ optimize(input: PromptOptimizerInput): Promise<PromptOptimizerResult>;
104
+ }
105
+ ```
106
+
107
+ ### RoutingStrategy (existing)
108
+
109
+ ```typescript
110
+ // src/routing/strategy.ts (already exists in v0.9.3)
111
+ export interface RoutingStrategy {
112
+ readonly name: string;
113
+ route(story: UserStory, context: RoutingContext): RoutingDecision | null | Promise<RoutingDecision | null>;
114
+ }
115
+ ```
116
+
117
+ Plugin routers are inserted into the strategy chain **before** the built-in strategies. If a plugin router returns `null`, the chain continues to keyword/LLM/adaptive as normal.
118
+
119
+ ### AgentAdapter (existing)
120
+
121
+ ```typescript
122
+ // src/agents/types.ts (already exists in v0.9.3)
123
+ export interface AgentAdapter {
124
+ readonly name: string;
125
+ readonly displayName: string;
126
+ readonly binary: string;
127
+ readonly capabilities: AgentCapabilities;
128
+ isInstalled(): Promise<boolean>;
129
+ run(options: AgentRunOptions): Promise<AgentResult>;
130
+ buildCommand(options: AgentRunOptions): string[];
131
+ plan(options: PlanOptions): Promise<PlanResult>;
132
+ decompose(options: DecomposeOptions): Promise<DecomposeResult>;
133
+ runInteractive?(options: InteractiveRunOptions): PtyHandle;
134
+ }
135
+ ```
136
+
137
+ ### IReviewPlugin (new)
138
+
139
+ ```typescript
140
+ // src/plugins/types.ts
141
+ export interface IReviewPlugin {
142
+ /** Check name (e.g., "security-scan", "license-check") */
143
+ name: string;
144
+
145
+ /** Human-readable description */
146
+ description: string;
147
+
148
+ /**
149
+ * Run the review check against the working directory.
150
+ *
151
+ * @param workdir - Project root directory
152
+ * @param changedFiles - Files modified by the agent in this story
153
+ * @returns Review check result
154
+ */
155
+ check(workdir: string, changedFiles: string[]): Promise<ReviewCheckResult>;
156
+ }
157
+ ```
158
+
159
+ Review plugins run **after** built-in checks (typecheck, lint, test). A plugin check failure follows the same escalation/retry logic as built-in failures.
160
+
161
+ ### IContextProvider (new)
162
+
163
+ ```typescript
164
+ // src/plugins/types.ts
165
+ export interface IContextProvider {
166
+ /** Provider name (e.g., "jira", "linear", "confluence") */
167
+ name: string;
168
+
169
+ /**
170
+ * Fetch external context relevant to a story.
171
+ *
172
+ * @param story - The user story being executed
173
+ * @param config - Plugin-specific config
174
+ * @returns Markdown content to inject into the agent prompt
175
+ */
176
+ getContext(story: UserStory): Promise<ContextProviderResult>;
177
+ }
178
+
179
+ export interface ContextProviderResult {
180
+ /** Markdown content to inject */
181
+ content: string;
182
+ /** Token estimate for budget tracking */
183
+ estimatedTokens: number;
184
+ /** Section label in the prompt (e.g., "Jira Context") */
185
+ label: string;
186
+ }
187
+ ```
188
+
189
+ Context provider output is appended to the built context **after** the context stage, within the remaining token budget. If the budget is exceeded, provider content is truncated with a warning.
190
+
191
+ ### IReporter (new)
192
+
193
+ ```typescript
194
+ // src/plugins/types.ts
195
+ export interface IReporter {
196
+ /** Reporter name */
197
+ name: string;
198
+
199
+ /** Called when a run starts */
200
+ onRunStart?(run: RunStartEvent): Promise<void>;
201
+
202
+ /** Called when a story completes (success or failure) */
203
+ onStoryComplete?(event: StoryCompleteEvent): Promise<void>;
204
+
205
+ /** Called when a run ends */
206
+ onRunEnd?(run: RunEndEvent): Promise<void>;
207
+ }
208
+
209
+ export interface RunStartEvent {
210
+ runId: string;
211
+ feature: string;
212
+ totalStories: number;
213
+ startTime: string;
214
+ }
215
+
216
+ export interface StoryCompleteEvent {
217
+ runId: string;
218
+ storyId: string;
219
+ status: "completed" | "failed" | "skipped" | "paused";
220
+ durationMs: number;
221
+ cost: number;
222
+ tier: string;
223
+ testStrategy: string;
224
+ }
225
+
226
+ export interface RunEndEvent {
227
+ runId: string;
228
+ totalDurationMs: number;
229
+ totalCost: number;
230
+ storySummary: {
231
+ completed: number;
232
+ failed: number;
233
+ skipped: number;
234
+ paused: number;
235
+ };
236
+ }
237
+ ```
238
+
239
+ Reporter methods are fire-and-forget — failures are logged but never block the pipeline.
240
+
241
+ ## Plugin Loading
242
+
243
+ ### Resolution Order
244
+
245
+ ```
246
+ 1. ~/.nax/plugins/* (global plugins — apply to all projects)
247
+ 2. nax/plugins/* (project plugins — override or add)
248
+ 3. config.json plugins (explicit module paths)
249
+ ```
250
+
251
+ ### Config
252
+
253
+ ```json
254
+ {
255
+ "plugins": [
256
+ {
257
+ "module": "./nax/plugins/my-security-scanner",
258
+ "config": { "severity": "high" }
259
+ },
260
+ {
261
+ "module": "@nathapp/nax-plugin-jira",
262
+ "config": { "baseUrl": "https://jira.example.com", "project": "NAX" }
263
+ },
264
+ {
265
+ "module": "~/custom-optimizer",
266
+ "config": {}
267
+ }
268
+ ]
269
+ }
270
+ ```
271
+
272
+ ### Directory Convention
273
+
274
+ Plugins in `~/.nax/plugins/` or `nax/plugins/` are auto-discovered (no config entry needed):
275
+
276
+ ```
277
+ ~/.nax/plugins/
278
+ telegram-reporter/
279
+ index.ts # exports NaxPlugin
280
+ package.json # optional, for dependencies
281
+ security-scan.ts # single-file plugin
282
+ ```
283
+
284
+ ### Loader Logic
285
+
286
+ ```typescript
287
+ // src/plugins/loader.ts
288
+
289
+ /**
290
+ * Load and validate all plugins from global + project + config sources.
291
+ *
292
+ * 1. Scan ~/.nax/plugins/ (if exists)
293
+ * 2. Scan <project>/nax/plugins/ (if exists)
294
+ * 3. Load explicit modules from config.plugins[]
295
+ * 4. Validate each: must export name (string), version (string),
296
+ * provides (PluginType[]), and matching extensions
297
+ * 5. Call setup() on each with its config
298
+ * 6. Return PluginRegistry
299
+ */
300
+ export async function loadPlugins(
301
+ globalDir: string,
302
+ projectDir: string,
303
+ configPlugins: PluginConfigEntry[]
304
+ ): Promise<PluginRegistry>;
305
+ ```
306
+
307
+ ### Plugin Registry
308
+
309
+ ```typescript
310
+ // src/plugins/registry.ts
311
+
312
+ export class PluginRegistry {
313
+ /** All loaded plugins */
314
+ readonly plugins: ReadonlyArray<NaxPlugin>;
315
+
316
+ /** Get all optimizers (built-in + plugin) */
317
+ getOptimizers(): IPromptOptimizer[];
318
+
319
+ /** Get all routing strategies (plugin strategies, inserted before built-in) */
320
+ getRouters(): RoutingStrategy[];
321
+
322
+ /** Get agent adapter by name */
323
+ getAgent(name: string): AgentAdapter | undefined;
324
+
325
+ /** Get all review plugins */
326
+ getReviewers(): IReviewPlugin[];
327
+
328
+ /** Get all context providers */
329
+ getContextProviders(): IContextProvider[];
330
+
331
+ /** Get all reporters */
332
+ getReporters(): IReporter[];
333
+
334
+ /** Teardown all plugins */
335
+ async teardownAll(): Promise<void>;
336
+ }
337
+ ```
338
+
339
+ The registry is created once at run start and passed through the pipeline context.
340
+
341
+ ## Pipeline Integration
342
+
343
+ ```typescript
344
+ // PipelineContext additions
345
+ export interface PipelineContext {
346
+ // ... existing fields ...
347
+
348
+ /** Plugin registry (set by runner before pipeline starts) */
349
+ plugins?: PluginRegistry;
350
+ }
351
+ ```
352
+
353
+ ### Where Plugins Hook In
354
+
355
+ | Stage | Plugin Type | Integration |
356
+ |:------|:-----------|:------------|
357
+ | `routing` | `router` | Plugin strategies prepended to strategy chain |
358
+ | `context` | `context-provider` | Provider content appended after built context |
359
+ | `optimizer` (new) | `optimizer` | Plugin optimizer replaces or chains with built-in |
360
+ | `execution` | `agent` | Plugin agent selected by `config.agent` name |
361
+ | `review` | `reviewer` | Plugin checks run after built-in checks |
362
+ | Pipeline runner | `reporter` | Events fired at run start, story complete, run end |
363
+
364
+ ## Conflict Resolution
365
+
366
+ | Scenario | Behavior |
367
+ |:---------|:---------|
368
+ | Multiple optimizers | Only the **last** loaded optimizer is active (project overrides global). Log warning if multiple found. |
369
+ | Multiple routers | All router plugins are chained (in load order, before built-in). First non-null decision wins. |
370
+ | Multiple agents | All registered. Config `agent` field selects which one to use. Default: `claude-code`. |
371
+ | Multiple reviewers | All run (additive). Each produces independent results. |
372
+ | Multiple context providers | All run (additive). Combined output subject to token budget. |
373
+ | Multiple reporters | All run (additive). Independent, fire-and-forget. |
374
+ | Plugin name collision | Last loaded wins (project overrides global). Log warning. |
375
+
376
+ ## File Structure
377
+
378
+ ```
379
+ src/plugins/
380
+ types.ts # NaxPlugin, PluginType, extension interfaces
381
+ loader.ts # loadPlugins() — discover, import, validate
382
+ registry.ts # PluginRegistry class
383
+ validator.ts # validatePlugin() — runtime type checks
384
+ index.ts # Public API exports
385
+ ```
386
+
387
+ ## User Stories
388
+
389
+ | # | Title | Complexity | Est. LOC | Dependencies |
390
+ |:--|:------|:-----------|:---------|:-------------|
391
+ | US-001 | Define NaxPlugin interface and all extension point types | simple | 120 | — |
392
+ | US-002 | Plugin loader (directory scan + config modules + validation) | medium | 150 | US-001 |
393
+ | US-003 | PluginRegistry with typed getters and teardown | medium | 100 | US-001 |
394
+ | US-004 | Integrate plugin routers into routing strategy chain | simple | 50 | US-003 |
395
+ | US-005 | Integrate plugin reviewers into review stage | simple | 50 | US-003 |
396
+ | US-006 | Integrate context providers into context stage | medium | 80 | US-003 |
397
+ | US-007 | Reporter event emission from pipeline runner | medium | 80 | US-003 |
398
+ | US-008 | Add PluginRegistry to PipelineContext + runner initialization | simple | 40 | US-002, US-003 |
399
+ | US-009 | `nax plugins list` CLI command (show loaded plugins) | simple | 50 | US-002 |
400
+
401
+ ## Design Decisions
402
+
403
+ 1. **Plain module exports over class registration** — plugins are just objects with a known shape. No decorators, no base classes, no framework lock-in.
404
+ 2. **Auto-discovery + explicit config** — directory convention for convenience, config entries for control. Both work together.
405
+ 3. **Last-loaded-wins for singular types** (optimizer, agent) — keeps it simple. No complex priority systems.
406
+ 4. **Additive for plural types** (reviewer, reporter, context-provider, router) — more plugins = more capability.
407
+ 5. **Fire-and-forget reporters** — never block the pipeline for reporting failures.
408
+ 6. **Reuse existing interfaces** — `RoutingStrategy` and `AgentAdapter` already exist. Plugins just provide new implementations via the same contracts.
409
+ 7. **Plugin config in nax config.json** — no separate plugin config files. Each plugin gets a `config` object passed to `setup()`.
410
+ 8. **No hot-reload** — plugins are loaded once at run start. Restart to pick up changes.
411
+ 9. **v0.10 implements loader + registry + optimizer integration** — other extension point integrations (router, reviewer, context, reporter) are wired but implementations are community-driven.
412
+
413
+ ---
414
+
415
+ *Draft — pending William's review.*