@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,206 @@
|
|
|
1
|
+
# v0.10 — Global + Project Config Layering
|
|
2
|
+
|
|
3
|
+
**Status:** Draft
|
|
4
|
+
**Author:** Subrina
|
|
5
|
+
**Date:** 2026-03-03
|
|
6
|
+
**Base:** v0.9.3
|
|
7
|
+
**Issue:** #14
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
Introduce a global `~/.nax/` directory for user-wide defaults. Project-level `nax/` overrides global via deep merge. Hooks concatenate (global fires first, then project).
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
- Users repeat the same config across projects (model mappings, cost limits, hooks)
|
|
16
|
+
- No way to set personal defaults without copy-pasting `nax/config.json`
|
|
17
|
+
- Notification hooks (Telegram, Slack) are user-level, not project-level
|
|
18
|
+
- Constitution rules often have a universal component ("always strict TypeScript") plus project-specific additions
|
|
19
|
+
|
|
20
|
+
## Directory Structure
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
~/.nax/ # Global (user-wide)
|
|
24
|
+
config.json # Global defaults
|
|
25
|
+
constitution.md # Global coding standards
|
|
26
|
+
hooks/
|
|
27
|
+
on-complete.sh # Fires after every run
|
|
28
|
+
on-error.sh # Fires on story failure
|
|
29
|
+
on-pause.sh # Fires when story pauses
|
|
30
|
+
on-start.sh # Fires when run starts
|
|
31
|
+
|
|
32
|
+
<project>/nax/ # Project (existing, unchanged)
|
|
33
|
+
config.json # Project overrides
|
|
34
|
+
constitution.md # Project-specific rules
|
|
35
|
+
hooks/
|
|
36
|
+
on-complete.sh # Project-specific hooks
|
|
37
|
+
features/
|
|
38
|
+
<feature>/prd.json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Merge Strategy
|
|
42
|
+
|
|
43
|
+
### Config: Deep Merge (project wins)
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
global config.json + project config.json = effective config
|
|
47
|
+
───────────────── ──────────────────── ────────────────
|
|
48
|
+
{ { {
|
|
49
|
+
"models": { "models": { "models": {
|
|
50
|
+
"fast": "haiku", "fast": "flash" "fast": "flash", ← project wins
|
|
51
|
+
"balanced": "sonnet", "balanced": "sonnet", ← from global
|
|
52
|
+
"powerful": "opus" "powerful": "opus" ← from global
|
|
53
|
+
}, }, },
|
|
54
|
+
"execution": { "execution": { "execution": {
|
|
55
|
+
"costLimit": 5.0, "costLimit": 2.0 "costLimit": 2.0, ← project wins
|
|
56
|
+
"sessionTimeout": 600 "sessionTimeout": 600 ← from global
|
|
57
|
+
} } }
|
|
58
|
+
} } }
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Rules:
|
|
62
|
+
- Objects are recursively merged; project values override global at the leaf level
|
|
63
|
+
- Arrays are **replaced** (not concatenated) — e.g., `escalation.tierOrder` from project fully replaces global
|
|
64
|
+
- `null` in project explicitly removes a global key
|
|
65
|
+
- Missing sections in project inherit from global as-is
|
|
66
|
+
|
|
67
|
+
### Hooks: Concatenate (global first, then project)
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
Effective hook execution order:
|
|
71
|
+
1. ~/.nax/hooks/on-complete.sh (if exists)
|
|
72
|
+
2. <project>/nax/hooks/on-complete.sh (if exists)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
- Both fire independently — global hook failure does NOT block project hook
|
|
76
|
+
- Each hook receives the same environment variables (run metadata, exit code, cost, etc.)
|
|
77
|
+
- To skip global hooks for a project, set `"hooks": { "skipGlobal": true }` in project config
|
|
78
|
+
|
|
79
|
+
### Constitution: Concatenate (global first, then project)
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
Effective constitution:
|
|
83
|
+
1. ~/.nax/constitution.md content
|
|
84
|
+
2. ---
|
|
85
|
+
3. <project>/nax/constitution.md content
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- Global constitution prepended to project constitution with `---` separator
|
|
89
|
+
- To skip global constitution, set `"constitution": { "skipGlobal": true }` in project config
|
|
90
|
+
|
|
91
|
+
## Config Resolution Order
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
1. Built-in defaults (hardcoded in schema.ts)
|
|
95
|
+
2. ~/.nax/config.json (global)
|
|
96
|
+
3. <project>/nax/config.json (project)
|
|
97
|
+
4. CLI flags (--cost-limit, --model, etc.) — highest priority
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Global Config Scope
|
|
101
|
+
|
|
102
|
+
All existing config sections are valid at global level:
|
|
103
|
+
|
|
104
|
+
| Section | Global Use Case |
|
|
105
|
+
|:--------|:----------------|
|
|
106
|
+
| `models` | Default model mappings (your API keys, preferred providers) |
|
|
107
|
+
| `autoMode` | Default complexity→tier routing and escalation budgets |
|
|
108
|
+
| `routing` | Preferred routing strategy (llm vs keyword) |
|
|
109
|
+
| `execution` | Default cost limit, session timeout, verification timeout |
|
|
110
|
+
| `quality` | Default stripEnvVars, forceExit |
|
|
111
|
+
| `tdd` | Default session tiers, testWriterAllowedPaths |
|
|
112
|
+
| `constitution` | Path (always relative to `~/.nax/`) |
|
|
113
|
+
| `context` | Default test coverage detail level and token budget |
|
|
114
|
+
| `acceptance` | Default enabled/disabled |
|
|
115
|
+
| `hooks` | Global hook directory path |
|
|
116
|
+
| `analyze` | Default LLM-enhanced analysis settings |
|
|
117
|
+
|
|
118
|
+
## New Config Fields
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
// Added to NaxConfig (or a new GlobalConfig extending it)
|
|
122
|
+
interface HooksConfig {
|
|
123
|
+
/** Skip global hooks for this project */
|
|
124
|
+
skipGlobal?: boolean;
|
|
125
|
+
/** Hook directory path (default: "hooks/" relative to config dir) */
|
|
126
|
+
dir?: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
interface ConstitutionConfig {
|
|
130
|
+
/** Path to constitution file (relative to config dir) */
|
|
131
|
+
path?: string;
|
|
132
|
+
/** Skip global constitution for this project */
|
|
133
|
+
skipGlobal?: boolean;
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Implementation
|
|
138
|
+
|
|
139
|
+
### File Structure
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
src/config/
|
|
143
|
+
schema.ts # Add HooksConfig, ConstitutionConfig schemas
|
|
144
|
+
loader.ts # Modify: load global → project → merge
|
|
145
|
+
merger.ts # NEW: deep merge logic with concatenation rules
|
|
146
|
+
paths.ts # NEW: resolve ~/.nax/ and project nax/ paths
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Key Functions
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// paths.ts
|
|
153
|
+
export function globalConfigDir(): string; // ~/.nax/
|
|
154
|
+
export function projectConfigDir(): string; // <cwd>/nax/
|
|
155
|
+
|
|
156
|
+
// merger.ts
|
|
157
|
+
export function mergeConfigs(global: Partial<NaxConfig>, project: Partial<NaxConfig>): NaxConfig;
|
|
158
|
+
|
|
159
|
+
// loader.ts (modified)
|
|
160
|
+
export async function loadConfig(options?: { projectDir?: string }): Promise<NaxConfig> {
|
|
161
|
+
const defaults = getDefaults();
|
|
162
|
+
const global = await loadConfigFile(globalConfigDir());
|
|
163
|
+
const project = await loadConfigFile(projectConfigDir(options?.projectDir));
|
|
164
|
+
return mergeConfigs(defaults, mergeConfigs(global, project));
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### `nax init --global`
|
|
169
|
+
|
|
170
|
+
New flag to initialize `~/.nax/`:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
nax init --global
|
|
174
|
+
# Creates:
|
|
175
|
+
# ~/.nax/config.json (with commented examples)
|
|
176
|
+
# ~/.nax/constitution.md (empty template)
|
|
177
|
+
# ~/.nax/hooks/ (empty directory)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Existing `nax init` (without `--global`) continues to initialize project-level `nax/`.
|
|
181
|
+
|
|
182
|
+
## User Stories
|
|
183
|
+
|
|
184
|
+
| # | Title | Complexity | Est. LOC | Dependencies |
|
|
185
|
+
|:--|:------|:-----------|:---------|:-------------|
|
|
186
|
+
| US-001 | Config paths resolver (`~/.nax/` + project `nax/`) | simple | 40 | — |
|
|
187
|
+
| US-002 | Deep merge utility with array-replace and null-remove semantics | simple | 60 | — |
|
|
188
|
+
| US-003 | Update `loadConfig()` to load global → project → merge | medium | 80 | US-001, US-002 |
|
|
189
|
+
| US-004 | Hook concatenation (global + project, independent execution) | medium | 100 | US-001, US-003 |
|
|
190
|
+
| US-005 | Constitution concatenation with `skipGlobal` support | simple | 50 | US-001, US-003 |
|
|
191
|
+
| US-006 | `nax init --global` command | simple | 60 | US-001 |
|
|
192
|
+
| US-007 | Update Zod schema for HooksConfig and ConstitutionConfig | simple | 40 | — |
|
|
193
|
+
|
|
194
|
+
## Design Decisions
|
|
195
|
+
|
|
196
|
+
1. **Deep merge over section replace** — more intuitive; users only override what they change
|
|
197
|
+
2. **Hooks concatenate, arrays replace** — hooks are additive (notification + CI); config arrays like `tierOrder` are intentional overrides
|
|
198
|
+
3. **`skipGlobal` opt-out** — simple boolean rather than complex inheritance rules
|
|
199
|
+
4. **Global first in concatenation** — global rules are "baseline", project adds specifics
|
|
200
|
+
5. **`null` removes keys** — explicit opt-out mechanism for global defaults you don't want in a specific project
|
|
201
|
+
6. **CLI flags beat everything** — one-off overrides without touching files
|
|
202
|
+
7. **No `nax config show`** — defer to v0.11; users can check effective config via `nax prompts` audit
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
*Draft — pending William's review.*
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
# v0.10 — Plugin System
|
|
2
|
+
|
|
3
|
+
**Status:** Draft
|
|
4
|
+
**Author:** Subrina
|
|
5
|
+
**Date:** 2026-03-03
|
|
6
|
+
**Base:** v0.9.3
|
|
7
|
+
**Issue:** #14 (bundled with global config)
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
A lightweight plugin system that lets developers extend nax with custom optimizers, routing strategies, review checks, context providers, reporters, and agent adapters. Plugins are plain JS/TS modules that export a `NaxPlugin` object.
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
- Prompt optimization, routing, and review are already extensible in concept but hardcoded in practice
|
|
16
|
+
- Users want to integrate external tools (LLMLingua, Jira, security scanners) without forking nax
|
|
17
|
+
- nax has well-defined interfaces (`RoutingStrategy`, `AgentAdapter`, `ReviewConfig`) — plugins just need a standard way to register implementations
|
|
18
|
+
- Global plugins (in `~/.nax/plugins/`) apply to all projects; project plugins override or add
|
|
19
|
+
|
|
20
|
+
## Plugin Interface
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
// src/plugins/types.ts
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Extension point types that plugins can provide.
|
|
27
|
+
*/
|
|
28
|
+
export type PluginType =
|
|
29
|
+
| "optimizer"
|
|
30
|
+
| "router"
|
|
31
|
+
| "agent"
|
|
32
|
+
| "reviewer"
|
|
33
|
+
| "context-provider"
|
|
34
|
+
| "reporter";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* A nax plugin module.
|
|
38
|
+
*
|
|
39
|
+
* Plugins export a single NaxPlugin object (default or named export).
|
|
40
|
+
* Each plugin declares which extension points it provides and supplies
|
|
41
|
+
* the corresponding implementations.
|
|
42
|
+
*/
|
|
43
|
+
export interface NaxPlugin {
|
|
44
|
+
/** Unique plugin name (e.g., "jira-context", "llmlingua-optimizer") */
|
|
45
|
+
name: string;
|
|
46
|
+
|
|
47
|
+
/** Plugin version (semver) */
|
|
48
|
+
version: string;
|
|
49
|
+
|
|
50
|
+
/** Which extension points this plugin provides */
|
|
51
|
+
provides: PluginType[];
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Called once when plugin is loaded. Use for initialization,
|
|
55
|
+
* validating config, establishing connections, etc.
|
|
56
|
+
*
|
|
57
|
+
* @param config - Plugin-specific config from nax config.json
|
|
58
|
+
*/
|
|
59
|
+
setup?(config: Record<string, unknown>): Promise<void>;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Called when the nax run ends (success or failure).
|
|
63
|
+
* Use for cleanup, closing connections, flushing buffers.
|
|
64
|
+
*/
|
|
65
|
+
teardown?(): Promise<void>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Extension implementations. Only the types listed in `provides`
|
|
69
|
+
* are required; others are ignored.
|
|
70
|
+
*/
|
|
71
|
+
extensions: PluginExtensions;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface PluginExtensions {
|
|
75
|
+
/** Custom prompt optimizer */
|
|
76
|
+
optimizer?: IPromptOptimizer;
|
|
77
|
+
|
|
78
|
+
/** Custom routing strategy (inserted into the strategy chain) */
|
|
79
|
+
router?: RoutingStrategy;
|
|
80
|
+
|
|
81
|
+
/** Custom agent adapter (e.g., Codex, Gemini, Aider) */
|
|
82
|
+
agent?: AgentAdapter;
|
|
83
|
+
|
|
84
|
+
/** Custom review check (runs alongside built-in typecheck/lint/test) */
|
|
85
|
+
reviewer?: IReviewPlugin;
|
|
86
|
+
|
|
87
|
+
/** Custom context provider (injects external context into prompts) */
|
|
88
|
+
contextProvider?: IContextProvider;
|
|
89
|
+
|
|
90
|
+
/** Custom reporter (receives run events for dashboards, CI, etc.) */
|
|
91
|
+
reporter?: IReporter;
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Extension Point Interfaces
|
|
96
|
+
|
|
97
|
+
### IPromptOptimizer (existing from optimizer spec)
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
// src/optimizer/types.ts (from v0.10-prompt-optimizer.md)
|
|
101
|
+
export interface IPromptOptimizer {
|
|
102
|
+
name: string;
|
|
103
|
+
optimize(input: PromptOptimizerInput): Promise<PromptOptimizerResult>;
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### RoutingStrategy (existing)
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// src/routing/strategy.ts (already exists in v0.9.3)
|
|
111
|
+
export interface RoutingStrategy {
|
|
112
|
+
readonly name: string;
|
|
113
|
+
route(story: UserStory, context: RoutingContext): RoutingDecision | null | Promise<RoutingDecision | null>;
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Plugin routers are inserted into the strategy chain **before** the built-in strategies. If a plugin router returns `null`, the chain continues to keyword/LLM/adaptive as normal.
|
|
118
|
+
|
|
119
|
+
### AgentAdapter (existing)
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// src/agents/types.ts (already exists in v0.9.3)
|
|
123
|
+
export interface AgentAdapter {
|
|
124
|
+
readonly name: string;
|
|
125
|
+
readonly displayName: string;
|
|
126
|
+
readonly binary: string;
|
|
127
|
+
readonly capabilities: AgentCapabilities;
|
|
128
|
+
isInstalled(): Promise<boolean>;
|
|
129
|
+
run(options: AgentRunOptions): Promise<AgentResult>;
|
|
130
|
+
buildCommand(options: AgentRunOptions): string[];
|
|
131
|
+
plan(options: PlanOptions): Promise<PlanResult>;
|
|
132
|
+
decompose(options: DecomposeOptions): Promise<DecomposeResult>;
|
|
133
|
+
runInteractive?(options: InteractiveRunOptions): PtyHandle;
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### IReviewPlugin (new)
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// src/plugins/types.ts
|
|
141
|
+
export interface IReviewPlugin {
|
|
142
|
+
/** Check name (e.g., "security-scan", "license-check") */
|
|
143
|
+
name: string;
|
|
144
|
+
|
|
145
|
+
/** Human-readable description */
|
|
146
|
+
description: string;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Run the review check against the working directory.
|
|
150
|
+
*
|
|
151
|
+
* @param workdir - Project root directory
|
|
152
|
+
* @param changedFiles - Files modified by the agent in this story
|
|
153
|
+
* @returns Review check result
|
|
154
|
+
*/
|
|
155
|
+
check(workdir: string, changedFiles: string[]): Promise<ReviewCheckResult>;
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Review plugins run **after** built-in checks (typecheck, lint, test). A plugin check failure follows the same escalation/retry logic as built-in failures.
|
|
160
|
+
|
|
161
|
+
### IContextProvider (new)
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
// src/plugins/types.ts
|
|
165
|
+
export interface IContextProvider {
|
|
166
|
+
/** Provider name (e.g., "jira", "linear", "confluence") */
|
|
167
|
+
name: string;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Fetch external context relevant to a story.
|
|
171
|
+
*
|
|
172
|
+
* @param story - The user story being executed
|
|
173
|
+
* @param config - Plugin-specific config
|
|
174
|
+
* @returns Markdown content to inject into the agent prompt
|
|
175
|
+
*/
|
|
176
|
+
getContext(story: UserStory): Promise<ContextProviderResult>;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface ContextProviderResult {
|
|
180
|
+
/** Markdown content to inject */
|
|
181
|
+
content: string;
|
|
182
|
+
/** Token estimate for budget tracking */
|
|
183
|
+
estimatedTokens: number;
|
|
184
|
+
/** Section label in the prompt (e.g., "Jira Context") */
|
|
185
|
+
label: string;
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Context provider output is appended to the built context **after** the context stage, within the remaining token budget. If the budget is exceeded, provider content is truncated with a warning.
|
|
190
|
+
|
|
191
|
+
### IReporter (new)
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
// src/plugins/types.ts
|
|
195
|
+
export interface IReporter {
|
|
196
|
+
/** Reporter name */
|
|
197
|
+
name: string;
|
|
198
|
+
|
|
199
|
+
/** Called when a run starts */
|
|
200
|
+
onRunStart?(run: RunStartEvent): Promise<void>;
|
|
201
|
+
|
|
202
|
+
/** Called when a story completes (success or failure) */
|
|
203
|
+
onStoryComplete?(event: StoryCompleteEvent): Promise<void>;
|
|
204
|
+
|
|
205
|
+
/** Called when a run ends */
|
|
206
|
+
onRunEnd?(run: RunEndEvent): Promise<void>;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export interface RunStartEvent {
|
|
210
|
+
runId: string;
|
|
211
|
+
feature: string;
|
|
212
|
+
totalStories: number;
|
|
213
|
+
startTime: string;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export interface StoryCompleteEvent {
|
|
217
|
+
runId: string;
|
|
218
|
+
storyId: string;
|
|
219
|
+
status: "completed" | "failed" | "skipped" | "paused";
|
|
220
|
+
durationMs: number;
|
|
221
|
+
cost: number;
|
|
222
|
+
tier: string;
|
|
223
|
+
testStrategy: string;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export interface RunEndEvent {
|
|
227
|
+
runId: string;
|
|
228
|
+
totalDurationMs: number;
|
|
229
|
+
totalCost: number;
|
|
230
|
+
storySummary: {
|
|
231
|
+
completed: number;
|
|
232
|
+
failed: number;
|
|
233
|
+
skipped: number;
|
|
234
|
+
paused: number;
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Reporter methods are fire-and-forget — failures are logged but never block the pipeline.
|
|
240
|
+
|
|
241
|
+
## Plugin Loading
|
|
242
|
+
|
|
243
|
+
### Resolution Order
|
|
244
|
+
|
|
245
|
+
```
|
|
246
|
+
1. ~/.nax/plugins/* (global plugins — apply to all projects)
|
|
247
|
+
2. nax/plugins/* (project plugins — override or add)
|
|
248
|
+
3. config.json plugins (explicit module paths)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Config
|
|
252
|
+
|
|
253
|
+
```json
|
|
254
|
+
{
|
|
255
|
+
"plugins": [
|
|
256
|
+
{
|
|
257
|
+
"module": "./nax/plugins/my-security-scanner",
|
|
258
|
+
"config": { "severity": "high" }
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"module": "@nathapp/nax-plugin-jira",
|
|
262
|
+
"config": { "baseUrl": "https://jira.example.com", "project": "NAX" }
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
"module": "~/custom-optimizer",
|
|
266
|
+
"config": {}
|
|
267
|
+
}
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Directory Convention
|
|
273
|
+
|
|
274
|
+
Plugins in `~/.nax/plugins/` or `nax/plugins/` are auto-discovered (no config entry needed):
|
|
275
|
+
|
|
276
|
+
```
|
|
277
|
+
~/.nax/plugins/
|
|
278
|
+
telegram-reporter/
|
|
279
|
+
index.ts # exports NaxPlugin
|
|
280
|
+
package.json # optional, for dependencies
|
|
281
|
+
security-scan.ts # single-file plugin
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Loader Logic
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
// src/plugins/loader.ts
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Load and validate all plugins from global + project + config sources.
|
|
291
|
+
*
|
|
292
|
+
* 1. Scan ~/.nax/plugins/ (if exists)
|
|
293
|
+
* 2. Scan <project>/nax/plugins/ (if exists)
|
|
294
|
+
* 3. Load explicit modules from config.plugins[]
|
|
295
|
+
* 4. Validate each: must export name (string), version (string),
|
|
296
|
+
* provides (PluginType[]), and matching extensions
|
|
297
|
+
* 5. Call setup() on each with its config
|
|
298
|
+
* 6. Return PluginRegistry
|
|
299
|
+
*/
|
|
300
|
+
export async function loadPlugins(
|
|
301
|
+
globalDir: string,
|
|
302
|
+
projectDir: string,
|
|
303
|
+
configPlugins: PluginConfigEntry[]
|
|
304
|
+
): Promise<PluginRegistry>;
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Plugin Registry
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
// src/plugins/registry.ts
|
|
311
|
+
|
|
312
|
+
export class PluginRegistry {
|
|
313
|
+
/** All loaded plugins */
|
|
314
|
+
readonly plugins: ReadonlyArray<NaxPlugin>;
|
|
315
|
+
|
|
316
|
+
/** Get all optimizers (built-in + plugin) */
|
|
317
|
+
getOptimizers(): IPromptOptimizer[];
|
|
318
|
+
|
|
319
|
+
/** Get all routing strategies (plugin strategies, inserted before built-in) */
|
|
320
|
+
getRouters(): RoutingStrategy[];
|
|
321
|
+
|
|
322
|
+
/** Get agent adapter by name */
|
|
323
|
+
getAgent(name: string): AgentAdapter | undefined;
|
|
324
|
+
|
|
325
|
+
/** Get all review plugins */
|
|
326
|
+
getReviewers(): IReviewPlugin[];
|
|
327
|
+
|
|
328
|
+
/** Get all context providers */
|
|
329
|
+
getContextProviders(): IContextProvider[];
|
|
330
|
+
|
|
331
|
+
/** Get all reporters */
|
|
332
|
+
getReporters(): IReporter[];
|
|
333
|
+
|
|
334
|
+
/** Teardown all plugins */
|
|
335
|
+
async teardownAll(): Promise<void>;
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
The registry is created once at run start and passed through the pipeline context.
|
|
340
|
+
|
|
341
|
+
## Pipeline Integration
|
|
342
|
+
|
|
343
|
+
```typescript
|
|
344
|
+
// PipelineContext additions
|
|
345
|
+
export interface PipelineContext {
|
|
346
|
+
// ... existing fields ...
|
|
347
|
+
|
|
348
|
+
/** Plugin registry (set by runner before pipeline starts) */
|
|
349
|
+
plugins?: PluginRegistry;
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Where Plugins Hook In
|
|
354
|
+
|
|
355
|
+
| Stage | Plugin Type | Integration |
|
|
356
|
+
|:------|:-----------|:------------|
|
|
357
|
+
| `routing` | `router` | Plugin strategies prepended to strategy chain |
|
|
358
|
+
| `context` | `context-provider` | Provider content appended after built context |
|
|
359
|
+
| `optimizer` (new) | `optimizer` | Plugin optimizer replaces or chains with built-in |
|
|
360
|
+
| `execution` | `agent` | Plugin agent selected by `config.agent` name |
|
|
361
|
+
| `review` | `reviewer` | Plugin checks run after built-in checks |
|
|
362
|
+
| Pipeline runner | `reporter` | Events fired at run start, story complete, run end |
|
|
363
|
+
|
|
364
|
+
## Conflict Resolution
|
|
365
|
+
|
|
366
|
+
| Scenario | Behavior |
|
|
367
|
+
|:---------|:---------|
|
|
368
|
+
| Multiple optimizers | Only the **last** loaded optimizer is active (project overrides global). Log warning if multiple found. |
|
|
369
|
+
| Multiple routers | All router plugins are chained (in load order, before built-in). First non-null decision wins. |
|
|
370
|
+
| Multiple agents | All registered. Config `agent` field selects which one to use. Default: `claude-code`. |
|
|
371
|
+
| Multiple reviewers | All run (additive). Each produces independent results. |
|
|
372
|
+
| Multiple context providers | All run (additive). Combined output subject to token budget. |
|
|
373
|
+
| Multiple reporters | All run (additive). Independent, fire-and-forget. |
|
|
374
|
+
| Plugin name collision | Last loaded wins (project overrides global). Log warning. |
|
|
375
|
+
|
|
376
|
+
## File Structure
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
src/plugins/
|
|
380
|
+
types.ts # NaxPlugin, PluginType, extension interfaces
|
|
381
|
+
loader.ts # loadPlugins() — discover, import, validate
|
|
382
|
+
registry.ts # PluginRegistry class
|
|
383
|
+
validator.ts # validatePlugin() — runtime type checks
|
|
384
|
+
index.ts # Public API exports
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
## User Stories
|
|
388
|
+
|
|
389
|
+
| # | Title | Complexity | Est. LOC | Dependencies |
|
|
390
|
+
|:--|:------|:-----------|:---------|:-------------|
|
|
391
|
+
| US-001 | Define NaxPlugin interface and all extension point types | simple | 120 | — |
|
|
392
|
+
| US-002 | Plugin loader (directory scan + config modules + validation) | medium | 150 | US-001 |
|
|
393
|
+
| US-003 | PluginRegistry with typed getters and teardown | medium | 100 | US-001 |
|
|
394
|
+
| US-004 | Integrate plugin routers into routing strategy chain | simple | 50 | US-003 |
|
|
395
|
+
| US-005 | Integrate plugin reviewers into review stage | simple | 50 | US-003 |
|
|
396
|
+
| US-006 | Integrate context providers into context stage | medium | 80 | US-003 |
|
|
397
|
+
| US-007 | Reporter event emission from pipeline runner | medium | 80 | US-003 |
|
|
398
|
+
| US-008 | Add PluginRegistry to PipelineContext + runner initialization | simple | 40 | US-002, US-003 |
|
|
399
|
+
| US-009 | `nax plugins list` CLI command (show loaded plugins) | simple | 50 | US-002 |
|
|
400
|
+
|
|
401
|
+
## Design Decisions
|
|
402
|
+
|
|
403
|
+
1. **Plain module exports over class registration** — plugins are just objects with a known shape. No decorators, no base classes, no framework lock-in.
|
|
404
|
+
2. **Auto-discovery + explicit config** — directory convention for convenience, config entries for control. Both work together.
|
|
405
|
+
3. **Last-loaded-wins for singular types** (optimizer, agent) — keeps it simple. No complex priority systems.
|
|
406
|
+
4. **Additive for plural types** (reviewer, reporter, context-provider, router) — more plugins = more capability.
|
|
407
|
+
5. **Fire-and-forget reporters** — never block the pipeline for reporting failures.
|
|
408
|
+
6. **Reuse existing interfaces** — `RoutingStrategy` and `AgentAdapter` already exist. Plugins just provide new implementations via the same contracts.
|
|
409
|
+
7. **Plugin config in nax config.json** — no separate plugin config files. Each plugin gets a `config` object passed to `setup()`.
|
|
410
|
+
8. **No hot-reload** — plugins are loaded once at run start. Restart to pick up changes.
|
|
411
|
+
9. **v0.10 implements loader + registry + optimizer integration** — other extension point integrations (router, reviewer, context, reporter) are wired but implementations are community-driven.
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
415
|
+
*Draft — pending William's review.*
|