@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,543 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runner Plugin Integration Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests for US-001: Wire plugin loading into the runner startup
|
|
5
|
+
*
|
|
6
|
+
* Acceptance Criteria:
|
|
7
|
+
* 1. Runner calls loadPlugins() during initialization before story loop starts
|
|
8
|
+
* 2. PluginRegistry is accessible from pipeline context (RunContext or similar)
|
|
9
|
+
* 3. registry.teardownAll() is called on both success and failure paths
|
|
10
|
+
* 4. If no plugins are found, an empty registry is used (no error)
|
|
11
|
+
* 5. Plugin loading errors are logged but do not abort the run
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from "bun:test";
|
|
15
|
+
import * as fs from "node:fs/promises";
|
|
16
|
+
import * as os from "node:os";
|
|
17
|
+
import * as path from "node:path";
|
|
18
|
+
import * as agentModule from "../../src/agents";
|
|
19
|
+
import type { NaxConfig } from "../../src/config/schema";
|
|
20
|
+
import { run } from "../../src/execution/runner";
|
|
21
|
+
import type { LoadedHooksConfig } from "../../src/hooks";
|
|
22
|
+
import type { NaxPlugin } from "../../src/plugins/types";
|
|
23
|
+
|
|
24
|
+
// Test fixture helpers
|
|
25
|
+
async function createTempDir(): Promise<string> {
|
|
26
|
+
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "nax-runner-plugin-test-"));
|
|
27
|
+
return tmpDir;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function cleanupTempDir(dir: string): Promise<void> {
|
|
31
|
+
try {
|
|
32
|
+
await fs.rm(dir, { recursive: true, force: true });
|
|
33
|
+
} catch {
|
|
34
|
+
// Ignore cleanup errors
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function createMinimalPRD(workdir: string, feature: string): Promise<string> {
|
|
39
|
+
const featureDir = path.join(workdir, "nax", "features", feature);
|
|
40
|
+
await fs.mkdir(featureDir, { recursive: true });
|
|
41
|
+
|
|
42
|
+
const prdPath = path.join(featureDir, "prd.json");
|
|
43
|
+
const prd = {
|
|
44
|
+
featureName: feature,
|
|
45
|
+
userStories: [
|
|
46
|
+
{
|
|
47
|
+
id: "US-001",
|
|
48
|
+
title: "Test story",
|
|
49
|
+
description: "A test story",
|
|
50
|
+
acceptanceCriteria: [],
|
|
51
|
+
dependencies: [],
|
|
52
|
+
tags: [],
|
|
53
|
+
status: "pending",
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
await fs.writeFile(prdPath, JSON.stringify(prd, null, 2));
|
|
59
|
+
return prdPath;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function createMinimalConfig(): Promise<NaxConfig> {
|
|
63
|
+
return {
|
|
64
|
+
autoMode: {
|
|
65
|
+
defaultAgent: "claude-code",
|
|
66
|
+
complexityRouting: {
|
|
67
|
+
simple: "fast",
|
|
68
|
+
medium: "balanced",
|
|
69
|
+
complex: "powerful",
|
|
70
|
+
expert: "powerful",
|
|
71
|
+
},
|
|
72
|
+
escalation: {
|
|
73
|
+
enabled: true,
|
|
74
|
+
tierOrder: [
|
|
75
|
+
{ tier: "fast", attempts: 1 },
|
|
76
|
+
{ tier: "balanced", attempts: 1 },
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
models: {
|
|
81
|
+
fast: { provider: "anthropic", modelName: "claude-3-5-haiku-20241022" },
|
|
82
|
+
balanced: { provider: "anthropic", modelName: "claude-3-5-sonnet-20241022" },
|
|
83
|
+
powerful: { provider: "anthropic", modelName: "claude-3-7-sonnet-20250219" },
|
|
84
|
+
},
|
|
85
|
+
execution: {
|
|
86
|
+
maxIterations: 2,
|
|
87
|
+
costLimit: 100,
|
|
88
|
+
iterationDelayMs: 0,
|
|
89
|
+
maxStoriesPerFeature: 100,
|
|
90
|
+
},
|
|
91
|
+
routing: {
|
|
92
|
+
strategy: "simple",
|
|
93
|
+
},
|
|
94
|
+
tdd: {
|
|
95
|
+
mode: "standard",
|
|
96
|
+
testStrategy: "test-after",
|
|
97
|
+
testCommand: "echo 'tests pass'",
|
|
98
|
+
},
|
|
99
|
+
quality: {
|
|
100
|
+
commands: {},
|
|
101
|
+
},
|
|
102
|
+
acceptance: {
|
|
103
|
+
enabled: false,
|
|
104
|
+
testCommand: "",
|
|
105
|
+
maxRetries: 0,
|
|
106
|
+
},
|
|
107
|
+
analyze: {
|
|
108
|
+
model: "balanced",
|
|
109
|
+
maxContextTokens: 100000,
|
|
110
|
+
},
|
|
111
|
+
plugins: [],
|
|
112
|
+
} as NaxConfig;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function createPluginFile(dir: string, filename: string, plugin: NaxPlugin): Promise<void> {
|
|
116
|
+
const setupCode = plugin.setup ? "async setup(config) { }," : "";
|
|
117
|
+
const teardownCode = plugin.teardown ? "async teardown() { }," : "";
|
|
118
|
+
|
|
119
|
+
let extensionsCode = "";
|
|
120
|
+
if (plugin.extensions.reporter) {
|
|
121
|
+
extensionsCode = `
|
|
122
|
+
reporter: {
|
|
123
|
+
name: "${plugin.extensions.reporter.name}",
|
|
124
|
+
async onRunStart(event) {},
|
|
125
|
+
async onStoryComplete(event) {},
|
|
126
|
+
async onRunEnd(event) {}
|
|
127
|
+
}`;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const pluginCode = `
|
|
131
|
+
export default {
|
|
132
|
+
name: "${plugin.name}",
|
|
133
|
+
version: "${plugin.version}",
|
|
134
|
+
provides: ${JSON.stringify(plugin.provides)},
|
|
135
|
+
${setupCode}
|
|
136
|
+
${teardownCode}
|
|
137
|
+
extensions: {${extensionsCode}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
`;
|
|
141
|
+
await fs.writeFile(path.join(dir, filename), pluginCode, "utf-8");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
describe("Runner Plugin Integration (US-001)", () => {
|
|
145
|
+
let tempDir: string;
|
|
146
|
+
let getAgentSpy: any;
|
|
147
|
+
|
|
148
|
+
beforeEach(async () => {
|
|
149
|
+
tempDir = await createTempDir();
|
|
150
|
+
|
|
151
|
+
// Mock getAgent to return a valid agent
|
|
152
|
+
getAgentSpy = spyOn(agentModule, "getAgent").mockReturnValue({
|
|
153
|
+
name: "claude-code",
|
|
154
|
+
binary: "claude",
|
|
155
|
+
isInstalled: async () => true,
|
|
156
|
+
spawn: async () => ({
|
|
157
|
+
success: true,
|
|
158
|
+
estimatedCost: 0,
|
|
159
|
+
transcript: "",
|
|
160
|
+
}),
|
|
161
|
+
} as any);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
afterEach(async () => {
|
|
165
|
+
await cleanupTempDir(tempDir);
|
|
166
|
+
getAgentSpy?.mockRestore();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("AC1: Runner calls loadPlugins() during initialization before story loop starts", async () => {
|
|
170
|
+
// Create a minimal PRD
|
|
171
|
+
const prdPath = await createMinimalPRD(tempDir, "test-feature");
|
|
172
|
+
const config = await createMinimalConfig();
|
|
173
|
+
|
|
174
|
+
// Create a plugin in the global directory
|
|
175
|
+
const globalPluginsDir = path.join(tempDir, ".nax", "plugins");
|
|
176
|
+
await fs.mkdir(globalPluginsDir, { recursive: true });
|
|
177
|
+
|
|
178
|
+
const plugin: NaxPlugin = {
|
|
179
|
+
name: "test-reporter",
|
|
180
|
+
version: "1.0.0",
|
|
181
|
+
provides: ["reporter"],
|
|
182
|
+
extensions: {
|
|
183
|
+
reporter: {
|
|
184
|
+
name: "test-reporter",
|
|
185
|
+
async onRunStart(event) {
|
|
186
|
+
// This proves the plugin was loaded before the run started
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
await createPluginFile(globalPluginsDir, "reporter.ts", plugin);
|
|
193
|
+
|
|
194
|
+
// Override HOME to use our temp directory
|
|
195
|
+
const originalHome = process.env.HOME;
|
|
196
|
+
process.env.HOME = tempDir;
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
// Run with dry-run to avoid actual agent execution
|
|
200
|
+
const result = await run({
|
|
201
|
+
prdPath,
|
|
202
|
+
workdir: tempDir,
|
|
203
|
+
config,
|
|
204
|
+
hooks: { hooks: [] },
|
|
205
|
+
feature: "test-feature",
|
|
206
|
+
dryRun: true,
|
|
207
|
+
skipPrecheck: true,
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// If we get here, plugins were loaded successfully
|
|
211
|
+
expect(result.success).toBe(true);
|
|
212
|
+
} finally {
|
|
213
|
+
process.env.HOME = originalHome;
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test("AC2: PluginRegistry is accessible from pipeline context", async () => {
|
|
218
|
+
// This is verified by checking that pipeline stages can access ctx.plugins
|
|
219
|
+
// The implementation already passes plugins to PipelineContext (runner.ts:706)
|
|
220
|
+
// We verify this indirectly by confirming no errors occur when plugins are used
|
|
221
|
+
|
|
222
|
+
const prdPath = await createMinimalPRD(tempDir, "test-feature");
|
|
223
|
+
const config = await createMinimalConfig();
|
|
224
|
+
|
|
225
|
+
// Create a plugin
|
|
226
|
+
const projectPluginsDir = path.join(tempDir, "nax", "plugins");
|
|
227
|
+
await fs.mkdir(projectPluginsDir, { recursive: true });
|
|
228
|
+
|
|
229
|
+
const plugin: NaxPlugin = {
|
|
230
|
+
name: "test-plugin",
|
|
231
|
+
version: "1.0.0",
|
|
232
|
+
provides: ["reporter"],
|
|
233
|
+
extensions: {
|
|
234
|
+
reporter: {
|
|
235
|
+
name: "test",
|
|
236
|
+
async onRunStart(event) {},
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
await createPluginFile(projectPluginsDir, "test.ts", plugin);
|
|
242
|
+
|
|
243
|
+
// Run with dry-run
|
|
244
|
+
const result = await run({
|
|
245
|
+
prdPath,
|
|
246
|
+
workdir: tempDir,
|
|
247
|
+
config,
|
|
248
|
+
hooks: { hooks: [] },
|
|
249
|
+
feature: "test-feature",
|
|
250
|
+
dryRun: true,
|
|
251
|
+
skipPrecheck: true,
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
expect(result.success).toBe(true);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
test("AC3: registry.teardownAll() is called on success path", async () => {
|
|
258
|
+
const prdPath = await createMinimalPRD(tempDir, "test-feature");
|
|
259
|
+
const config = await createMinimalConfig();
|
|
260
|
+
|
|
261
|
+
// Create a plugin with teardown
|
|
262
|
+
const projectPluginsDir = path.join(tempDir, "nax", "plugins");
|
|
263
|
+
await fs.mkdir(projectPluginsDir, { recursive: true });
|
|
264
|
+
|
|
265
|
+
// Use a file to track teardown calls
|
|
266
|
+
const teardownMarkerPath = path.join(tempDir, "teardown-called.txt");
|
|
267
|
+
|
|
268
|
+
const pluginCode = `
|
|
269
|
+
let teardownCalled = false;
|
|
270
|
+
|
|
271
|
+
export default {
|
|
272
|
+
name: "teardown-test",
|
|
273
|
+
version: "1.0.0",
|
|
274
|
+
provides: ["reporter"],
|
|
275
|
+
async setup(config) {},
|
|
276
|
+
async teardown() {
|
|
277
|
+
const fs = require("node:fs/promises");
|
|
278
|
+
await fs.writeFile("${teardownMarkerPath.replace(/\\/g, "\\\\")}", "teardown-called", "utf-8");
|
|
279
|
+
},
|
|
280
|
+
extensions: {
|
|
281
|
+
reporter: {
|
|
282
|
+
name: "test",
|
|
283
|
+
async onRunStart(event) {}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
`;
|
|
288
|
+
await fs.writeFile(path.join(projectPluginsDir, "teardown.ts"), pluginCode, "utf-8");
|
|
289
|
+
|
|
290
|
+
// Run successfully
|
|
291
|
+
await run({
|
|
292
|
+
prdPath,
|
|
293
|
+
workdir: tempDir,
|
|
294
|
+
config,
|
|
295
|
+
hooks: { hooks: [] },
|
|
296
|
+
feature: "test-feature",
|
|
297
|
+
dryRun: true,
|
|
298
|
+
skipPrecheck: true,
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
// Check that teardown was called
|
|
302
|
+
const teardownContent = await fs.readFile(teardownMarkerPath, "utf-8");
|
|
303
|
+
expect(teardownContent).toBe("teardown-called");
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
test("AC3: registry.teardownAll() is called on failure path", async () => {
|
|
307
|
+
const prdPath = await createMinimalPRD(tempDir, "test-feature");
|
|
308
|
+
const config = await createMinimalConfig();
|
|
309
|
+
|
|
310
|
+
// Create a plugin with teardown
|
|
311
|
+
const projectPluginsDir = path.join(tempDir, "nax", "plugins");
|
|
312
|
+
await fs.mkdir(projectPluginsDir, { recursive: true });
|
|
313
|
+
|
|
314
|
+
const teardownMarkerPath = path.join(tempDir, "teardown-called-fail.txt");
|
|
315
|
+
|
|
316
|
+
const pluginCode = `
|
|
317
|
+
export default {
|
|
318
|
+
name: "teardown-fail-test",
|
|
319
|
+
version: "1.0.0",
|
|
320
|
+
provides: ["reporter"],
|
|
321
|
+
async setup(config) {},
|
|
322
|
+
async teardown() {
|
|
323
|
+
const fs = require("node:fs/promises");
|
|
324
|
+
await fs.writeFile("${teardownMarkerPath.replace(/\\/g, "\\\\")}", "teardown-called", "utf-8");
|
|
325
|
+
},
|
|
326
|
+
extensions: {
|
|
327
|
+
reporter: {
|
|
328
|
+
name: "test",
|
|
329
|
+
async onRunStart(event) {}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
`;
|
|
334
|
+
await fs.writeFile(path.join(projectPluginsDir, "teardown-fail.ts"), pluginCode, "utf-8");
|
|
335
|
+
|
|
336
|
+
// Create an invalid PRD to trigger failure
|
|
337
|
+
const invalidPrd = {
|
|
338
|
+
featureName: "test-feature",
|
|
339
|
+
userStories: [], // Empty stories should cause early exit
|
|
340
|
+
};
|
|
341
|
+
await fs.writeFile(prdPath, JSON.stringify(invalidPrd, null, 2));
|
|
342
|
+
|
|
343
|
+
// Run and expect failure/early exit
|
|
344
|
+
try {
|
|
345
|
+
await run({
|
|
346
|
+
prdPath,
|
|
347
|
+
workdir: tempDir,
|
|
348
|
+
config,
|
|
349
|
+
hooks: { hooks: [] },
|
|
350
|
+
feature: "test-feature",
|
|
351
|
+
dryRun: true,
|
|
352
|
+
skipPrecheck: true,
|
|
353
|
+
});
|
|
354
|
+
} catch (error) {
|
|
355
|
+
// May throw or return early
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Check that teardown was called even on failure
|
|
359
|
+
const teardownContent = await fs.readFile(teardownMarkerPath, "utf-8");
|
|
360
|
+
expect(teardownContent).toBe("teardown-called");
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
test("AC4: If no plugins are found, an empty registry is used (no error)", async () => {
|
|
364
|
+
const prdPath = await createMinimalPRD(tempDir, "test-feature");
|
|
365
|
+
const config = await createMinimalConfig();
|
|
366
|
+
|
|
367
|
+
// Ensure no plugins exist
|
|
368
|
+
const globalPluginsDir = path.join(tempDir, ".nax", "plugins");
|
|
369
|
+
const projectPluginsDir = path.join(tempDir, "nax", "plugins");
|
|
370
|
+
|
|
371
|
+
// Don't create these directories - test with non-existent plugin dirs
|
|
372
|
+
|
|
373
|
+
const originalHome = process.env.HOME;
|
|
374
|
+
process.env.HOME = tempDir;
|
|
375
|
+
|
|
376
|
+
try {
|
|
377
|
+
// Run with no plugins
|
|
378
|
+
const result = await run({
|
|
379
|
+
prdPath,
|
|
380
|
+
workdir: tempDir,
|
|
381
|
+
config,
|
|
382
|
+
hooks: { hooks: [] },
|
|
383
|
+
feature: "test-feature",
|
|
384
|
+
dryRun: true,
|
|
385
|
+
skipPrecheck: true,
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
// Should succeed with empty registry
|
|
389
|
+
expect(result.success).toBe(true);
|
|
390
|
+
} finally {
|
|
391
|
+
process.env.HOME = originalHome;
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
test("AC5: Plugin loading errors are logged but do not abort the run", async () => {
|
|
396
|
+
const prdPath = await createMinimalPRD(tempDir, "test-feature");
|
|
397
|
+
const config = await createMinimalConfig();
|
|
398
|
+
|
|
399
|
+
// Create a malformed plugin file
|
|
400
|
+
const projectPluginsDir = path.join(tempDir, "nax", "plugins");
|
|
401
|
+
await fs.mkdir(projectPluginsDir, { recursive: true });
|
|
402
|
+
|
|
403
|
+
const malformedPlugin = `
|
|
404
|
+
export default {
|
|
405
|
+
// Missing required fields (name, version)
|
|
406
|
+
provides: ["reporter"],
|
|
407
|
+
extensions: {}
|
|
408
|
+
};
|
|
409
|
+
`;
|
|
410
|
+
await fs.writeFile(path.join(projectPluginsDir, "malformed.ts"), malformedPlugin, "utf-8");
|
|
411
|
+
|
|
412
|
+
// Create a valid plugin as well
|
|
413
|
+
const validPlugin: NaxPlugin = {
|
|
414
|
+
name: "valid-plugin",
|
|
415
|
+
version: "1.0.0",
|
|
416
|
+
provides: ["reporter"],
|
|
417
|
+
extensions: {
|
|
418
|
+
reporter: {
|
|
419
|
+
name: "valid",
|
|
420
|
+
async onRunStart(event) {},
|
|
421
|
+
},
|
|
422
|
+
},
|
|
423
|
+
};
|
|
424
|
+
await createPluginFile(projectPluginsDir, "valid.ts", validPlugin);
|
|
425
|
+
|
|
426
|
+
// Run should succeed despite malformed plugin
|
|
427
|
+
const result = await run({
|
|
428
|
+
prdPath,
|
|
429
|
+
workdir: tempDir,
|
|
430
|
+
config,
|
|
431
|
+
hooks: { hooks: [] },
|
|
432
|
+
feature: "test-feature",
|
|
433
|
+
dryRun: true,
|
|
434
|
+
skipPrecheck: true,
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
// Should succeed - malformed plugin is skipped, valid plugin is loaded
|
|
438
|
+
expect(result.success).toBe(true);
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
test("Plugin loading resolves correct directory paths", async () => {
|
|
442
|
+
const prdPath = await createMinimalPRD(tempDir, "test-feature");
|
|
443
|
+
const config = await createMinimalConfig();
|
|
444
|
+
|
|
445
|
+
// Create plugins in both global and project directories
|
|
446
|
+
const globalPluginsDir = path.join(tempDir, ".nax", "plugins");
|
|
447
|
+
const projectPluginsDir = path.join(tempDir, "nax", "plugins");
|
|
448
|
+
await fs.mkdir(globalPluginsDir, { recursive: true });
|
|
449
|
+
await fs.mkdir(projectPluginsDir, { recursive: true });
|
|
450
|
+
|
|
451
|
+
const globalPlugin: NaxPlugin = {
|
|
452
|
+
name: "global-plugin",
|
|
453
|
+
version: "1.0.0",
|
|
454
|
+
provides: ["reporter"],
|
|
455
|
+
extensions: {
|
|
456
|
+
reporter: {
|
|
457
|
+
name: "global",
|
|
458
|
+
async onRunStart(event) {},
|
|
459
|
+
},
|
|
460
|
+
},
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const projectPlugin: NaxPlugin = {
|
|
464
|
+
name: "project-plugin",
|
|
465
|
+
version: "1.0.0",
|
|
466
|
+
provides: ["reporter"],
|
|
467
|
+
extensions: {
|
|
468
|
+
reporter: {
|
|
469
|
+
name: "project",
|
|
470
|
+
async onRunStart(event) {},
|
|
471
|
+
},
|
|
472
|
+
},
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
await createPluginFile(globalPluginsDir, "global.ts", globalPlugin);
|
|
476
|
+
await createPluginFile(projectPluginsDir, "project.ts", projectPlugin);
|
|
477
|
+
|
|
478
|
+
const originalHome = process.env.HOME;
|
|
479
|
+
process.env.HOME = tempDir;
|
|
480
|
+
|
|
481
|
+
try {
|
|
482
|
+
// Run
|
|
483
|
+
const result = await run({
|
|
484
|
+
prdPath,
|
|
485
|
+
workdir: tempDir,
|
|
486
|
+
config,
|
|
487
|
+
hooks: { hooks: [] },
|
|
488
|
+
feature: "test-feature",
|
|
489
|
+
dryRun: true,
|
|
490
|
+
skipPrecheck: true,
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
// Should load both plugins successfully
|
|
494
|
+
expect(result.success).toBe(true);
|
|
495
|
+
} finally {
|
|
496
|
+
process.env.HOME = originalHome;
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
test("Config plugins are loaded alongside directory plugins", async () => {
|
|
501
|
+
const prdPath = await createMinimalPRD(tempDir, "test-feature");
|
|
502
|
+
const config = await createMinimalConfig();
|
|
503
|
+
|
|
504
|
+
// Create a config plugin
|
|
505
|
+
const configPluginDir = path.join(tempDir, "custom-plugin");
|
|
506
|
+
await fs.mkdir(configPluginDir, { recursive: true });
|
|
507
|
+
|
|
508
|
+
const configPlugin: NaxPlugin = {
|
|
509
|
+
name: "config-plugin",
|
|
510
|
+
version: "1.0.0",
|
|
511
|
+
provides: ["reporter"],
|
|
512
|
+
extensions: {
|
|
513
|
+
reporter: {
|
|
514
|
+
name: "config",
|
|
515
|
+
async onRunStart(event) {},
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
await createPluginFile(configPluginDir, "index.ts", configPlugin);
|
|
521
|
+
|
|
522
|
+
// Add plugin to config
|
|
523
|
+
config.plugins = [
|
|
524
|
+
{
|
|
525
|
+
module: path.join(configPluginDir, "index.ts"),
|
|
526
|
+
config: {},
|
|
527
|
+
},
|
|
528
|
+
];
|
|
529
|
+
|
|
530
|
+
// Run
|
|
531
|
+
const result = await run({
|
|
532
|
+
prdPath,
|
|
533
|
+
workdir: tempDir,
|
|
534
|
+
config,
|
|
535
|
+
hooks: { hooks: [] },
|
|
536
|
+
feature: "test-feature",
|
|
537
|
+
dryRun: true,
|
|
538
|
+
skipPrecheck: true,
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
expect(result.success).toBe(true);
|
|
542
|
+
});
|
|
543
|
+
});
|