@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,301 @@
|
|
|
1
|
+
import { getSafeLogger } from "../logger";
|
|
2
|
+
import type { WorktreeManager } from "./manager";
|
|
3
|
+
|
|
4
|
+
export interface MergeResult {
|
|
5
|
+
success: boolean;
|
|
6
|
+
storyId: string;
|
|
7
|
+
conflictFiles?: string[];
|
|
8
|
+
retryCount?: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface StoryDependencies {
|
|
12
|
+
[storyId: string]: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class MergeEngine {
|
|
16
|
+
constructor(private worktreeManager: WorktreeManager) {}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Merges branch nax/<storyId> into current branch with --no-ff
|
|
20
|
+
* Returns { success: true } on clean merge
|
|
21
|
+
* Returns { success: false, conflictFiles: [...] } on conflict
|
|
22
|
+
* Cleans up worktree after successful merge
|
|
23
|
+
*/
|
|
24
|
+
async merge(projectRoot: string, storyId: string): Promise<Omit<MergeResult, "storyId">> {
|
|
25
|
+
const branchName = `nax/${storyId}`;
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
// Perform merge with --no-ff
|
|
29
|
+
const mergeProc = Bun.spawn(["git", "merge", "--no-ff", branchName, "-m", `Merge branch '${branchName}'`], {
|
|
30
|
+
cwd: projectRoot,
|
|
31
|
+
stdout: "pipe",
|
|
32
|
+
stderr: "pipe",
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const exitCode = await mergeProc.exited;
|
|
36
|
+
const stderr = await new Response(mergeProc.stderr).text();
|
|
37
|
+
const stdout = await new Response(mergeProc.stdout).text();
|
|
38
|
+
|
|
39
|
+
if (exitCode === 0) {
|
|
40
|
+
// Clean merge - cleanup worktree
|
|
41
|
+
try {
|
|
42
|
+
await this.worktreeManager.remove(projectRoot, storyId);
|
|
43
|
+
} catch (error) {
|
|
44
|
+
// Log warning but don't fail the merge
|
|
45
|
+
const logger = getSafeLogger();
|
|
46
|
+
logger?.warn("worktree", `Failed to cleanup worktree for ${storyId}`, {
|
|
47
|
+
error: error instanceof Error ? error.message : String(error),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { success: true };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Merge failed - check for conflicts
|
|
55
|
+
const output = `${stdout}\n${stderr}`;
|
|
56
|
+
if (output.includes("CONFLICT") || output.includes("conflict") || output.includes("Automatic merge failed")) {
|
|
57
|
+
// Extract conflict files
|
|
58
|
+
const conflictFiles = await this.getConflictFiles(projectRoot);
|
|
59
|
+
|
|
60
|
+
// Abort the merge
|
|
61
|
+
await this.abortMerge(projectRoot);
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
conflictFiles,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Other error
|
|
70
|
+
throw new Error(`Merge failed: ${stderr || stdout || "unknown error"}`);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (error instanceof Error) {
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
throw new Error(`Failed to merge branch ${branchName}: ${String(error)}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Merges stories in topological order based on dependencies
|
|
81
|
+
* On conflict: retries once after rebasing worktree on updated base
|
|
82
|
+
* On 2nd conflict: marks story as failed, continues with remaining stories
|
|
83
|
+
*/
|
|
84
|
+
async mergeAll(projectRoot: string, storyIds: string[], dependencies: StoryDependencies): Promise<MergeResult[]> {
|
|
85
|
+
// Sort stories in topological order
|
|
86
|
+
const orderedStories = this.topologicalSort(storyIds, dependencies);
|
|
87
|
+
const results: MergeResult[] = [];
|
|
88
|
+
const failedStories = new Set<string>();
|
|
89
|
+
|
|
90
|
+
for (const storyId of orderedStories) {
|
|
91
|
+
// Check if any dependencies failed
|
|
92
|
+
const deps = dependencies[storyId] || [];
|
|
93
|
+
const hasFailedDeps = deps.some((dep) => failedStories.has(dep));
|
|
94
|
+
|
|
95
|
+
if (hasFailedDeps) {
|
|
96
|
+
results.push({
|
|
97
|
+
success: false,
|
|
98
|
+
storyId,
|
|
99
|
+
conflictFiles: [],
|
|
100
|
+
});
|
|
101
|
+
failedStories.add(storyId);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Try to merge
|
|
106
|
+
let result = await this.merge(projectRoot, storyId);
|
|
107
|
+
|
|
108
|
+
// If conflict, retry once after rebasing
|
|
109
|
+
if (!result.success && result.conflictFiles) {
|
|
110
|
+
try {
|
|
111
|
+
// Rebase worktree on updated base
|
|
112
|
+
await this.rebaseWorktree(projectRoot, storyId);
|
|
113
|
+
|
|
114
|
+
// Retry merge
|
|
115
|
+
result = await this.merge(projectRoot, storyId);
|
|
116
|
+
|
|
117
|
+
// If still fails, mark as failed
|
|
118
|
+
if (!result.success) {
|
|
119
|
+
results.push({
|
|
120
|
+
success: false,
|
|
121
|
+
storyId,
|
|
122
|
+
conflictFiles: result.conflictFiles,
|
|
123
|
+
retryCount: 1,
|
|
124
|
+
});
|
|
125
|
+
failedStories.add(storyId);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Success after retry
|
|
130
|
+
results.push({
|
|
131
|
+
success: true,
|
|
132
|
+
storyId,
|
|
133
|
+
retryCount: 1,
|
|
134
|
+
});
|
|
135
|
+
} catch (error) {
|
|
136
|
+
// Rebase failed, mark as failed
|
|
137
|
+
results.push({
|
|
138
|
+
success: false,
|
|
139
|
+
storyId,
|
|
140
|
+
conflictFiles: result.conflictFiles,
|
|
141
|
+
retryCount: 1,
|
|
142
|
+
});
|
|
143
|
+
failedStories.add(storyId);
|
|
144
|
+
}
|
|
145
|
+
} else if (result.success) {
|
|
146
|
+
// First attempt succeeded
|
|
147
|
+
results.push({
|
|
148
|
+
success: true,
|
|
149
|
+
storyId,
|
|
150
|
+
retryCount: 0,
|
|
151
|
+
});
|
|
152
|
+
} else {
|
|
153
|
+
// Failed without conflicts (shouldn't happen normally)
|
|
154
|
+
results.push({
|
|
155
|
+
success: false,
|
|
156
|
+
storyId,
|
|
157
|
+
retryCount: 0,
|
|
158
|
+
});
|
|
159
|
+
failedStories.add(storyId);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return results;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Topological sort of stories based on dependencies
|
|
168
|
+
* Returns stories in order where dependencies come before dependents
|
|
169
|
+
*/
|
|
170
|
+
private topologicalSort(storyIds: string[], dependencies: StoryDependencies): string[] {
|
|
171
|
+
const visited = new Set<string>();
|
|
172
|
+
const sorted: string[] = [];
|
|
173
|
+
const visiting = new Set<string>();
|
|
174
|
+
|
|
175
|
+
const visit = (storyId: string) => {
|
|
176
|
+
if (visited.has(storyId)) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (visiting.has(storyId)) {
|
|
181
|
+
throw new Error(`Circular dependency detected involving ${storyId}`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
visiting.add(storyId);
|
|
185
|
+
|
|
186
|
+
// Visit dependencies first
|
|
187
|
+
const deps = dependencies[storyId] || [];
|
|
188
|
+
for (const dep of deps) {
|
|
189
|
+
if (storyIds.includes(dep)) {
|
|
190
|
+
visit(dep);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
visiting.delete(storyId);
|
|
195
|
+
visited.add(storyId);
|
|
196
|
+
sorted.push(storyId);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
for (const storyId of storyIds) {
|
|
200
|
+
visit(storyId);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return sorted;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Rebases worktree on current base branch
|
|
208
|
+
*/
|
|
209
|
+
private async rebaseWorktree(projectRoot: string, storyId: string): Promise<void> {
|
|
210
|
+
const worktreePath = `${projectRoot}/.nax-wt/${storyId}`;
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
// Get current branch name from main repo
|
|
214
|
+
const currentBranchProc = Bun.spawn(["git", "rev-parse", "--abbrev-ref", "HEAD"], {
|
|
215
|
+
cwd: projectRoot,
|
|
216
|
+
stdout: "pipe",
|
|
217
|
+
stderr: "pipe",
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
const exitCode = await currentBranchProc.exited;
|
|
221
|
+
if (exitCode !== 0) {
|
|
222
|
+
throw new Error("Failed to get current branch");
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const currentBranch = (await new Response(currentBranchProc.stdout).text()).trim();
|
|
226
|
+
|
|
227
|
+
// Rebase worktree branch onto current branch
|
|
228
|
+
const rebaseProc = Bun.spawn(["git", "rebase", currentBranch], {
|
|
229
|
+
cwd: worktreePath,
|
|
230
|
+
stdout: "pipe",
|
|
231
|
+
stderr: "pipe",
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
const rebaseExitCode = await rebaseProc.exited;
|
|
235
|
+
if (rebaseExitCode !== 0) {
|
|
236
|
+
const stderr = await new Response(rebaseProc.stderr).text();
|
|
237
|
+
|
|
238
|
+
// Abort rebase on failure
|
|
239
|
+
await Bun.spawn(["git", "rebase", "--abort"], {
|
|
240
|
+
cwd: worktreePath,
|
|
241
|
+
stdout: "pipe",
|
|
242
|
+
stderr: "pipe",
|
|
243
|
+
}).exited;
|
|
244
|
+
|
|
245
|
+
throw new Error(`Rebase failed: ${stderr || "unknown error"}`);
|
|
246
|
+
}
|
|
247
|
+
} catch (error) {
|
|
248
|
+
if (error instanceof Error) {
|
|
249
|
+
throw error;
|
|
250
|
+
}
|
|
251
|
+
throw new Error(`Failed to rebase worktree ${storyId}: ${String(error)}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Gets list of conflicted files
|
|
257
|
+
*/
|
|
258
|
+
private async getConflictFiles(projectRoot: string): Promise<string[]> {
|
|
259
|
+
try {
|
|
260
|
+
const proc = Bun.spawn(["git", "diff", "--name-only", "--diff-filter=U"], {
|
|
261
|
+
cwd: projectRoot,
|
|
262
|
+
stdout: "pipe",
|
|
263
|
+
stderr: "pipe",
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
const exitCode = await proc.exited;
|
|
267
|
+
if (exitCode !== 0) {
|
|
268
|
+
return [];
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const stdout = await new Response(proc.stdout).text();
|
|
272
|
+
return stdout
|
|
273
|
+
.trim()
|
|
274
|
+
.split("\n")
|
|
275
|
+
.filter((line) => line.length > 0);
|
|
276
|
+
} catch {
|
|
277
|
+
return [];
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Aborts an in-progress merge
|
|
283
|
+
*/
|
|
284
|
+
private async abortMerge(projectRoot: string): Promise<void> {
|
|
285
|
+
try {
|
|
286
|
+
const proc = Bun.spawn(["git", "merge", "--abort"], {
|
|
287
|
+
cwd: projectRoot,
|
|
288
|
+
stdout: "pipe",
|
|
289
|
+
stderr: "pipe",
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
await proc.exited;
|
|
293
|
+
} catch (error) {
|
|
294
|
+
// Log warning but don't throw - merge might already be aborted
|
|
295
|
+
const logger = getSafeLogger();
|
|
296
|
+
logger?.warn("worktree", "Failed to abort merge", {
|
|
297
|
+
error: error instanceof Error ? error.message : String(error),
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Test Coverage for US-001: Precheck types and check implementations
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
Created comprehensive failing tests for the precheck system. All tests fail with "Not implemented" errors as expected.
|
|
6
|
+
|
|
7
|
+
## Test Files Created/Verified
|
|
8
|
+
|
|
9
|
+
### 1. `test/unit/precheck-types.test.ts` (13 tests) ✅ PASSING
|
|
10
|
+
Tests the type definitions only - these pass because TypeScript validates structure at compile time.
|
|
11
|
+
|
|
12
|
+
**Coverage:**
|
|
13
|
+
- PrecheckResult type structure (blockers[], warnings[] arrays)
|
|
14
|
+
- Check type structure (name, tier, passed, message fields)
|
|
15
|
+
- CheckTier type values ("blocker", "warning")
|
|
16
|
+
- CheckStatus type values ("passed", "failed", "skipped")
|
|
17
|
+
|
|
18
|
+
### 2. `test/unit/precheck-checks.test.ts` (55 tests) ❌ FAILING (as expected)
|
|
19
|
+
Tests individual check implementations.
|
|
20
|
+
|
|
21
|
+
#### Tier 1 Blocker Tests (33 tests):
|
|
22
|
+
1. **checkGitRepoExists** (3 tests)
|
|
23
|
+
- ✅ Passes when .git directory exists
|
|
24
|
+
- ✅ Fails when .git directory does not exist
|
|
25
|
+
- ✅ Uses git rev-parse --git-dir command
|
|
26
|
+
|
|
27
|
+
2. **checkWorkingTreeClean** (3 tests)
|
|
28
|
+
- ✅ Uses git status --porcelain command
|
|
29
|
+
- ✅ Returns blocker tier
|
|
30
|
+
- ✅ Includes helpful message
|
|
31
|
+
|
|
32
|
+
3. **checkStaleLock** (4 tests)
|
|
33
|
+
- ✅ Passes when no lock file exists
|
|
34
|
+
- ✅ Passes when lock file is fresh (< 2 hours old)
|
|
35
|
+
- ✅ Fails when lock file is stale (> 2 hours old)
|
|
36
|
+
- ✅ Detects exactly 2 hours as the threshold
|
|
37
|
+
|
|
38
|
+
4. **checkPRDValid** (6 tests)
|
|
39
|
+
- ✅ Passes when all stories have required fields
|
|
40
|
+
- ✅ Fails when story is missing id
|
|
41
|
+
- ✅ Fails when story is missing title
|
|
42
|
+
- ✅ Fails when story is missing description
|
|
43
|
+
- ✅ Auto-defaults missing tags to empty array in-memory
|
|
44
|
+
- ✅ Auto-defaults missing status to pending in-memory
|
|
45
|
+
- ✅ Auto-defaults missing storyPoints to 1 in-memory
|
|
46
|
+
- ✅ Checks all required fields per story
|
|
47
|
+
|
|
48
|
+
5. **checkClaudeCLI** (3 tests)
|
|
49
|
+
- ✅ Runs claude --version command
|
|
50
|
+
- ✅ Returns blocker tier
|
|
51
|
+
- ✅ Provides helpful error message on failure
|
|
52
|
+
|
|
53
|
+
6. **checkDependenciesInstalled** (6 tests)
|
|
54
|
+
- ✅ Detects Node.js dependencies via node_modules
|
|
55
|
+
- ✅ Detects Rust dependencies via target directory
|
|
56
|
+
- ✅ Detects Python dependencies via venv directory
|
|
57
|
+
- ✅ Detects PHP dependencies via vendor directory
|
|
58
|
+
- ✅ Fails when no dependency directories exist
|
|
59
|
+
- ✅ Is language-aware and checks all supported package managers
|
|
60
|
+
|
|
61
|
+
7. **checkTestCommand** (4 tests)
|
|
62
|
+
- ✅ Passes when test command is configured
|
|
63
|
+
- ✅ Skips silently when test command is null
|
|
64
|
+
- ✅ Skips silently when test command is false
|
|
65
|
+
- ✅ Reads command from config.execution
|
|
66
|
+
|
|
67
|
+
8. **checkLintCommand** (4 tests)
|
|
68
|
+
- ✅ Passes when lint command is configured
|
|
69
|
+
- ✅ Skips silently when lint command is null
|
|
70
|
+
- ✅ Skips silently when lint command is false
|
|
71
|
+
- ✅ Reads command from config.execution
|
|
72
|
+
|
|
73
|
+
9. **checkTypecheckCommand** (4 tests)
|
|
74
|
+
- ✅ Passes when typecheck command is configured
|
|
75
|
+
- ✅ Skips silently when typecheck command is null
|
|
76
|
+
- ✅ Skips silently when typecheck command is false
|
|
77
|
+
- ✅ Reads command from config.execution
|
|
78
|
+
|
|
79
|
+
10. **checkGitUserConfigured** (3 tests)
|
|
80
|
+
- ✅ Checks git config user.name and user.email
|
|
81
|
+
- ✅ Returns blocker tier
|
|
82
|
+
- ✅ Provides helpful message
|
|
83
|
+
|
|
84
|
+
#### Tier 2 Warning Tests (22 tests):
|
|
85
|
+
1. **checkClaudeMdExists** (3 tests)
|
|
86
|
+
- ✅ Passes when CLAUDE.md exists
|
|
87
|
+
- ✅ Fails when CLAUDE.md does not exist
|
|
88
|
+
- ✅ Returns warning tier not blocker
|
|
89
|
+
|
|
90
|
+
2. **checkDiskSpace** (4 tests)
|
|
91
|
+
- ✅ Passes when disk space is above 1GB
|
|
92
|
+
- ✅ Fails when disk space is below 1GB
|
|
93
|
+
- ✅ Triggers warning below 1GB threshold
|
|
94
|
+
- ✅ Provides disk space information in message
|
|
95
|
+
|
|
96
|
+
3. **checkPendingStories** (3 tests)
|
|
97
|
+
- ✅ Passes when there are pending stories
|
|
98
|
+
- ✅ Warns when all stories are passed
|
|
99
|
+
- ✅ Counts pending and in-progress as actionable
|
|
100
|
+
|
|
101
|
+
4. **checkOptionalCommands** (3 tests)
|
|
102
|
+
- ✅ Warns when optional commands are missing
|
|
103
|
+
- ✅ Passes when all optional commands are configured
|
|
104
|
+
- ✅ Lists which commands are missing
|
|
105
|
+
|
|
106
|
+
5. **checkGitignoreCoversNax** (6 tests)
|
|
107
|
+
- ✅ Passes when .gitignore exists and covers nax runtime files
|
|
108
|
+
- ✅ Fails when .gitignore does not exist
|
|
109
|
+
- ✅ Fails when .gitignore exists but does not cover nax.lock
|
|
110
|
+
- ✅ Fails when .gitignore exists but does not cover runs directories
|
|
111
|
+
- ✅ Fails when .gitignore exists but does not cover test/tmp
|
|
112
|
+
- ✅ Checks all three nax runtime file patterns
|
|
113
|
+
|
|
114
|
+
### 3. `test/integration/precheck.test.ts` (25 tests) ❌ FAILING (as expected)
|
|
115
|
+
Integration tests for the complete precheck workflow.
|
|
116
|
+
|
|
117
|
+
**Coverage:**
|
|
118
|
+
- ✅ Returns PrecheckResult with blockers and warnings arrays
|
|
119
|
+
- ✅ Separates blocker checks from warning checks
|
|
120
|
+
- ✅ Includes all 10 blocker checks
|
|
121
|
+
- ✅ Includes all 5 warning checks
|
|
122
|
+
- ✅ Auto-defaults missing PRD fields in-memory during validation
|
|
123
|
+
- ✅ Handles PRD with multiple stories
|
|
124
|
+
- ✅ Detects invalid PRD with missing required fields
|
|
125
|
+
- ✅ Skips command checks when commands are set to null
|
|
126
|
+
- ✅ Completes all checks even if some fail
|
|
127
|
+
- ✅ Provides detailed messages for each check
|
|
128
|
+
- ✅ Stale lock detection (2 tests)
|
|
129
|
+
- ✅ .gitignore validation (4 tests)
|
|
130
|
+
|
|
131
|
+
## Source Files Created
|
|
132
|
+
|
|
133
|
+
### 1. `src/precheck/types.ts`
|
|
134
|
+
Type definitions for:
|
|
135
|
+
- `CheckTier` = "blocker" | "warning"
|
|
136
|
+
- `CheckStatus` = "passed" | "failed" | "skipped"
|
|
137
|
+
- `Check` interface (name, tier, passed, message)
|
|
138
|
+
- `PrecheckResult` interface (blockers[], warnings[])
|
|
139
|
+
|
|
140
|
+
### 2. `src/precheck/checks.ts`
|
|
141
|
+
Stub implementations for all check functions:
|
|
142
|
+
- 10 Tier 1 blocker checks
|
|
143
|
+
- 5 Tier 2 warning checks
|
|
144
|
+
- All throw "Not implemented" errors
|
|
145
|
+
|
|
146
|
+
### 3. `src/precheck/index.ts`
|
|
147
|
+
Stub for runPrecheck orchestrator (US-002):
|
|
148
|
+
- `runPrecheck(config, prd)` - throws "Not implemented" with note about US-002
|
|
149
|
+
|
|
150
|
+
## Acceptance Criteria Coverage
|
|
151
|
+
|
|
152
|
+
✅ **AC1:** PrecheckResult type includes blockers[] and warnings[] arrays
|
|
153
|
+
- Verified in test/unit/precheck-types.test.ts
|
|
154
|
+
|
|
155
|
+
✅ **AC2:** Git repo check uses git rev-parse --git-dir
|
|
156
|
+
- Verified in test/unit/precheck-checks.test.ts
|
|
157
|
+
|
|
158
|
+
✅ **AC3:** Working tree check uses git status --porcelain
|
|
159
|
+
- Verified in test/unit/precheck-checks.test.ts
|
|
160
|
+
|
|
161
|
+
✅ **AC4:** Stale lock detection: nax.lock older than 2 hours
|
|
162
|
+
- Verified in test/unit/precheck-checks.test.ts (4 tests)
|
|
163
|
+
|
|
164
|
+
✅ **AC5:** PRD validation checks id, title, description per story
|
|
165
|
+
- Verified in test/unit/precheck-checks.test.ts (8 tests)
|
|
166
|
+
|
|
167
|
+
✅ **AC6:** PRD auto-defaults missing optional fields in-memory
|
|
168
|
+
- Verified in test/unit/precheck-checks.test.ts (3 tests)
|
|
169
|
+
- tags=[], status=pending, storyPoints=1
|
|
170
|
+
|
|
171
|
+
✅ **AC7:** Claude CLI check runs claude --version
|
|
172
|
+
- Verified in test/unit/precheck-checks.test.ts
|
|
173
|
+
|
|
174
|
+
✅ **AC8:** Dependency detection is language-aware
|
|
175
|
+
- Verified in test/unit/precheck-checks.test.ts (6 tests)
|
|
176
|
+
- node_modules, target, venv, vendor
|
|
177
|
+
|
|
178
|
+
✅ **AC9:** Test/lint/typecheck commands read from config.execution
|
|
179
|
+
- Verified in test/unit/precheck-checks.test.ts (12 tests)
|
|
180
|
+
|
|
181
|
+
✅ **AC10:** Commands set to null/false are skipped silently
|
|
182
|
+
- Verified in test/unit/precheck-checks.test.ts (6 tests)
|
|
183
|
+
|
|
184
|
+
✅ **AC11:** Disk space warning triggers below 1GB
|
|
185
|
+
- Verified in test/unit/precheck-checks.test.ts (4 tests)
|
|
186
|
+
|
|
187
|
+
✅ **AC12:** .gitignore warning if missing or does not cover nax runtime files
|
|
188
|
+
- Verified in test/unit/precheck-checks.test.ts (6 tests)
|
|
189
|
+
- Checks: nax.lock, nax/features/*/runs/, test/tmp/
|
|
190
|
+
|
|
191
|
+
## Test Execution Results
|
|
192
|
+
|
|
193
|
+
### Unit Tests - Types
|
|
194
|
+
```
|
|
195
|
+
bun test ./test/unit/precheck-types.test.ts
|
|
196
|
+
✅ 13 pass, 0 fail, 20 expect() calls
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Unit Tests - Checks
|
|
200
|
+
```
|
|
201
|
+
bun test ./test/unit/precheck-checks.test.ts
|
|
202
|
+
❌ All tests fail with "Not implemented" errors (expected behavior)
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Integration Tests
|
|
206
|
+
```
|
|
207
|
+
bun test ./test/integration/precheck.test.ts
|
|
208
|
+
❌ All tests fail with "Not implemented" errors (expected behavior)
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Next Steps
|
|
212
|
+
|
|
213
|
+
The implementer (Session 2) should now implement:
|
|
214
|
+
1. All check functions in `src/precheck/checks.ts`
|
|
215
|
+
2. The `runPrecheck` orchestrator in `src/precheck/index.ts` (for US-002)
|
|
216
|
+
|
|
217
|
+
All tests are ready and will validate correct implementation behavior.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Test Coverage: US-003 - CLI nax precheck command
|
|
2
|
+
|
|
3
|
+
## Story: US-003
|
|
4
|
+
CLI nax precheck command with --json flag
|
|
5
|
+
|
|
6
|
+
## Test File
|
|
7
|
+
`test/integration/cli-precheck.test.ts` - 7 tests
|
|
8
|
+
|
|
9
|
+
## Coverage
|
|
10
|
+
|
|
11
|
+
### 1. Command Registration
|
|
12
|
+
✅ Command is registered as `nax precheck`
|
|
13
|
+
✅ Supports `-f, --feature <name>` flag
|
|
14
|
+
✅ Supports `-d, --dir <path>` flag
|
|
15
|
+
✅ Supports `--json` flag
|
|
16
|
+
|
|
17
|
+
### 2. Project Resolution
|
|
18
|
+
✅ Uses `resolveProject()` from common.ts (US-001)
|
|
19
|
+
✅ Resolves project directory with `-d` flag
|
|
20
|
+
✅ Resolves feature directory from `-f` flag or config.json
|
|
21
|
+
✅ Validates nax/ directory exists
|
|
22
|
+
✅ Validates prd.json exists
|
|
23
|
+
|
|
24
|
+
### 3. Output Formats
|
|
25
|
+
✅ Human-readable format (default) - emoji indicators (✓/✗/⚠)
|
|
26
|
+
✅ Machine-readable JSON format (--json flag)
|
|
27
|
+
✅ JSON includes: passed, blockers, warnings, summary, feature
|
|
28
|
+
|
|
29
|
+
### 4. Exit Codes
|
|
30
|
+
✅ Exit code 0 - All checks passed (or warnings only)
|
|
31
|
+
✅ Exit code 1 - Blocker detected
|
|
32
|
+
✅ Exit code 2 - Invalid PRD (missing prd.json or invalid structure)
|
|
33
|
+
|
|
34
|
+
### 5. Error Handling
|
|
35
|
+
✅ Missing feature flag with no config.json feature - exit 1
|
|
36
|
+
✅ Missing prd.json - exit 2
|
|
37
|
+
✅ Invalid PRD structure - exit 2
|
|
38
|
+
✅ Missing feature directory - proper error message
|
|
39
|
+
|
|
40
|
+
## Test Structure
|
|
41
|
+
- Uses temp directories for isolation
|
|
42
|
+
- Sets up minimal git repo to satisfy checks
|
|
43
|
+
- Mocks process.exit to capture exit codes
|
|
44
|
+
- Tests both human and JSON output formats
|
|
45
|
+
|
|
46
|
+
## Integration Points
|
|
47
|
+
- ✅ Uses resolveProject() from src/commands/common.ts
|
|
48
|
+
- ✅ Uses runPrecheck() from src/precheck/index.ts
|
|
49
|
+
- ✅ Uses loadConfig() from src/config
|
|
50
|
+
- ✅ Uses loadPRD() from src/prd
|
|
51
|
+
- ✅ Respects EXIT_CODES from src/precheck
|
|
52
|
+
|
|
53
|
+
## Verified Behavior
|
|
54
|
+
1. Command registered in bin/nax.ts
|
|
55
|
+
2. Exported from src/commands/index.ts
|
|
56
|
+
3. Uses same project resolution as `nax status` and `nax logs`
|
|
57
|
+
4. Fail-fast on Tier 1 blockers
|
|
58
|
+
5. Collects all Tier 2 warnings
|
|
59
|
+
6. Proper exit codes for automation/CI
|
|
60
|
+
|
|
61
|
+
## Manual Testing
|
|
62
|
+
```bash
|
|
63
|
+
# Human format (default)
|
|
64
|
+
nax precheck -f precheck
|
|
65
|
+
# Exit code: 0 (warnings only)
|
|
66
|
+
|
|
67
|
+
# JSON format
|
|
68
|
+
nax precheck -f precheck --json
|
|
69
|
+
# Output: {"passed":true,"feature":"precheck","summary":{...}}
|
|
70
|
+
|
|
71
|
+
# Explicit directory
|
|
72
|
+
nax precheck -f precheck -d /path/to/project
|
|
73
|
+
|
|
74
|
+
# Missing feature
|
|
75
|
+
nax precheck
|
|
76
|
+
# Error: No feature specified
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Coverage Summary
|
|
80
|
+
- 7 integration tests
|
|
81
|
+
- All acceptance criteria verified
|
|
82
|
+
- All flags tested
|
|
83
|
+
- All exit codes tested
|
|
84
|
+
- Error paths covered
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Test Coverage: US-005 Config-Driven Review Commands
|
|
2
|
+
|
|
3
|
+
## Story
|
|
4
|
+
Config-driven review commands replacing hardcoded lint
|
|
5
|
+
|
|
6
|
+
## Implementation Summary
|
|
7
|
+
|
|
8
|
+
### Files Modified
|
|
9
|
+
1. **src/config/schema.ts**
|
|
10
|
+
- Added `lintCommand?: string | null` to `ExecutionConfig`
|
|
11
|
+
- Added `typecheckCommand?: string | null` to `ExecutionConfig`
|
|
12
|
+
- Updated `ExecutionConfigSchema` to validate these fields
|
|
13
|
+
|
|
14
|
+
2. **src/review/runner.ts**
|
|
15
|
+
- Added `loadPackageJson()` - loads package.json from workdir
|
|
16
|
+
- Added `hasScript()` - checks if package.json has a script
|
|
17
|
+
- Added `resolveCommand()` - implements resolution strategy
|
|
18
|
+
- Modified `runReview()` - accepts optional `executionConfig` parameter
|
|
19
|
+
- Implements command resolution order:
|
|
20
|
+
1. `executionConfig.lintCommand` / `executionConfig.typecheckCommand` (null = disabled)
|
|
21
|
+
2. `config.review.commands[check]` (legacy, backwards compat)
|
|
22
|
+
3. package.json scripts -> `bun run <script>`
|
|
23
|
+
4. Not found -> skip with warning
|
|
24
|
+
|
|
25
|
+
3. **src/pipeline/stages/review.ts**
|
|
26
|
+
- Updated `runReview()` call to pass `ctx.config.execution`
|
|
27
|
+
|
|
28
|
+
### Test Coverage
|
|
29
|
+
|
|
30
|
+
**New Tests: test/integration/review-config-commands.test.ts (12 tests)**
|
|
31
|
+
- ✅ uses explicit executionConfig.lintCommand when provided
|
|
32
|
+
- ✅ uses explicit executionConfig.typecheckCommand when provided
|
|
33
|
+
- ✅ skips check when executionConfig command is null (explicitly disabled)
|
|
34
|
+
- ✅ uses package.json script when no executionConfig override
|
|
35
|
+
- ✅ skips check when package.json script not found
|
|
36
|
+
- ✅ executionConfig takes precedence over package.json
|
|
37
|
+
- ✅ reviewConfig.commands takes precedence over package.json (backwards compat)
|
|
38
|
+
- ✅ executionConfig takes precedence over reviewConfig.commands
|
|
39
|
+
- ✅ handles missing package.json gracefully
|
|
40
|
+
- ✅ handles invalid package.json gracefully
|
|
41
|
+
- ✅ resolution order: executionConfig > reviewConfig > package.json
|
|
42
|
+
- ✅ test command ignores executionConfig (not affected by this story)
|
|
43
|
+
|
|
44
|
+
**Updated Tests: test/integration/review.test.ts**
|
|
45
|
+
- ✅ Modified "uses default commands when not specified" test to match new behavior
|
|
46
|
+
|
|
47
|
+
## Acceptance Criteria Coverage
|
|
48
|
+
|
|
49
|
+
| Criterion | Status | Evidence |
|
|
50
|
+
|-----------|--------|----------|
|
|
51
|
+
| Review stage reads lintCommand from config.execution | ✅ | `test/integration/review-config-commands.test.ts:23-37` |
|
|
52
|
+
| Review stage reads typecheckCommand from config.execution | ✅ | `test/integration/review-config-commands.test.ts:39-53` |
|
|
53
|
+
| Resolution order: config -> package.json -> skip | ✅ | `test/integration/review-config-commands.test.ts:185-214` |
|
|
54
|
+
| Setting command to null/false explicitly disables it | ✅ | `test/integration/review-config-commands.test.ts:55-71` |
|
|
55
|
+
| Missing command logs warning instead of failing | ✅ | `src/review/runner.ts:140-143` + test output shows warnings |
|
|
56
|
+
| Config schema updated with lintCommand and typecheckCommand fields | ✅ | `src/config/schema.ts:113-114` |
|
|
57
|
+
| BUG-005 (hardcoded bun run lint) is resolved | ✅ | No hardcoded commands, all resolved via strategy |
|
|
58
|
+
|
|
59
|
+
## Behavior Changes
|
|
60
|
+
|
|
61
|
+
### Before
|
|
62
|
+
- Always used hardcoded defaults: `bun run lint`, `bun run typecheck`, `bun test`
|
|
63
|
+
- Commands from `config.review.commands` could override defaults
|
|
64
|
+
- No way to explicitly disable a check without removing it from `checks` array
|
|
65
|
+
|
|
66
|
+
### After
|
|
67
|
+
- Command resolution follows priority:
|
|
68
|
+
1. `config.execution.lintCommand` / `typecheckCommand` (highest priority)
|
|
69
|
+
2. `config.review.commands[check]` (legacy, for backwards compatibility)
|
|
70
|
+
3. package.json scripts (auto-detected)
|
|
71
|
+
4. Skip with warning (no command found)
|
|
72
|
+
- Setting `lintCommand: null` explicitly disables lint check
|
|
73
|
+
- Missing commands no longer fail - they skip with a warning
|
|
74
|
+
|
|
75
|
+
## Backwards Compatibility
|
|
76
|
+
|
|
77
|
+
✅ **Fully backwards compatible**
|
|
78
|
+
- Existing configs using `config.review.commands` continue to work
|
|
79
|
+
- Projects without explicit config fall back to package.json detection
|
|
80
|
+
- No breaking changes to existing APIs
|
|
81
|
+
|
|
82
|
+
## Notes
|
|
83
|
+
|
|
84
|
+
- `test` command intentionally NOT added to `ExecutionConfig` (not part of this story scope)
|
|
85
|
+
- Resolution order ensures maximum flexibility: explicit config > legacy config > auto-detect > skip
|
|
86
|
+
- Warning messages logged when commands are skipped for debugging visibility
|