@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,468 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for precheck integration with nax run
|
|
3
|
+
*
|
|
4
|
+
* Tests US-004: Integrate precheck into nax run
|
|
5
|
+
* - AC1: Precheck runs automatically before first story
|
|
6
|
+
* - AC2: Tier 1 blocker aborts run with descriptive error
|
|
7
|
+
* - AC3: Tier 2 warnings logged but don't block execution
|
|
8
|
+
* - AC4: --skip-precheck flag bypasses all checks
|
|
9
|
+
* - AC5: Precheck results included in run JSONL log
|
|
10
|
+
* - AC6: Failed precheck updates status.json with precheck-failed status
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
14
|
+
|
|
15
|
+
// Skip in CI: these tests call run() which invokes the full nax execution pipeline
|
|
16
|
+
// including spawning real agent subprocesses. CI runners lack the claude binary and
|
|
17
|
+
// have restricted process/file system environments. These are end-to-end smoke tests
|
|
18
|
+
// that must run in a properly configured dev environment (local, Mac01, or VPS).
|
|
19
|
+
const skipInCI = process.env.CI ? test.skip : test;
|
|
20
|
+
import { mkdirSync, rmSync } from "node:fs";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
import type { NaxConfig } from "../../src/config";
|
|
23
|
+
import { DEFAULT_CONFIG } from "../../src/config";
|
|
24
|
+
import { run } from "../../src/execution";
|
|
25
|
+
import type { PRD } from "../../src/prd";
|
|
26
|
+
import { loadPRD } from "../../src/prd";
|
|
27
|
+
|
|
28
|
+
describe("Precheck Integration with nax run", () => {
|
|
29
|
+
let testDir: string;
|
|
30
|
+
let savedSkipPrecheck: string | undefined;
|
|
31
|
+
|
|
32
|
+
beforeEach(async () => {
|
|
33
|
+
// Temporarily remove NAX_SKIP_PRECHECK so precheck actually runs in these tests
|
|
34
|
+
savedSkipPrecheck = process.env.NAX_SKIP_PRECHECK;
|
|
35
|
+
delete process.env.NAX_SKIP_PRECHECK;
|
|
36
|
+
|
|
37
|
+
testDir = join(import.meta.dir, "..", "..", ".tmp", `precheck-integration-${Date.now()}`);
|
|
38
|
+
mkdirSync(testDir, { recursive: true });
|
|
39
|
+
|
|
40
|
+
// Initialize as git repo to pass git checks
|
|
41
|
+
const { spawnSync } = await import("bun");
|
|
42
|
+
spawnSync(["git", "init"], { cwd: testDir });
|
|
43
|
+
spawnSync(["git", "config", "user.name", "Test User"], { cwd: testDir });
|
|
44
|
+
spawnSync(["git", "config", "user.email", "test@example.com"], { cwd: testDir });
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
afterEach(() => {
|
|
48
|
+
// Restore NAX_SKIP_PRECHECK to its original value
|
|
49
|
+
if (savedSkipPrecheck !== undefined) {
|
|
50
|
+
process.env.NAX_SKIP_PRECHECK = savedSkipPrecheck;
|
|
51
|
+
} else {
|
|
52
|
+
delete process.env.NAX_SKIP_PRECHECK;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
57
|
+
} catch (error) {
|
|
58
|
+
// Ignore cleanup errors
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Helper to create a basic PRD with one simple story
|
|
64
|
+
*/
|
|
65
|
+
function createBasicPRD(feature: string): PRD {
|
|
66
|
+
return {
|
|
67
|
+
feature,
|
|
68
|
+
project: "test-project",
|
|
69
|
+
branchName: `feat/${feature}`,
|
|
70
|
+
userStories: [
|
|
71
|
+
{
|
|
72
|
+
id: "US-001",
|
|
73
|
+
title: "Test Story",
|
|
74
|
+
description: "A test story",
|
|
75
|
+
acceptanceCriteria: ["Story works"],
|
|
76
|
+
status: "pending",
|
|
77
|
+
dependencies: [],
|
|
78
|
+
tags: [],
|
|
79
|
+
estimatedComplexity: "simple",
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Helper to create feature directory and PRD file
|
|
87
|
+
*/
|
|
88
|
+
async function setupFeature(feature: string): Promise<string> {
|
|
89
|
+
const naxDir = join(testDir, "nax");
|
|
90
|
+
const featuresDir = join(naxDir, "features");
|
|
91
|
+
const featureDir = join(featuresDir, feature);
|
|
92
|
+
mkdirSync(featureDir, { recursive: true });
|
|
93
|
+
|
|
94
|
+
// Create .gitignore to exclude nax runtime files
|
|
95
|
+
await Bun.write(join(testDir, ".gitignore"), "nax.lock\n*.jsonl\nstatus.json\n.nax-wt/\n");
|
|
96
|
+
|
|
97
|
+
// Create dummy package.json and node_modules to pass dependency check
|
|
98
|
+
await Bun.write(join(testDir, "package.json"), JSON.stringify({ name: "test", version: "1.0.0" }, null, 2));
|
|
99
|
+
mkdirSync(join(testDir, "node_modules"), { recursive: true });
|
|
100
|
+
|
|
101
|
+
const prd = createBasicPRD(feature);
|
|
102
|
+
const prdPath = join(featureDir, "prd.json");
|
|
103
|
+
await Bun.write(prdPath, JSON.stringify(prd, null, 2));
|
|
104
|
+
|
|
105
|
+
// Commit the PRD file and .gitignore to avoid "working tree not clean" errors
|
|
106
|
+
const { spawnSync } = await import("bun");
|
|
107
|
+
spawnSync(["git", "add", "."], { cwd: testDir });
|
|
108
|
+
spawnSync(["git", "commit", "-m", `Setup ${feature} feature`], { cwd: testDir });
|
|
109
|
+
|
|
110
|
+
return prdPath;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Helper to read JSONL log and parse precheck entry
|
|
115
|
+
*/
|
|
116
|
+
async function readPrecheckLog(logFilePath: string): Promise<any | null> {
|
|
117
|
+
const logFile = Bun.file(logFilePath);
|
|
118
|
+
if (!(await logFile.exists())) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const content = await logFile.text();
|
|
123
|
+
const lines = content.trim().split("\n");
|
|
124
|
+
|
|
125
|
+
for (const line of lines) {
|
|
126
|
+
const entry = JSON.parse(line);
|
|
127
|
+
if (entry.type === "precheck") {
|
|
128
|
+
return entry;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Helper to read status.json
|
|
137
|
+
*/
|
|
138
|
+
async function readStatusFile(statusFilePath: string): Promise<any | null> {
|
|
139
|
+
const statusFile = Bun.file(statusFilePath);
|
|
140
|
+
if (!(await statusFile.exists())) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return await statusFile.json();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
148
|
+
// AC4: --skip-precheck flag bypasses all checks
|
|
149
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
150
|
+
|
|
151
|
+
test("AC4: --skip-precheck bypasses precheck validations", async () => {
|
|
152
|
+
// Create non-git temp directory (will fail precheck)
|
|
153
|
+
const nonGitDir = join(import.meta.dir, "..", "..", ".tmp", `non-git-${Date.now()}`);
|
|
154
|
+
mkdirSync(nonGitDir, { recursive: true });
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
const prdPath = await setupFeature("skip-test");
|
|
158
|
+
const logFilePath = join(nonGitDir, "nax", "features", "skip-test", "runs", "test.jsonl");
|
|
159
|
+
const statusFilePath = join(nonGitDir, "nax", "features", "skip-test", "status.json");
|
|
160
|
+
|
|
161
|
+
const config: NaxConfig = {
|
|
162
|
+
...DEFAULT_CONFIG,
|
|
163
|
+
execution: {
|
|
164
|
+
...DEFAULT_CONFIG.execution,
|
|
165
|
+
maxIterations: 1,
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Run with skipPrecheck: true (should succeed even without git repo)
|
|
170
|
+
const result = await run({
|
|
171
|
+
prdPath,
|
|
172
|
+
workdir: nonGitDir,
|
|
173
|
+
config,
|
|
174
|
+
hooks: { hooks: {} },
|
|
175
|
+
feature: "skip-test",
|
|
176
|
+
dryRun: true, // Use dry-run to avoid actual agent execution
|
|
177
|
+
skipPrecheck: true,
|
|
178
|
+
logFilePath,
|
|
179
|
+
statusFile: statusFilePath,
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Should complete without error
|
|
183
|
+
expect(result.success).toBe(true);
|
|
184
|
+
|
|
185
|
+
// Verify precheck was NOT logged to JSONL
|
|
186
|
+
const precheckLog = await readPrecheckLog(logFilePath);
|
|
187
|
+
expect(precheckLog).toBeNull();
|
|
188
|
+
} finally {
|
|
189
|
+
rmSync(nonGitDir, { recursive: true, force: true });
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
194
|
+
// AC1: Precheck runs automatically before first story
|
|
195
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
196
|
+
|
|
197
|
+
skipInCI("AC1: precheck runs automatically before first story", async () => {
|
|
198
|
+
const prdPath = await setupFeature("auto-test");
|
|
199
|
+
const logFilePath = join(testDir, "nax", "features", "auto-test", "runs", "test.jsonl");
|
|
200
|
+
const runsDir = join(testDir, "nax", "features", "auto-test", "runs");
|
|
201
|
+
|
|
202
|
+
// Pre-create and commit the runs directory to avoid uncommitted changes during test
|
|
203
|
+
mkdirSync(runsDir, { recursive: true });
|
|
204
|
+
const { spawnSync } = await import("bun");
|
|
205
|
+
spawnSync(["git", "add", "."], { cwd: testDir });
|
|
206
|
+
spawnSync(["git", "commit", "-m", "Add runs dir"], { cwd: testDir });
|
|
207
|
+
|
|
208
|
+
const config: NaxConfig = {
|
|
209
|
+
...DEFAULT_CONFIG,
|
|
210
|
+
execution: {
|
|
211
|
+
...DEFAULT_CONFIG.execution,
|
|
212
|
+
maxIterations: 1,
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// Run without skipPrecheck (default behavior)
|
|
217
|
+
await run({
|
|
218
|
+
prdPath,
|
|
219
|
+
workdir: testDir,
|
|
220
|
+
config,
|
|
221
|
+
hooks: { hooks: {} },
|
|
222
|
+
feature: "auto-test",
|
|
223
|
+
dryRun: true,
|
|
224
|
+
logFilePath,
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
// Verify precheck was logged to JSONL (AC5)
|
|
228
|
+
const precheckLog = await readPrecheckLog(logFilePath);
|
|
229
|
+
expect(precheckLog).not.toBeNull();
|
|
230
|
+
expect(precheckLog.type).toBe("precheck");
|
|
231
|
+
expect(precheckLog.passed).toBeDefined();
|
|
232
|
+
expect(precheckLog.summary).toBeDefined();
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
236
|
+
// AC2: Tier 1 blocker aborts run with descriptive error
|
|
237
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
238
|
+
|
|
239
|
+
test("AC2: Tier 1 blocker aborts run with descriptive error", async () => {
|
|
240
|
+
// Create directory with uncommitted changes (will fail working-tree-clean check)
|
|
241
|
+
const dirtyDir = join(import.meta.dir, "..", "..", ".tmp", `dirty-${Date.now()}`);
|
|
242
|
+
mkdirSync(dirtyDir, { recursive: true });
|
|
243
|
+
|
|
244
|
+
try {
|
|
245
|
+
// Initialize git and create a dirty state
|
|
246
|
+
const { spawnSync } = await import("bun");
|
|
247
|
+
spawnSync(["git", "init"], { cwd: dirtyDir });
|
|
248
|
+
spawnSync(["git", "config", "user.name", "Test User"], { cwd: dirtyDir });
|
|
249
|
+
spawnSync(["git", "config", "user.email", "test@example.com"], { cwd: dirtyDir });
|
|
250
|
+
|
|
251
|
+
// Create a file, add it, then modify it (creating uncommitted changes)
|
|
252
|
+
await Bun.write(join(dirtyDir, "test.txt"), "initial");
|
|
253
|
+
spawnSync(["git", "add", "test.txt"], { cwd: dirtyDir });
|
|
254
|
+
spawnSync(["git", "commit", "-m", "initial"], { cwd: dirtyDir });
|
|
255
|
+
await Bun.write(join(dirtyDir, "test.txt"), "modified");
|
|
256
|
+
|
|
257
|
+
// Setup feature
|
|
258
|
+
const naxDir = join(dirtyDir, "nax");
|
|
259
|
+
const featuresDir = join(naxDir, "features");
|
|
260
|
+
const featureDir = join(featuresDir, "blocker-test");
|
|
261
|
+
mkdirSync(featureDir, { recursive: true });
|
|
262
|
+
|
|
263
|
+
const prd = createBasicPRD("blocker-test");
|
|
264
|
+
const prdPath = join(featureDir, "prd.json");
|
|
265
|
+
await Bun.write(prdPath, JSON.stringify(prd, null, 2));
|
|
266
|
+
|
|
267
|
+
// Commit the PRD file
|
|
268
|
+
spawnSync(["git", "add", "."], { cwd: dirtyDir });
|
|
269
|
+
spawnSync(["git", "commit", "-m", "Add PRD"], { cwd: dirtyDir });
|
|
270
|
+
|
|
271
|
+
// Create a new dirty file AFTER the commit so working tree is actually dirty
|
|
272
|
+
await Bun.write(join(dirtyDir, "dirty.txt"), "uncommitted change");
|
|
273
|
+
|
|
274
|
+
const logFilePath = join(featureDir, "runs", "test.jsonl");
|
|
275
|
+
const statusFilePath = join(featureDir, "status.json");
|
|
276
|
+
|
|
277
|
+
const config: NaxConfig = {
|
|
278
|
+
...DEFAULT_CONFIG,
|
|
279
|
+
execution: {
|
|
280
|
+
...DEFAULT_CONFIG.execution,
|
|
281
|
+
maxIterations: 1,
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
// Run should throw error due to precheck failure
|
|
286
|
+
try {
|
|
287
|
+
await run({
|
|
288
|
+
prdPath,
|
|
289
|
+
workdir: dirtyDir,
|
|
290
|
+
config,
|
|
291
|
+
hooks: { hooks: {} },
|
|
292
|
+
feature: "blocker-test",
|
|
293
|
+
dryRun: true,
|
|
294
|
+
logFilePath,
|
|
295
|
+
statusFile: statusFilePath,
|
|
296
|
+
});
|
|
297
|
+
expect(true).toBe(false); // Should not reach here
|
|
298
|
+
} catch (error) {
|
|
299
|
+
// Verify error message is descriptive
|
|
300
|
+
expect((error as Error).message).toContain("Precheck failed");
|
|
301
|
+
expect((error as Error).message).toContain("working-tree-clean");
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Verify precheck failure was logged (AC5)
|
|
305
|
+
const precheckLog = await readPrecheckLog(logFilePath);
|
|
306
|
+
expect(precheckLog).not.toBeNull();
|
|
307
|
+
expect(precheckLog.passed).toBe(false);
|
|
308
|
+
expect(precheckLog.blockers.length).toBeGreaterThan(0);
|
|
309
|
+
|
|
310
|
+
// Verify status.json shows precheck-failed (AC6)
|
|
311
|
+
const status = await readStatusFile(statusFilePath);
|
|
312
|
+
expect(status).not.toBeNull();
|
|
313
|
+
expect(status.run.status).toBe("precheck-failed");
|
|
314
|
+
} finally {
|
|
315
|
+
rmSync(dirtyDir, { recursive: true, force: true });
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
320
|
+
// AC3: Tier 2 warnings logged but don't block execution
|
|
321
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
322
|
+
|
|
323
|
+
skipInCI("AC3: Tier 2 warnings don't block execution", async () => {
|
|
324
|
+
// Setup feature (clean git repo should pass all Tier 1 but may have Tier 2 warnings)
|
|
325
|
+
const prdPath = await setupFeature("warning-test");
|
|
326
|
+
const logFilePath = join(testDir, "nax", "features", "warning-test", "runs", "test.jsonl");
|
|
327
|
+
const runsDir = join(testDir, "nax", "features", "warning-test", "runs");
|
|
328
|
+
|
|
329
|
+
// Pre-create and commit the runs directory to avoid uncommitted changes during test
|
|
330
|
+
mkdirSync(runsDir, { recursive: true });
|
|
331
|
+
const { spawnSync } = await import("bun");
|
|
332
|
+
spawnSync(["git", "add", "."], { cwd: testDir });
|
|
333
|
+
spawnSync(["git", "commit", "-m", "Add runs dir"], { cwd: testDir });
|
|
334
|
+
|
|
335
|
+
const config: NaxConfig = {
|
|
336
|
+
...DEFAULT_CONFIG,
|
|
337
|
+
execution: {
|
|
338
|
+
...DEFAULT_CONFIG.execution,
|
|
339
|
+
maxIterations: 1,
|
|
340
|
+
},
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
// Run should succeed even with warnings
|
|
344
|
+
const result = await run({
|
|
345
|
+
prdPath,
|
|
346
|
+
workdir: testDir,
|
|
347
|
+
config,
|
|
348
|
+
hooks: { hooks: {} },
|
|
349
|
+
feature: "warning-test",
|
|
350
|
+
dryRun: true,
|
|
351
|
+
logFilePath,
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// Should complete successfully
|
|
355
|
+
expect(result.success).toBe(true);
|
|
356
|
+
|
|
357
|
+
// Verify precheck passed (may have warnings)
|
|
358
|
+
const precheckLog = await readPrecheckLog(logFilePath);
|
|
359
|
+
expect(precheckLog).not.toBeNull();
|
|
360
|
+
expect(precheckLog.passed).toBe(true);
|
|
361
|
+
// Warnings are OK (don't block execution)
|
|
362
|
+
expect(precheckLog.warnings).toBeDefined();
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
366
|
+
// AC5: Precheck results included in run JSONL log
|
|
367
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
368
|
+
|
|
369
|
+
skipInCI("AC5: precheck results logged to JSONL", async () => {
|
|
370
|
+
const prdPath = await setupFeature("log-test");
|
|
371
|
+
const logFilePath = join(testDir, "nax", "features", "log-test", "runs", "test.jsonl");
|
|
372
|
+
const runsDir = join(testDir, "nax", "features", "log-test", "runs");
|
|
373
|
+
|
|
374
|
+
// Pre-create and commit the runs directory to avoid uncommitted changes during test
|
|
375
|
+
mkdirSync(runsDir, { recursive: true });
|
|
376
|
+
const { spawnSync } = await import("bun");
|
|
377
|
+
spawnSync(["git", "add", "."], { cwd: testDir });
|
|
378
|
+
spawnSync(["git", "commit", "-m", "Add runs dir"], { cwd: testDir });
|
|
379
|
+
|
|
380
|
+
const config: NaxConfig = {
|
|
381
|
+
...DEFAULT_CONFIG,
|
|
382
|
+
execution: {
|
|
383
|
+
...DEFAULT_CONFIG.execution,
|
|
384
|
+
maxIterations: 1,
|
|
385
|
+
},
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
await run({
|
|
389
|
+
prdPath,
|
|
390
|
+
workdir: testDir,
|
|
391
|
+
config,
|
|
392
|
+
hooks: { hooks: {} },
|
|
393
|
+
feature: "log-test",
|
|
394
|
+
dryRun: true,
|
|
395
|
+
logFilePath,
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
// Verify precheck entry structure
|
|
399
|
+
const precheckLog = await readPrecheckLog(logFilePath);
|
|
400
|
+
expect(precheckLog).not.toBeNull();
|
|
401
|
+
expect(precheckLog.type).toBe("precheck");
|
|
402
|
+
expect(precheckLog.timestamp).toBeDefined();
|
|
403
|
+
expect(precheckLog.passed).toBeDefined();
|
|
404
|
+
expect(precheckLog.blockers).toBeDefined();
|
|
405
|
+
expect(precheckLog.warnings).toBeDefined();
|
|
406
|
+
expect(precheckLog.summary).toBeDefined();
|
|
407
|
+
expect(precheckLog.summary.total).toBeGreaterThan(0);
|
|
408
|
+
expect(precheckLog.summary.passed).toBeGreaterThan(0);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
412
|
+
// AC6: Failed precheck updates status.json with precheck-failed status
|
|
413
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
414
|
+
|
|
415
|
+
test("AC6: failed precheck updates status.json", async () => {
|
|
416
|
+
// Create non-git directory (will fail precheck)
|
|
417
|
+
const nonGitDir = join(import.meta.dir, "..", "..", ".tmp", `non-git-status-${Date.now()}`);
|
|
418
|
+
mkdirSync(nonGitDir, { recursive: true });
|
|
419
|
+
|
|
420
|
+
try {
|
|
421
|
+
// Setup feature (intentionally no git repo to fail precheck)
|
|
422
|
+
const naxDir = join(nonGitDir, "nax");
|
|
423
|
+
const featuresDir = join(naxDir, "features");
|
|
424
|
+
const featureDir = join(featuresDir, "status-test");
|
|
425
|
+
mkdirSync(featureDir, { recursive: true });
|
|
426
|
+
|
|
427
|
+
const prd = createBasicPRD("status-test");
|
|
428
|
+
const prdPath = join(featureDir, "prd.json");
|
|
429
|
+
await Bun.write(prdPath, JSON.stringify(prd, null, 2));
|
|
430
|
+
|
|
431
|
+
// Note: NOT committing to git since this test needs to verify precheck failure
|
|
432
|
+
|
|
433
|
+
const statusFilePath = join(featureDir, "status.json");
|
|
434
|
+
|
|
435
|
+
const config: NaxConfig = {
|
|
436
|
+
...DEFAULT_CONFIG,
|
|
437
|
+
execution: {
|
|
438
|
+
...DEFAULT_CONFIG.execution,
|
|
439
|
+
maxIterations: 1,
|
|
440
|
+
},
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
// Run should fail due to precheck
|
|
444
|
+
try {
|
|
445
|
+
await run({
|
|
446
|
+
prdPath,
|
|
447
|
+
workdir: nonGitDir,
|
|
448
|
+
config,
|
|
449
|
+
hooks: { hooks: {} },
|
|
450
|
+
feature: "status-test",
|
|
451
|
+
dryRun: true,
|
|
452
|
+
statusFile: statusFilePath,
|
|
453
|
+
});
|
|
454
|
+
} catch (error) {
|
|
455
|
+
// Expected failure
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Verify status.json exists and has precheck-failed status
|
|
459
|
+
const status = await readStatusFile(statusFilePath);
|
|
460
|
+
expect(status).not.toBeNull();
|
|
461
|
+
expect(status.run).toBeDefined();
|
|
462
|
+
expect(status.run.status).toBe("precheck-failed");
|
|
463
|
+
expect(status.run.feature).toBe("status-test");
|
|
464
|
+
} finally {
|
|
465
|
+
rmSync(nonGitDir, { recursive: true, force: true });
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
});
|