@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.
- package/.gitlab-ci.yml +96 -0
- package/BRIEF.md +140 -0
- package/CHANGELOG.md +60 -0
- package/CLAUDE.md +159 -0
- package/README.md +373 -0
- package/US-007-IMPLEMENTATION.md +139 -0
- package/bin/nax.ts +930 -0
- package/biome.json +14 -0
- package/bun.lock +168 -0
- package/bunfig.toml +11 -0
- package/docs/20260216-fix-plan-context-review.md +56 -0
- package/docs/20260216-relentless-vs-ngent-comparison.md +208 -0
- package/docs/20260216-v02-plan.md +136 -0
- package/docs/20260216-v02-review.md +685 -0
- package/docs/20260217-dogfood-findings.md +56 -0
- package/docs/20260217-p2-plus-plan.md +117 -0
- package/docs/20260217-partial-fixes-plan.md +62 -0
- package/docs/20260217-plan-analyze-spec.md +117 -0
- package/docs/20260217-post-impl-review.md +1137 -0
- package/docs/20260217-quick-wins-plan.md +66 -0
- package/docs/20260217-split-runner-plan.md +75 -0
- package/docs/20260217-v03-impl-plan.md +80 -0
- package/docs/20260217-v03-post-impl-review.md +589 -0
- package/docs/20260217-v04-impl-plan.md +86 -0
- package/docs/20260217-v05-post-impl-review.md +850 -0
- package/docs/20260217-v06-post-impl-review.md +817 -0
- package/docs/20260218-adr003-port-plan.md +151 -0
- package/docs/20260218-review-adr003-verification.md +175 -0
- package/docs/20260219-fix-plan-bug16-19.md +79 -0
- package/docs/20260219-fix-plan-bug20-22.md +114 -0
- package/docs/20260219-plan-llm-routing.md +116 -0
- package/docs/20260219-review-bug20-22-fixes.md +135 -0
- package/docs/20260219-routing-baseline-keyword.md +63 -0
- package/docs/20260220-plan-structured-logging-p1.md +80 -0
- package/docs/20260220-plan-structured-logging-p2.md +37 -0
- package/docs/20260220-review-llm-routing.md +180 -0
- package/docs/20260220-review-post-fix-llm-routing.md +70 -0
- package/docs/20260221-fix-plan-relevantfiles-split.md +101 -0
- package/docs/20260221-fix-plan-routing-mode.md +125 -0
- package/docs/20260221-review-v0.9-implementation.md +379 -0
- package/docs/20260222-fix-plan-v091-routing-isolation.md +197 -0
- package/docs/20260223-fix-plan-prompt-audit.md +62 -0
- package/docs/20260224-nax-roadmap-phases.md +189 -0
- package/docs/20260225-phase2-llm-service-layer.md +401 -0
- package/docs/20260225-review-v0.10.1.md +187 -0
- package/docs/20260303-v010-implementation-plan.md +165 -0
- package/docs/CLAUDE.md.bak +191 -0
- package/docs/ROADMAP.md +165 -0
- package/docs/SPEC-rectification.md +0 -0
- package/docs/SPEC.md +324 -0
- package/docs/US-001-plugin-loading-verification.md +152 -0
- package/docs/architecture-analysis.md +1076 -0
- package/docs/bugs/BUG-21-escalation-null-attempts.md +48 -0
- package/docs/bugs-from-dogfood-run-c.md +243 -0
- package/docs/code-review-20260228.md +612 -0
- package/docs/code-review-v0.15.0.md +629 -0
- package/docs/hook-lifecycle-test-plan.md +149 -0
- package/docs/releases/v0.11.0-and-earlier.md +20 -0
- package/docs/releases/v0.12.0.md +15 -0
- package/docs/releases/v0.13.0.md +14 -0
- package/docs/releases/v0.14.0.md +20 -0
- package/docs/releases/v0.14.1.md +36 -0
- package/docs/releases/v0.14.2.md +51 -0
- package/docs/releases/v0.14.3.md +174 -0
- package/docs/releases/v0.14.4.md +94 -0
- package/docs/releases/v0.15.0.md +502 -0
- package/docs/releases/v0.15.1.md +170 -0
- package/docs/releases/v0.15.3.md +193 -0
- package/docs/specs/status-file-v0.10.1.md +812 -0
- package/docs/v0.10-global-config.md +206 -0
- package/docs/v0.10-plugin-system.md +415 -0
- package/docs/v0.10-prompt-optimizer.md +234 -0
- package/docs/v0.3-spec.md +244 -0
- package/docs/v0.4-spec.md +140 -0
- package/docs/v0.5-spec.md +237 -0
- package/docs/v0.6-spec.md +371 -0
- package/docs/v0.7-spec.md +177 -0
- package/docs/v0.8-llm-routing.md +206 -0
- package/docs/v0.8-structured-logging.md +132 -0
- package/docs/v0.9.3-prompt-audit.md +112 -0
- package/examples/plugins/console-reporter/index.test.ts +207 -0
- package/examples/plugins/console-reporter/index.ts +110 -0
- package/nax/config.json +147 -0
- package/nax/features/bugfix-v0171/prd.json +52 -0
- package/nax/features/config-management/prd.json +108 -0
- package/nax/features/config-management/progress.txt +5 -0
- package/nax/features/diagnose/acceptance.test.ts +412 -0
- package/nax/features/diagnose/prd.json +41 -0
- package/nax/features/orchestration-fixes/prd.json +89 -0
- package/nax/features/orchestration-fixes/progress.txt +1 -0
- package/nax/features/plugin-integration/US-007-VERIFICATION.md +259 -0
- package/nax/features/plugin-integration/prd.json +208 -0
- package/nax/features/plugin-integration/progress.txt +5 -0
- package/nax/features/precheck/prd.json +205 -0
- package/nax/features/precheck/progress.txt +15 -0
- package/nax/features/structured-logging/prd.json +199 -0
- package/nax/features/unlock/prd.json +36 -0
- package/package.json +47 -0
- package/src/acceptance/fix-generator.ts +348 -0
- package/src/acceptance/generator.ts +282 -0
- package/src/acceptance/index.ts +30 -0
- package/src/acceptance/types.ts +79 -0
- package/src/agents/claude-decompose.ts +169 -0
- package/src/agents/claude-plan.ts +139 -0
- package/src/agents/claude.ts +324 -0
- package/src/agents/cost.ts +268 -0
- package/src/agents/index.ts +13 -0
- package/src/agents/registry.ts +48 -0
- package/src/agents/types-extended.ts +133 -0
- package/src/agents/types.ts +113 -0
- package/src/agents/validation.ts +69 -0
- package/src/analyze/classifier.ts +305 -0
- package/src/analyze/index.ts +16 -0
- package/src/analyze/scanner.ts +175 -0
- package/src/analyze/types.ts +51 -0
- package/src/cli/accept.ts +108 -0
- package/src/cli/analyze-parser.ts +284 -0
- package/src/cli/analyze.ts +207 -0
- package/src/cli/config.ts +561 -0
- package/src/cli/constitution.ts +109 -0
- package/src/cli/diagnose-analysis.ts +159 -0
- package/src/cli/diagnose-formatter.ts +87 -0
- package/src/cli/diagnose.ts +203 -0
- package/src/cli/generate.ts +127 -0
- package/src/cli/index.ts +37 -0
- package/src/cli/init.ts +188 -0
- package/src/cli/interact.ts +295 -0
- package/src/cli/plan.ts +198 -0
- package/src/cli/plugins.ts +111 -0
- package/src/cli/prompts.ts +295 -0
- package/src/cli/runs.ts +174 -0
- package/src/cli/status-cost.ts +151 -0
- package/src/cli/status-features.ts +338 -0
- package/src/cli/status.ts +13 -0
- package/src/commands/common.ts +171 -0
- package/src/commands/diagnose.ts +17 -0
- package/src/commands/index.ts +8 -0
- package/src/commands/logs.ts +384 -0
- package/src/commands/precheck.ts +86 -0
- package/src/commands/unlock.ts +96 -0
- package/src/config/defaults.ts +160 -0
- package/src/config/index.ts +22 -0
- package/src/config/loader.ts +121 -0
- package/src/config/merger.ts +147 -0
- package/src/config/path-security.ts +121 -0
- package/src/config/paths.ts +27 -0
- package/src/config/schema.ts +56 -0
- package/src/config/schemas.ts +286 -0
- package/src/config/types.ts +423 -0
- package/src/config/validate.ts +103 -0
- package/src/constitution/generator.ts +191 -0
- package/src/constitution/generators/aider.ts +41 -0
- package/src/constitution/generators/claude.ts +35 -0
- package/src/constitution/generators/cursor.ts +36 -0
- package/src/constitution/generators/opencode.ts +38 -0
- package/src/constitution/generators/types.ts +33 -0
- package/src/constitution/generators/windsurf.ts +36 -0
- package/src/constitution/index.ts +10 -0
- package/src/constitution/loader.ts +133 -0
- package/src/constitution/types.ts +31 -0
- package/src/context/auto-detect.ts +227 -0
- package/src/context/builder.ts +246 -0
- package/src/context/elements.ts +83 -0
- package/src/context/formatter.ts +107 -0
- package/src/context/generator.ts +129 -0
- package/src/context/generators/aider.ts +34 -0
- package/src/context/generators/claude.ts +28 -0
- package/src/context/generators/cursor.ts +28 -0
- package/src/context/generators/opencode.ts +30 -0
- package/src/context/generators/windsurf.ts +28 -0
- package/src/context/greenfield.ts +114 -0
- package/src/context/index.ts +33 -0
- package/src/context/injector.ts +279 -0
- package/src/context/test-scanner.ts +370 -0
- package/src/context/types.ts +98 -0
- package/src/errors.ts +67 -0
- package/src/execution/batching.ts +157 -0
- package/src/execution/crash-recovery.ts +373 -0
- package/src/execution/escalation/escalation.ts +44 -0
- package/src/execution/escalation/index.ts +13 -0
- package/src/execution/escalation/tier-escalation.ts +295 -0
- package/src/execution/escalation/tier-outcome.ts +158 -0
- package/src/execution/helpers.ts +38 -0
- package/src/execution/index.ts +45 -0
- package/src/execution/lifecycle/acceptance-loop.ts +272 -0
- package/src/execution/lifecycle/headless-formatter.ts +85 -0
- package/src/execution/lifecycle/index.ts +12 -0
- package/src/execution/lifecycle/parallel-lifecycle.ts +101 -0
- package/src/execution/lifecycle/precheck-runner.ts +140 -0
- package/src/execution/lifecycle/run-cleanup.ts +81 -0
- package/src/execution/lifecycle/run-completion.ts +129 -0
- package/src/execution/lifecycle/run-initialization.ts +141 -0
- package/src/execution/lifecycle/run-lifecycle.ts +312 -0
- package/src/execution/lifecycle/run-setup.ts +204 -0
- package/src/execution/lifecycle/story-hooks.ts +38 -0
- package/src/execution/lifecycle/story-size-prompts.ts +123 -0
- package/src/execution/lock.ts +115 -0
- package/src/execution/parallel-executor.ts +216 -0
- package/src/execution/parallel.ts +400 -0
- package/src/execution/pid-registry.ts +280 -0
- package/src/execution/pipeline-result-handler.ts +388 -0
- package/src/execution/post-verify-rectification.ts +188 -0
- package/src/execution/post-verify.ts +274 -0
- package/src/execution/progress.ts +25 -0
- package/src/execution/prompts.ts +127 -0
- package/src/execution/queue-handler.ts +109 -0
- package/src/execution/rectification.ts +13 -0
- package/src/execution/runner.ts +377 -0
- package/src/execution/sequential-executor.ts +388 -0
- package/src/execution/status-file.ts +264 -0
- package/src/execution/status-writer.ts +139 -0
- package/src/execution/story-context.ts +229 -0
- package/src/execution/test-output-parser.ts +14 -0
- package/src/execution/verification.ts +72 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/runner.ts +286 -0
- package/src/hooks/types.ts +67 -0
- package/src/interaction/chain.ts +154 -0
- package/src/interaction/index.ts +60 -0
- package/src/interaction/init.ts +83 -0
- package/src/interaction/plugins/auto.ts +217 -0
- package/src/interaction/plugins/cli.ts +300 -0
- package/src/interaction/plugins/telegram.ts +384 -0
- package/src/interaction/plugins/webhook.ts +258 -0
- package/src/interaction/state.ts +171 -0
- package/src/interaction/triggers.ts +229 -0
- package/src/interaction/types.ts +163 -0
- package/src/logger/formatters.ts +84 -0
- package/src/logger/index.ts +16 -0
- package/src/logger/logger.ts +298 -0
- package/src/logger/types.ts +48 -0
- package/src/logging/formatter.ts +355 -0
- package/src/logging/index.ts +22 -0
- package/src/logging/types.ts +93 -0
- package/src/metrics/aggregator.ts +190 -0
- package/src/metrics/index.ts +14 -0
- package/src/metrics/tracker.ts +200 -0
- package/src/metrics/types.ts +109 -0
- package/src/optimizer/index.ts +62 -0
- package/src/optimizer/noop.optimizer.ts +24 -0
- package/src/optimizer/rule-based.optimizer.ts +248 -0
- package/src/optimizer/types.ts +53 -0
- package/src/pipeline/events.ts +130 -0
- package/src/pipeline/index.ts +19 -0
- package/src/pipeline/runner.ts +161 -0
- package/src/pipeline/stages/acceptance.ts +197 -0
- package/src/pipeline/stages/completion.ts +99 -0
- package/src/pipeline/stages/constitution.ts +63 -0
- package/src/pipeline/stages/context.ts +117 -0
- package/src/pipeline/stages/execution.ts +194 -0
- package/src/pipeline/stages/index.ts +62 -0
- package/src/pipeline/stages/optimizer.ts +74 -0
- package/src/pipeline/stages/prompt.ts +57 -0
- package/src/pipeline/stages/queue-check.ts +103 -0
- package/src/pipeline/stages/review.ts +181 -0
- package/src/pipeline/stages/routing.ts +81 -0
- package/src/pipeline/stages/verify.ts +100 -0
- package/src/pipeline/types.ts +167 -0
- package/src/plugins/index.ts +31 -0
- package/src/plugins/loader.ts +287 -0
- package/src/plugins/registry.ts +168 -0
- package/src/plugins/types.ts +327 -0
- package/src/plugins/validator.ts +352 -0
- package/src/prd/index.ts +172 -0
- package/src/prd/types.ts +202 -0
- package/src/precheck/checks-blockers.ts +391 -0
- package/src/precheck/checks-warnings.ts +142 -0
- package/src/precheck/checks.ts +30 -0
- package/src/precheck/index.ts +247 -0
- package/src/precheck/story-size-gate.ts +144 -0
- package/src/precheck/types.ts +31 -0
- package/src/queue/index.ts +2 -0
- package/src/queue/manager.ts +254 -0
- package/src/queue/types.ts +54 -0
- package/src/review/index.ts +8 -0
- package/src/review/runner.ts +172 -0
- package/src/review/types.ts +66 -0
- package/src/routing/builder.ts +81 -0
- package/src/routing/chain.ts +74 -0
- package/src/routing/index.ts +16 -0
- package/src/routing/loader.ts +58 -0
- package/src/routing/router.ts +303 -0
- package/src/routing/strategies/adaptive.ts +215 -0
- package/src/routing/strategies/index.ts +8 -0
- package/src/routing/strategies/keyword.ts +163 -0
- package/src/routing/strategies/llm-prompts.ts +209 -0
- package/src/routing/strategies/llm.ts +235 -0
- package/src/routing/strategies/manual.ts +50 -0
- package/src/routing/strategy.ts +99 -0
- package/src/tdd/cleanup.ts +111 -0
- package/src/tdd/index.ts +23 -0
- package/src/tdd/isolation.ts +123 -0
- package/src/tdd/orchestrator.ts +383 -0
- package/src/tdd/prompts.ts +270 -0
- package/src/tdd/rectification-gate.ts +183 -0
- package/src/tdd/session-runner.ts +179 -0
- package/src/tdd/types.ts +81 -0
- package/src/tdd/verdict.ts +271 -0
- package/src/tui/App.tsx +265 -0
- package/src/tui/components/AgentPanel.tsx +75 -0
- package/src/tui/components/CostOverlay.tsx +118 -0
- package/src/tui/components/HelpOverlay.tsx +107 -0
- package/src/tui/components/StatusBar.tsx +63 -0
- package/src/tui/components/StoriesPanel.tsx +177 -0
- package/src/tui/hooks/useKeyboard.ts +142 -0
- package/src/tui/hooks/useLayout.ts +137 -0
- package/src/tui/hooks/usePipelineEvents.ts +183 -0
- package/src/tui/hooks/usePty.ts +194 -0
- package/src/tui/index.tsx +38 -0
- package/src/tui/types.ts +76 -0
- package/src/utils/git.ts +83 -0
- package/src/utils/queue-writer.ts +54 -0
- package/src/verification/executor.ts +235 -0
- package/src/verification/gate.ts +207 -0
- package/src/verification/index.ts +12 -0
- package/src/verification/parser.ts +230 -0
- package/src/verification/rectification.ts +108 -0
- package/src/verification/types.ts +113 -0
- package/src/worktree/dispatcher.ts +65 -0
- package/src/worktree/index.ts +2 -0
- package/src/worktree/manager.ts +187 -0
- package/src/worktree/merge.ts +301 -0
- package/src/worktree/types.ts +4 -0
- package/test/TEST_COVERAGE_US001.md +217 -0
- package/test/TEST_COVERAGE_US003.md +84 -0
- package/test/TEST_COVERAGE_US005.md +86 -0
- package/test/US-002-orchestrator.test.ts +246 -0
- package/test/acceptance/cm-003-default-view.test.ts +194 -0
- package/test/execution/pid-registry.test.ts +240 -0
- package/test/execution/post-verify.test.ts +224 -0
- package/test/helpers/timeout.ts +42 -0
- package/test/integration/US-002-TEST-SUMMARY.md +107 -0
- package/test/integration/US-003-TEST-SUMMARY.md +149 -0
- package/test/integration/US-004-TEST-SUMMARY.md +106 -0
- package/test/integration/US-005-TEST-SUMMARY.md +138 -0
- package/test/integration/US-007-TEST-SUMMARY.md +100 -0
- package/test/integration/agent-validation.test.ts +439 -0
- package/test/integration/analyze-integration.test.ts +261 -0
- package/test/integration/analyze-scanner.test.ts +131 -0
- package/test/integration/cli-config-default-edge-cases.test.ts +222 -0
- package/test/integration/cli-config-default-view.test.ts +229 -0
- package/test/integration/cli-config-diff.test.ts +460 -0
- package/test/integration/cli-config.test.ts +736 -0
- package/test/integration/cli-diagnose.test.ts +592 -0
- package/test/integration/cli-logs.test.ts +314 -0
- package/test/integration/cli-plugins.test.ts +678 -0
- package/test/integration/cli-precheck.test.ts +371 -0
- package/test/integration/cli-run-headless.test.ts +173 -0
- package/test/integration/cli.test.ts +75 -0
- package/test/integration/config/merger.test.ts +465 -0
- package/test/integration/config/paths.test.ts +51 -0
- package/test/integration/config-loader.test.ts +265 -0
- package/test/integration/config.test.ts +444 -0
- package/test/integration/context-integration.test.ts +702 -0
- package/test/integration/context-provider-injection.test.ts +506 -0
- package/test/integration/context-verification-integration.test.ts +295 -0
- package/test/integration/e2e.test.ts +896 -0
- package/test/integration/execution.test.ts +625 -0
- package/test/integration/helpers.test.ts +295 -0
- package/test/integration/hooks.test.ts +361 -0
- package/test/integration/interaction-chain-pipeline.test.ts +464 -0
- package/test/integration/isolation.test.ts +143 -0
- package/test/integration/logger.test.ts +461 -0
- package/test/integration/parallel.test.ts +250 -0
- package/test/integration/path-security.test.ts +173 -0
- package/test/integration/pipeline-acceptance.test.ts +302 -0
- package/test/integration/pipeline-events.test.ts +475 -0
- package/test/integration/pipeline.test.ts +658 -0
- package/test/integration/plan.test.ts +157 -0
- package/test/integration/plugin-routing.test.ts +921 -0
- package/test/integration/plugins/config-integration.test.ts +172 -0
- package/test/integration/plugins/config-resolution.test.ts +522 -0
- package/test/integration/plugins/loader.test.ts +641 -0
- package/test/integration/plugins/registry.test.ts +746 -0
- package/test/integration/plugins/validator.test.ts +563 -0
- package/test/integration/prd-pause.test.ts +205 -0
- package/test/integration/prd-resolvers.test.ts +185 -0
- package/test/integration/precheck-integration.test.ts +468 -0
- package/test/integration/precheck.test.ts +805 -0
- package/test/integration/progress.test.ts +34 -0
- package/test/integration/rectification-flow.test.ts +512 -0
- package/test/integration/reporter-lifecycle.test.ts +860 -0
- package/test/integration/review-config-commands.test.ts +319 -0
- package/test/integration/review-config-schema.test.ts +116 -0
- package/test/integration/review-plugin-integration.test.ts +722 -0
- package/test/integration/review.test.ts +149 -0
- package/test/integration/routing-stage-bug-021.test.ts +274 -0
- package/test/integration/routing-stage-greenfield.test.ts +286 -0
- package/test/integration/runner-config-plugins.test.ts +461 -0
- package/test/integration/runner-fixes.test.ts +399 -0
- package/test/integration/runner-plugin-integration.test.ts +543 -0
- package/test/integration/runner.test.ts +1679 -0
- package/test/integration/s5-greenfield-fallback.test.ts +297 -0
- package/test/integration/status-file-integration.test.ts +325 -0
- package/test/integration/status-file.test.ts +379 -0
- package/test/integration/status-writer.test.ts +345 -0
- package/test/integration/story-id-in-events.test.ts +273 -0
- package/test/integration/tdd-cleanup.test.ts +246 -0
- package/test/integration/tdd-orchestrator.test.ts +1762 -0
- package/test/integration/test-scanner.test.ts +403 -0
- package/test/integration/verification-asset-check.test.ts +142 -0
- package/test/integration/verify-stage.test.ts +275 -0
- package/test/integration/worktree/manager.test.ts +218 -0
- package/test/integration/worktree/merge.test.ts +341 -0
- package/test/manual/logging-formatter-demo.ts +158 -0
- package/test/ui/tui-agent-panel.test.tsx +99 -0
- package/test/ui/tui-controls.test.ts +334 -0
- package/test/ui/tui-cost-and-pty.test.ts +189 -0
- package/test/ui/tui-layout.test.ts +378 -0
- package/test/ui/tui-pty-integration.test.tsx +159 -0
- package/test/ui/tui-stories.test.ts +332 -0
- package/test/unit/acceptance.test.ts +186 -0
- package/test/unit/agent-stderr-capture.test.ts +146 -0
- package/test/unit/analyze-classifier.test.ts +215 -0
- package/test/unit/analyze.test.ts +224 -0
- package/test/unit/auto-detect.test.ts +249 -0
- package/test/unit/cli-status.test.ts +417 -0
- package/test/unit/commands/common.test.ts +320 -0
- package/test/unit/commands/logs.test.ts +416 -0
- package/test/unit/commands/unlock.test.ts +319 -0
- package/test/unit/constitution-generators.test.ts +160 -0
- package/test/unit/constitution.test.ts +209 -0
- package/test/unit/context.test.ts +1722 -0
- package/test/unit/cost.test.ts +231 -0
- package/test/unit/crash-recovery.test.ts +308 -0
- package/test/unit/escalation.test.ts +126 -0
- package/test/unit/execution-logging-stderr.test.ts +156 -0
- package/test/unit/execution-stage.test.ts +122 -0
- package/test/unit/fix-generator.test.ts +275 -0
- package/test/unit/formatters.test.ts +469 -0
- package/test/unit/greenfield.test.ts +179 -0
- package/test/unit/helpers.test.ts +317 -0
- package/test/unit/interaction/human-review-trigger.test.ts +164 -0
- package/test/unit/interaction-network-failures.test.ts +389 -0
- package/test/unit/interaction-plugins.test.ts +164 -0
- package/test/unit/isolation.test.ts +134 -0
- package/test/unit/logging/formatter.test.ts +455 -0
- package/test/unit/merge.test.ts +268 -0
- package/test/unit/metrics.test.ts +276 -0
- package/test/unit/optimizer/noop.optimizer.test.ts +125 -0
- package/test/unit/optimizer/rule-based.optimizer.test.ts +358 -0
- package/test/unit/prd-auto-default.test.ts +290 -0
- package/test/unit/prd-failure-category.test.ts +176 -0
- package/test/unit/prd-get-next-story.test.ts +186 -0
- package/test/unit/precheck-checks.test.ts +840 -0
- package/test/unit/precheck-story-size-gate.test.ts +287 -0
- package/test/unit/precheck-types.test.ts +142 -0
- package/test/unit/prompts.test.ts +475 -0
- package/test/unit/queue.test.ts +237 -0
- package/test/unit/rectification.test.ts +284 -0
- package/test/unit/registry.test.ts +287 -0
- package/test/unit/routing.test.ts +937 -0
- package/test/unit/run-lifecycle.test.ts +140 -0
- package/test/unit/storyid-events.test.ts +224 -0
- package/test/unit/tdd-verdict.test.ts +492 -0
- package/test/unit/test-output-parser.test.ts +377 -0
- package/test/unit/verdict.test.ts +324 -0
- package/test/unit/worktree-manager.test.ts +158 -0
- package/tsconfig.json +27 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Post-Fix Code Review: BUG-20, BUG-21, BUG-22
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-02-19
|
|
4
|
+
**Reviewer:** Subrina (AI)
|
|
5
|
+
**Scope:** `fix/bug-20-22-tdd-orchestrator` branch (3 commits, 7 files)
|
|
6
|
+
**Depth:** Standard (post-fix verification)
|
|
7
|
+
**Files:** 7 (lib: ~170 LOC added, test: ~470 LOC added)
|
|
8
|
+
**Baseline:** 21 new tests, 67 assertions — all passing
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Overall Grade: B+ (82/100)
|
|
13
|
+
|
|
14
|
+
Solid bug fixes with good test coverage and clean separation. The `cleanup.ts` module is well-structured with proper JSDoc and graceful error handling. The orchestrator changes address the root causes correctly. However, there are a few issues around race conditions, missing type narrowing, and a potential security concern in the BUG-22 fix that should be addressed before merge.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Scoring
|
|
19
|
+
|
|
20
|
+
| Dimension | Score | Notes |
|
|
21
|
+
|:---|:---|:---|
|
|
22
|
+
| Security | 16/20 | `executeWithTimeout` called with config-derived command — acceptable but no sanitization |
|
|
23
|
+
| Reliability | 15/20 | SIGTERM→SIGKILL race window; no PGID validation; `reviewReason` type narrowing |
|
|
24
|
+
| API Design | 18/20 | Clean module boundary; `pid` optional on `AgentResult` is correct |
|
|
25
|
+
| Code Quality | 17/20 | Good JSDoc; test mocking pattern is verbose but thorough |
|
|
26
|
+
| Best Practices | 16/20 | Bun.sleep mock in tests is fragile; `@ts-ignore` used for mocking |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Findings
|
|
31
|
+
|
|
32
|
+
### 🟡 MEDIUM
|
|
33
|
+
|
|
34
|
+
#### BUG-1: Race condition in SIGTERM→SIGKILL cleanup
|
|
35
|
+
**Severity:** MEDIUM | **Category:** Bug
|
|
36
|
+
```typescript
|
|
37
|
+
// src/tdd/cleanup.ts:73-76
|
|
38
|
+
process.kill(-pgid, "SIGTERM");
|
|
39
|
+
await Bun.sleep(3000); // ← Fixed 3s delay
|
|
40
|
+
process.kill(-pgid, "SIGKILL");
|
|
41
|
+
```
|
|
42
|
+
**Risk:** If the process group exits cleanly in <3s and the PGID is reassigned to a new process group (unlikely but possible on busy systems), SIGKILL hits the wrong group. Also, 3s is hardcoded with no configurability.
|
|
43
|
+
**Fix:** Check if processes still exist before SIGKILL:
|
|
44
|
+
```typescript
|
|
45
|
+
const stillAlive = await getPgid(pid);
|
|
46
|
+
if (stillAlive === pgid) {
|
|
47
|
+
process.kill(-pgid, "SIGKILL");
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
#### BUG-2: BUG-22 post-verification runs `bun test` without workdir context
|
|
52
|
+
**Severity:** MEDIUM | **Category:** Bug
|
|
53
|
+
```typescript
|
|
54
|
+
// src/tdd/orchestrator.ts:430-432
|
|
55
|
+
const testCmd = config.quality?.commands?.test ?? "bun test";
|
|
56
|
+
const timeoutSeconds = config.quality?.verificationTimeoutSeconds ?? 120;
|
|
57
|
+
const postVerify = await executeWithTimeout(testCmd, timeoutSeconds);
|
|
58
|
+
```
|
|
59
|
+
**Risk:** `executeWithTimeout` may not inherit the correct working directory. If the orchestrator's cwd differs from the project workdir, post-verification runs tests against the wrong codebase or fails with "no tests found."
|
|
60
|
+
**Fix:** Pass `workdir` to `executeWithTimeout`:
|
|
61
|
+
```typescript
|
|
62
|
+
const postVerify = await executeWithTimeout(testCmd, timeoutSeconds, { cwd: workdir });
|
|
63
|
+
```
|
|
64
|
+
*(Verify `executeWithTimeout` accepts cwd option — if not, needs a small change.)*
|
|
65
|
+
|
|
66
|
+
#### ENH-1: `reviewReason` type could be `undefined | string` but is set via `let`
|
|
67
|
+
**Severity:** MEDIUM | **Category:** Type Safety
|
|
68
|
+
```typescript
|
|
69
|
+
// src/tdd/orchestrator.ts:441
|
|
70
|
+
reviewReason = undefined; // ← assignment to undefined in success path
|
|
71
|
+
```
|
|
72
|
+
**Risk:** The `reviewReason` variable is declared with `let` higher up. The `undefined` assignment works but the type should be explicit to avoid accidental string checks downstream.
|
|
73
|
+
**Fix:** Declare as `let reviewReason: string | undefined;` if not already.
|
|
74
|
+
|
|
75
|
+
### 🟢 LOW
|
|
76
|
+
|
|
77
|
+
#### STYLE-1: `@ts-ignore` comments in tests instead of proper typing
|
|
78
|
+
**Severity:** LOW | **Category:** Style
|
|
79
|
+
```typescript
|
|
80
|
+
// test/tdd-cleanup.test.ts:24
|
|
81
|
+
// @ts-ignore — mocking global
|
|
82
|
+
Bun.spawn = mock((cmd: string[], spawnOpts?: any) => {
|
|
83
|
+
```
|
|
84
|
+
**Risk:** If `Bun.spawn` signature changes, tests won't catch the type mismatch at compile time.
|
|
85
|
+
**Fix:** Consider a wrapper function pattern:
|
|
86
|
+
```typescript
|
|
87
|
+
const mockSpawn = mock((...args: Parameters<typeof Bun.spawn>) => { ... });
|
|
88
|
+
Object.defineProperty(Bun, 'spawn', { value: mockSpawn, writable: true });
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### STYLE-2: Verbose mock setup repeated across tests
|
|
92
|
+
**Severity:** LOW | **Category:** Style
|
|
93
|
+
The `Bun.spawn` mock setup for git commands is duplicated across `tdd-cleanup.test.ts` and `tdd-orchestrator.test.ts` with slightly different patterns.
|
|
94
|
+
**Fix:** Extract a `createGitMock()` helper into a shared test utility (e.g., `test/helpers/git-mock.ts`).
|
|
95
|
+
|
|
96
|
+
#### ENH-2: `cleanupProcessTree` hardcoded 3s grace period
|
|
97
|
+
**Severity:** LOW | **Category:** Enhancement
|
|
98
|
+
```typescript
|
|
99
|
+
await Bun.sleep(3000);
|
|
100
|
+
```
|
|
101
|
+
**Fix:** Accept optional `gracePeriodMs` parameter with 3000 default:
|
|
102
|
+
```typescript
|
|
103
|
+
export async function cleanupProcessTree(pid: number, gracePeriodMs = 3000): Promise<void> {
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### PERF-1: BUG-20 test file detection uses regex on every file per session
|
|
107
|
+
**Severity:** LOW | **Category:** Performance
|
|
108
|
+
```typescript
|
|
109
|
+
const testFilePatterns = /\.(test|spec)\.(ts|js|tsx|jsx)$/;
|
|
110
|
+
const testFilesCreated = session1.filesChanged.filter((f) => testFilePatterns.test(f));
|
|
111
|
+
```
|
|
112
|
+
**Risk:** Negligible perf impact (typically <50 files), but the regex is recompiled each call.
|
|
113
|
+
**Fix:** Move `testFilePatterns` to module scope as a constant. Minor.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Priority Fix Order
|
|
118
|
+
|
|
119
|
+
| Priority | ID | Effort | Description |
|
|
120
|
+
|:---|:---|:---|:---|
|
|
121
|
+
| P1 | BUG-2 | S | Pass workdir to post-TDD verification `executeWithTimeout` |
|
|
122
|
+
| P2 | BUG-1 | S | Verify process still alive before SIGKILL |
|
|
123
|
+
| P3 | ENH-1 | S | Explicit type for `reviewReason` |
|
|
124
|
+
| P3 | ENH-2 | S | Configurable grace period in `cleanupProcessTree` |
|
|
125
|
+
| P4 | STYLE-1 | M | Replace `@ts-ignore` with proper mock typing |
|
|
126
|
+
| P4 | STYLE-2 | M | Extract shared git mock helper |
|
|
127
|
+
| P5 | PERF-1 | S | Move test file regex to module scope |
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Verdict
|
|
132
|
+
|
|
133
|
+
**Ship with P1 fix.** BUG-2 (missing workdir in post-verification) is the only functional risk. The SIGKILL race (BUG-1) is theoretical on macOS but worth a quick fix. Everything else is polish.
|
|
134
|
+
|
|
135
|
+
The test coverage is thorough — 21 tests covering happy path, failure modes, isolation violations, dry-run, and all 3 bug-specific scenarios. The `cleanup.ts` module is clean, well-documented, and properly handles edge cases (dead processes, ESRCH, unexpected errors).
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Keyword Routing Baseline — Config-Loader Dogfood
|
|
2
|
+
|
|
3
|
+
> Recorded from Run D + Run D2 (2026-02-19) for comparison with LLM routing.
|
|
4
|
+
|
|
5
|
+
## Run D (US-001 to US-007)
|
|
6
|
+
|
|
7
|
+
| Story | Title | Classified | Model | Test Strategy | Routing Reason | Cost | Status |
|
|
8
|
+
|:---|:---|:---|:---|:---|:---|:---|:---|
|
|
9
|
+
| US-001 | Define core types and error handling | simple | balanced | test-after | simple task (medium) | ~$0.08 | ✅ |
|
|
10
|
+
| US-002 | Implement environment variable interpolation | medium | balanced | test-after | simple task (medium) | ~$0.08 | ✅ |
|
|
11
|
+
| US-003 | Implement deep merge utility | medium | balanced | test-after | simple task (medium) | ~$0.08 | ✅ |
|
|
12
|
+
| US-004 | Implement config file discovery | simple | balanced | test-after | simple task (medium) | ~$0.08 | ✅ |
|
|
13
|
+
| US-005 | Implement synchronous config loader | medium | balanced | test-after | simple task (medium) | ~$0.10 | ✅ |
|
|
14
|
+
| US-006 | Implement async config loader | medium | balanced | test-after | simple task (medium) | ~$0.10 | ✅ |
|
|
15
|
+
| US-007 | Implement config file watcher | complex | powerful | three-session-tdd | complexity:expert | — | ❌ TDD failure (BUG-20) |
|
|
16
|
+
|
|
17
|
+
**Run D total: $0.65, 6/9 passed, 174 tests, 9.8 min**
|
|
18
|
+
|
|
19
|
+
## Run D2 (US-007 to US-009, resumed)
|
|
20
|
+
|
|
21
|
+
| Story | Title | Classified | Model | Test Strategy | Routing Reason | Cost | Status |
|
|
22
|
+
|:---|:---|:---|:---|:---|:---|:---|:---|
|
|
23
|
+
| US-007 | Implement config file watcher | complex | powerful | three-session-tdd | complexity:expert | $1.74 | ✅ |
|
|
24
|
+
| US-008 (attempt 1) | Export public API and create barrel exports | simple | powerful | three-session-tdd | public-api, complexity:complex | $1.26 | ✅ but ASSET_CHECK failed |
|
|
25
|
+
| US-008 (attempt 2) | Export public API and create barrel exports | simple | powerful | three-session-tdd | public-api, complexity:complex | $1.21 | ✅ |
|
|
26
|
+
| US-009 | Comprehensive integration tests and documentation | medium | powerful | three-session-tdd | complexity:complex | $4.95 | ⏸ Human review (verifier issues) |
|
|
27
|
+
|
|
28
|
+
**Run D2 total: $4.20 (completed) + $4.95 (US-009 paused) = ~$9.15, 41.4 min**
|
|
29
|
+
|
|
30
|
+
## Misroute Analysis
|
|
31
|
+
|
|
32
|
+
| Story | Keyword Route | Ideal Route | Wasted Cost |
|
|
33
|
+
|:---|:---|:---|:---|
|
|
34
|
+
| US-008 | powerful + three-session-tdd ($2.47 over 2 attempts) | fast + test-after (~$0.10) | **~$2.37** |
|
|
35
|
+
| US-009 | powerful + three-session-tdd ($4.95) | balanced + test-after (~$0.20) | **~$4.75** |
|
|
36
|
+
|
|
37
|
+
**Total misroute waste: ~$7.12** (77% of Run D2 spend)
|
|
38
|
+
|
|
39
|
+
### Why Keyword Routing Failed
|
|
40
|
+
|
|
41
|
+
**US-008:** Title "Export **public API** and create barrel exports" matches `PUBLIC_API_KEYWORDS` → forces TDD. But this is just creating `index.ts` barrel files — no logic, no contracts, no breaking changes. A 2-minute task got 3-session TDD with Opus.
|
|
42
|
+
|
|
43
|
+
**US-009:** "Comprehensive **integration tests** and documentation" — classified as medium by AC count, but routing reason says `complexity:complex`. The word "comprehensive" + AC count likely pushed it. Also got TDD despite the story literally being "write tests" — TDD for writing tests is circular.
|
|
44
|
+
|
|
45
|
+
### Expected LLM Routing (to validate later)
|
|
46
|
+
|
|
47
|
+
| Story | Expected LLM Route | Expected Cost |
|
|
48
|
+
|:---|:---|:---|
|
|
49
|
+
| US-001 | fast / test-after | ~$0.05 |
|
|
50
|
+
| US-002 | fast / test-after | ~$0.05 |
|
|
51
|
+
| US-003 | fast / test-after | ~$0.05 |
|
|
52
|
+
| US-004 | fast / test-after | ~$0.05 |
|
|
53
|
+
| US-005 | balanced / test-after | ~$0.10 |
|
|
54
|
+
| US-006 | balanced / test-after | ~$0.10 |
|
|
55
|
+
| US-007 | powerful / three-session-tdd | ~$1.50 |
|
|
56
|
+
| US-008 | fast / test-after | ~$0.05 |
|
|
57
|
+
| US-009 | balanced / test-after | ~$0.15 |
|
|
58
|
+
|
|
59
|
+
**Expected total with LLM routing: ~$2.10** vs actual $9.80 (Run D + D2)
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
*Recorded 2026-02-19 for A/B comparison with v0.8 LLM routing.*
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Fix Plan: nax v0.8 Structured Logging — Phase 1
|
|
2
|
+
**Date:** 2026-02-20
|
|
3
|
+
**Branch:** `feat/v0.8-structured-logging`
|
|
4
|
+
|
|
5
|
+
## Scope
|
|
6
|
+
Phase 1: Logger core, CLI flags, JSONL file output, debug mode.
|
|
7
|
+
Covers AC-1, AC-2, AC-3, AC-4, AC-5, AC-8.
|
|
8
|
+
Does NOT touch existing console.log calls (Phase 2).
|
|
9
|
+
|
|
10
|
+
## Phase 1A: Logger Core
|
|
11
|
+
**Commit:** `feat(logger): implement structured Logger with level gating and JSONL output`
|
|
12
|
+
|
|
13
|
+
### File: `src/logger/index.ts` (NEW)
|
|
14
|
+
Export barrel.
|
|
15
|
+
|
|
16
|
+
### File: `src/logger/logger.ts` (NEW)
|
|
17
|
+
- `Logger` class with `error`, `warn`, `info`, `debug` methods
|
|
18
|
+
- Each method signature: `(stage: string, message: string, data?: Record<string, unknown>)`
|
|
19
|
+
- `withStory(storyId: string)` returns a `StoryLogger` with storyId auto-injected
|
|
20
|
+
- Constructor: `{ level: LogLevel, filePath?: string, useChalk?: boolean }`
|
|
21
|
+
- Console output: chalk-formatted, filtered by level
|
|
22
|
+
- File output: JSON Lines, all levels written regardless of console level
|
|
23
|
+
- Singleton pattern: `getLogger()` / `initLogger(opts)`
|
|
24
|
+
|
|
25
|
+
### File: `src/logger/types.ts` (NEW)
|
|
26
|
+
- `LogLevel` type: `"error" | "warn" | "info" | "debug"`
|
|
27
|
+
- `LogEntry` interface: `{ timestamp, level, stage, storyId?, message, data? }`
|
|
28
|
+
- `LoggerOptions` interface
|
|
29
|
+
|
|
30
|
+
### File: `src/logger/formatters.ts` (NEW)
|
|
31
|
+
- `formatConsole(entry: LogEntry): string` — chalk-formatted human-readable
|
|
32
|
+
- `formatJsonl(entry: LogEntry): string` — JSON.stringify one-liner
|
|
33
|
+
|
|
34
|
+
## Phase 1B: CLI Integration
|
|
35
|
+
**Commit:** `feat(cli): add --verbose, --quiet, --silent flags and run directory`
|
|
36
|
+
|
|
37
|
+
### File: `bin/nax.ts`
|
|
38
|
+
- Add `--verbose` flag → sets log level to `debug`
|
|
39
|
+
- Add `--quiet` flag → sets log level to `warn`
|
|
40
|
+
- Add `--silent` flag → sets log level to `error`
|
|
41
|
+
- Add `NAX_LOG_LEVEL` env var support (overrides flags)
|
|
42
|
+
- Create run directory: `nax/features/<name>/runs/`
|
|
43
|
+
- Generate run ID: ISO timestamp `YYYY-MM-DDTHH-mm-ssZ`
|
|
44
|
+
- Pass `filePath` to logger init: `nax/features/<name>/runs/<run-id>.jsonl`
|
|
45
|
+
- After run, create/update `latest.jsonl` symlink
|
|
46
|
+
|
|
47
|
+
### File: `src/config/schema.ts`
|
|
48
|
+
- Add `logging` section to NaxConfig: `{ level: LogLevel, verbose: boolean }`
|
|
49
|
+
|
|
50
|
+
## Phase 1C: Stage Events
|
|
51
|
+
**Commit:** `feat(logger): emit structured stage lifecycle events`
|
|
52
|
+
|
|
53
|
+
### File: `src/execution/runner.ts`
|
|
54
|
+
- Add logger calls at key lifecycle points (alongside existing console.log, not replacing):
|
|
55
|
+
- `run.start`, `iteration.start`, `context.built`
|
|
56
|
+
- `agent.start`, `agent.complete`
|
|
57
|
+
- `story.complete`, `run.complete`
|
|
58
|
+
- These write to JSONL file even at `info` level
|
|
59
|
+
|
|
60
|
+
### File: `src/pipeline/stages/routing.ts`
|
|
61
|
+
- Add logger call for routing decision
|
|
62
|
+
|
|
63
|
+
## Phase 1D: Tests
|
|
64
|
+
**Commit:** `test(logger): add unit tests for Logger, formatters, and JSONL output`
|
|
65
|
+
|
|
66
|
+
### Test targets:
|
|
67
|
+
- `test/logger.test.ts` — Logger class, level gating, withStory, file output
|
|
68
|
+
- `test/formatters.test.ts` — console and JSONL formatters
|
|
69
|
+
- Verify: JSONL lines are valid JSON with required fields
|
|
70
|
+
- Verify: level gating (debug hidden at info level, etc.)
|
|
71
|
+
- Verify: file always gets all levels regardless of console setting
|
|
72
|
+
|
|
73
|
+
## Test Strategy
|
|
74
|
+
- Mode: test-after (implementing against spec)
|
|
75
|
+
- Run: `bun test`
|
|
76
|
+
|
|
77
|
+
## Notes
|
|
78
|
+
- Do NOT replace any existing `console.log` calls (Phase 2)
|
|
79
|
+
- Logger runs alongside existing output in Phase 1
|
|
80
|
+
- Console formatter should closely match current chalk output style
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Fix Plan: nax v0.8 Structured Logging — Phase 2
|
|
2
|
+
**Date:** 2026-02-20
|
|
3
|
+
**Covers:** AC-6 (runs list/show), AC-7 (per-story metrics), AC-9 (console.log migration)
|
|
4
|
+
|
|
5
|
+
## Migration Rules
|
|
6
|
+
1. Import `getLogger` from `../logger` (adjust path as needed)
|
|
7
|
+
2. Get logger instance: `const logger = getLogger()`
|
|
8
|
+
3. Replace `console.log(chalk.X(...))` → `logger.info(stage, message, data?)`
|
|
9
|
+
4. Replace `console.warn(...)` → `logger.warn(stage, message, data?)`
|
|
10
|
+
5. Replace `console.error(...)` → `logger.error(stage, message, data?)`
|
|
11
|
+
6. Replace verbose/debug output → `logger.debug(stage, message, data?)`
|
|
12
|
+
7. `stage` should be the module/concern: "routing", "context", "agent", "tdd", "pipeline", "config", "cli", etc.
|
|
13
|
+
8. Keep chalk formatting in the logger's console formatter — do NOT use chalk in the migrated calls
|
|
14
|
+
9. For `data` objects, include structured fields (storyId, cost, duration, etc.) not string interpolation
|
|
15
|
+
10. Do NOT change test files — only src/ files
|
|
16
|
+
|
|
17
|
+
## Phase 2A: Core execution pipeline (highest impact)
|
|
18
|
+
**Files:** src/execution/runner.ts, src/execution/helpers.ts, src/execution/post-verify.ts, src/execution/queue-handler.ts
|
|
19
|
+
**Commit:** `refactor(execution): migrate console.log to structured logger`
|
|
20
|
+
|
|
21
|
+
## Phase 2B: Pipeline stages
|
|
22
|
+
**Files:** src/pipeline/runner.ts, src/pipeline/events.ts, src/pipeline/stages/*.ts (acceptance, completion, constitution, execution, prompt, review, routing, verification)
|
|
23
|
+
**Commit:** `refactor(pipeline): migrate console.log to structured logger`
|
|
24
|
+
|
|
25
|
+
## Phase 2C: Agents, routing, context, config
|
|
26
|
+
**Files:** src/agents/claude.ts, src/agents/cost.ts, src/agents/validation.ts, src/routing/strategies/*.ts, src/context/builder.ts, src/config/loader.ts, src/analyze/*.ts
|
|
27
|
+
**Commit:** `refactor(agents): migrate console.log to structured logger`
|
|
28
|
+
|
|
29
|
+
## Phase 2D: CLI, TDD, hooks, metrics + runs list/show commands
|
|
30
|
+
**Files:** src/cli/*.ts, src/tdd/*.ts, src/hooks/*.ts, src/metrics/*.ts, src/review/*.ts, src/acceptance/*.ts
|
|
31
|
+
**Also:** Implement `nax runs list -f <feature>` and `nax runs show <run-id> -f <feature>` commands in bin/nax.ts
|
|
32
|
+
**Also:** Add per-story metrics summary table to run.complete event
|
|
33
|
+
**Commit:** `feat(cli): add nax runs commands and migrate remaining console.log`
|
|
34
|
+
|
|
35
|
+
## Verification
|
|
36
|
+
After all phases: `grep -rn "console\.\(log\|warn\|error\)" src/ | grep -v "logger\.ts\|formatters\.ts" | wc -l` should be 0
|
|
37
|
+
Run: `bun test` — all tests must pass
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Code Review: nax v0.8 LLM-Enhanced Routing
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-02-20
|
|
4
|
+
**Reviewer:** Subrina (AI)
|
|
5
|
+
**Branch:** `feat/v0.8-llm-routing` (7 commits, LLM routing scope)
|
|
6
|
+
**Files:** 12 changed (src: ~450 LOC, test: ~700 LOC)
|
|
7
|
+
**Baseline:** 633 pass, 0 fail, 2 skip
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Overall Grade: B+ (83/100)
|
|
12
|
+
|
|
13
|
+
Solid implementation of LLM-based routing with good test coverage (532-line test file), clean separation from keyword strategy, proper fallback chain, and batch mode support. Two notable issues: a **process leak on timeout** (P1) and **duplicate batch routing code** (P2). The async strategy refactor is clean and non-breaking.
|
|
14
|
+
|
|
15
|
+
| Dimension | Score | Notes |
|
|
16
|
+
|:---|:---|:---|
|
|
17
|
+
| Security | 16/20 | Process leak on timeout; prompt injection surface (low risk — internal tool) |
|
|
18
|
+
| Reliability | 15/20 | Timeout doesn't kill process; no retry on transient failures |
|
|
19
|
+
| API Design | 18/20 | Clean strategy interface, good batch/cache separation |
|
|
20
|
+
| Code Quality | 17/20 | Well-documented, good JSDoc. Some duplication in runner.ts |
|
|
21
|
+
| Best Practices | 17/20 | Proper fallback chain, zod validation, backward compat via `routeTask` |
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Findings
|
|
26
|
+
|
|
27
|
+
### 🔴 CRITICAL
|
|
28
|
+
|
|
29
|
+
*(none)*
|
|
30
|
+
|
|
31
|
+
### 🟠 HIGH
|
|
32
|
+
|
|
33
|
+
#### BUG-1: Process leak on LLM timeout
|
|
34
|
+
**Severity:** HIGH | **Category:** Memory/Resource
|
|
35
|
+
**File:** `src/routing/strategies/llm.ts:131-149`
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
const timeoutPromise = new Promise<never>((_, reject) => {
|
|
39
|
+
setTimeout(() => reject(new Error(`LLM call timeout after ${timeoutMs}ms`)), timeoutMs);
|
|
40
|
+
});
|
|
41
|
+
// ...
|
|
42
|
+
return await Promise.race([outputPromise, timeoutPromise]);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
When the timeout fires, `Promise.race` rejects but the spawned `claude` process continues running. There's no `proc.kill()` on timeout. This leaks a process that could run for minutes.
|
|
46
|
+
|
|
47
|
+
**Risk:** Orphaned `claude` processes accumulating on Mac01, consuming memory and API credits.
|
|
48
|
+
|
|
49
|
+
**Fix:**
|
|
50
|
+
```typescript
|
|
51
|
+
const controller = new AbortController();
|
|
52
|
+
const timeoutId = setTimeout(() => {
|
|
53
|
+
proc.kill();
|
|
54
|
+
controller.abort();
|
|
55
|
+
}, timeoutMs);
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
const output = await outputPromise;
|
|
59
|
+
clearTimeout(timeoutId);
|
|
60
|
+
return output;
|
|
61
|
+
} catch (err) {
|
|
62
|
+
proc.kill();
|
|
63
|
+
clearTimeout(timeoutId);
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### BUG-2: `setTimeout` in `timeoutPromise` is never cleared on success
|
|
69
|
+
**Severity:** HIGH | **Category:** Bug
|
|
70
|
+
**File:** `src/routing/strategies/llm.ts:135`
|
|
71
|
+
|
|
72
|
+
Even when the LLM responds quickly, the `setTimeout` callback still fires after `timeoutMs`, creating a rejected promise with no handler (unhandled rejection in some runtimes). In Bun this is silently swallowed, but it's undefined behavior.
|
|
73
|
+
|
|
74
|
+
**Fix:** Use `clearTimeout` pattern (see BUG-1 fix above).
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
### 🟡 MEDIUM
|
|
79
|
+
|
|
80
|
+
#### ENH-1: Duplicate batch routing logic in `runner.ts`
|
|
81
|
+
**Severity:** MEDIUM | **Category:** Enhancement
|
|
82
|
+
**File:** `src/execution/runner.ts:140-154` and `src/execution/runner.ts:183-193`
|
|
83
|
+
|
|
84
|
+
The LLM batch routing block (check strategy, call `llmRouteBatch`, catch and warn) is duplicated verbatim for initial routing and re-routing after dependency resolution. Extract to a helper.
|
|
85
|
+
|
|
86
|
+
**Fix:**
|
|
87
|
+
```typescript
|
|
88
|
+
async function tryBatchRoute(config: NaxConfig, stories: UserStory[]): Promise<void> {
|
|
89
|
+
if (config.routing.strategy !== "llm" || !config.routing.llm?.batchMode || stories.length === 0) return;
|
|
90
|
+
try {
|
|
91
|
+
console.log(chalk.dim(` LLM batch routing: routing ${stories.length} stories...`));
|
|
92
|
+
await llmRouteBatch(stories, { config });
|
|
93
|
+
} catch (err) {
|
|
94
|
+
console.warn(chalk.yellow(` LLM batch routing failed: ${(err as Error).message}`));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### ENH-2: Duplicate cached-routing override blocks in `runner.ts`
|
|
100
|
+
**Severity:** MEDIUM | **Category:** Enhancement
|
|
101
|
+
**File:** `src/execution/runner.ts:228-237` and `src/execution/runner.ts:258-267`
|
|
102
|
+
|
|
103
|
+
The `if (story.routing)` override block (complexity + modelTier + testStrategy) is duplicated for batch vs single-story paths. Same fix: extract helper.
|
|
104
|
+
|
|
105
|
+
#### PERF-1: `buildStrategyChain` called per-story in `routeStory`
|
|
106
|
+
**Severity:** MEDIUM | **Category:** Performance
|
|
107
|
+
**File:** `src/routing/router.ts`
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
export async function routeStory(...): Promise<RoutingDecision> {
|
|
111
|
+
const chain = await buildStrategyChain(context.config, workdir);
|
|
112
|
+
return await chain.route(story, context);
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The chain is rebuilt for every story call from the pipeline routing stage. For keyword/manual strategies this is cheap, but `buildStrategyChain` could load a custom strategy file each time. Consider caching the chain per-run.
|
|
117
|
+
|
|
118
|
+
**Risk:** Low for current usage (pipeline already uses batch routing for LLM). But `routeStory` is the public API.
|
|
119
|
+
|
|
120
|
+
#### TYPE-1: `parseBatchResponse` re-serializes then re-parses each entry
|
|
121
|
+
**Severity:** MEDIUM | **Category:** Performance/Style
|
|
122
|
+
**File:** `src/routing/strategies/llm.ts:239`
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
const decision = parseRoutingResponse(JSON.stringify(entry), story, config);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Each batch entry is `JSON.stringify`'d then immediately `JSON.parse`'d inside `parseRoutingResponse`. This works but is wasteful. Consider extracting validation into a shared function that accepts an object.
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### 🟢 LOW
|
|
133
|
+
|
|
134
|
+
#### ENH-3: `maxInputTokens` config field is unused
|
|
135
|
+
**Severity:** LOW | **Category:** Enhancement
|
|
136
|
+
**File:** `src/config/schema.ts` (LlmRoutingConfig)
|
|
137
|
+
|
|
138
|
+
`maxInputTokens` is defined in the schema and has a default of 2000, but nothing in `llm.ts` reads or enforces it. Either implement truncation of story context or remove the field to avoid config confusion.
|
|
139
|
+
|
|
140
|
+
#### STYLE-1: `console.log`/`console.warn` for routing logs
|
|
141
|
+
**Severity:** LOW | **Category:** Style
|
|
142
|
+
**File:** `src/routing/strategies/llm.ts` (multiple)
|
|
143
|
+
|
|
144
|
+
Uses raw `console.log`/`console.warn` with `[routing]` prefix. This will be addressed by the v0.8 structured logging feature, so noting for tracking only.
|
|
145
|
+
|
|
146
|
+
#### ENH-4: No validation that `strategy: "llm"` has `routing.llm` config
|
|
147
|
+
**Severity:** LOW | **Category:** Enhancement
|
|
148
|
+
**File:** `src/config/schema.ts`
|
|
149
|
+
|
|
150
|
+
When `strategy` is `"llm"`, there's a zod refinement for `customStrategyPath` on `"custom"` but no refinement requiring `llm` config when `strategy` is `"llm"`. The runtime handles it gracefully (falls through to keyword), but a config validation error would be more user-friendly.
|
|
151
|
+
|
|
152
|
+
#### STYLE-2: Adaptive strategy now has unnecessary null guards
|
|
153
|
+
**Severity:** LOW | **Category:** Style
|
|
154
|
+
**File:** `src/routing/strategies/adaptive.ts:170,193`
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
const decision = await keywordStrategy.route(story, context);
|
|
158
|
+
if (!decision) return null; // keyword never returns null
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The keyword strategy **never** returns null (it always produces a decision). The null guard is defensive but misleading — it suggests keyword might return null when it can't.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Priority Fix Order
|
|
166
|
+
|
|
167
|
+
| Priority | ID | Effort | Description |
|
|
168
|
+
|:---|:---|:---|:---|
|
|
169
|
+
| P1 | BUG-1 + BUG-2 | S | Kill process on timeout, clear setTimeout on success |
|
|
170
|
+
| P2 | ENH-1 + ENH-2 | S | Extract duplicate batch routing + override helpers in runner.ts |
|
|
171
|
+
| P3 | TYPE-1 | S | Avoid re-serializing batch entries for validation |
|
|
172
|
+
| P4 | PERF-1 | M | Cache strategy chain per-run (optional) |
|
|
173
|
+
| P5 | ENH-3 | S | Remove or implement `maxInputTokens` |
|
|
174
|
+
| — | ENH-4, STYLE-1, STYLE-2 | S | Low priority / deferred to structured logging |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Verdict
|
|
179
|
+
|
|
180
|
+
**Ship after P1 fix.** The process leak on timeout is the only blocker — it could accumulate orphaned `claude` processes costing real API credits. P2-P5 are quality improvements that can land in a follow-up.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
Code Review Report — Post-fix LLM routing
|
|
2
|
+
Date: 2026-02-20
|
|
3
|
+
Branch: feat/v0.8-llm-routing
|
|
4
|
+
Commit: a70d4f61d29ce1e528fd1e3d82ec9987b4737a79
|
|
5
|
+
|
|
6
|
+
Summary
|
|
7
|
+
- Reviewed only the latest commit (the P1–P5 fix commit).
|
|
8
|
+
- Verified code changes for P1, P2, P3, P5 and test mock updates in the diff between HEAD~1 and HEAD.
|
|
9
|
+
- Could not complete test run: 'bun test' appeared to hang in this environment within the allotted time. (See note at the end.)
|
|
10
|
+
|
|
11
|
+
What I accomplished / found
|
|
12
|
+
1) P1 (BUG-1+2): callLlm timeout, process kill and clearTimeout
|
|
13
|
+
- Changes made in src/routing/strategies/llm.ts:
|
|
14
|
+
- Introduced timeoutId variable, setTimeout now kills the spawned process (proc.kill()) and rejects on timeout.
|
|
15
|
+
- Promise.race is wrapped in try/catch and both success and error paths clearTimeout(timeoutId) and ensure proc.kill() is called on the error path.
|
|
16
|
+
- Assessment: Good improvements. This addresses the resource leak (leftover child) on timeout and ensures the timer is cleared on both success and failure.
|
|
17
|
+
- Notes / minor suggestions:
|
|
18
|
+
- clearTimeout is called with timeoutId which is possibly undefined in the narrow window before setTimeout assigned it; that's safe because clearTimeout(undefined) is benign in Node.
|
|
19
|
+
- proc.kill() is invoked both inside the timeout handler and again in catch — double-kill is usually safe but could be redundant; acceptable.
|
|
20
|
+
- If proc.exited already resolved, kill() is a no-op. No dangling promises observed in this snippet.
|
|
21
|
+
|
|
22
|
+
2) P2 (ENH-1+2): tryLlmBatchRoute and applyCachedRouting
|
|
23
|
+
- Changes made in src/execution/runner.ts:
|
|
24
|
+
- Extracted the LLM batch routing logic into tryLlmBatchRoute that logs and swallows errors and returns early when not applicable.
|
|
25
|
+
- Extracted cached-routing override into applyCachedRouting(routing, story, config) and replaced inline blocks with the helper.
|
|
26
|
+
- Assessment: Behavior preserved. The helpers are straightforward extractions with identical logic (I compared the code before/after in the diff). applyCachedRouting reproduces the previous override logic for complexity -> modelTier mapping and testStrategy.
|
|
27
|
+
- Minor suggestion: applyCachedRouting accepts routing produced by routeTask; that function's return type is used via ReturnType<> which is OK. Consider adding a narrow explicit type alias for clarity in future.
|
|
28
|
+
|
|
29
|
+
3) P3 (TYPE-1): validateRoutingDecision and stripCodeFences
|
|
30
|
+
- Changes made in src/routing/strategies/llm.ts:
|
|
31
|
+
- Extracted validateRoutingDecision(parsed, config) which validates parsed object fields and returns typed RoutingDecision.
|
|
32
|
+
- Extracted stripCodeFences(text) to remove markdown/json code fences.
|
|
33
|
+
- parseRoutingResponse now strips fences, JSON.parse once, and validates via validateRoutingDecision.
|
|
34
|
+
- parseBatchResponse uses validateRoutingDecision(entry, config) directly instead of re-serializing entry->string->parse again.
|
|
35
|
+
- Assessment: Correct and type-safer.
|
|
36
|
+
- validateRoutingDecision uses type assertions (as Complexity/TestStrategy/ModelTier) before returning typed fields — appropriate.
|
|
37
|
+
- Using direct validation on batch entries avoids unnecessary serialization/parsing and fixes the prior issue where batch entries were re-serialized.
|
|
38
|
+
- Minor caution: validateRoutingDecision checks `if (!parsed.complexity || !parsed.modelTier || ...)` — if any field is present but falsy (empty string) it will still be caught; that likely matches intended validation.
|
|
39
|
+
|
|
40
|
+
4) P5 (ENH-3): Removed maxInputTokens from config schema
|
|
41
|
+
- Changes made in src/config/schema.ts: removed maxInputTokens from LlmRoutingConfig interface, schema and DEFAULT_CONFIG.
|
|
42
|
+
- Assessment: Removal in the three spots shown in diff is correct. I searched the diff for remaining references and did not see other references in the commit diff. (A full repo-wide search was not performed in this review scope.)
|
|
43
|
+
|
|
44
|
+
5) Test mocks: mock spawn kill handlers
|
|
45
|
+
- Changes made in test/routing/llm-strategy.test.ts: added kill: () => {} to all 9 mock spawn objects.
|
|
46
|
+
- Assessment: Matches the code changes in callLlm that call proc.kill() on timeout and in catch — tests needed mocks to provide a kill function to avoid runtime errors. Good.
|
|
47
|
+
|
|
48
|
+
Tests
|
|
49
|
+
- I attempted to run tests with `bun test` but the runner in this environment did not complete within the quick-review time window (process appeared to hang). I aborted attempts to repeatedly poll.
|
|
50
|
+
- Because tests did not finish here, I could not validate runtime behavior across the suite. Local/CI test run is recommended.
|
|
51
|
+
|
|
52
|
+
Grade (per requested areas)
|
|
53
|
+
- P1 (BUG-1+2): PASS — timeout handling and process cleanup implemented; no obvious resource leaks or dangling timers.
|
|
54
|
+
- P2 (ENH-1+2): PASS — helpers extracted; logic preserved.
|
|
55
|
+
- P3 (TYPE-1): PASS — validation and fence-stripping extracted; batch entry validation fixed to avoid re-serialization.
|
|
56
|
+
- P5 (ENH-3): PASS (within commit diff) — removed config field; no remaining references in diff.
|
|
57
|
+
- Test mocks: PASS — all mocked spawns in the tested file now include kill() handler.
|
|
58
|
+
|
|
59
|
+
Recommendations / Follow-ups
|
|
60
|
+
- Run the full test suite in CI or locally to confirm all tests pass. The new timeout/process kill behavior and the added kill mocks should make tests stable, but I couldn't confirm here.
|
|
61
|
+
- Optional: avoid double-kill redundancy by checking proc.killed/exited state before calling kill() if platform provides it — not required.
|
|
62
|
+
- Optional: add unit tests for validateRoutingDecision and stripCodeFences to assert correct behavior on edge cases (fenced JSON, invalid fields, batch entries).
|
|
63
|
+
|
|
64
|
+
Note about test run
|
|
65
|
+
- The environment's `bun test` invocation did not complete in this review session; please run tests in CI or locally and paste the last 20 lines of output if you want me to re-check test failures (if any).
|
|
66
|
+
|
|
67
|
+
Artifacts
|
|
68
|
+
- Saved report at: docs/20260220-review-post-fix-llm-routing.md
|
|
69
|
+
|
|
70
|
+
End of report.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Fix Plan: Split relevantFiles into contextFiles + expectedFiles
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-02-21
|
|
4
|
+
**Branch:** `feat/v0.9-relevantfiles-split`
|
|
5
|
+
**Issue:** #1
|
|
6
|
+
**Base:** `master` (`b459e9f`)
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
`relevantFiles` conflates two purposes:
|
|
11
|
+
1. **Context injection** — files loaded into agent prompt before execution
|
|
12
|
+
2. **Asset verification** — files that must exist after execution (pre-flight gate)
|
|
13
|
+
|
|
14
|
+
This causes false negatives: LLM-predicted filenames fail asset check even when code is correct and tests pass. Observed in dogfood Runs F and H.
|
|
15
|
+
|
|
16
|
+
## Phase 1: Type Changes + Resolver Functions
|
|
17
|
+
|
|
18
|
+
### Fix 1.1: Add new fields to UserStory type
|
|
19
|
+
**File:** `src/prd/types.ts`
|
|
20
|
+
**Change:** Add `contextFiles?: string[]` and `expectedFiles?: string[]` to `UserStory` interface. Keep `relevantFiles?: string[]` as deprecated.
|
|
21
|
+
|
|
22
|
+
### Fix 1.2: Add resolver functions
|
|
23
|
+
**File:** `src/prd/types.ts` (or new `src/prd/helpers.ts`)
|
|
24
|
+
**Change:** Create two helper functions:
|
|
25
|
+
```typescript
|
|
26
|
+
export function getContextFiles(story: UserStory): string[] {
|
|
27
|
+
return story.contextFiles ?? story.relevantFiles ?? [];
|
|
28
|
+
}
|
|
29
|
+
export function getExpectedFiles(story: UserStory): string[] {
|
|
30
|
+
return story.expectedFiles ?? [];
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
**Key:** `getExpectedFiles` does NOT fall back to `relevantFiles`. Asset check is opt-in only.
|
|
34
|
+
|
|
35
|
+
### Fix 1.3: Export helpers from prd index
|
|
36
|
+
**File:** `src/prd/index.ts`
|
|
37
|
+
**Change:** Export `getContextFiles` and `getExpectedFiles`.
|
|
38
|
+
|
|
39
|
+
**Commit:** `refactor(prd): add contextFiles + expectedFiles types and resolvers`
|
|
40
|
+
|
|
41
|
+
## Phase 2: Wire Context Builder
|
|
42
|
+
|
|
43
|
+
### Fix 2.1: Use getContextFiles in context builder
|
|
44
|
+
**File:** `src/context/builder.ts`
|
|
45
|
+
**Change:** Replace `currentStory.relevantFiles` with `getContextFiles(currentStory)` at line ~296. Import from prd.
|
|
46
|
+
|
|
47
|
+
**Commit:** `refactor(context): use getContextFiles for prompt injection`
|
|
48
|
+
|
|
49
|
+
## Phase 3: Wire Verification
|
|
50
|
+
|
|
51
|
+
### Fix 3.1: Use getExpectedFiles in post-verify
|
|
52
|
+
**File:** `src/execution/post-verify.ts`
|
|
53
|
+
**Change:** Replace `story.relevantFiles` (line ~73) with `getExpectedFiles(story)`. Import from prd.
|
|
54
|
+
|
|
55
|
+
### Fix 3.2: Update verification function signature
|
|
56
|
+
**File:** `src/execution/verification.ts`
|
|
57
|
+
**Change:** Rename parameter `relevantFiles` to `expectedFiles` in `runVerification()` and `verifyAssets()` for clarity.
|
|
58
|
+
|
|
59
|
+
**Commit:** `refactor(verification): use getExpectedFiles for asset check (opt-in only)`
|
|
60
|
+
|
|
61
|
+
## Phase 4: Wire Analyze + Decompose Output
|
|
62
|
+
|
|
63
|
+
### Fix 4.1: Update classifier output
|
|
64
|
+
**File:** `src/analyze/classifier.ts`
|
|
65
|
+
**Change:** Map LLM output `relevantFiles` -> `contextFiles` in parsed result.
|
|
66
|
+
|
|
67
|
+
### Fix 4.2: Update analyze types
|
|
68
|
+
**File:** `src/analyze/types.ts`
|
|
69
|
+
**Change:** Add `contextFiles` field alongside `relevantFiles`.
|
|
70
|
+
|
|
71
|
+
### Fix 4.3: Update decompose prompt
|
|
72
|
+
**File:** `src/agents/claude.ts`
|
|
73
|
+
**Change:** In decompose prompt (~line 455), rename field 8 from `relevantFiles` to `contextFiles`.
|
|
74
|
+
|
|
75
|
+
### Fix 4.4: Update CLI analyze output
|
|
76
|
+
**File:** `src/cli/analyze.ts`
|
|
77
|
+
**Change:** Map `relevantFiles` -> `contextFiles` in feature creation output.
|
|
78
|
+
|
|
79
|
+
### Fix 4.5: Update acceptance fix-generator
|
|
80
|
+
**File:** `src/acceptance/fix-generator.ts`
|
|
81
|
+
**Change:** Replace `relevantFiles: []` with `contextFiles: []`.
|
|
82
|
+
|
|
83
|
+
**Commit:** `refactor(analyze): output contextFiles instead of relevantFiles`
|
|
84
|
+
|
|
85
|
+
## Phase 5: Tests
|
|
86
|
+
|
|
87
|
+
### Fix 5.1: Update verification tests
|
|
88
|
+
**Change:** Add test: story with `relevantFiles` but no `expectedFiles` -> asset check PASSES. Add test: story with `expectedFiles` set -> asset check verifies those files.
|
|
89
|
+
|
|
90
|
+
### Fix 5.2: Update context builder tests
|
|
91
|
+
**Change:** Test `contextFiles` used when present. Test `relevantFiles` fallback. Test empty when neither set.
|
|
92
|
+
|
|
93
|
+
### Fix 5.3: Update classifier/analyze tests
|
|
94
|
+
**Change:** Verify output uses `contextFiles` field.
|
|
95
|
+
|
|
96
|
+
**Commit:** `test: update tests for contextFiles/expectedFiles split`
|
|
97
|
+
|
|
98
|
+
## Test Strategy
|
|
99
|
+
- Mode: test-after
|
|
100
|
+
- Run `bun test` after each phase
|
|
101
|
+
- All existing test files should continue passing (backward compat)
|