@nathapp/nax 0.28.0 → 0.30.0
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/CHANGELOG.md +23 -2
- package/bin/nax.ts +2 -3
- package/dist/nax.js +72753 -0
- package/package.json +11 -3
- package/src/cli/analyze.ts +2 -7
- package/src/cli/config.ts +3 -1
- package/src/config/defaults.ts +1 -0
- package/src/config/schemas.ts +1 -0
- package/src/config/types.ts +1 -0
- package/src/context/builder.ts +10 -1
- package/src/execution/lifecycle/headless-formatter.ts +2 -4
- package/src/prompts/builder.ts +12 -69
- package/src/prompts/sections/isolation.ts +38 -8
- package/src/prompts/sections/role-task.ts +79 -17
- package/src/review/runner.ts +6 -1
- package/src/version.ts +2 -1
- package/.claude/rules/01-project-conventions.md +0 -34
- package/.claude/rules/02-test-architecture.md +0 -39
- package/.claude/rules/03-test-writing.md +0 -58
- package/.claude/rules/04-forbidden-patterns.md +0 -29
- package/.claude/settings.json +0 -15
- package/.githooks/pre-commit +0 -16
- package/.gitlab-ci.yml +0 -103
- package/.mcp.json +0 -8
- package/BRIEF.md +0 -140
- package/CLAUDE.md +0 -143
- package/US-007-IMPLEMENTATION.md +0 -139
- package/biome.json +0 -14
- package/bun.lock +0 -163
- package/bunfig.toml +0 -12
- package/docker-compose.test.yml +0 -15
- package/docs/20260216-fix-plan-context-review.md +0 -56
- package/docs/20260216-relentless-vs-ngent-comparison.md +0 -208
- package/docs/20260216-v02-plan.md +0 -136
- package/docs/20260216-v02-review.md +0 -685
- package/docs/20260217-dogfood-findings.md +0 -56
- package/docs/20260217-p2-plus-plan.md +0 -117
- package/docs/20260217-partial-fixes-plan.md +0 -62
- package/docs/20260217-plan-analyze-spec.md +0 -117
- package/docs/20260217-post-impl-review.md +0 -1137
- package/docs/20260217-quick-wins-plan.md +0 -66
- package/docs/20260217-split-runner-plan.md +0 -75
- package/docs/20260217-v03-impl-plan.md +0 -80
- package/docs/20260217-v03-post-impl-review.md +0 -589
- package/docs/20260217-v04-impl-plan.md +0 -86
- package/docs/20260217-v05-post-impl-review.md +0 -850
- package/docs/20260217-v06-post-impl-review.md +0 -817
- package/docs/20260218-adr003-port-plan.md +0 -151
- package/docs/20260218-review-adr003-verification.md +0 -175
- package/docs/20260219-fix-plan-bug16-19.md +0 -79
- package/docs/20260219-fix-plan-bug20-22.md +0 -114
- package/docs/20260219-plan-llm-routing.md +0 -116
- package/docs/20260219-review-bug20-22-fixes.md +0 -135
- package/docs/20260219-routing-baseline-keyword.md +0 -63
- package/docs/20260220-plan-structured-logging-p1.md +0 -80
- package/docs/20260220-plan-structured-logging-p2.md +0 -37
- package/docs/20260220-review-llm-routing.md +0 -180
- package/docs/20260220-review-post-fix-llm-routing.md +0 -70
- package/docs/20260221-fix-plan-relevantfiles-split.md +0 -101
- package/docs/20260221-fix-plan-routing-mode.md +0 -125
- package/docs/20260221-review-v0.9-implementation.md +0 -379
- package/docs/20260222-fix-plan-v091-routing-isolation.md +0 -197
- package/docs/20260223-fix-plan-prompt-audit.md +0 -62
- package/docs/20260224-nax-roadmap-phases.md +0 -189
- package/docs/20260225-phase2-llm-service-layer.md +0 -401
- package/docs/20260225-review-v0.10.1.md +0 -187
- package/docs/20260303-v010-implementation-plan.md +0 -165
- package/docs/20260304-review-nax.md +0 -492
- package/docs/CLAUDE.md.bak +0 -191
- package/docs/ROADMAP.md +0 -390
- package/docs/SPEC-rectification.md +0 -0
- package/docs/SPEC.md +0 -324
- package/docs/US-001-plugin-loading-verification.md +0 -152
- package/docs/adr/ADR-005-implementation-plan.md +0 -655
- package/docs/adr/ADR-005-pipeline-re-architecture.md +0 -464
- package/docs/architecture-analysis.md +0 -1076
- package/docs/bugs/BUG-21-escalation-null-attempts.md +0 -48
- package/docs/bugs-from-dogfood-run-c.md +0 -243
- package/docs/code-review-20260228.md +0 -612
- package/docs/code-review-v0.15.0.md +0 -629
- package/docs/hook-lifecycle-test-plan.md +0 -149
- package/docs/releases/v0.11.0-and-earlier.md +0 -20
- package/docs/releases/v0.12.0.md +0 -15
- package/docs/releases/v0.13.0.md +0 -14
- package/docs/releases/v0.14.0.md +0 -20
- package/docs/releases/v0.14.1.md +0 -36
- package/docs/releases/v0.14.2.md +0 -51
- package/docs/releases/v0.14.3.md +0 -174
- package/docs/releases/v0.14.4.md +0 -94
- package/docs/releases/v0.15.0.md +0 -502
- package/docs/releases/v0.15.1.md +0 -170
- package/docs/releases/v0.15.3.md +0 -193
- package/docs/specs/bug-039-orphan-processes.md +0 -131
- package/docs/specs/bug-040-review-rectification.md +0 -82
- package/docs/specs/bug-041-cross-story-test-isolation.md +0 -88
- package/docs/specs/bug-042-verifier-failure-capture.md +0 -117
- package/docs/specs/bun-pty-migration.md +0 -171
- package/docs/specs/central-run-registry.md +0 -116
- package/docs/specs/feat-010-smart-runner-git-history.md +0 -96
- package/docs/specs/feat-011-file-context-strategy.md +0 -73
- package/docs/specs/feat-012-tdd-writer-tier.md +0 -79
- package/docs/specs/feat-013-test-after-review.md +0 -89
- package/docs/specs/feat-014-heartbeat-observability.md +0 -127
- package/docs/specs/status-file-consolidation.md +0 -93
- package/docs/specs/status-file-v0.10.1.md +0 -812
- package/docs/specs/trigger-completion.md +0 -145
- package/docs/specs/verification-architecture-v2.md +0 -343
- package/docs/tdd/strategies.md +0 -97
- package/docs/v0.10-global-config.md +0 -206
- package/docs/v0.10-plugin-system.md +0 -415
- package/docs/v0.10-prompt-optimizer.md +0 -234
- package/docs/v0.3-spec.md +0 -244
- package/docs/v0.4-spec.md +0 -140
- package/docs/v0.5-spec.md +0 -237
- package/docs/v0.6-spec.md +0 -371
- package/docs/v0.7-spec.md +0 -177
- package/docs/v0.8-llm-routing.md +0 -206
- package/docs/v0.8-structured-logging.md +0 -132
- package/docs/v0.9.3-prompt-audit.md +0 -112
- package/examples/plugins/console-reporter/index.test.ts +0 -207
- package/examples/plugins/console-reporter/index.ts +0 -110
- package/memory/topic/feat-010-baseref.md +0 -28
- package/memory/topic/feat-013-test-after-deprecation.md +0 -22
- package/nax/config.json +0 -154
- package/nax/features/bug-039-medium/prd.json +0 -45
- package/nax/features/bugfix-v0171/prd.json +0 -52
- package/nax/features/central-run-registry/prd.json +0 -105
- package/nax/features/config-management/prd.json +0 -108
- package/nax/features/config-management/progress.txt +0 -5
- package/nax/features/diagnose/acceptance.test.ts +0 -414
- package/nax/features/diagnose/prd.json +0 -41
- package/nax/features/nax-compliance/prd.json +0 -52
- package/nax/features/nax-compliance/progress.txt +0 -1
- package/nax/features/orchestration-fixes/prd.json +0 -89
- package/nax/features/orchestration-fixes/progress.txt +0 -1
- package/nax/features/plugin-integration/US-007-VERIFICATION.md +0 -259
- package/nax/features/plugin-integration/prd.json +0 -208
- package/nax/features/plugin-integration/progress.txt +0 -5
- package/nax/features/post-rearch-bugfix/prd.json +0 -137
- package/nax/features/precheck/prd.json +0 -205
- package/nax/features/precheck/progress.txt +0 -15
- package/nax/features/prompt-builder/prd.json +0 -152
- package/nax/features/prompt-builder/progress.txt +0 -3
- package/nax/features/review-quality/prd.json +0 -55
- package/nax/features/routing-persistence/prd.json +0 -104
- package/nax/features/routing-persistence/progress.txt +0 -1
- package/nax/features/smart-test-runner/plan.md +0 -7
- package/nax/features/smart-test-runner/prd.json +0 -203
- package/nax/features/smart-test-runner/progress.txt +0 -13
- package/nax/features/smart-test-runner/spec.md +0 -7
- package/nax/features/smart-test-runner/tasks.md +0 -8
- package/nax/features/status-file-consolidation/prd.json +0 -106
- package/nax/features/structured-logging/prd.json +0 -199
- package/nax/features/trigger-completion/prd.json +0 -150
- package/nax/features/trigger-completion/progress.txt +0 -7
- package/nax/features/unlock/prd.json +0 -36
- package/nax/features/v0.18.3-execution-reliability/prd.json +0 -80
- package/nax/features/v0.18.3-execution-reliability/progress.txt +0 -3
- package/nax/features/v0.19.0-hardening/plan.md +0 -7
- package/nax/features/v0.19.0-hardening/prd.json +0 -84
- package/nax/features/v0.19.0-hardening/progress.txt +0 -7
- package/nax/features/v0.19.0-hardening/spec.md +0 -18
- package/nax/features/v0.19.0-hardening/tasks.md +0 -8
- package/nax/features/verify-v2/prd.json +0 -79
- package/nax/features/verify-v2/progress.txt +0 -3
- package/nax/status.json +0 -36
- package/src/prompts/templates/implementer.ts +0 -6
- package/src/prompts/templates/single-session.ts +0 -6
- package/src/prompts/templates/test-writer.ts +0 -6
- package/src/prompts/templates/verifier.ts +0 -6
- package/test/COVERAGE-GAPS.md +0 -333
- package/test/e2e/cm-003-default-view.test.ts +0 -195
- package/test/e2e/plan-analyze-run.test.ts +0 -902
- package/test/helpers/helpers.test.ts +0 -295
- package/test/helpers/timeout.ts +0 -42
- package/test/integration/US-002-TEST-SUMMARY.md +0 -107
- package/test/integration/US-003-TEST-SUMMARY.md +0 -149
- package/test/integration/US-004-TEST-SUMMARY.md +0 -106
- package/test/integration/US-005-TEST-SUMMARY.md +0 -138
- package/test/integration/US-007-TEST-SUMMARY.md +0 -100
- package/test/integration/cli/agent-validation.test.ts +0 -439
- package/test/integration/cli/cli-config-default-edge-cases.test.ts +0 -223
- package/test/integration/cli/cli-config-default-view.test.ts +0 -230
- package/test/integration/cli/cli-config-diff.test.ts +0 -461
- package/test/integration/cli/cli-config-prompts-explain.test.ts +0 -74
- package/test/integration/cli/cli-config.test.ts +0 -737
- package/test/integration/cli/cli-diagnose.test.ts +0 -595
- package/test/integration/cli/cli-logs.test.ts +0 -346
- package/test/integration/cli/cli-plugins.test.ts +0 -679
- package/test/integration/cli/cli-precheck.test.ts +0 -372
- package/test/integration/cli/cli-run-headless.test.ts +0 -174
- package/test/integration/cli/cli.test.ts +0 -76
- package/test/integration/cli/precheck-integration.test.ts +0 -476
- package/test/integration/cli/precheck-orchestrator.test.ts +0 -247
- package/test/integration/cli/precheck.test.ts +0 -806
- package/test/integration/config/config-loader.test.ts +0 -266
- package/test/integration/config/config.test.ts +0 -444
- package/test/integration/config/merger.test.ts +0 -466
- package/test/integration/config/paths.test.ts +0 -52
- package/test/integration/config/security-loader.test.ts +0 -83
- package/test/integration/context/context-integration.test.ts +0 -703
- package/test/integration/context/context-path-security.test.ts +0 -173
- package/test/integration/context/context-provider-injection.test.ts +0 -507
- package/test/integration/context/context-verification-integration.test.ts +0 -296
- package/test/integration/context/s5-greenfield-fallback.test.ts +0 -298
- package/test/integration/execution/execution-isolation.test.ts +0 -143
- package/test/integration/execution/execution.test.ts +0 -634
- package/test/integration/execution/feature-status-write.test.ts +0 -302
- package/test/integration/execution/parallel.test.ts +0 -251
- package/test/integration/execution/prd-pause.test.ts +0 -205
- package/test/integration/execution/prd-resolvers.test.ts +0 -186
- package/test/integration/execution/progress.test.ts +0 -34
- package/test/integration/execution/runner-batching.test.ts +0 -682
- package/test/integration/execution/runner-config-plugins.test.ts +0 -462
- package/test/integration/execution/runner-escalation.test.ts +0 -561
- package/test/integration/execution/runner-fixes.test.ts +0 -400
- package/test/integration/execution/runner-plugin-integration.test.ts +0 -544
- package/test/integration/execution/runner-queue-and-attempts.test.ts +0 -476
- package/test/integration/execution/status-file-integration.test.ts +0 -289
- package/test/integration/execution/status-file.test.ts +0 -380
- package/test/integration/execution/status-writer.test.ts +0 -447
- package/test/integration/execution/story-id-in-events.test.ts +0 -274
- package/test/integration/interaction/interaction-chain-pipeline.test.ts +0 -476
- package/test/integration/pipeline/hooks.test.ts +0 -363
- package/test/integration/pipeline/pipeline-acceptance.test.ts +0 -303
- package/test/integration/pipeline/pipeline-events.test.ts +0 -476
- package/test/integration/pipeline/pipeline.test.ts +0 -660
- package/test/integration/pipeline/reporter-lifecycle.test.ts +0 -862
- package/test/integration/pipeline/verify-stage.test.ts +0 -286
- package/test/integration/plan/analyze-integration.test.ts +0 -262
- package/test/integration/plan/analyze-scanner.test.ts +0 -132
- package/test/integration/plan/logger.test.ts +0 -461
- package/test/integration/plan/plan.test.ts +0 -157
- package/test/integration/plugins/config-integration.test.ts +0 -173
- package/test/integration/plugins/config-resolution.test.ts +0 -523
- package/test/integration/plugins/loader.test.ts +0 -644
- package/test/integration/plugins/plugins-registry.test.ts +0 -747
- package/test/integration/plugins/validator.test.ts +0 -564
- package/test/integration/prompts/pb-004-migration.test.ts +0 -523
- package/test/integration/review/review-config-commands.test.ts +0 -320
- package/test/integration/review/review-config-schema.test.ts +0 -117
- package/test/integration/review/review-plugin-integration.test.ts +0 -729
- package/test/integration/review/review.test.ts +0 -150
- package/test/integration/routing/plugin-routing-advanced.test.ts +0 -461
- package/test/integration/routing/plugin-routing-core.test.ts +0 -527
- package/test/integration/routing/routing-stage-bug-021.test.ts +0 -275
- package/test/integration/routing/routing-stage-greenfield.test.ts +0 -287
- package/test/integration/tdd/tdd-cleanup.test.ts +0 -246
- package/test/integration/tdd/tdd-orchestrator-core.test.ts +0 -565
- package/test/integration/tdd/tdd-orchestrator-failureCategory.test.ts +0 -355
- package/test/integration/tdd/tdd-orchestrator-fallback.test.ts +0 -311
- package/test/integration/tdd/tdd-orchestrator-lite.test.ts +0 -289
- package/test/integration/tdd/tdd-orchestrator-prompts.test.ts +0 -260
- package/test/integration/tdd/tdd-orchestrator-verdict.test.ts +0 -536
- package/test/integration/tmp/headless-test/test.jsonl +0 -30
- package/test/integration/verification/test-scanner.test.ts +0 -403
- package/test/integration/verification/verification-asset-check.test.ts +0 -143
- package/test/integration/worktree/manager.test.ts +0 -218
- package/test/integration/worktree/worktree-merge.test.ts +0 -341
- package/test/manual/logging-formatter-demo.ts +0 -158
- package/test/ui/tui-agent-panel.test.tsx +0 -99
- package/test/ui/tui-pty-integration.test.tsx +0 -146
- package/test/unit/acceptance.test.ts +0 -187
- package/test/unit/agent-stderr-capture.test.ts +0 -147
- package/test/unit/agents/claude.test.ts +0 -107
- package/test/unit/analyze-classifier.test.ts +0 -216
- package/test/unit/analyze.test.ts +0 -224
- package/test/unit/auto-detect.test.ts +0 -250
- package/test/unit/cli-status-project-level.test.ts +0 -283
- package/test/unit/cli-status.test.ts +0 -418
- package/test/unit/commands/common.test.ts +0 -321
- package/test/unit/commands/logs.test.ts +0 -458
- package/test/unit/commands/runs.test.ts +0 -303
- package/test/unit/commands/unlock.test.ts +0 -320
- package/test/unit/config/defaults.test.ts +0 -70
- package/test/unit/config/quality-commands-schema.test.ts +0 -72
- package/test/unit/config/regression-gate-schema.test.ts +0 -160
- package/test/unit/config/smart-runner-flag.test.ts +0 -250
- package/test/unit/constitution-generators.test.ts +0 -161
- package/test/unit/constitution.test.ts +0 -210
- package/test/unit/context/context-autodetect.test.ts +0 -297
- package/test/unit/context/context-build.test.ts +0 -575
- package/test/unit/context/context-coverage.test.ts +0 -236
- package/test/unit/context/context-error.test.ts +0 -93
- package/test/unit/context/context-estimate-tokens.test.ts +0 -201
- package/test/unit/context/context-format.test.ts +0 -302
- package/test/unit/context/context-isolation.test.ts +0 -267
- package/test/unit/context/context-sort.test.ts +0 -93
- package/test/unit/context/context-story.test.ts +0 -108
- package/test/unit/context/prior-failures.test.ts +0 -463
- package/test/unit/context.test.ts +0 -1726
- package/test/unit/cost.test.ts +0 -231
- package/test/unit/crash-recovery.test.ts +0 -309
- package/test/unit/escalation.test.ts +0 -127
- package/test/unit/execution/lifecycle/run-completion.test.ts +0 -240
- package/test/unit/execution/lifecycle/run-regression.test.ts +0 -420
- package/test/unit/execution/pid-registry.test.ts +0 -241
- package/test/unit/execution/sequential-executor.test.ts +0 -235
- package/test/unit/execution/sfc-004-dead-code-cleanup.test.ts +0 -89
- package/test/unit/execution/structured-failure.test.ts +0 -415
- package/test/unit/execution-logging-stderr.test.ts +0 -157
- package/test/unit/execution-stage.test.ts +0 -123
- package/test/unit/fix-generator.test.ts +0 -276
- package/test/unit/formatters.test.ts +0 -468
- package/test/unit/greenfield.test.ts +0 -180
- package/test/unit/hooks/shell-security.test.ts +0 -40
- package/test/unit/interaction/auto-plugin.test.ts +0 -162
- package/test/unit/interaction/human-review-trigger.test.ts +0 -165
- package/test/unit/interaction-network-failures.test.ts +0 -390
- package/test/unit/interaction-plugins.test.ts +0 -472
- package/test/unit/logging/formatter.test.ts +0 -456
- package/test/unit/merge.test.ts +0 -269
- package/test/unit/metrics/aggregator.test.ts +0 -164
- package/test/unit/metrics/tracker.test.ts +0 -186
- package/test/unit/metrics.test.ts +0 -276
- package/test/unit/optimizer/noop.optimizer.test.ts +0 -125
- package/test/unit/optimizer/rule-based.optimizer.test.ts +0 -358
- package/test/unit/pipeline/event-bus.test.ts +0 -105
- package/test/unit/pipeline/routing-partial-override.test.ts +0 -121
- package/test/unit/pipeline/runner-retry.test.ts +0 -89
- package/test/unit/pipeline/stages/autofix.test.ts +0 -97
- package/test/unit/pipeline/stages/completion-review-gate.test.ts +0 -218
- package/test/unit/pipeline/stages/execution-ambiguity.test.ts +0 -311
- package/test/unit/pipeline/stages/execution-merge-conflict.test.ts +0 -218
- package/test/unit/pipeline/stages/rectify.test.ts +0 -101
- package/test/unit/pipeline/stages/regression-stage.test.ts +0 -69
- package/test/unit/pipeline/stages/review.test.ts +0 -201
- package/test/unit/pipeline/stages/routing-idempotence.test.ts +0 -139
- package/test/unit/pipeline/stages/routing-initial-complexity.test.ts +0 -321
- package/test/unit/pipeline/stages/routing-persistence.test.ts +0 -380
- package/test/unit/pipeline/stages/verify.test.ts +0 -267
- package/test/unit/pipeline/subscribers/events-writer.test.ts +0 -227
- package/test/unit/pipeline/subscribers/hooks.test.ts +0 -84
- package/test/unit/pipeline/subscribers/interaction.test.ts +0 -313
- package/test/unit/pipeline/subscribers/registry.test.ts +0 -149
- package/test/unit/pipeline/subscribers/reporters.test.ts +0 -90
- package/test/unit/pipeline/verify-smart-runner.test.ts +0 -345
- package/test/unit/prd-auto-default.test.ts +0 -291
- package/test/unit/prd-failure-category.test.ts +0 -177
- package/test/unit/prd-get-next-story.test.ts +0 -215
- package/test/unit/precheck/checks-warnings.test.ts +0 -114
- package/test/unit/precheck-checks.test.ts +0 -841
- package/test/unit/precheck-story-size-gate.test.ts +0 -288
- package/test/unit/precheck-types.test.ts +0 -143
- package/test/unit/prompts/builder.test.ts +0 -258
- package/test/unit/prompts/loader.test.ts +0 -355
- package/test/unit/prompts/sections/conventions.test.ts +0 -30
- package/test/unit/prompts/sections/isolation.test.ts +0 -35
- package/test/unit/prompts/sections/role-task.test.ts +0 -40
- package/test/unit/prompts/sections/sections.test.ts +0 -238
- package/test/unit/prompts/sections/story.test.ts +0 -45
- package/test/unit/prompts/sections/verdict.test.ts +0 -58
- package/test/unit/prompts.test.ts +0 -476
- package/test/unit/queue.test.ts +0 -237
- package/test/unit/rectification.test.ts +0 -285
- package/test/unit/registry.test.ts +0 -288
- package/test/unit/review/runner.test.ts +0 -117
- package/test/unit/routing/content-hash.test.ts +0 -99
- package/test/unit/routing/routing-stability.test.ts +0 -208
- package/test/unit/routing/strategies/llm.test.ts +0 -306
- package/test/unit/routing-advanced.test.ts +0 -313
- package/test/unit/routing-core.test.ts +0 -341
- package/test/unit/routing-strategies.test.ts +0 -440
- package/test/unit/storyid-events.test.ts +0 -213
- package/test/unit/tdd-verdict.test.ts +0 -492
- package/test/unit/test-output-parser.test.ts +0 -377
- package/test/unit/ui/tui-controls.test.ts +0 -335
- package/test/unit/ui/tui-cost-and-pty.test.ts +0 -190
- package/test/unit/ui/tui-layout.test.ts +0 -379
- package/test/unit/ui/tui-stories.test.ts +0 -333
- package/test/unit/unit-isolation.test.ts +0 -135
- package/test/unit/utils/git.test.ts +0 -50
- package/test/unit/utils/path-security.test.ts +0 -47
- package/test/unit/utils-helpers.test.ts +0 -318
- package/test/unit/verdict.test.ts +0 -325
- package/test/unit/verification/orchestrator-types.test.ts +0 -54
- package/test/unit/verification/orchestrator.test.ts +0 -66
- package/test/unit/verification/smart-runner-config.test.ts +0 -163
- package/test/unit/verification/smart-runner-discovery.test.ts +0 -354
- package/test/unit/verification/smart-runner.test.ts +0 -262
- package/test/unit/verification/strategies/acceptance.test.ts +0 -33
- package/test/unit/verification/strategies/regression.test.ts +0 -87
- package/test/unit/verification/strategies/scoped.test.ts +0 -100
- package/test/unit/worktree-manager.test.ts +0 -159
- package/tsconfig.json +0 -27
|
@@ -1,390 +0,0 @@
|
|
|
1
|
-
// RE-ARCH: keep
|
|
2
|
-
/**
|
|
3
|
-
* Interaction Plugins Network Failure Tests (v0.15.1)
|
|
4
|
-
*
|
|
5
|
-
* Tests network error handling, exponential backoff, payload limits, and malformed input.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { describe, expect, test } from "bun:test";
|
|
9
|
-
import type { InteractionRequest } from "../../src/interaction";
|
|
10
|
-
import { TelegramInteractionPlugin } from "../../src/interaction/plugins/telegram";
|
|
11
|
-
import { WebhookInteractionPlugin } from "../../src/interaction/plugins/webhook";
|
|
12
|
-
|
|
13
|
-
describe("TelegramInteractionPlugin - Network Failures", () => {
|
|
14
|
-
test("should handle network error in send()", async () => {
|
|
15
|
-
const plugin = new TelegramInteractionPlugin();
|
|
16
|
-
await plugin.init({ botToken: "test-token", chatId: "12345" });
|
|
17
|
-
|
|
18
|
-
// Mock fetch to throw network error
|
|
19
|
-
const originalFetch = globalThis.fetch;
|
|
20
|
-
globalThis.fetch = async () => {
|
|
21
|
-
throw new Error("ECONNREFUSED");
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const request: InteractionRequest = {
|
|
25
|
-
id: "test-network-error",
|
|
26
|
-
type: "confirm",
|
|
27
|
-
featureName: "test-feature",
|
|
28
|
-
stage: "review",
|
|
29
|
-
summary: "Test network error",
|
|
30
|
-
fallback: "abort",
|
|
31
|
-
createdAt: Date.now(),
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
await expect(plugin.send(request)).rejects.toThrow("Failed to send Telegram message");
|
|
35
|
-
|
|
36
|
-
// Restore
|
|
37
|
-
globalThis.fetch = originalFetch;
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test("should handle malformed API response in send()", async () => {
|
|
41
|
-
const plugin = new TelegramInteractionPlugin();
|
|
42
|
-
await plugin.init({ botToken: "test-token", chatId: "12345" });
|
|
43
|
-
|
|
44
|
-
// Mock fetch to return invalid JSON
|
|
45
|
-
const originalFetch = globalThis.fetch;
|
|
46
|
-
globalThis.fetch = async () => {
|
|
47
|
-
return new Response("not json", { status: 200 });
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const request: InteractionRequest = {
|
|
51
|
-
id: "test-malformed-response",
|
|
52
|
-
type: "confirm",
|
|
53
|
-
featureName: "test-feature",
|
|
54
|
-
stage: "review",
|
|
55
|
-
summary: "Test malformed response",
|
|
56
|
-
fallback: "abort",
|
|
57
|
-
createdAt: Date.now(),
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
await expect(plugin.send(request)).rejects.toThrow("Failed to send Telegram message");
|
|
61
|
-
|
|
62
|
-
// Restore
|
|
63
|
-
globalThis.fetch = originalFetch;
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test("should handle HTTP error status in send()", async () => {
|
|
67
|
-
const plugin = new TelegramInteractionPlugin();
|
|
68
|
-
await plugin.init({ botToken: "test-token", chatId: "12345" });
|
|
69
|
-
|
|
70
|
-
// Mock fetch to return 500 error
|
|
71
|
-
const originalFetch = globalThis.fetch;
|
|
72
|
-
globalThis.fetch = async () => {
|
|
73
|
-
return new Response("Internal Server Error", { status: 500 });
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const request: InteractionRequest = {
|
|
77
|
-
id: "test-http-error",
|
|
78
|
-
type: "confirm",
|
|
79
|
-
featureName: "test-feature",
|
|
80
|
-
stage: "review",
|
|
81
|
-
summary: "Test HTTP error",
|
|
82
|
-
fallback: "abort",
|
|
83
|
-
createdAt: Date.now(),
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
await expect(plugin.send(request)).rejects.toThrow("Telegram API error (500)");
|
|
87
|
-
|
|
88
|
-
// Restore
|
|
89
|
-
globalThis.fetch = originalFetch;
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test("should return empty updates on getUpdates() network failure", async () => {
|
|
93
|
-
const plugin = new TelegramInteractionPlugin();
|
|
94
|
-
await plugin.init({ botToken: "test-token", chatId: "12345" });
|
|
95
|
-
|
|
96
|
-
// Mock fetch to throw network error
|
|
97
|
-
const originalFetch = globalThis.fetch;
|
|
98
|
-
globalThis.fetch = async () => {
|
|
99
|
-
throw new Error("Network timeout");
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
// Access private method via type assertion for testing
|
|
103
|
-
const getUpdates = (plugin as unknown as { getUpdates: () => Promise<unknown[]> }).getUpdates;
|
|
104
|
-
const updates = await getUpdates.call(plugin);
|
|
105
|
-
|
|
106
|
-
expect(updates).toEqual([]);
|
|
107
|
-
|
|
108
|
-
// Restore
|
|
109
|
-
globalThis.fetch = originalFetch;
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
test("should apply exponential backoff on consecutive getUpdates() failures", async () => {
|
|
113
|
-
const plugin = new TelegramInteractionPlugin();
|
|
114
|
-
await plugin.init({ botToken: "test-token", chatId: "12345" });
|
|
115
|
-
|
|
116
|
-
const originalFetch = globalThis.fetch;
|
|
117
|
-
let fetchCallCount = 0;
|
|
118
|
-
|
|
119
|
-
globalThis.fetch = async () => {
|
|
120
|
-
fetchCallCount++;
|
|
121
|
-
throw new Error("Network error");
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
// Access private getUpdates
|
|
125
|
-
const getUpdates = (plugin as unknown as { getUpdates: () => Promise<unknown[]> }).getUpdates;
|
|
126
|
-
|
|
127
|
-
// Call getUpdates multiple times to trigger backoff
|
|
128
|
-
await getUpdates.call(plugin);
|
|
129
|
-
await getUpdates.call(plugin);
|
|
130
|
-
await getUpdates.call(plugin);
|
|
131
|
-
|
|
132
|
-
// Verify backoff is increasing (check private backoffMs property)
|
|
133
|
-
const backoffMs = (plugin as unknown as { backoffMs: number }).backoffMs;
|
|
134
|
-
expect(backoffMs).toBeGreaterThan(1000); // Should have increased from initial 1000ms
|
|
135
|
-
|
|
136
|
-
// Restore
|
|
137
|
-
globalThis.fetch = originalFetch;
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
test("should reset backoff on successful getUpdates()", async () => {
|
|
141
|
-
const plugin = new TelegramInteractionPlugin();
|
|
142
|
-
await plugin.init({ botToken: "test-token", chatId: "12345" });
|
|
143
|
-
|
|
144
|
-
const originalFetch = globalThis.fetch;
|
|
145
|
-
let callCount = 0;
|
|
146
|
-
|
|
147
|
-
globalThis.fetch = async () => {
|
|
148
|
-
callCount++;
|
|
149
|
-
if (callCount === 1) {
|
|
150
|
-
// First call fails
|
|
151
|
-
throw new Error("Network error");
|
|
152
|
-
}
|
|
153
|
-
// Second call succeeds
|
|
154
|
-
return new Response(JSON.stringify({ ok: true, result: [] }), { status: 200 });
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
const getUpdates = (plugin as unknown as { getUpdates: () => Promise<unknown[]> }).getUpdates;
|
|
158
|
-
|
|
159
|
-
// First call - triggers backoff
|
|
160
|
-
await getUpdates.call(plugin);
|
|
161
|
-
const backoffAfterFailure = (plugin as unknown as { backoffMs: number }).backoffMs;
|
|
162
|
-
expect(backoffAfterFailure).toBeGreaterThan(1000);
|
|
163
|
-
|
|
164
|
-
// Second call - should reset backoff
|
|
165
|
-
await getUpdates.call(plugin);
|
|
166
|
-
const backoffAfterSuccess = (plugin as unknown as { backoffMs: number }).backoffMs;
|
|
167
|
-
expect(backoffAfterSuccess).toBe(1000); // Reset to initial value
|
|
168
|
-
|
|
169
|
-
// Restore
|
|
170
|
-
globalThis.fetch = originalFetch;
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
describe("WebhookInteractionPlugin - Network Failures", () => {
|
|
175
|
-
test("should handle network error in send()", async () => {
|
|
176
|
-
const plugin = new WebhookInteractionPlugin();
|
|
177
|
-
await plugin.init({ url: "https://example.com/webhook" });
|
|
178
|
-
|
|
179
|
-
// Mock fetch to throw network error
|
|
180
|
-
const originalFetch = globalThis.fetch;
|
|
181
|
-
globalThis.fetch = async () => {
|
|
182
|
-
throw new Error("ECONNREFUSED");
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
const request: InteractionRequest = {
|
|
186
|
-
id: "test-network-error",
|
|
187
|
-
type: "confirm",
|
|
188
|
-
featureName: "test-feature",
|
|
189
|
-
stage: "review",
|
|
190
|
-
summary: "Test network error",
|
|
191
|
-
fallback: "abort",
|
|
192
|
-
createdAt: Date.now(),
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
await expect(plugin.send(request)).rejects.toThrow("Failed to send webhook request");
|
|
196
|
-
|
|
197
|
-
// Restore
|
|
198
|
-
globalThis.fetch = originalFetch;
|
|
199
|
-
await plugin.destroy();
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
test("should handle HTTP error in send()", async () => {
|
|
203
|
-
const plugin = new WebhookInteractionPlugin();
|
|
204
|
-
await plugin.init({ url: "https://example.com/webhook" });
|
|
205
|
-
|
|
206
|
-
// Mock fetch to return 503 error
|
|
207
|
-
const originalFetch = globalThis.fetch;
|
|
208
|
-
globalThis.fetch = async () => {
|
|
209
|
-
return new Response("Service Unavailable", { status: 503 });
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
const request: InteractionRequest = {
|
|
213
|
-
id: "test-http-error",
|
|
214
|
-
type: "confirm",
|
|
215
|
-
featureName: "test-feature",
|
|
216
|
-
stage: "review",
|
|
217
|
-
summary: "Test HTTP error",
|
|
218
|
-
fallback: "abort",
|
|
219
|
-
createdAt: Date.now(),
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
await expect(plugin.send(request)).rejects.toThrow("Webhook POST failed (503)");
|
|
223
|
-
|
|
224
|
-
// Restore
|
|
225
|
-
globalThis.fetch = originalFetch;
|
|
226
|
-
await plugin.destroy();
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
test("should apply exponential backoff in receive() polling", async () => {
|
|
230
|
-
const plugin = new WebhookInteractionPlugin();
|
|
231
|
-
await plugin.init({ url: "https://example.com/webhook" });
|
|
232
|
-
|
|
233
|
-
const startTime = Date.now();
|
|
234
|
-
|
|
235
|
-
// Call receive with short timeout
|
|
236
|
-
const response = await plugin.receive("test-request", 500);
|
|
237
|
-
|
|
238
|
-
const duration = Date.now() - startTime;
|
|
239
|
-
|
|
240
|
-
// Should timeout with exponential backoff
|
|
241
|
-
expect(response.action).toBe("skip");
|
|
242
|
-
expect(response.respondedBy).toBe("timeout");
|
|
243
|
-
|
|
244
|
-
// Duration should be at least timeout (500ms) but less than timeout + max backoff
|
|
245
|
-
expect(duration).toBeGreaterThanOrEqual(500);
|
|
246
|
-
expect(duration).toBeLessThan(3000); // Max backoff is 2s
|
|
247
|
-
|
|
248
|
-
await plugin.destroy();
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
describe("WebhookInteractionPlugin - Payload Security", () => {
|
|
253
|
-
test("should reject oversized payload via Content-Length header", async () => {
|
|
254
|
-
const plugin = new WebhookInteractionPlugin();
|
|
255
|
-
await plugin.init({ url: "https://example.com/webhook", maxPayloadBytes: 1000 });
|
|
256
|
-
|
|
257
|
-
// Create a mock request with large Content-Length
|
|
258
|
-
const req = new Request("http://localhost:8765/nax/interact/test-id", {
|
|
259
|
-
method: "POST",
|
|
260
|
-
headers: {
|
|
261
|
-
"Content-Type": "application/json",
|
|
262
|
-
"Content-Length": "10000", // 10KB - exceeds 1000 byte limit
|
|
263
|
-
},
|
|
264
|
-
body: JSON.stringify({ requestId: "test-id", action: "approve" }),
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
const handleRequest = (plugin as unknown as { handleRequest: (req: Request) => Promise<Response> }).handleRequest;
|
|
268
|
-
const response = await handleRequest.call(plugin, req);
|
|
269
|
-
|
|
270
|
-
expect(response.status).toBe(413); // Payload Too Large
|
|
271
|
-
expect(await response.text()).toBe("Payload Too Large");
|
|
272
|
-
|
|
273
|
-
await plugin.destroy();
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
test("should reject oversized payload by actual body size", async () => {
|
|
277
|
-
const plugin = new WebhookInteractionPlugin();
|
|
278
|
-
await plugin.init({ url: "https://example.com/webhook", secret: "test-secret", maxPayloadBytes: 100 });
|
|
279
|
-
|
|
280
|
-
// Create a large payload
|
|
281
|
-
const largePayload = "x".repeat(200);
|
|
282
|
-
|
|
283
|
-
const req = new Request("http://localhost:8765/nax/interact/test-id", {
|
|
284
|
-
method: "POST",
|
|
285
|
-
headers: {
|
|
286
|
-
"Content-Type": "application/json",
|
|
287
|
-
"X-Nax-Signature": "dummy-signature",
|
|
288
|
-
},
|
|
289
|
-
body: largePayload,
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
const handleRequest = (plugin as unknown as { handleRequest: (req: Request) => Promise<Response> }).handleRequest;
|
|
293
|
-
const response = await handleRequest.call(plugin, req);
|
|
294
|
-
|
|
295
|
-
expect(response.status).toBe(413); // Payload Too Large
|
|
296
|
-
|
|
297
|
-
await plugin.destroy();
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
test("should reject malformed JSON with sanitized error", async () => {
|
|
301
|
-
const plugin = new WebhookInteractionPlugin();
|
|
302
|
-
await plugin.init({ url: "https://example.com/webhook" });
|
|
303
|
-
|
|
304
|
-
const req = new Request("http://localhost:8765/nax/interact/test-id", {
|
|
305
|
-
method: "POST",
|
|
306
|
-
headers: { "Content-Type": "application/json" },
|
|
307
|
-
body: "not valid json{",
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
const handleRequest = (plugin as unknown as { handleRequest: (req: Request) => Promise<Response> }).handleRequest;
|
|
311
|
-
const response = await handleRequest.call(plugin, req);
|
|
312
|
-
|
|
313
|
-
expect(response.status).toBe(400);
|
|
314
|
-
const errorText = await response.text();
|
|
315
|
-
|
|
316
|
-
// Should not leak parse error details
|
|
317
|
-
expect(errorText).toBe("Bad Request: Invalid response format");
|
|
318
|
-
expect(errorText).not.toContain("JSON");
|
|
319
|
-
expect(errorText).not.toContain("parse");
|
|
320
|
-
expect(errorText).not.toContain("Unexpected");
|
|
321
|
-
|
|
322
|
-
await plugin.destroy();
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
test("should reject invalid schema with sanitized error", async () => {
|
|
326
|
-
const plugin = new WebhookInteractionPlugin();
|
|
327
|
-
await plugin.init({ url: "https://example.com/webhook" });
|
|
328
|
-
|
|
329
|
-
// Valid JSON but invalid InteractionResponse schema
|
|
330
|
-
const req = new Request("http://localhost:8765/nax/interact/test-id", {
|
|
331
|
-
method: "POST",
|
|
332
|
-
headers: { "Content-Type": "application/json" },
|
|
333
|
-
body: JSON.stringify({ malicious: "payload", action: "invalid-action" }),
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
const handleRequest = (plugin as unknown as { handleRequest: (req: Request) => Promise<Response> }).handleRequest;
|
|
337
|
-
const response = await handleRequest.call(plugin, req);
|
|
338
|
-
|
|
339
|
-
expect(response.status).toBe(400);
|
|
340
|
-
const errorText = await response.text();
|
|
341
|
-
|
|
342
|
-
// Should not leak Zod validation error details
|
|
343
|
-
expect(errorText).toBe("Bad Request: Invalid response format");
|
|
344
|
-
expect(errorText).not.toContain("Zod");
|
|
345
|
-
expect(errorText).not.toContain("validation");
|
|
346
|
-
expect(errorText).not.toContain("enum");
|
|
347
|
-
|
|
348
|
-
await plugin.destroy();
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
test("should reject request without signature when secret is configured", async () => {
|
|
352
|
-
const plugin = new WebhookInteractionPlugin();
|
|
353
|
-
await plugin.init({ url: "https://example.com/webhook", secret: "test-secret" });
|
|
354
|
-
|
|
355
|
-
const req = new Request("http://localhost:8765/nax/interact/test-id", {
|
|
356
|
-
method: "POST",
|
|
357
|
-
headers: { "Content-Type": "application/json" },
|
|
358
|
-
body: JSON.stringify({ requestId: "test-id", action: "approve", respondedAt: Date.now() }),
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
const handleRequest = (plugin as unknown as { handleRequest: (req: Request) => Promise<Response> }).handleRequest;
|
|
362
|
-
const response = await handleRequest.call(plugin, req);
|
|
363
|
-
|
|
364
|
-
expect(response.status).toBe(401); // Unauthorized
|
|
365
|
-
expect(await response.text()).toBe("Unauthorized");
|
|
366
|
-
|
|
367
|
-
await plugin.destroy();
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
test("should reject request with invalid signature", async () => {
|
|
371
|
-
const plugin = new WebhookInteractionPlugin();
|
|
372
|
-
await plugin.init({ url: "https://example.com/webhook", secret: "test-secret" });
|
|
373
|
-
|
|
374
|
-
const req = new Request("http://localhost:8765/nax/interact/test-id", {
|
|
375
|
-
method: "POST",
|
|
376
|
-
headers: {
|
|
377
|
-
"Content-Type": "application/json",
|
|
378
|
-
"X-Nax-Signature": "invalid-signature",
|
|
379
|
-
},
|
|
380
|
-
body: JSON.stringify({ requestId: "test-id", action: "approve", respondedAt: Date.now() }),
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
const handleRequest = (plugin as unknown as { handleRequest: (req: Request) => Promise<Response> }).handleRequest;
|
|
384
|
-
const response = await handleRequest.call(plugin, req);
|
|
385
|
-
|
|
386
|
-
expect(response.status).toBe(401); // Unauthorized
|
|
387
|
-
|
|
388
|
-
await plugin.destroy();
|
|
389
|
-
});
|
|
390
|
-
});
|