@nathapp/nax 0.27.1 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (383) hide show
  1. package/CHANGELOG.md +13 -2
  2. package/dist/nax.js +72691 -0
  3. package/package.json +12 -4
  4. package/src/cli/config.ts +42 -1
  5. package/src/cli/prompts.ts +18 -6
  6. package/src/config/defaults.ts +2 -0
  7. package/src/config/schemas.ts +11 -0
  8. package/src/config/types.ts +8 -0
  9. package/src/context/builder.ts +10 -1
  10. package/src/pipeline/stages/execution.ts +5 -0
  11. package/src/pipeline/stages/prompt.ts +13 -4
  12. package/src/precheck/checks-warnings.ts +37 -0
  13. package/src/precheck/checks.ts +1 -0
  14. package/src/precheck/index.ts +14 -7
  15. package/src/prompts/builder.ts +178 -0
  16. package/src/prompts/index.ts +2 -0
  17. package/src/prompts/loader.ts +43 -0
  18. package/src/prompts/sections/conventions.ts +15 -0
  19. package/src/prompts/sections/index.ts +11 -0
  20. package/src/prompts/sections/isolation.ts +24 -0
  21. package/src/prompts/sections/role-task.ts +34 -0
  22. package/src/prompts/sections/story.ts +13 -0
  23. package/src/prompts/sections/verdict.ts +70 -0
  24. package/src/prompts/templates/implementer.ts +6 -0
  25. package/src/prompts/templates/single-session.ts +6 -0
  26. package/src/prompts/templates/test-writer.ts +6 -0
  27. package/src/prompts/templates/verifier.ts +6 -0
  28. package/src/prompts/types.ts +21 -0
  29. package/src/review/runner.ts +6 -1
  30. package/src/tdd/session-runner.ts +12 -12
  31. package/src/version.ts +2 -1
  32. package/.claude/rules/01-project-conventions.md +0 -34
  33. package/.claude/rules/02-test-architecture.md +0 -39
  34. package/.claude/rules/03-test-writing.md +0 -58
  35. package/.claude/rules/04-forbidden-patterns.md +0 -29
  36. package/.claude/settings.json +0 -15
  37. package/.githooks/pre-commit +0 -16
  38. package/.gitlab-ci.yml +0 -103
  39. package/.mcp.json +0 -8
  40. package/BRIEF.md +0 -140
  41. package/CLAUDE.md +0 -143
  42. package/US-007-IMPLEMENTATION.md +0 -139
  43. package/biome.json +0 -14
  44. package/bun.lock +0 -163
  45. package/bunfig.toml +0 -12
  46. package/docker-compose.test.yml +0 -15
  47. package/docs/20260216-fix-plan-context-review.md +0 -56
  48. package/docs/20260216-relentless-vs-ngent-comparison.md +0 -208
  49. package/docs/20260216-v02-plan.md +0 -136
  50. package/docs/20260216-v02-review.md +0 -685
  51. package/docs/20260217-dogfood-findings.md +0 -56
  52. package/docs/20260217-p2-plus-plan.md +0 -117
  53. package/docs/20260217-partial-fixes-plan.md +0 -62
  54. package/docs/20260217-plan-analyze-spec.md +0 -117
  55. package/docs/20260217-post-impl-review.md +0 -1137
  56. package/docs/20260217-quick-wins-plan.md +0 -66
  57. package/docs/20260217-split-runner-plan.md +0 -75
  58. package/docs/20260217-v03-impl-plan.md +0 -80
  59. package/docs/20260217-v03-post-impl-review.md +0 -589
  60. package/docs/20260217-v04-impl-plan.md +0 -86
  61. package/docs/20260217-v05-post-impl-review.md +0 -850
  62. package/docs/20260217-v06-post-impl-review.md +0 -817
  63. package/docs/20260218-adr003-port-plan.md +0 -151
  64. package/docs/20260218-review-adr003-verification.md +0 -175
  65. package/docs/20260219-fix-plan-bug16-19.md +0 -79
  66. package/docs/20260219-fix-plan-bug20-22.md +0 -114
  67. package/docs/20260219-plan-llm-routing.md +0 -116
  68. package/docs/20260219-review-bug20-22-fixes.md +0 -135
  69. package/docs/20260219-routing-baseline-keyword.md +0 -63
  70. package/docs/20260220-plan-structured-logging-p1.md +0 -80
  71. package/docs/20260220-plan-structured-logging-p2.md +0 -37
  72. package/docs/20260220-review-llm-routing.md +0 -180
  73. package/docs/20260220-review-post-fix-llm-routing.md +0 -70
  74. package/docs/20260221-fix-plan-relevantfiles-split.md +0 -101
  75. package/docs/20260221-fix-plan-routing-mode.md +0 -125
  76. package/docs/20260221-review-v0.9-implementation.md +0 -379
  77. package/docs/20260222-fix-plan-v091-routing-isolation.md +0 -197
  78. package/docs/20260223-fix-plan-prompt-audit.md +0 -62
  79. package/docs/20260224-nax-roadmap-phases.md +0 -189
  80. package/docs/20260225-phase2-llm-service-layer.md +0 -401
  81. package/docs/20260225-review-v0.10.1.md +0 -187
  82. package/docs/20260303-v010-implementation-plan.md +0 -165
  83. package/docs/20260304-review-nax.md +0 -492
  84. package/docs/CLAUDE.md.bak +0 -191
  85. package/docs/ROADMAP.md +0 -364
  86. package/docs/SPEC-rectification.md +0 -0
  87. package/docs/SPEC.md +0 -324
  88. package/docs/US-001-plugin-loading-verification.md +0 -152
  89. package/docs/adr/ADR-005-implementation-plan.md +0 -655
  90. package/docs/adr/ADR-005-pipeline-re-architecture.md +0 -464
  91. package/docs/architecture-analysis.md +0 -1076
  92. package/docs/bugs/BUG-21-escalation-null-attempts.md +0 -48
  93. package/docs/bugs-from-dogfood-run-c.md +0 -243
  94. package/docs/code-review-20260228.md +0 -612
  95. package/docs/code-review-v0.15.0.md +0 -629
  96. package/docs/hook-lifecycle-test-plan.md +0 -149
  97. package/docs/releases/v0.11.0-and-earlier.md +0 -20
  98. package/docs/releases/v0.12.0.md +0 -15
  99. package/docs/releases/v0.13.0.md +0 -14
  100. package/docs/releases/v0.14.0.md +0 -20
  101. package/docs/releases/v0.14.1.md +0 -36
  102. package/docs/releases/v0.14.2.md +0 -51
  103. package/docs/releases/v0.14.3.md +0 -174
  104. package/docs/releases/v0.14.4.md +0 -94
  105. package/docs/releases/v0.15.0.md +0 -502
  106. package/docs/releases/v0.15.1.md +0 -170
  107. package/docs/releases/v0.15.3.md +0 -193
  108. package/docs/specs/bug-039-orphan-processes.md +0 -131
  109. package/docs/specs/bug-040-review-rectification.md +0 -82
  110. package/docs/specs/bug-041-cross-story-test-isolation.md +0 -88
  111. package/docs/specs/bug-042-verifier-failure-capture.md +0 -117
  112. package/docs/specs/bun-pty-migration.md +0 -171
  113. package/docs/specs/central-run-registry.md +0 -116
  114. package/docs/specs/feat-010-smart-runner-git-history.md +0 -96
  115. package/docs/specs/feat-011-file-context-strategy.md +0 -73
  116. package/docs/specs/feat-012-tdd-writer-tier.md +0 -79
  117. package/docs/specs/feat-013-test-after-review.md +0 -89
  118. package/docs/specs/feat-014-heartbeat-observability.md +0 -127
  119. package/docs/specs/status-file-consolidation.md +0 -93
  120. package/docs/specs/status-file-v0.10.1.md +0 -812
  121. package/docs/specs/trigger-completion.md +0 -145
  122. package/docs/specs/verification-architecture-v2.md +0 -343
  123. package/docs/tdd/strategies.md +0 -97
  124. package/docs/v0.10-global-config.md +0 -206
  125. package/docs/v0.10-plugin-system.md +0 -415
  126. package/docs/v0.10-prompt-optimizer.md +0 -234
  127. package/docs/v0.3-spec.md +0 -244
  128. package/docs/v0.4-spec.md +0 -140
  129. package/docs/v0.5-spec.md +0 -237
  130. package/docs/v0.6-spec.md +0 -371
  131. package/docs/v0.7-spec.md +0 -177
  132. package/docs/v0.8-llm-routing.md +0 -206
  133. package/docs/v0.8-structured-logging.md +0 -132
  134. package/docs/v0.9.3-prompt-audit.md +0 -112
  135. package/examples/plugins/console-reporter/index.test.ts +0 -207
  136. package/examples/plugins/console-reporter/index.ts +0 -110
  137. package/memory/topic/feat-010-baseref.md +0 -28
  138. package/memory/topic/feat-013-test-after-deprecation.md +0 -22
  139. package/nax/config.json +0 -154
  140. package/nax/features/bug-039-medium/prd.json +0 -45
  141. package/nax/features/bugfix-v0171/prd.json +0 -52
  142. package/nax/features/central-run-registry/prd.json +0 -105
  143. package/nax/features/config-management/prd.json +0 -108
  144. package/nax/features/config-management/progress.txt +0 -5
  145. package/nax/features/diagnose/acceptance.test.ts +0 -414
  146. package/nax/features/diagnose/prd.json +0 -41
  147. package/nax/features/nax-compliance/prd.json +0 -52
  148. package/nax/features/nax-compliance/progress.txt +0 -1
  149. package/nax/features/orchestration-fixes/prd.json +0 -89
  150. package/nax/features/orchestration-fixes/progress.txt +0 -1
  151. package/nax/features/plugin-integration/US-007-VERIFICATION.md +0 -259
  152. package/nax/features/plugin-integration/prd.json +0 -208
  153. package/nax/features/plugin-integration/progress.txt +0 -5
  154. package/nax/features/post-rearch-bugfix/prd.json +0 -137
  155. package/nax/features/precheck/prd.json +0 -205
  156. package/nax/features/precheck/progress.txt +0 -15
  157. package/nax/features/review-quality/prd.json +0 -55
  158. package/nax/features/routing-persistence/prd.json +0 -104
  159. package/nax/features/routing-persistence/progress.txt +0 -1
  160. package/nax/features/smart-test-runner/plan.md +0 -7
  161. package/nax/features/smart-test-runner/prd.json +0 -203
  162. package/nax/features/smart-test-runner/progress.txt +0 -13
  163. package/nax/features/smart-test-runner/spec.md +0 -7
  164. package/nax/features/smart-test-runner/tasks.md +0 -8
  165. package/nax/features/status-file-consolidation/prd.json +0 -106
  166. package/nax/features/structured-logging/prd.json +0 -199
  167. package/nax/features/trigger-completion/prd.json +0 -150
  168. package/nax/features/trigger-completion/progress.txt +0 -7
  169. package/nax/features/unlock/prd.json +0 -36
  170. package/nax/features/v0.18.3-execution-reliability/prd.json +0 -80
  171. package/nax/features/v0.18.3-execution-reliability/progress.txt +0 -3
  172. package/nax/features/v0.19.0-hardening/plan.md +0 -7
  173. package/nax/features/v0.19.0-hardening/prd.json +0 -84
  174. package/nax/features/v0.19.0-hardening/progress.txt +0 -7
  175. package/nax/features/v0.19.0-hardening/spec.md +0 -18
  176. package/nax/features/v0.19.0-hardening/tasks.md +0 -8
  177. package/nax/features/verify-v2/prd.json +0 -79
  178. package/nax/features/verify-v2/progress.txt +0 -3
  179. package/nax/status.json +0 -36
  180. package/test/COVERAGE-GAPS.md +0 -333
  181. package/test/e2e/cm-003-default-view.test.ts +0 -195
  182. package/test/e2e/plan-analyze-run.test.ts +0 -902
  183. package/test/helpers/helpers.test.ts +0 -295
  184. package/test/helpers/timeout.ts +0 -42
  185. package/test/integration/US-002-TEST-SUMMARY.md +0 -107
  186. package/test/integration/US-003-TEST-SUMMARY.md +0 -149
  187. package/test/integration/US-004-TEST-SUMMARY.md +0 -106
  188. package/test/integration/US-005-TEST-SUMMARY.md +0 -138
  189. package/test/integration/US-007-TEST-SUMMARY.md +0 -100
  190. package/test/integration/cli/agent-validation.test.ts +0 -439
  191. package/test/integration/cli/cli-config-default-edge-cases.test.ts +0 -223
  192. package/test/integration/cli/cli-config-default-view.test.ts +0 -230
  193. package/test/integration/cli/cli-config-diff.test.ts +0 -461
  194. package/test/integration/cli/cli-config.test.ts +0 -737
  195. package/test/integration/cli/cli-diagnose.test.ts +0 -595
  196. package/test/integration/cli/cli-logs.test.ts +0 -346
  197. package/test/integration/cli/cli-plugins.test.ts +0 -679
  198. package/test/integration/cli/cli-precheck.test.ts +0 -372
  199. package/test/integration/cli/cli-run-headless.test.ts +0 -174
  200. package/test/integration/cli/cli.test.ts +0 -76
  201. package/test/integration/cli/precheck-integration.test.ts +0 -476
  202. package/test/integration/cli/precheck-orchestrator.test.ts +0 -247
  203. package/test/integration/cli/precheck.test.ts +0 -806
  204. package/test/integration/config/config-loader.test.ts +0 -266
  205. package/test/integration/config/config.test.ts +0 -444
  206. package/test/integration/config/merger.test.ts +0 -466
  207. package/test/integration/config/paths.test.ts +0 -52
  208. package/test/integration/config/security-loader.test.ts +0 -83
  209. package/test/integration/context/context-integration.test.ts +0 -703
  210. package/test/integration/context/context-path-security.test.ts +0 -173
  211. package/test/integration/context/context-provider-injection.test.ts +0 -507
  212. package/test/integration/context/context-verification-integration.test.ts +0 -296
  213. package/test/integration/context/s5-greenfield-fallback.test.ts +0 -298
  214. package/test/integration/execution/execution-isolation.test.ts +0 -143
  215. package/test/integration/execution/execution.test.ts +0 -634
  216. package/test/integration/execution/feature-status-write.test.ts +0 -302
  217. package/test/integration/execution/parallel.test.ts +0 -251
  218. package/test/integration/execution/prd-pause.test.ts +0 -205
  219. package/test/integration/execution/prd-resolvers.test.ts +0 -186
  220. package/test/integration/execution/progress.test.ts +0 -34
  221. package/test/integration/execution/runner-batching.test.ts +0 -682
  222. package/test/integration/execution/runner-config-plugins.test.ts +0 -462
  223. package/test/integration/execution/runner-escalation.test.ts +0 -561
  224. package/test/integration/execution/runner-fixes.test.ts +0 -400
  225. package/test/integration/execution/runner-plugin-integration.test.ts +0 -544
  226. package/test/integration/execution/runner-queue-and-attempts.test.ts +0 -476
  227. package/test/integration/execution/status-file-integration.test.ts +0 -289
  228. package/test/integration/execution/status-file.test.ts +0 -380
  229. package/test/integration/execution/status-writer.test.ts +0 -447
  230. package/test/integration/execution/story-id-in-events.test.ts +0 -274
  231. package/test/integration/interaction/interaction-chain-pipeline.test.ts +0 -476
  232. package/test/integration/pipeline/hooks.test.ts +0 -363
  233. package/test/integration/pipeline/pipeline-acceptance.test.ts +0 -303
  234. package/test/integration/pipeline/pipeline-events.test.ts +0 -476
  235. package/test/integration/pipeline/pipeline.test.ts +0 -660
  236. package/test/integration/pipeline/reporter-lifecycle.test.ts +0 -862
  237. package/test/integration/pipeline/verify-stage.test.ts +0 -286
  238. package/test/integration/plan/analyze-integration.test.ts +0 -262
  239. package/test/integration/plan/analyze-scanner.test.ts +0 -132
  240. package/test/integration/plan/logger.test.ts +0 -461
  241. package/test/integration/plan/plan.test.ts +0 -157
  242. package/test/integration/plugins/config-integration.test.ts +0 -173
  243. package/test/integration/plugins/config-resolution.test.ts +0 -523
  244. package/test/integration/plugins/loader.test.ts +0 -644
  245. package/test/integration/plugins/plugins-registry.test.ts +0 -747
  246. package/test/integration/plugins/validator.test.ts +0 -564
  247. package/test/integration/review/review-config-commands.test.ts +0 -320
  248. package/test/integration/review/review-config-schema.test.ts +0 -117
  249. package/test/integration/review/review-plugin-integration.test.ts +0 -729
  250. package/test/integration/review/review.test.ts +0 -150
  251. package/test/integration/routing/plugin-routing-advanced.test.ts +0 -461
  252. package/test/integration/routing/plugin-routing-core.test.ts +0 -527
  253. package/test/integration/routing/routing-stage-bug-021.test.ts +0 -275
  254. package/test/integration/routing/routing-stage-greenfield.test.ts +0 -287
  255. package/test/integration/tdd/tdd-cleanup.test.ts +0 -246
  256. package/test/integration/tdd/tdd-orchestrator-core.test.ts +0 -565
  257. package/test/integration/tdd/tdd-orchestrator-failureCategory.test.ts +0 -355
  258. package/test/integration/tdd/tdd-orchestrator-fallback.test.ts +0 -311
  259. package/test/integration/tdd/tdd-orchestrator-lite.test.ts +0 -289
  260. package/test/integration/tdd/tdd-orchestrator-prompts.test.ts +0 -260
  261. package/test/integration/tdd/tdd-orchestrator-verdict.test.ts +0 -536
  262. package/test/integration/tmp/headless-test/test.jsonl +0 -30
  263. package/test/integration/verification/test-scanner.test.ts +0 -403
  264. package/test/integration/verification/verification-asset-check.test.ts +0 -143
  265. package/test/integration/worktree/manager.test.ts +0 -218
  266. package/test/integration/worktree/worktree-merge.test.ts +0 -341
  267. package/test/manual/logging-formatter-demo.ts +0 -158
  268. package/test/ui/tui-agent-panel.test.tsx +0 -99
  269. package/test/ui/tui-pty-integration.test.tsx +0 -146
  270. package/test/unit/acceptance.test.ts +0 -187
  271. package/test/unit/agent-stderr-capture.test.ts +0 -147
  272. package/test/unit/agents/claude.test.ts +0 -107
  273. package/test/unit/analyze-classifier.test.ts +0 -216
  274. package/test/unit/analyze.test.ts +0 -224
  275. package/test/unit/auto-detect.test.ts +0 -250
  276. package/test/unit/cli-status-project-level.test.ts +0 -283
  277. package/test/unit/cli-status.test.ts +0 -418
  278. package/test/unit/commands/common.test.ts +0 -321
  279. package/test/unit/commands/logs.test.ts +0 -458
  280. package/test/unit/commands/runs.test.ts +0 -303
  281. package/test/unit/commands/unlock.test.ts +0 -320
  282. package/test/unit/config/defaults.test.ts +0 -70
  283. package/test/unit/config/quality-commands-schema.test.ts +0 -72
  284. package/test/unit/config/regression-gate-schema.test.ts +0 -160
  285. package/test/unit/config/smart-runner-flag.test.ts +0 -250
  286. package/test/unit/constitution-generators.test.ts +0 -161
  287. package/test/unit/constitution.test.ts +0 -210
  288. package/test/unit/context/context-autodetect.test.ts +0 -297
  289. package/test/unit/context/context-build.test.ts +0 -575
  290. package/test/unit/context/context-coverage.test.ts +0 -236
  291. package/test/unit/context/context-error.test.ts +0 -93
  292. package/test/unit/context/context-estimate-tokens.test.ts +0 -201
  293. package/test/unit/context/context-format.test.ts +0 -302
  294. package/test/unit/context/context-isolation.test.ts +0 -267
  295. package/test/unit/context/context-sort.test.ts +0 -93
  296. package/test/unit/context/context-story.test.ts +0 -108
  297. package/test/unit/context/prior-failures.test.ts +0 -463
  298. package/test/unit/context.test.ts +0 -1726
  299. package/test/unit/cost.test.ts +0 -231
  300. package/test/unit/crash-recovery.test.ts +0 -309
  301. package/test/unit/escalation.test.ts +0 -127
  302. package/test/unit/execution/lifecycle/run-completion.test.ts +0 -240
  303. package/test/unit/execution/lifecycle/run-regression.test.ts +0 -420
  304. package/test/unit/execution/pid-registry.test.ts +0 -241
  305. package/test/unit/execution/sequential-executor.test.ts +0 -235
  306. package/test/unit/execution/sfc-004-dead-code-cleanup.test.ts +0 -89
  307. package/test/unit/execution/structured-failure.test.ts +0 -415
  308. package/test/unit/execution-logging-stderr.test.ts +0 -157
  309. package/test/unit/execution-stage.test.ts +0 -123
  310. package/test/unit/fix-generator.test.ts +0 -276
  311. package/test/unit/formatters.test.ts +0 -468
  312. package/test/unit/greenfield.test.ts +0 -180
  313. package/test/unit/hooks/shell-security.test.ts +0 -40
  314. package/test/unit/interaction/auto-plugin.test.ts +0 -162
  315. package/test/unit/interaction/human-review-trigger.test.ts +0 -165
  316. package/test/unit/interaction-network-failures.test.ts +0 -390
  317. package/test/unit/interaction-plugins.test.ts +0 -472
  318. package/test/unit/logging/formatter.test.ts +0 -456
  319. package/test/unit/merge.test.ts +0 -269
  320. package/test/unit/metrics/aggregator.test.ts +0 -164
  321. package/test/unit/metrics/tracker.test.ts +0 -186
  322. package/test/unit/metrics.test.ts +0 -276
  323. package/test/unit/optimizer/noop.optimizer.test.ts +0 -125
  324. package/test/unit/optimizer/rule-based.optimizer.test.ts +0 -358
  325. package/test/unit/pipeline/event-bus.test.ts +0 -105
  326. package/test/unit/pipeline/routing-partial-override.test.ts +0 -121
  327. package/test/unit/pipeline/runner-retry.test.ts +0 -89
  328. package/test/unit/pipeline/stages/autofix.test.ts +0 -97
  329. package/test/unit/pipeline/stages/completion-review-gate.test.ts +0 -218
  330. package/test/unit/pipeline/stages/execution-ambiguity.test.ts +0 -311
  331. package/test/unit/pipeline/stages/execution-merge-conflict.test.ts +0 -218
  332. package/test/unit/pipeline/stages/rectify.test.ts +0 -101
  333. package/test/unit/pipeline/stages/regression-stage.test.ts +0 -69
  334. package/test/unit/pipeline/stages/review.test.ts +0 -201
  335. package/test/unit/pipeline/stages/routing-idempotence.test.ts +0 -139
  336. package/test/unit/pipeline/stages/routing-initial-complexity.test.ts +0 -321
  337. package/test/unit/pipeline/stages/routing-persistence.test.ts +0 -380
  338. package/test/unit/pipeline/stages/verify.test.ts +0 -267
  339. package/test/unit/pipeline/subscribers/events-writer.test.ts +0 -227
  340. package/test/unit/pipeline/subscribers/hooks.test.ts +0 -84
  341. package/test/unit/pipeline/subscribers/interaction.test.ts +0 -313
  342. package/test/unit/pipeline/subscribers/registry.test.ts +0 -149
  343. package/test/unit/pipeline/subscribers/reporters.test.ts +0 -90
  344. package/test/unit/pipeline/verify-smart-runner.test.ts +0 -345
  345. package/test/unit/prd-auto-default.test.ts +0 -291
  346. package/test/unit/prd-failure-category.test.ts +0 -177
  347. package/test/unit/prd-get-next-story.test.ts +0 -215
  348. package/test/unit/precheck-checks.test.ts +0 -841
  349. package/test/unit/precheck-story-size-gate.test.ts +0 -288
  350. package/test/unit/precheck-types.test.ts +0 -143
  351. package/test/unit/prompts.test.ts +0 -476
  352. package/test/unit/queue.test.ts +0 -237
  353. package/test/unit/rectification.test.ts +0 -285
  354. package/test/unit/registry.test.ts +0 -288
  355. package/test/unit/review/runner.test.ts +0 -117
  356. package/test/unit/routing/content-hash.test.ts +0 -99
  357. package/test/unit/routing/routing-stability.test.ts +0 -208
  358. package/test/unit/routing/strategies/llm.test.ts +0 -306
  359. package/test/unit/routing-advanced.test.ts +0 -313
  360. package/test/unit/routing-core.test.ts +0 -341
  361. package/test/unit/routing-strategies.test.ts +0 -440
  362. package/test/unit/storyid-events.test.ts +0 -213
  363. package/test/unit/tdd-verdict.test.ts +0 -492
  364. package/test/unit/test-output-parser.test.ts +0 -377
  365. package/test/unit/ui/tui-controls.test.ts +0 -335
  366. package/test/unit/ui/tui-cost-and-pty.test.ts +0 -190
  367. package/test/unit/ui/tui-layout.test.ts +0 -379
  368. package/test/unit/ui/tui-stories.test.ts +0 -333
  369. package/test/unit/unit-isolation.test.ts +0 -135
  370. package/test/unit/utils/git.test.ts +0 -50
  371. package/test/unit/utils/path-security.test.ts +0 -47
  372. package/test/unit/utils-helpers.test.ts +0 -318
  373. package/test/unit/verdict.test.ts +0 -325
  374. package/test/unit/verification/orchestrator-types.test.ts +0 -54
  375. package/test/unit/verification/orchestrator.test.ts +0 -66
  376. package/test/unit/verification/smart-runner-config.test.ts +0 -163
  377. package/test/unit/verification/smart-runner-discovery.test.ts +0 -354
  378. package/test/unit/verification/smart-runner.test.ts +0 -262
  379. package/test/unit/verification/strategies/acceptance.test.ts +0 -33
  380. package/test/unit/verification/strategies/regression.test.ts +0 -87
  381. package/test/unit/verification/strategies/scoped.test.ts +0 -100
  382. package/test/unit/worktree-manager.test.ts +0 -159
  383. package/tsconfig.json +0 -27
