@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,506 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Provider Injection Tests (US-002)
|
|
3
|
+
*
|
|
4
|
+
* Tests that context providers are called before agent execution
|
|
5
|
+
* and their content is injected into the agent prompt with proper
|
|
6
|
+
* token budget management and error handling.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
10
|
+
import { DEFAULT_CONFIG } from "../../src/config/schema";
|
|
11
|
+
import { contextStage } from "../../src/pipeline/stages/context";
|
|
12
|
+
import type { PipelineContext } from "../../src/pipeline/types";
|
|
13
|
+
import { PluginRegistry } from "../../src/plugins/registry";
|
|
14
|
+
import type { IContextProvider, NaxPlugin } from "../../src/plugins/types";
|
|
15
|
+
import type { PRD, UserStory } from "../../src/prd/types";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Create a minimal test context for context stage testing
|
|
19
|
+
*/
|
|
20
|
+
function createTestContext(overrides?: Partial<PipelineContext>): PipelineContext {
|
|
21
|
+
const story: UserStory = {
|
|
22
|
+
id: "US-002",
|
|
23
|
+
title: "Test Story",
|
|
24
|
+
description: "Test story for context provider injection",
|
|
25
|
+
acceptanceCriteria: ["AC1", "AC2"],
|
|
26
|
+
status: "pending",
|
|
27
|
+
dependencies: [],
|
|
28
|
+
reasoning: "test",
|
|
29
|
+
estimatedComplexity: "simple",
|
|
30
|
+
tags: [],
|
|
31
|
+
metadata: {},
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const prd: PRD = {
|
|
35
|
+
version: 1,
|
|
36
|
+
feature: "test-feature",
|
|
37
|
+
description: "Test feature",
|
|
38
|
+
stories: [story],
|
|
39
|
+
acceptanceCriteria: [],
|
|
40
|
+
technicalNotes: "",
|
|
41
|
+
contextFiles: [],
|
|
42
|
+
dependencies: {},
|
|
43
|
+
codebaseSummary: "",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
config: DEFAULT_CONFIG,
|
|
48
|
+
prd,
|
|
49
|
+
story,
|
|
50
|
+
stories: [story],
|
|
51
|
+
routing: {
|
|
52
|
+
complexity: "simple",
|
|
53
|
+
modelTier: "fast",
|
|
54
|
+
testStrategy: "test-after",
|
|
55
|
+
reasoning: "test",
|
|
56
|
+
},
|
|
57
|
+
workdir: "/test/workdir",
|
|
58
|
+
hooks: { hooks: {} },
|
|
59
|
+
...overrides,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Create a mock context provider for testing
|
|
65
|
+
*/
|
|
66
|
+
function createMockProvider(
|
|
67
|
+
name: string,
|
|
68
|
+
content: string,
|
|
69
|
+
estimatedTokens: number,
|
|
70
|
+
label: string,
|
|
71
|
+
shouldThrow = false,
|
|
72
|
+
): IContextProvider {
|
|
73
|
+
return {
|
|
74
|
+
name,
|
|
75
|
+
async getContext(story: UserStory) {
|
|
76
|
+
if (shouldThrow) {
|
|
77
|
+
throw new Error(`Provider ${name} failed`);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
content,
|
|
81
|
+
estimatedTokens,
|
|
82
|
+
label,
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Create a mock plugin with a context provider
|
|
90
|
+
*/
|
|
91
|
+
function createMockPlugin(provider: IContextProvider): NaxPlugin {
|
|
92
|
+
return {
|
|
93
|
+
name: `plugin-${provider.name}`,
|
|
94
|
+
version: "1.0.0",
|
|
95
|
+
provides: ["context-provider"],
|
|
96
|
+
extensions: {
|
|
97
|
+
contextProvider: provider,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
describe("US-002: Context Provider Injection", () => {
|
|
103
|
+
describe("AC1: All registered context providers are called before agent execution", () => {
|
|
104
|
+
test("calls all registered context providers", async () => {
|
|
105
|
+
const provider1 = createMockProvider("jira", "Jira ticket data", 100, "Jira Context");
|
|
106
|
+
const provider2 = createMockProvider("linear", "Linear issue data", 150, "Linear Context");
|
|
107
|
+
|
|
108
|
+
const plugins = [createMockPlugin(provider1), createMockPlugin(provider2)];
|
|
109
|
+
const registry = new PluginRegistry(plugins);
|
|
110
|
+
|
|
111
|
+
const ctx = createTestContext({ plugins: registry });
|
|
112
|
+
|
|
113
|
+
const result = await contextStage.execute(ctx);
|
|
114
|
+
|
|
115
|
+
expect(result.action).toBe("continue");
|
|
116
|
+
expect(ctx.contextMarkdown).toContain("Jira Context");
|
|
117
|
+
expect(ctx.contextMarkdown).toContain("Jira ticket data");
|
|
118
|
+
expect(ctx.contextMarkdown).toContain("Linear Context");
|
|
119
|
+
expect(ctx.contextMarkdown).toContain("Linear issue data");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
test("providers are called with the current story", async () => {
|
|
123
|
+
let capturedStory: UserStory | undefined;
|
|
124
|
+
const provider = createMockProvider("test", "content", 100, "Test");
|
|
125
|
+
provider.getContext = async (story: UserStory) => {
|
|
126
|
+
capturedStory = story;
|
|
127
|
+
return { content: "test", estimatedTokens: 100, label: "Test" };
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const registry = new PluginRegistry([createMockPlugin(provider)]);
|
|
131
|
+
const ctx = createTestContext({ plugins: registry });
|
|
132
|
+
|
|
133
|
+
await contextStage.execute(ctx);
|
|
134
|
+
|
|
135
|
+
expect(capturedStory).toBeDefined();
|
|
136
|
+
expect(capturedStory?.id).toBe("US-002");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("works with no context providers registered", async () => {
|
|
140
|
+
const registry = new PluginRegistry([]);
|
|
141
|
+
const ctx = createTestContext({ plugins: registry });
|
|
142
|
+
|
|
143
|
+
const result = await contextStage.execute(ctx);
|
|
144
|
+
|
|
145
|
+
expect(result.action).toBe("continue");
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
describe("AC2: Provider content is appended under markdown section with provider's label", () => {
|
|
150
|
+
test("appends provider content under labeled markdown section", async () => {
|
|
151
|
+
const provider = createMockProvider("jira", "Ticket details here", 100, "Jira Context");
|
|
152
|
+
|
|
153
|
+
const registry = new PluginRegistry([createMockPlugin(provider)]);
|
|
154
|
+
const ctx = createTestContext({ plugins: registry });
|
|
155
|
+
|
|
156
|
+
await contextStage.execute(ctx);
|
|
157
|
+
|
|
158
|
+
expect(ctx.contextMarkdown).toContain("## Jira Context");
|
|
159
|
+
expect(ctx.contextMarkdown).toContain("Ticket details here");
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test("multiple providers create separate labeled sections", async () => {
|
|
163
|
+
const provider1 = createMockProvider("jira", "Jira data", 100, "Jira Context");
|
|
164
|
+
const provider2 = createMockProvider("confluence", "Confluence data", 150, "Confluence Docs");
|
|
165
|
+
|
|
166
|
+
const plugins = [createMockPlugin(provider1), createMockPlugin(provider2)];
|
|
167
|
+
const registry = new PluginRegistry(plugins);
|
|
168
|
+
|
|
169
|
+
const ctx = createTestContext({ plugins: registry });
|
|
170
|
+
|
|
171
|
+
await contextStage.execute(ctx);
|
|
172
|
+
|
|
173
|
+
expect(ctx.contextMarkdown).toContain("## Jira Context");
|
|
174
|
+
expect(ctx.contextMarkdown).toContain("Jira data");
|
|
175
|
+
expect(ctx.contextMarkdown).toContain("## Confluence Docs");
|
|
176
|
+
expect(ctx.contextMarkdown).toContain("Confluence data");
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
test("provider content is appended to existing context markdown", async () => {
|
|
180
|
+
const provider = createMockProvider("jira", "New context", 100, "Jira Context");
|
|
181
|
+
const registry = new PluginRegistry([createMockPlugin(provider)]);
|
|
182
|
+
|
|
183
|
+
const ctx = createTestContext({
|
|
184
|
+
plugins: registry,
|
|
185
|
+
contextMarkdown: "Existing context\n\n## Dependencies",
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
await contextStage.execute(ctx);
|
|
189
|
+
|
|
190
|
+
expect(ctx.contextMarkdown).toContain("Existing context");
|
|
191
|
+
expect(ctx.contextMarkdown).toContain("## Dependencies");
|
|
192
|
+
expect(ctx.contextMarkdown).toContain("## Jira Context");
|
|
193
|
+
expect(ctx.contextMarkdown).toContain("New context");
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe("AC3: Total injected tokens respect the token budget", () => {
|
|
198
|
+
test("respects default token budget of 2000 tokens when not configured", async () => {
|
|
199
|
+
// This test expects the implementation to use config.execution.contextProviderTokenBudget
|
|
200
|
+
// Currently uses hardcoded 20_000, which is why this test will FAIL
|
|
201
|
+
const provider1 = createMockProvider("provider1", "content1", 1000, "Provider 1");
|
|
202
|
+
const provider2 = createMockProvider("provider2", "content2", 1500, "Provider 2");
|
|
203
|
+
const provider3 = createMockProvider("provider3", "content3", 500, "Provider 3");
|
|
204
|
+
|
|
205
|
+
const plugins = [createMockPlugin(provider1), createMockPlugin(provider2), createMockPlugin(provider3)];
|
|
206
|
+
const registry = new PluginRegistry(plugins);
|
|
207
|
+
|
|
208
|
+
// Create config with default token budget (2000)
|
|
209
|
+
const configWithBudget = {
|
|
210
|
+
...DEFAULT_CONFIG,
|
|
211
|
+
execution: {
|
|
212
|
+
...DEFAULT_CONFIG.execution,
|
|
213
|
+
contextProviderTokenBudget: 2000,
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const ctx = createTestContext({
|
|
218
|
+
plugins: registry,
|
|
219
|
+
config: configWithBudget,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
await contextStage.execute(ctx);
|
|
223
|
+
|
|
224
|
+
// Should include provider1 (1000) and provider2 (1500) = 2500 total
|
|
225
|
+
// But should stop before adding all due to budget
|
|
226
|
+
// With 2000 budget, only provider1 should be added
|
|
227
|
+
expect(ctx.contextMarkdown).toContain("Provider 1");
|
|
228
|
+
expect(ctx.contextMarkdown).not.toContain("Provider 2"); // Would exceed budget
|
|
229
|
+
expect(ctx.contextMarkdown).not.toContain("Provider 3");
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test("respects custom token budget from config", async () => {
|
|
233
|
+
const provider1 = createMockProvider("provider1", "content1", 500, "Provider 1");
|
|
234
|
+
const provider2 = createMockProvider("provider2", "content2", 400, "Provider 2");
|
|
235
|
+
const provider3 = createMockProvider("provider3", "content3", 300, "Provider 3");
|
|
236
|
+
|
|
237
|
+
const plugins = [createMockPlugin(provider1), createMockPlugin(provider2), createMockPlugin(provider3)];
|
|
238
|
+
const registry = new PluginRegistry(plugins);
|
|
239
|
+
|
|
240
|
+
// Set budget to 1000 tokens
|
|
241
|
+
const configWithBudget = {
|
|
242
|
+
...DEFAULT_CONFIG,
|
|
243
|
+
execution: {
|
|
244
|
+
...DEFAULT_CONFIG.execution,
|
|
245
|
+
contextProviderTokenBudget: 1000,
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const ctx = createTestContext({
|
|
250
|
+
plugins: registry,
|
|
251
|
+
config: configWithBudget,
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
await contextStage.execute(ctx);
|
|
255
|
+
|
|
256
|
+
// Should include provider1 (500) and provider2 (400) = 900 total
|
|
257
|
+
// Should skip provider3 (would make total 1200, exceeding 1000 budget)
|
|
258
|
+
expect(ctx.contextMarkdown).toContain("Provider 1");
|
|
259
|
+
expect(ctx.contextMarkdown).toContain("Provider 2");
|
|
260
|
+
expect(ctx.contextMarkdown).not.toContain("Provider 3");
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("providers added in order until budget exhausted", async () => {
|
|
264
|
+
const provider1 = createMockProvider("provider1", "content1", 800, "Provider 1");
|
|
265
|
+
const provider2 = createMockProvider("provider2", "content2", 800, "Provider 2");
|
|
266
|
+
const provider3 = createMockProvider("provider3", "content3", 100, "Provider 3");
|
|
267
|
+
|
|
268
|
+
const plugins = [createMockPlugin(provider1), createMockPlugin(provider2), createMockPlugin(provider3)];
|
|
269
|
+
const registry = new PluginRegistry(plugins);
|
|
270
|
+
|
|
271
|
+
const configWithBudget = {
|
|
272
|
+
...DEFAULT_CONFIG,
|
|
273
|
+
execution: {
|
|
274
|
+
...DEFAULT_CONFIG.execution,
|
|
275
|
+
contextProviderTokenBudget: 1000,
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
const ctx = createTestContext({
|
|
280
|
+
plugins: registry,
|
|
281
|
+
config: configWithBudget,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
await contextStage.execute(ctx);
|
|
285
|
+
|
|
286
|
+
// Should only include provider1 (800 tokens)
|
|
287
|
+
// provider2 would exceed budget (800 + 800 = 1600 > 1000)
|
|
288
|
+
expect(ctx.contextMarkdown).toContain("Provider 1");
|
|
289
|
+
expect(ctx.contextMarkdown).not.toContain("Provider 2");
|
|
290
|
+
expect(ctx.contextMarkdown).not.toContain("Provider 3");
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
test("single provider exceeding budget is included if it's the first", async () => {
|
|
294
|
+
const provider1 = createMockProvider("provider1", "large content", 3000, "Provider 1");
|
|
295
|
+
const provider2 = createMockProvider("provider2", "content2", 100, "Provider 2");
|
|
296
|
+
|
|
297
|
+
const plugins = [createMockPlugin(provider1), createMockPlugin(provider2)];
|
|
298
|
+
const registry = new PluginRegistry(plugins);
|
|
299
|
+
|
|
300
|
+
const configWithBudget = {
|
|
301
|
+
...DEFAULT_CONFIG,
|
|
302
|
+
execution: {
|
|
303
|
+
...DEFAULT_CONFIG.execution,
|
|
304
|
+
contextProviderTokenBudget: 2000,
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
const ctx = createTestContext({
|
|
309
|
+
plugins: registry,
|
|
310
|
+
config: configWithBudget,
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
await contextStage.execute(ctx);
|
|
314
|
+
|
|
315
|
+
// First provider should be skipped as it exceeds budget alone
|
|
316
|
+
// Implementation should skip providers that would exceed budget
|
|
317
|
+
expect(ctx.contextMarkdown).not.toContain("Provider 1");
|
|
318
|
+
expect(ctx.contextMarkdown).not.toContain("Provider 2");
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
describe("AC4: Provider errors are caught, logged, and skipped", () => {
|
|
323
|
+
test("continues when a provider throws an error", async () => {
|
|
324
|
+
const provider1 = createMockProvider("failing", "content", 100, "Failing Provider", true);
|
|
325
|
+
const provider2 = createMockProvider("working", "content2", 100, "Working Provider");
|
|
326
|
+
|
|
327
|
+
const plugins = [createMockPlugin(provider1), createMockPlugin(provider2)];
|
|
328
|
+
const registry = new PluginRegistry(plugins);
|
|
329
|
+
|
|
330
|
+
const ctx = createTestContext({ plugins: registry });
|
|
331
|
+
|
|
332
|
+
const result = await contextStage.execute(ctx);
|
|
333
|
+
|
|
334
|
+
// Should continue despite provider1 failing
|
|
335
|
+
expect(result.action).toBe("continue");
|
|
336
|
+
expect(ctx.contextMarkdown).not.toContain("Failing Provider");
|
|
337
|
+
expect(ctx.contextMarkdown).toContain("Working Provider");
|
|
338
|
+
expect(ctx.contextMarkdown).toContain("content2");
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
test("handles all providers failing gracefully", async () => {
|
|
342
|
+
const provider1 = createMockProvider("failing1", "content", 100, "Provider 1", true);
|
|
343
|
+
const provider2 = createMockProvider("failing2", "content", 100, "Provider 2", true);
|
|
344
|
+
|
|
345
|
+
const plugins = [createMockPlugin(provider1), createMockPlugin(provider2)];
|
|
346
|
+
const registry = new PluginRegistry(plugins);
|
|
347
|
+
|
|
348
|
+
const ctx = createTestContext({ plugins: registry });
|
|
349
|
+
|
|
350
|
+
const result = await contextStage.execute(ctx);
|
|
351
|
+
|
|
352
|
+
expect(result.action).toBe("continue");
|
|
353
|
+
// Context markdown should be empty or contain only base context
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
test("error in one provider does not affect others", async () => {
|
|
357
|
+
const provider1 = createMockProvider("provider1", "content1", 100, "Provider 1");
|
|
358
|
+
const provider2 = createMockProvider("failing", "content", 100, "Failing Provider", true);
|
|
359
|
+
const provider3 = createMockProvider("provider3", "content3", 100, "Provider 3");
|
|
360
|
+
|
|
361
|
+
const plugins = [createMockPlugin(provider1), createMockPlugin(provider2), createMockPlugin(provider3)];
|
|
362
|
+
const registry = new PluginRegistry(plugins);
|
|
363
|
+
|
|
364
|
+
const ctx = createTestContext({ plugins: registry });
|
|
365
|
+
|
|
366
|
+
await contextStage.execute(ctx);
|
|
367
|
+
|
|
368
|
+
expect(ctx.contextMarkdown).toContain("Provider 1");
|
|
369
|
+
expect(ctx.contextMarkdown).toContain("content1");
|
|
370
|
+
expect(ctx.contextMarkdown).not.toContain("Failing Provider");
|
|
371
|
+
expect(ctx.contextMarkdown).toContain("Provider 3");
|
|
372
|
+
expect(ctx.contextMarkdown).toContain("content3");
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
describe("AC5: Token budget is configurable via execution.contextProviderTokenBudget", () => {
|
|
377
|
+
test("config schema includes contextProviderTokenBudget field", () => {
|
|
378
|
+
// This test will FAIL because the schema doesn't have this field yet
|
|
379
|
+
const config = {
|
|
380
|
+
...DEFAULT_CONFIG,
|
|
381
|
+
execution: {
|
|
382
|
+
...DEFAULT_CONFIG.execution,
|
|
383
|
+
contextProviderTokenBudget: 5000,
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
// Should not throw when accessing the field
|
|
388
|
+
expect(config.execution.contextProviderTokenBudget).toBe(5000);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
test("default config includes contextProviderTokenBudget with default of 2000", () => {
|
|
392
|
+
// Verify DEFAULT_CONFIG has the field with default value
|
|
393
|
+
// This will FAIL until ExecutionConfig type is updated
|
|
394
|
+
expect(DEFAULT_CONFIG.execution).toHaveProperty("contextProviderTokenBudget");
|
|
395
|
+
expect(DEFAULT_CONFIG.execution.contextProviderTokenBudget).toBe(2000);
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
test("uses configured token budget instead of hardcoded value", async () => {
|
|
399
|
+
const provider1 = createMockProvider("provider1", "content1", 3000, "Provider 1");
|
|
400
|
+
const provider2 = createMockProvider("provider2", "content2", 2000, "Provider 2");
|
|
401
|
+
|
|
402
|
+
const plugins = [createMockPlugin(provider1), createMockPlugin(provider2)];
|
|
403
|
+
const registry = new PluginRegistry(plugins);
|
|
404
|
+
|
|
405
|
+
// Set custom budget of 5000 tokens
|
|
406
|
+
const configWithBudget = {
|
|
407
|
+
...DEFAULT_CONFIG,
|
|
408
|
+
execution: {
|
|
409
|
+
...DEFAULT_CONFIG.execution,
|
|
410
|
+
contextProviderTokenBudget: 5000,
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
const ctx = createTestContext({
|
|
415
|
+
plugins: registry,
|
|
416
|
+
config: configWithBudget,
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
await contextStage.execute(ctx);
|
|
420
|
+
|
|
421
|
+
// Both providers should be included (3000 + 2000 = 5000)
|
|
422
|
+
expect(ctx.contextMarkdown).toContain("Provider 1");
|
|
423
|
+
expect(ctx.contextMarkdown).toContain("Provider 2");
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
test("different projects can have different token budgets", async () => {
|
|
427
|
+
const provider = createMockProvider("provider", "content", 2500, "Provider");
|
|
428
|
+
const registry = new PluginRegistry([createMockPlugin(provider)]);
|
|
429
|
+
|
|
430
|
+
// Project 1: low budget
|
|
431
|
+
const ctx1 = createTestContext({
|
|
432
|
+
plugins: registry,
|
|
433
|
+
config: {
|
|
434
|
+
...DEFAULT_CONFIG,
|
|
435
|
+
execution: {
|
|
436
|
+
...DEFAULT_CONFIG.execution,
|
|
437
|
+
contextProviderTokenBudget: 2000,
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
await contextStage.execute(ctx1);
|
|
443
|
+
expect(ctx1.contextMarkdown).not.toContain("Provider"); // Exceeds budget
|
|
444
|
+
|
|
445
|
+
// Project 2: high budget
|
|
446
|
+
const ctx2 = createTestContext({
|
|
447
|
+
plugins: registry,
|
|
448
|
+
config: {
|
|
449
|
+
...DEFAULT_CONFIG,
|
|
450
|
+
execution: {
|
|
451
|
+
...DEFAULT_CONFIG.execution,
|
|
452
|
+
contextProviderTokenBudget: 3000,
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
await contextStage.execute(ctx2);
|
|
458
|
+
expect(ctx2.contextMarkdown).toContain("Provider"); // Within budget
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
describe("Integration: Context providers inject into full pipeline", () => {
|
|
463
|
+
test("context markdown is available to prompt stage", async () => {
|
|
464
|
+
const provider = createMockProvider("jira", "Ticket ABC-123", 100, "Jira Context");
|
|
465
|
+
const registry = new PluginRegistry([createMockPlugin(provider)]);
|
|
466
|
+
|
|
467
|
+
const ctx = createTestContext({ plugins: registry });
|
|
468
|
+
|
|
469
|
+
// Run context stage
|
|
470
|
+
await contextStage.execute(ctx);
|
|
471
|
+
|
|
472
|
+
// Verify context markdown is set and available for prompt stage
|
|
473
|
+
expect(ctx.contextMarkdown).toBeDefined();
|
|
474
|
+
expect(ctx.contextMarkdown).toContain("Jira Context");
|
|
475
|
+
expect(ctx.contextMarkdown).toContain("Ticket ABC-123");
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
test("built context tracks plugin elements", async () => {
|
|
479
|
+
const provider = createMockProvider("jira", "content", 150, "Jira Context");
|
|
480
|
+
const registry = new PluginRegistry([createMockPlugin(provider)]);
|
|
481
|
+
|
|
482
|
+
const ctx = createTestContext({ plugins: registry });
|
|
483
|
+
|
|
484
|
+
await contextStage.execute(ctx);
|
|
485
|
+
|
|
486
|
+
// After running context stage, built context should include plugin elements
|
|
487
|
+
// This test expects the implementation to populate builtContext
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
test("context providers work alongside PRD context", async () => {
|
|
491
|
+
const provider = createMockProvider("jira", "External context", 100, "External");
|
|
492
|
+
const registry = new PluginRegistry([createMockPlugin(provider)]);
|
|
493
|
+
|
|
494
|
+
const ctx = createTestContext({
|
|
495
|
+
plugins: registry,
|
|
496
|
+
contextMarkdown: "# Story Context\n\nPRD-based context here",
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
await contextStage.execute(ctx);
|
|
500
|
+
|
|
501
|
+
// Should preserve existing context and append plugin context
|
|
502
|
+
expect(ctx.contextMarkdown).toContain("PRD-based context");
|
|
503
|
+
expect(ctx.contextMarkdown).toContain("External");
|
|
504
|
+
});
|
|
505
|
+
});
|
|
506
|
+
});
|