@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,416 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for nax logs command
|
|
3
|
+
*
|
|
4
|
+
* Tests the logs command implementation including:
|
|
5
|
+
* - Latest run log display
|
|
6
|
+
* - --follow mode (real-time streaming)
|
|
7
|
+
* - --story filter
|
|
8
|
+
* - --level filter
|
|
9
|
+
* - --list (runs table)
|
|
10
|
+
* - --run (specific run selection)
|
|
11
|
+
* - --json (raw JSONL output)
|
|
12
|
+
* - Combined filters
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
16
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
import { type LogsOptions, logsCommand } from "../../../src/commands/logs";
|
|
19
|
+
|
|
20
|
+
const TEST_WORKSPACE = join(import.meta.dir, "..", "..", "tmp", "logs-test");
|
|
21
|
+
|
|
22
|
+
function setupTestProject(featureName: string): string {
|
|
23
|
+
const projectDir = join(TEST_WORKSPACE, `project-${Date.now()}`);
|
|
24
|
+
const naxDir = join(projectDir, "nax");
|
|
25
|
+
const featureDir = join(naxDir, "features", featureName);
|
|
26
|
+
const runsDir = join(featureDir, "runs");
|
|
27
|
+
|
|
28
|
+
mkdirSync(runsDir, { recursive: true });
|
|
29
|
+
|
|
30
|
+
// Create minimal config.json
|
|
31
|
+
writeFileSync(join(naxDir, "config.json"), JSON.stringify({ feature: featureName }));
|
|
32
|
+
|
|
33
|
+
// Create sample JSONL log files
|
|
34
|
+
const sampleLogs = [
|
|
35
|
+
{
|
|
36
|
+
timestamp: "2026-02-27T10:00:00.000Z",
|
|
37
|
+
level: "info",
|
|
38
|
+
stage: "run.start",
|
|
39
|
+
message: "Starting feature",
|
|
40
|
+
data: { runId: "run-001", feature: featureName },
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
timestamp: "2026-02-27T10:00:01.000Z",
|
|
44
|
+
level: "info",
|
|
45
|
+
stage: "story.start",
|
|
46
|
+
storyId: "US-001",
|
|
47
|
+
message: "Starting story",
|
|
48
|
+
data: { storyId: "US-001", title: "Test Story" },
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
timestamp: "2026-02-27T10:00:02.000Z",
|
|
52
|
+
level: "debug",
|
|
53
|
+
stage: "routing",
|
|
54
|
+
storyId: "US-001",
|
|
55
|
+
message: "Routing decision",
|
|
56
|
+
data: { tier: "haiku" },
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
timestamp: "2026-02-27T10:00:03.000Z",
|
|
60
|
+
level: "info",
|
|
61
|
+
stage: "story.complete",
|
|
62
|
+
storyId: "US-001",
|
|
63
|
+
message: "Story passed",
|
|
64
|
+
data: { success: true, cost: 0.0023 },
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
timestamp: "2026-02-27T10:00:04.000Z",
|
|
68
|
+
level: "error",
|
|
69
|
+
stage: "story.start",
|
|
70
|
+
storyId: "US-002",
|
|
71
|
+
message: "Story failed",
|
|
72
|
+
data: { storyId: "US-002", title: "Failed Story" },
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
// Write latest run log
|
|
77
|
+
const latestRunPath = join(runsDir, "2026-02-27T10-00-00.jsonl");
|
|
78
|
+
writeFileSync(latestRunPath, sampleLogs.map((log) => JSON.stringify(log)).join("\n"));
|
|
79
|
+
|
|
80
|
+
// Write older run log
|
|
81
|
+
const olderLogs = [
|
|
82
|
+
{
|
|
83
|
+
timestamp: "2026-02-26T09:00:00.000Z",
|
|
84
|
+
level: "info",
|
|
85
|
+
stage: "run.start",
|
|
86
|
+
message: "Starting feature",
|
|
87
|
+
data: { runId: "run-000", feature: featureName },
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
timestamp: "2026-02-26T09:00:01.000Z",
|
|
91
|
+
level: "info",
|
|
92
|
+
stage: "story.start",
|
|
93
|
+
storyId: "US-001",
|
|
94
|
+
message: "Old run",
|
|
95
|
+
data: { storyId: "US-001", title: "Old Story" },
|
|
96
|
+
},
|
|
97
|
+
];
|
|
98
|
+
const olderRunPath = join(runsDir, "2026-02-26T09-00-00.jsonl");
|
|
99
|
+
writeFileSync(olderRunPath, olderLogs.map((log) => JSON.stringify(log)).join("\n"));
|
|
100
|
+
|
|
101
|
+
return projectDir;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function cleanup(projectDir: string) {
|
|
105
|
+
if (existsSync(projectDir)) {
|
|
106
|
+
rmSync(projectDir, { recursive: true, force: true });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
describe("logsCommand", () => {
|
|
111
|
+
let projectDir: string;
|
|
112
|
+
|
|
113
|
+
beforeEach(() => {
|
|
114
|
+
projectDir = setupTestProject("test-feature");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
afterEach(() => {
|
|
118
|
+
cleanup(projectDir);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe("default behavior (latest run formatted)", () => {
|
|
122
|
+
test("displays latest run logs with formatting", async () => {
|
|
123
|
+
const options: LogsOptions = { dir: projectDir };
|
|
124
|
+
|
|
125
|
+
// This should format and display the latest run
|
|
126
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("uses resolveProject() to find project directory", async () => {
|
|
130
|
+
// Change to project directory
|
|
131
|
+
const originalCwd = process.cwd();
|
|
132
|
+
process.chdir(projectDir);
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
const options: LogsOptions = {};
|
|
136
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
137
|
+
} finally {
|
|
138
|
+
process.chdir(originalCwd);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("throws when no nax directory found", async () => {
|
|
143
|
+
const options: LogsOptions = { dir: "/nonexistent/path" };
|
|
144
|
+
|
|
145
|
+
await expect(logsCommand(options)).rejects.toThrow();
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test("displays error when no runs exist", async () => {
|
|
149
|
+
// Create fresh project with no runs
|
|
150
|
+
const emptyProject = setupTestProject("empty-feature");
|
|
151
|
+
const runsDir = join(emptyProject, "nax", "features", "empty-feature", "runs");
|
|
152
|
+
rmSync(join(runsDir, "2026-02-27T10-00-00.jsonl"));
|
|
153
|
+
rmSync(join(runsDir, "2026-02-26T09-00-00.jsonl"));
|
|
154
|
+
|
|
155
|
+
const options: LogsOptions = { dir: emptyProject };
|
|
156
|
+
|
|
157
|
+
await expect(logsCommand(options)).rejects.toThrow(/no runs found/i);
|
|
158
|
+
|
|
159
|
+
cleanup(emptyProject);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
describe("--follow mode (real-time streaming)", () => {
|
|
164
|
+
// Note: Follow mode tests are skipped in unit tests because they run indefinitely.
|
|
165
|
+
// They are tested in integration tests (test/integration/cli-logs.test.ts) where we can spawn and kill processes.
|
|
166
|
+
test.skip("streams new log entries in real-time", async () => {
|
|
167
|
+
// Skipped: tested in integration tests
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test.skip("follows the latest run by default", async () => {
|
|
171
|
+
// Skipped: tested in integration tests
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test.skip("can follow a specific run with --run flag", async () => {
|
|
175
|
+
// Skipped: tested in integration tests
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe("--story filter", () => {
|
|
180
|
+
test("filters logs to specific story", async () => {
|
|
181
|
+
const options: LogsOptions = { dir: projectDir, story: "US-001" };
|
|
182
|
+
|
|
183
|
+
// Should only show logs with storyId: "US-001"
|
|
184
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test.skip("filters work with --follow mode", async () => {
|
|
188
|
+
// Skipped: tested in integration tests
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test("shows empty result when story not found", async () => {
|
|
192
|
+
const options: LogsOptions = { dir: projectDir, story: "US-999" };
|
|
193
|
+
|
|
194
|
+
// No logs match this story
|
|
195
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
describe("--level filter", () => {
|
|
200
|
+
test("filters logs by error level", async () => {
|
|
201
|
+
const options: LogsOptions = { dir: projectDir, level: "error" };
|
|
202
|
+
|
|
203
|
+
// Should only show error-level logs
|
|
204
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("filters logs by info level", async () => {
|
|
208
|
+
const options: LogsOptions = { dir: projectDir, level: "info" };
|
|
209
|
+
|
|
210
|
+
// Should show info, warn, error (all >= info)
|
|
211
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test("filters logs by debug level", async () => {
|
|
215
|
+
const options: LogsOptions = { dir: projectDir, level: "debug" };
|
|
216
|
+
|
|
217
|
+
// Should show all logs (debug is lowest level)
|
|
218
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test.skip("filters work with --follow mode", async () => {
|
|
222
|
+
// Skipped: tested in integration tests
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
describe("--list (runs table)", () => {
|
|
227
|
+
test("displays table of all runs", async () => {
|
|
228
|
+
const options: LogsOptions = { dir: projectDir, list: true };
|
|
229
|
+
|
|
230
|
+
// Should display a table of runs with timestamps, status, duration
|
|
231
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test("includes run metadata in table", async () => {
|
|
235
|
+
const options: LogsOptions = { dir: projectDir, list: true };
|
|
236
|
+
|
|
237
|
+
// Table should include: timestamp, stories count, cost, duration
|
|
238
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test("sorts runs by timestamp descending (newest first)", async () => {
|
|
242
|
+
const options: LogsOptions = { dir: projectDir, list: true };
|
|
243
|
+
|
|
244
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test("shows empty message when no runs exist", async () => {
|
|
248
|
+
const emptyProject = setupTestProject("empty-feature");
|
|
249
|
+
const runsDir = join(emptyProject, "nax", "features", "empty-feature", "runs");
|
|
250
|
+
rmSync(join(runsDir, "2026-02-27T10-00-00.jsonl"));
|
|
251
|
+
rmSync(join(runsDir, "2026-02-26T09-00-00.jsonl"));
|
|
252
|
+
|
|
253
|
+
const options: LogsOptions = { dir: emptyProject, list: true };
|
|
254
|
+
|
|
255
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
256
|
+
|
|
257
|
+
cleanup(emptyProject);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
describe("--run (specific run selection)", () => {
|
|
262
|
+
test("displays specific run by timestamp", async () => {
|
|
263
|
+
const options: LogsOptions = {
|
|
264
|
+
dir: projectDir,
|
|
265
|
+
run: "2026-02-26T09-00-00",
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
// Should display the older run
|
|
269
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
test("throws when specified run does not exist", async () => {
|
|
273
|
+
const options: LogsOptions = {
|
|
274
|
+
dir: projectDir,
|
|
275
|
+
run: "2026-01-01T00-00-00",
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
await expect(logsCommand(options)).rejects.toThrow(/run not found/i);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
test("works with partial timestamp matching", async () => {
|
|
282
|
+
const options: LogsOptions = {
|
|
283
|
+
dir: projectDir,
|
|
284
|
+
run: "2026-02-26",
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
// Should match "2026-02-26T09-00-00"
|
|
288
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
describe("--json (raw JSONL output)", () => {
|
|
293
|
+
test("outputs raw JSONL without formatting", async () => {
|
|
294
|
+
const options: LogsOptions = { dir: projectDir, json: true };
|
|
295
|
+
|
|
296
|
+
// Should output raw JSONL lines
|
|
297
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
test("combines with --story filter", async () => {
|
|
301
|
+
const options: LogsOptions = {
|
|
302
|
+
dir: projectDir,
|
|
303
|
+
story: "US-001",
|
|
304
|
+
json: true,
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
// Raw JSONL output but only for US-001
|
|
308
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test("combines with --level filter", async () => {
|
|
312
|
+
const options: LogsOptions = {
|
|
313
|
+
dir: projectDir,
|
|
314
|
+
level: "error",
|
|
315
|
+
json: true,
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
// Raw JSONL output but only error level
|
|
319
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
test.skip("works with --follow mode", async () => {
|
|
323
|
+
// Skipped: tested in integration tests
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
describe("combined filters", () => {
|
|
328
|
+
test("--story + --level filters", async () => {
|
|
329
|
+
const options: LogsOptions = {
|
|
330
|
+
dir: projectDir,
|
|
331
|
+
story: "US-001",
|
|
332
|
+
level: "info",
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
// Only US-001 logs with info level or higher
|
|
336
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
test("--story + --level + --json", async () => {
|
|
340
|
+
const options: LogsOptions = {
|
|
341
|
+
dir: projectDir,
|
|
342
|
+
story: "US-001",
|
|
343
|
+
level: "debug",
|
|
344
|
+
json: true,
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
test("--run + --story + --level", async () => {
|
|
351
|
+
const options: LogsOptions = {
|
|
352
|
+
dir: projectDir,
|
|
353
|
+
run: "2026-02-27T10-00-00",
|
|
354
|
+
story: "US-001",
|
|
355
|
+
level: "info",
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
test("all filters combined", async () => {
|
|
362
|
+
const options: LogsOptions = {
|
|
363
|
+
dir: projectDir,
|
|
364
|
+
run: "2026-02-27T10-00-00",
|
|
365
|
+
story: "US-001",
|
|
366
|
+
level: "info",
|
|
367
|
+
json: true,
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
test("--list ignores other filters", async () => {
|
|
374
|
+
const options: LogsOptions = {
|
|
375
|
+
dir: projectDir,
|
|
376
|
+
list: true,
|
|
377
|
+
story: "US-001", // Should be ignored
|
|
378
|
+
level: "error", // Should be ignored
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
// --list takes precedence, others ignored
|
|
382
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
383
|
+
});
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
describe("resolveProject integration", () => {
|
|
387
|
+
test("resolves project from -d flag", async () => {
|
|
388
|
+
const options: LogsOptions = { dir: projectDir };
|
|
389
|
+
|
|
390
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
test("resolves project from CWD", async () => {
|
|
394
|
+
const originalCwd = process.cwd();
|
|
395
|
+
process.chdir(projectDir);
|
|
396
|
+
|
|
397
|
+
try {
|
|
398
|
+
const options: LogsOptions = {};
|
|
399
|
+
await expect(logsCommand(options)).resolves.toBeUndefined();
|
|
400
|
+
} finally {
|
|
401
|
+
process.chdir(originalCwd);
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
test("validates nax/config.json exists", async () => {
|
|
406
|
+
const invalidProject = join(TEST_WORKSPACE, "invalid");
|
|
407
|
+
mkdirSync(join(invalidProject, "nax"), { recursive: true });
|
|
408
|
+
|
|
409
|
+
const options: LogsOptions = { dir: invalidProject };
|
|
410
|
+
|
|
411
|
+
await expect(logsCommand(options)).rejects.toThrow(/config.json/i);
|
|
412
|
+
|
|
413
|
+
cleanup(invalidProject);
|
|
414
|
+
});
|
|
415
|
+
});
|
|
416
|
+
});
|