@@ -1,295 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, test } from "bun:test";
2
- import { mkdirSync, rmSync } from "node:fs";
3
- import path from "node:path";
4
- import { spawn } from "bun";
5
- import { acquireLock, formatProgress, releaseLock } from "../../src/execution/helpers";
6
- import type { StoryCounts } from "../../src/execution/helpers";
7
-
8
- describe("formatProgress", () => {
9
- test("formats progress with all stories pending", () => {
10
- const counts: StoryCounts = {
11
- total: 12,
12
- passed: 0,
13
- failed: 0,
14
- pending: 12,
15
- };
16
-
17
- const progress = formatProgress(counts, 0, 5.0, 0, 12);
18
-
19
- expect(progress).toContain("0/12 stories");
20
- expect(progress).toContain("0 passed");
21
- expect(progress).toContain("0 failed");
22
- expect(progress).toContain("$0.00/$5.00");
23
- expect(progress).toContain("calculating...");
24
- });
25
-
26
- test("formats progress with some stories completed", () => {
27
- const counts: StoryCounts = {
28
- total: 12,
29
- passed: 5,
30
- failed: 1,
31
- pending: 6,
32
- };
33
-
34
- // 10 minutes elapsed (600000 ms), 6 stories completed
35
- // avg = 600000 / 6 = 100000 ms per story
36
- // remaining = 6 stories * 100000 = 600000 ms = 10 minutes
37
- const progress = formatProgress(counts, 0.45, 5.0, 600000, 12);
38
-
39
- expect(progress).toContain("6/12 stories");
40
- expect(progress).toContain("5 passed");
41
- expect(progress).toContain("1 failed");
42
- expect(progress).toContain("$0.45/$5.00");
43
- expect(progress).toContain("~10 min remaining");
44
- });
45
-
46
- test("formats progress when all stories are complete", () => {
47
- const counts: StoryCounts = {
48
- total: 12,
49
- passed: 10,
50
- failed: 2,
51
- pending: 0,
52
- };
53
-
54
- const progress = formatProgress(counts, 1.23, 5.0, 1200000, 12);
55
-
56
- expect(progress).toContain("12/12 stories");
57
- expect(progress).toContain("10 passed");
58
- expect(progress).toContain("2 failed");
59
- expect(progress).toContain("$1.23/$5.00");
60
- expect(progress).toContain("complete");
61
- });
62
-
63
- test("calculates ETA correctly for fast stories", () => {
64
- const counts: StoryCounts = {
65
- total: 20,
66
- passed: 10,
67
- failed: 0,
68
- pending: 10,
69
- };
70
-
71
- // 2 minutes elapsed (120000 ms) for 10 stories
72
- // avg = 120000 / 10 = 12000 ms per story
73
- // remaining = 10 stories * 12000 = 120000 ms = 2 minutes
74
- const progress = formatProgress(counts, 0.5, 10.0, 120000, 20);
75
-
76
- expect(progress).toContain("~2 min remaining");
77
- });
78
-
79
- test("rounds ETA to nearest minute", () => {
80
- const counts: StoryCounts = {
81
- total: 10,
82
- passed: 3,
83
- failed: 0,
84
- pending: 7,
85
- };
86
-
87
- // 8.5 minutes elapsed (510000 ms) for 3 stories
88
- // avg = 510000 / 3 = 170000 ms per story
89
- // remaining = 7 stories * 170000 = 1190000 ms ≈ 19.8 minutes → rounds to 20
90
- const progress = formatProgress(counts, 0.3, 5.0, 510000, 10);
91
-
92
- expect(progress).toContain("~20 min remaining");
93
- });
94
-
95
- test("includes cost information with proper formatting", () => {
96
- const counts: StoryCounts = {
97
- total: 5,
98
- passed: 2,
99
- failed: 0,
100
- pending: 3,
101
- };
102
-
103
- const progress = formatProgress(counts, 1.2345, 10.0, 300000, 5);
104
-
105
- // Should round cost to 2 decimal places
106
- expect(progress).toContain("$1.23/$10.00");
107
- });
108
-
109
- test("handles zero elapsed time gracefully", () => {
110
- const counts: StoryCounts = {
111
- total: 10,
112
- passed: 0,
113
- failed: 0,
114
- pending: 10,
115
- };
116
-
117
- const progress = formatProgress(counts, 0, 5.0, 0, 10);
118
-
119
- expect(progress).toContain("calculating...");
120
- expect(progress).not.toContain("NaN");
121
- expect(progress).not.toContain("Infinity");
122
- });
123
-
124
- test("includes all required progress indicators", () => {
125
- const counts: StoryCounts = {
126
- total: 10,
127
- passed: 3,
128
- failed: 1,
129
- pending: 6,
130
- };
131
-
132
- const progress = formatProgress(counts, 0.5, 5.0, 300000, 10);
133
-
134
- expect(progress).toContain("Progress:");
135
- expect(progress).toContain("passed");
136
- expect(progress).toContain("failed");
137
- expect(progress).toContain("$");
138
- expect(progress).toContain("min remaining");
139
- });
140
- });
141
-
142
- describe("acquireLock and releaseLock", () => {
143
- const testDir = path.join(import.meta.dir, ".test-locks");
144
- const lockPath = path.join(testDir, "nax.lock");
145
-
146
- beforeEach(() => {
147
- // Create clean test directory
148
- rmSync(testDir, { recursive: true, force: true });
149
- mkdirSync(testDir, { recursive: true });
150
- });
151
-
152
- afterEach(() => {
153
- // Clean up test directory
154
- rmSync(testDir, { recursive: true, force: true });
155
- });
156
-
157
- test("acquires lock when no lock file exists", async () => {
158
- const acquired = await acquireLock(testDir);
159
- expect(acquired).toBe(true);
160
-
161
- // Verify lock file was created
162
- const lockFile = Bun.file(lockPath);
163
- expect(await lockFile.exists()).toBe(true);
164
-
165
- // Verify lock file contains current PID
166
- const lockContent = await lockFile.text();
167
- const lockData = JSON.parse(lockContent);
168
- expect(lockData.pid).toBe(process.pid);
169
- expect(typeof lockData.timestamp).toBe("number");
170
-
171
- await releaseLock(testDir);
172
- });
173
-
174
- test("fails to acquire lock when another process holds it", async () => {
175
- // First process acquires lock
176
- const acquired1 = await acquireLock(testDir);
177
- expect(acquired1).toBe(true);
178
-
179
- // Second process tries to acquire lock
180
- const acquired2 = await acquireLock(testDir);
181
- expect(acquired2).toBe(false);
182
-
183
- await releaseLock(testDir);
184
- });
185
-
186
- test("releases lock successfully", async () => {
187
- await acquireLock(testDir);
188
- await releaseLock(testDir);
189
-
190
- // Verify lock file was deleted
191
- const lockFile = Bun.file(lockPath);
192
- expect(await lockFile.exists()).toBe(false);
193
- });
194
-
195
- test("can re-acquire lock after release", async () => {
196
- const acquired1 = await acquireLock(testDir);
197
- expect(acquired1).toBe(true);
198
-
199
- await releaseLock(testDir);
200
-
201
- const acquired2 = await acquireLock(testDir);
202
- expect(acquired2).toBe(true);
203
-
204
- await releaseLock(testDir);
205
- });
206
-
207
- test("removes stale lock when process is dead", async () => {
208
- // Create a lock file with a fake PID that doesn't exist
209
- const stalePid = 999999; // Very unlikely to be a real process
210
- const staleLock = {
211
- pid: stalePid,
212
- timestamp: Date.now() - 60000, // 1 minute ago
213
- };
214
- await Bun.write(lockPath, JSON.stringify(staleLock));
215
-
216
- // Try to acquire lock - should detect stale lock and remove it
217
- const acquired = await acquireLock(testDir);
218
- expect(acquired).toBe(true);
219
-
220
- // Verify new lock file has current PID
221
- const lockFile = Bun.file(lockPath);
222
- const lockContent = await lockFile.text();
223
- const lockData = JSON.parse(lockContent);
224
- expect(lockData.pid).toBe(process.pid);
225
-
226
- await releaseLock(testDir);
227
- });
228
-
229
- test("detects stale lock from OOM-killed process", async () => {
230
- // Spawn a short-lived child process
231
- const proc = spawn({
232
- cmd: ["sleep", "0.1"],
233
- stdout: "pipe",
234
- stderr: "pipe",
235
- });
236
-
237
- // Get the child PID
238
- const childPid = proc.pid;
239
-
240
- // Wait for it to exit
241
- await proc.exited;
242
-
243
- // Create a lock file with the dead child's PID
244
- const staleLock = {
245
- pid: childPid,
246
- timestamp: Date.now() - 60000, // 1 minute ago
247
- };
248
- await Bun.write(lockPath, JSON.stringify(staleLock));
249
-
250
- // Now try to acquire lock - should detect child process is dead
251
- const acquired = await acquireLock(testDir);
252
- expect(acquired).toBe(true);
253
-
254
- // Verify new lock has current PID
255
- const lockFile = Bun.file(lockPath);
256
- const lockContent = await lockFile.text();
257
- const lockData = JSON.parse(lockContent);
258
- expect(lockData.pid).toBe(process.pid);
259
-
260
- await releaseLock(testDir);
261
- });
262
-
263
- test("does not remove lock when process is still alive", async () => {
264
- // Create lock with current process PID
265
- const validLock = {
266
- pid: process.pid,
267
- timestamp: Date.now() - 60000, // 1 minute ago
268
- };
269
- await Bun.write(lockPath, JSON.stringify(validLock));
270
-
271
- // Try to acquire lock - should NOT remove it since process is alive
272
- const acquired = await acquireLock(testDir);
273
- expect(acquired).toBe(false);
274
-
275
- // Verify lock still exists with same PID
276
- const lockFile = Bun.file(lockPath);
277
- const lockContent = await lockFile.text();
278
- const lockData = JSON.parse(lockContent);
279
- expect(lockData.pid).toBe(process.pid);
280
- });
281
-
282
- test("handles corrupted lock file gracefully", async () => {
283
- // Create invalid JSON lock file
284
- await Bun.write(lockPath, "not valid json");
285
-
286
- // Should treat corrupt lock as stale and acquire successfully
287
- const acquired = await acquireLock(testDir);
288
- expect(acquired).toBe(true);
289
- });
290
-
291
- test("handles release when lock file doesn't exist", async () => {
292
- // Should not throw when releasing non-existent lock
293
- await expect(releaseLock(testDir)).resolves.toBeUndefined();
294
- });
295
- });
@@ -1,42 +0,0 @@
1
- /**
2
- * Test Timeout Helpers
3
- *
4
- * Utilities to prevent tests from hanging indefinitely.
5
- */
6
-
7
- /**
8
- * Wraps a promise with a hard timeout.
9
- * If the promise doesn't resolve within the timeout, rejects with a timeout error.
10
- *
11
- * @param promise The promise to wrap
12
- * @param timeoutMs Timeout in milliseconds
13
- * @param operation Description of the operation (for error messages)
14
- * @returns The promise result if it completes in time
15
- * @throws TimeoutError if the timeout is exceeded
16
- */
17
- export async function withTimeout<T>(promise: Promise<T>, timeoutMs: number, operation = "Operation"): Promise<T> {
18
- return Promise.race([
19
- promise,
20
- new Promise<T>((_, reject) =>
21
- setTimeout(() => reject(new Error(`${operation} timed out after ${timeoutMs}ms`)), timeoutMs),
22
- ),
23
- ]);
24
- }
25
-
26
- /**
27
- * Wraps a function call with a hard timeout.
28
- * Useful for wrapping synchronous or async functions that might hang.
29
- *
30
- * @param fn The function to execute
31
- * @param timeoutMs Timeout in milliseconds
32
- * @param operation Description of the operation (for error messages)
33
- * @returns The function result if it completes in time
34
- * @throws TimeoutError if the timeout is exceeded
35
- */
36
- export async function executeWithTimeout<T>(
37
- fn: () => Promise<T> | T,
38
- timeoutMs: number,
39
- operation = "Operation",
40
- ): Promise<T> {
41
- return withTimeout(Promise.resolve(fn()), timeoutMs, operation);
42
- }
@@ -1,107 +0,0 @@
1
- # US-002 Test Summary: Context Provider Injection
2
-
3
- ## Overview
4
- Created comprehensive test suite for US-002 that verifies context providers inject external data into agent prompts with proper token budget management.
5
-
6
- ## Test File
7
- - **Location**: `test/integration/context-provider-injection.test.ts`
8
- - **Total Tests**: 20
9
- - **Passing**: 14 (features already implemented)
10
- - **Failing**: 6 (features not yet implemented)
11
-
12
- ## Test Coverage by Acceptance Criteria
13
-
14
- ### ✅ AC1: All registered context providers are called before agent execution
15
- **Status**: All tests passing (feature implemented)
16
- - ✓ Calls all registered context providers
17
- - ✓ Providers receive the current story
18
- - ✓ Works with no providers registered
19
-
20
- ### ✅ AC2: Provider content appended under markdown section with label
21
- **Status**: All tests passing (feature implemented)
22
- - ✓ Appends provider content under labeled markdown section
23
- - ✓ Multiple providers create separate labeled sections
24
- - ✓ Provider content appended to existing context markdown
25
-
26
- ### ❌ AC3: Total injected tokens respect token budget
27
- **Status**: 4 tests failing (feature NOT implemented correctly)
28
-
29
- **Issue**: Current implementation uses hardcoded `PLUGIN_CONTEXT_MAX_TOKENS = 20_000` instead of reading from `config.execution.contextProviderTokenBudget`
30
-
31
- Failing tests:
32
- - ✗ Respects default token budget of 2000 tokens when not configured
33
- - ✗ Respects custom token budget from config
34
- - ✗ Providers added in order until budget exhausted
35
- - ✗ Single provider exceeding budget is skipped
36
-
37
- ### ✅ AC4: Provider errors caught, logged, and skipped
38
- **Status**: All tests passing (feature implemented)
39
- - ✓ Continues when a provider throws error
40
- - ✓ Handles all providers failing gracefully
41
- - ✓ Error in one provider doesn't affect others
42
-
43
- ### ❌ AC5: Token budget configurable via execution.contextProviderTokenBudget
44
- **Status**: 2 tests failing (feature NOT implemented)
45
-
46
- **Issue**:
47
- 1. `ExecutionConfig` type doesn't include `contextProviderTokenBudget` field
48
- 2. `DEFAULT_CONFIG` doesn't set default value of 2000 tokens
49
- 3. Context stage uses hardcoded value instead of reading from config
50
-
51
- Failing tests:
52
- - ✗ Default config includes contextProviderTokenBudget with default of 2000
53
- - ✗ Different projects can have different token budgets
54
-
55
- ## Implementation Gaps
56
-
57
- ### 1. Config Schema Missing Field
58
- **File**: `src/config/schema.ts`
59
- - Add `contextProviderTokenBudget: number` to `ExecutionConfig` interface
60
- - Add validation in `ExecutionConfigSchema` (Zod)
61
- - Set default value of 2000 in `DEFAULT_CONFIG.execution`
62
-
63
- ### 2. Context Stage Uses Hardcoded Value
64
- **File**: `src/pipeline/stages/context.ts`
65
- - Line 32: `const PLUGIN_CONTEXT_MAX_TOKENS = 20_000;` (hardcoded)
66
- - Should read from: `ctx.config.execution.contextProviderTokenBudget`
67
- - Lines 62, 72: Replace `PLUGIN_CONTEXT_MAX_TOKENS` with config value
68
-
69
- ## Test Execution
70
-
71
- ```bash
72
- # Run US-002 tests only
73
- bun test ./test/integration/context-provider-injection.test.ts
74
-
75
- # Current results:
76
- # 14 pass, 6 fail, 46 expect() calls
77
- ```
78
-
79
- ## Next Steps for Implementer
80
-
81
- 1. **Update ExecutionConfig interface** (src/config/schema.ts):
82
- - Add `contextProviderTokenBudget: number` field
83
- - Add Zod validation: `z.number().int().min(100).max(100000).default(2000)`
84
- - Add to DEFAULT_CONFIG: `contextProviderTokenBudget: 2000`
85
-
86
- 2. **Update context stage** (src/pipeline/stages/context.ts):
87
- - Remove hardcoded `PLUGIN_CONTEXT_MAX_TOKENS` constant
88
- - Read budget from `ctx.config.execution.contextProviderTokenBudget`
89
- - Use configured value in budget checks (lines 62, 72)
90
-
91
- 3. **Verify all tests pass**:
92
- ```bash
93
- bun test ./test/integration/context-provider-injection.test.ts
94
- ```
95
-
96
- ## Coverage Notes
97
-
98
- The test suite covers:
99
- - ✓ Provider registration and invocation
100
- - ✓ Markdown formatting with labels
101
- - ✓ Error handling and soft failures
102
- - ✓ Token budget enforcement (with config)
103
- - ✓ Multi-provider orchestration
104
- - ✓ Integration with existing PRD context
105
- - ✓ Built context element tracking
106
-
107
- All edge cases are covered per acceptance criteria.
@@ -1,149 +0,0 @@
1
- # US-003 Test Summary: Review Plugins Run After Built-in Verification
2
-
3
- **Story ID:** US-003
4
- **Date:** 2026-02-27
5
- **Status:** ✅ PASSED
6
- **Test File:** `test/integration/review-plugin-integration.test.ts`
7
-
8
- ## Overview
9
-
10
- This test suite verifies that plugin reviewers are correctly integrated into the review pipeline stage, running after built-in checks and triggering appropriate retry/escalation on failure.
11
-
12
- ## Test Results
13
-
14
- **Total Tests:** 19
15
- **Passed:** 19
16
- **Failed:** 0
17
- **Success Rate:** 100%
18
-
19
- ## Acceptance Criteria Coverage
20
-
21
- ### ✅ AC1: Plugin reviewers run after built-in checks pass
22
-
23
- | Test | Status |
24
- |------|--------|
25
- | Plugin reviewers execute when built-in checks pass | ✅ PASS |
26
- | Plugin reviewers do not run if built-in checks fail | ✅ PASS |
27
- | No plugin reviewers registered - continues normally | ✅ PASS |
28
-
29
- **Verification:** Plugin reviewers only execute after built-in checks succeed, preventing unnecessary work when code quality gates fail.
30
-
31
- ### ✅ AC2: Each reviewer receives workdir and changed files
32
-
33
- | Test | Status |
34
- |------|--------|
35
- | Reviewer receives correct workdir | ✅ PASS |
36
- | Reviewer receives list of changed files | ✅ PASS |
37
- | Reviewer receives empty array when no files changed | ✅ PASS |
38
-
39
- **Verification:** Reviewers receive accurate context about the working directory and which files were modified, enabling targeted analysis.
40
-
41
- ### ✅ AC3: Reviewer failure triggers retry/escalation
42
-
43
- | Test | Status |
44
- |------|--------|
45
- | Failing reviewer returns fail action | ✅ PASS |
46
- | Reviewer failure includes plugin name in reason | ✅ PASS |
47
-
48
- **Verification:** When a plugin reviewer fails, the pipeline returns a `fail` action with the plugin name in the failure reason, triggering the same retry/escalation logic as built-in check failures.
49
-
50
- ### ✅ AC4: Reviewer output included in story result
51
-
52
- | Test | Status |
53
- |------|--------|
54
- | Passing reviewer output is captured | ✅ PASS |
55
- | Failing reviewer output is captured | ✅ PASS |
56
-
57
- **Verification:** All reviewer outputs (success and failure) are stored in `ctx.reviewResult.pluginReviewers`, providing debugging information and audit trail.
58
-
59
- ### ✅ AC5: Exceptions count as failures
60
-
61
- | Test | Status |
62
- |------|--------|
63
- | Reviewer throwing exception counts as failure | ✅ PASS |
64
- | Exception message captured in output | ✅ PASS |
65
- | Non-Error exception converted to string | ✅ PASS |
66
-
67
- **Verification:** When a reviewer throws an exception, it's treated as a failure with the error message captured for debugging. The pipeline correctly handles both Error objects and primitive throws.
68
-
69
- ### ✅ AC6: Multiple reviewers run sequentially with short-circuiting
70
-
71
- | Test | Status |
72
- |------|--------|
73
- | Multiple reviewers run in order when all pass | ✅ PASS |
74
- | First failure short-circuits remaining reviewers | ✅ PASS |
75
- | Exception short-circuits remaining reviewers | ✅ PASS |
76
-
77
- **Verification:** Reviewers execute sequentially in registration order. When one fails (or throws), subsequent reviewers are skipped, providing fail-fast behavior.
78
-
79
- ### ✅ Edge Cases
80
-
81
- | Test | Status |
82
- |------|--------|
83
- | No plugins context - continues normally | ✅ PASS |
84
- | Reviewer returns empty output | ✅ PASS |
85
- | Reviewer without exitCode works | ✅ PASS |
86
-
87
- **Verification:** The implementation handles edge cases gracefully: missing plugin context, empty output strings, and optional exitCode field.
88
-
89
- ## Implementation Verification
90
-
91
- ### Key Files Modified
92
-
93
- 1. **`src/pipeline/stages/review.ts`**
94
- - Lines 77-155: Plugin reviewer execution logic
95
- - Lines 35-53: `getChangedFiles()` helper function
96
- - Correctly integrates plugin reviewers after built-in checks
97
-
98
- 2. **`src/review/types.ts`**
99
- - Lines 26-38: `PluginReviewerResult` interface
100
- - Line 51: Extended `ReviewResult` with `pluginReviewers` field
101
-
102
- 3. **`test/integration/review-plugin-integration.test.ts`**
103
- - 722 lines of comprehensive test coverage
104
- - Mock plugins and reviewers for isolated testing
105
- - Git repository setup for realistic changed file detection
106
-
107
- ### Type Safety
108
-
109
- - ✅ All TypeScript types correctly defined
110
- - ✅ No type errors (`bun run typecheck` passes)
111
- - ✅ Proper type guards and assertions
112
-
113
- ### Error Handling
114
-
115
- - ✅ Exceptions caught and converted to failures
116
- - ✅ Error messages preserved for debugging
117
- - ✅ Non-Error throws handled correctly
118
- - ✅ Missing optional fields handled safely
119
-
120
- ### Integration Points
121
-
122
- - ✅ Integrates with `PluginRegistry.getReviewers()`
123
- - ✅ Uses existing pipeline context structure
124
- - ✅ Follows established patterns from built-in checks
125
- - ✅ Compatible with retry/escalation logic
126
-
127
- ## Performance Considerations
128
-
129
- - Reviewers run sequentially (not parallel) to prevent resource contention
130
- - Fail-fast behavior minimizes wasted computation
131
- - Changed files retrieved once and reused for all reviewers
132
- - No unnecessary git operations or file system scans
133
-
134
- ## Conclusion
135
-
136
- **US-003 is fully implemented and verified.** All acceptance criteria are met with comprehensive test coverage. The implementation follows the codebase patterns, handles edge cases gracefully, and integrates seamlessly with the existing plugin system architecture.
137
-
138
- ## Test Execution
139
-
140
- ```bash
141
- $ bun test test/integration/review-plugin-integration.test.ts
142
-
143
- 19 pass
144
- 0 fail
145
- 51 expect() calls
146
- Ran 19 tests across 1 file. [1.71s]
147
- ```
148
-
149
- **Final Status:** ✅ READY FOR PRODUCTION
@@ -1,106 +0,0 @@
1
- # US-004: Reporter plugins receive lifecycle events — Test Summary
2
-
3
- **Status:** ✅ PASSED
4
- **Date:** 2026-02-27
5
- **Commit:** 26181a1
6
-
7
- ## Overview
8
-
9
- This story implements reporter lifecycle events that fire at appropriate points in the runner loop. All reporter calls are fire-and-forget (errors logged, never block pipeline).
10
-
11
- ## Implementation Summary
12
-
13
- ### Changes Made
14
-
15
- 1. **Moved PRD initialization** (runner.ts:205)
16
- - Moved `prd` declaration before try block to make it accessible in finally block
17
- - Ensures `prd` is available for onRunEnd event even on failure/abort
18
-
19
- 2. **Consolidated onRunEnd calls** (runner.ts:1417-1439)
20
- - Moved onRunEnd reporter events to finally block
21
- - Removed duplicate calls from success paths (parallel and sequential)
22
- - Guarantees onRunEnd fires even when run fails or is aborted
23
-
24
- 3. **Added dry-run onStoryComplete events** (runner.ts:666-684)
25
- - Added missing onStoryComplete events for dry-run mode
26
- - Ensures reporters receive events consistently across all execution modes
27
-
28
- ### Key Design Decisions
29
-
30
- - **Finally block placement**: onRunEnd must fire even on exceptions, so it's placed in the finally block before teardown and lock release
31
- - **Error isolation**: Each reporter call is wrapped in try/catch to prevent one reporter's failure from affecting others
32
- - **Event ordering**: onRunEnd fires before plugin teardown to ensure reporters can still access plugin state
33
-
34
- ## Test Results
35
-
36
- All 9 tests in `test/integration/reporter-lifecycle.test.ts` pass:
37
-
38
- ### AC1: onRunStart fires once at run start ✅
39
- - Verified event contains: runId, feature, totalStories, startTime
40
- - Verified event fires exactly once per run
41
-
42
- ### AC2: onStoryComplete fires after each story ✅
43
- - Verified event contains: runId, storyId, status, durationMs, cost, tier, testStrategy
44
- - Verified event fires for each story execution (including dry-run)
45
- - Verified correct status values (completed, failed, skipped, paused)
46
-
47
- ### AC3: onRunEnd fires once at run end ✅
48
- - Verified event contains: runId, totalDurationMs, totalCost, storySummary
49
- - Verified storySummary contains: completed, failed, skipped, paused counts
50
- - Verified correct counts match PRD state
51
-
52
- ### AC4: Reporter errors never block execution ✅
53
- - Verified failing reporter doesn't abort run
54
- - Verified run completes successfully despite reporter errors
55
- - Verified errors are logged (not thrown)
56
-
57
- ### AC5: Multiple reporters all receive events ✅
58
- - Verified two reporters both receive onRunStart, onStoryComplete, onRunEnd
59
- - Verified second reporter receives events even if first reporter fails
60
- - Verified no short-circuiting on error (all reporters always execute)
61
-
62
- ### AC6: Events fire even when run fails or is aborted ✅
63
- - Verified onRunStart and onRunEnd fire when stories are pre-failed
64
- - Verified onRunEnd fires in finally block (even on exception)
65
- - Verified storySummary reflects actual failure state
66
-
67
- ## Additional Test Coverage
68
-
69
- - **onStoryComplete for different outcomes**: Verified events for completed, failed, skipped, paused stories
70
- - **Multiple stories**: Verified consistent runId across all events in same run
71
- - **Dry-run mode**: Verified reporters receive events in dry-run mode
72
-
73
- ## Verification Command
74
-
75
- ```bash
76
- bun test test/integration/reporter-lifecycle.test.ts
77
- ```
78
-
79
- **Result:** 9 pass, 0 fail, 48 expect() calls
80
-
81
- ## Integration with Existing Code
82
-
83
- - **US-001 (Plugin loading)**: Uses pluginRegistry.getReporters() to retrieve all loaded reporters
84
- - **US-002 (Context provider injection)**: No conflicts, reporters operate independently
85
- - **US-003 (Review plugins)**: No conflicts, different lifecycle hooks
86
-
87
- ## Notes
88
-
89
- - Reporter events are fire-and-forget by design
90
- - All reporter methods are optional (IReporter interface)
91
- - Reporter errors are logged at WARN level (not ERROR) since they're non-critical
92
- - onRunEnd always fires in finally block, even if try block throws
93
- - PRD must be accessible in finally block, so it's initialized before try
94
-
95
- ## Acceptance Criteria Status
96
-
97
- | AC | Description | Status |
98
- |----|-------------|--------|
99
- | 1 | onRunStart fires once at run start with runId, feature, totalStories, startTime | ✅ |
100
- | 2 | onStoryComplete fires after each story with storyId, status, durationMs, cost, tier, testStrategy | ✅ |
101
- | 3 | onRunEnd fires once at run end with runId, totalDurationMs, totalCost, storySummary counts | ✅ |
102
- | 4 | Reporter errors are caught and logged but never block execution | ✅ |
103
- | 5 | Multiple reporters all receive events (not short-circuited on error) | ✅ |
104
- | 6 | Events fire even when the run fails or is aborted (onRunEnd still fires) | ✅ |
105
-
106
- **Overall Status:** ✅ ALL ACCEPTANCE CRITERIA MET