@nathapp/nax 0.20.0 → 0.22.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/.claude/settings.json +15 -0
- package/.mcp.json +8 -0
- package/docs/20260304-review-nax.md +492 -0
- package/docs/ROADMAP.md +65 -18
- package/docs/adr/ADR-005-implementation-plan.md +655 -0
- package/docs/adr/ADR-005-pipeline-re-architecture.md +464 -0
- package/docs/specs/bug-039-orphan-processes.md +131 -0
- package/docs/specs/bug-040-review-rectification.md +82 -0
- package/docs/specs/bug-041-cross-story-test-isolation.md +88 -0
- package/docs/specs/bug-042-verifier-failure-capture.md +117 -0
- package/docs/specs/feat-010-smart-runner-git-history.md +96 -0
- package/docs/specs/feat-011-file-context-strategy.md +73 -0
- package/docs/specs/feat-012-tdd-writer-tier.md +79 -0
- package/docs/specs/feat-013-test-after-review.md +89 -0
- package/docs/specs/feat-014-heartbeat-observability.md +127 -0
- package/memory/topic/feat-010-baseref.md +28 -0
- package/memory/topic/feat-013-test-after-deprecation.md +22 -0
- package/nax/config.json +7 -4
- package/nax/features/bug-039-medium/prd.json +45 -0
- package/package.json +2 -2
- package/src/agents/claude.ts +109 -15
- package/src/config/types.ts +11 -0
- package/src/context/builder.ts +9 -1
- package/src/execution/dry-run.ts +81 -0
- package/src/execution/escalation/tier-outcome.ts +29 -44
- package/src/execution/executor-types.ts +65 -0
- package/src/execution/index.ts +0 -17
- package/src/execution/iteration-runner.ts +132 -0
- package/src/execution/lifecycle/index.ts +0 -1
- package/src/execution/lifecycle/run-regression.ts +5 -5
- package/src/execution/pipeline-result-handler.ts +51 -254
- package/src/execution/sequential-executor.ts +72 -315
- package/src/execution/story-selector.ts +75 -0
- package/src/pipeline/event-bus.ts +276 -0
- package/src/pipeline/runner.ts +51 -77
- package/src/pipeline/stages/autofix.ts +133 -0
- package/src/pipeline/stages/completion.ts +22 -30
- package/src/pipeline/stages/index.ts +30 -13
- package/src/pipeline/stages/rectify.ts +93 -0
- package/src/pipeline/stages/regression.ts +88 -0
- package/src/pipeline/stages/review.ts +19 -153
- package/src/pipeline/stages/verify.ts +19 -3
- package/src/pipeline/subscribers/hooks.ts +133 -0
- package/src/pipeline/subscribers/interaction.ts +68 -0
- package/src/pipeline/subscribers/reporters.ts +174 -0
- package/src/pipeline/types.ts +12 -1
- package/src/review/orchestrator.ts +105 -0
- package/src/review/runner.ts +39 -4
- package/src/routing/router.ts +3 -3
- package/src/routing/strategies/keyword.ts +5 -2
- package/src/routing/strategies/llm.ts +27 -1
- package/src/tdd/prompts.ts +1 -1
- package/src/utils/git.ts +49 -25
- package/src/verification/executor.ts +8 -2
- package/src/verification/index.ts +1 -1
- package/src/verification/orchestrator-types.ts +145 -0
- package/src/verification/orchestrator.ts +76 -0
- package/src/{execution/post-verify-rectification.ts → verification/rectification-loop.ts} +13 -20
- package/src/verification/{gate.ts → runners.ts} +17 -105
- package/src/verification/smart-runner.ts +6 -10
- package/src/verification/strategies/acceptance.ts +133 -0
- package/src/verification/strategies/regression.ts +90 -0
- package/src/verification/strategies/scoped.ts +123 -0
- package/test/COVERAGE-GAPS.md +333 -0
- package/test/{acceptance → e2e}/cm-003-default-view.test.ts +1 -0
- package/test/{integration/e2e.test.ts → e2e/plan-analyze-run.test.ts} +1 -0
- package/test/integration/{agent-validation.test.ts → cli/agent-validation.test.ts} +3 -3
- package/test/integration/{cli-config-default-edge-cases.test.ts → cli/cli-config-default-edge-cases.test.ts} +6 -5
- package/test/integration/{cli-config-default-view.test.ts → cli/cli-config-default-view.test.ts} +8 -7
- package/test/integration/{cli-config-diff.test.ts → cli/cli-config-diff.test.ts} +3 -2
- package/test/integration/{cli-config.test.ts → cli/cli-config.test.ts} +3 -2
- package/test/integration/{cli-diagnose.test.ts → cli/cli-diagnose.test.ts} +5 -4
- package/test/integration/{cli-logs.test.ts → cli/cli-logs.test.ts} +12 -3
- package/test/integration/{cli-plugins.test.ts → cli/cli-plugins.test.ts} +4 -3
- package/test/integration/{cli-precheck.test.ts → cli/cli-precheck.test.ts} +4 -3
- package/test/integration/{cli-run-headless.test.ts → cli/cli-run-headless.test.ts} +3 -2
- package/test/integration/{cli.test.ts → cli/cli.test.ts} +2 -1
- package/test/integration/{precheck-integration.test.ts → cli/precheck-integration.test.ts} +10 -9
- package/test/integration/{precheck-orchestrator.test.ts → cli/precheck-orchestrator.test.ts} +4 -3
- package/test/integration/{precheck.test.ts → cli/precheck.test.ts} +5 -4
- package/test/integration/{config-loader.test.ts → config/config-loader.test.ts} +2 -1
- package/test/integration/{config.test.ts → config/config.test.ts} +2 -2
- package/test/integration/config/merger.test.ts +1 -0
- package/test/integration/config/paths.test.ts +1 -0
- package/test/integration/{security-loader.test.ts → config/security-loader.test.ts} +2 -2
- package/test/integration/{context-integration.test.ts → context/context-integration.test.ts} +7 -6
- package/test/integration/{path-security.test.ts → context/context-path-security.test.ts} +2 -2
- package/test/integration/{context-provider-injection.test.ts → context/context-provider-injection.test.ts} +7 -6
- package/test/integration/{context-verification-integration.test.ts → context/context-verification-integration.test.ts} +5 -4
- package/test/integration/{s5-greenfield-fallback.test.ts → context/s5-greenfield-fallback.test.ts} +4 -3
- package/test/integration/{isolation.test.ts → execution/execution-isolation.test.ts} +1 -1
- package/test/integration/{execution.test.ts → execution/execution.test.ts} +8 -8
- package/test/integration/{parallel.test.ts → execution/parallel.test.ts} +2 -1
- package/test/integration/{prd-pause.test.ts → execution/prd-pause.test.ts} +2 -2
- package/test/integration/{prd-resolvers.test.ts → execution/prd-resolvers.test.ts} +3 -2
- package/test/integration/{progress.test.ts → execution/progress.test.ts} +1 -1
- package/test/integration/execution/runner-batching.test.ts +682 -0
- package/test/integration/{runner-config-plugins.test.ts → execution/runner-config-plugins.test.ts} +3 -2
- package/test/integration/execution/runner-escalation.test.ts +561 -0
- package/test/integration/{runner-fixes.test.ts → execution/runner-fixes.test.ts} +4 -3
- package/test/integration/{runner-plugin-integration.test.ts → execution/runner-plugin-integration.test.ts} +6 -5
- package/test/integration/execution/runner-queue-and-attempts.test.ts +476 -0
- package/test/integration/{status-file-integration.test.ts → execution/status-file-integration.test.ts} +9 -8
- package/test/integration/{status-file.test.ts → execution/status-file.test.ts} +3 -2
- package/test/integration/{status-writer.test.ts → execution/status-writer.test.ts} +5 -4
- package/test/integration/{story-id-in-events.test.ts → execution/story-id-in-events.test.ts} +9 -8
- package/test/integration/{interaction-chain-pipeline.test.ts → interaction/interaction-chain-pipeline.test.ts} +26 -14
- package/test/integration/{hooks.test.ts → pipeline/hooks.test.ts} +4 -2
- package/test/integration/{pipeline-acceptance.test.ts → pipeline/pipeline-acceptance.test.ts} +7 -6
- package/test/integration/{pipeline-events.test.ts → pipeline/pipeline-events.test.ts} +7 -6
- package/test/integration/{pipeline.test.ts → pipeline/pipeline.test.ts} +9 -7
- package/test/integration/{reporter-lifecycle.test.ts → pipeline/reporter-lifecycle.test.ts} +9 -7
- package/test/integration/{verify-stage.test.ts → pipeline/verify-stage.test.ts} +7 -5
- package/test/integration/{analyze-integration.test.ts → plan/analyze-integration.test.ts} +3 -2
- package/test/integration/{analyze-scanner.test.ts → plan/analyze-scanner.test.ts} +8 -7
- package/test/integration/{logger.test.ts → plan/logger.test.ts} +1 -1
- package/test/integration/{plan.test.ts → plan/plan.test.ts} +3 -3
- package/test/integration/plugins/config-integration.test.ts +1 -0
- package/test/integration/plugins/config-resolution.test.ts +1 -0
- package/test/integration/plugins/loader.test.ts +1 -0
- package/test/integration/plugins/{registry.test.ts → plugins-registry.test.ts} +1 -0
- package/test/integration/plugins/validator.test.ts +1 -0
- package/test/integration/{review-config-commands.test.ts → review/review-config-commands.test.ts} +4 -3
- package/test/integration/{review-config-schema.test.ts → review/review-config-schema.test.ts} +3 -2
- package/test/integration/{review-plugin-integration.test.ts → review/review-plugin-integration.test.ts} +5 -4
- package/test/integration/{review.test.ts → review/review.test.ts} +3 -2
- package/test/integration/routing/plugin-routing-advanced.test.ts +461 -0
- package/test/integration/{plugin-routing.test.ts → routing/plugin-routing-core.test.ts} +10 -404
- package/test/integration/{routing-stage-bug-021.test.ts → routing/routing-stage-bug-021.test.ts} +8 -7
- package/test/integration/{routing-stage-greenfield.test.ts → routing/routing-stage-greenfield.test.ts} +7 -6
- package/test/integration/{tdd-cleanup.test.ts → tdd/tdd-cleanup.test.ts} +1 -1
- package/test/integration/tdd/tdd-orchestrator-core.test.ts +565 -0
- package/test/integration/tdd/tdd-orchestrator-failureCategory.test.ts +355 -0
- package/test/integration/tdd/tdd-orchestrator-fallback.test.ts +311 -0
- package/test/integration/tdd/tdd-orchestrator-lite.test.ts +289 -0
- package/test/integration/tdd/tdd-orchestrator-prompts.test.ts +260 -0
- package/test/integration/tdd/tdd-orchestrator-verdict.test.ts +536 -0
- package/test/integration/tmp/headless-test/test.jsonl +30 -0
- package/test/integration/{test-scanner.test.ts → verification/test-scanner.test.ts} +1 -1
- package/test/integration/{verification-asset-check.test.ts → verification/verification-asset-check.test.ts} +3 -2
- package/test/unit/acceptance.test.ts +1 -0
- package/test/unit/agent-stderr-capture.test.ts +1 -0
- package/test/unit/agents/claude.test.ts +107 -0
- package/test/unit/analyze-classifier.test.ts +1 -0
- package/test/unit/auto-detect.test.ts +1 -0
- package/test/unit/cli-status.test.ts +1 -0
- package/test/unit/commands/common.test.ts +1 -0
- package/test/unit/commands/logs.test.ts +1 -0
- package/test/unit/commands/unlock.test.ts +1 -0
- package/test/unit/config/defaults.test.ts +1 -0
- package/test/unit/config/regression-gate-schema.test.ts +1 -0
- package/test/unit/config/smart-runner-flag.test.ts +1 -0
- package/test/unit/constitution-generators.test.ts +1 -0
- package/test/unit/constitution.test.ts +1 -0
- package/test/unit/context/context-autodetect.test.ts +297 -0
- package/test/unit/context/context-build.test.ts +575 -0
- package/test/unit/context/context-coverage.test.ts +236 -0
- package/test/unit/context/context-error.test.ts +93 -0
- package/test/unit/context/context-estimate-tokens.test.ts +201 -0
- package/test/unit/context/context-format.test.ts +302 -0
- package/test/unit/context/context-isolation.test.ts +267 -0
- package/test/unit/context/context-sort.test.ts +93 -0
- package/test/unit/context/context-story.test.ts +108 -0
- package/test/{context → unit/context}/prior-failures.test.ts +5 -4
- package/test/unit/context.test.ts +7 -3
- package/test/unit/crash-recovery.test.ts +1 -0
- package/test/unit/escalation.test.ts +1 -0
- package/test/unit/execution/lifecycle/run-completion.test.ts +1 -0
- package/test/unit/execution/lifecycle/run-regression.test.ts +2 -0
- package/test/{execution → unit/execution}/pid-registry.test.ts +2 -1
- package/test/{execution → unit/execution}/structured-failure.test.ts +3 -2
- package/test/unit/execution-logging-stderr.test.ts +1 -0
- package/test/unit/execution-stage.test.ts +1 -0
- package/test/unit/fix-generator.test.ts +1 -0
- package/test/unit/greenfield.test.ts +1 -0
- package/test/unit/interaction/human-review-trigger.test.ts +1 -0
- package/test/unit/interaction-network-failures.test.ts +1 -0
- package/test/unit/interaction-plugins.test.ts +1 -0
- package/test/unit/logging/formatter.test.ts +1 -0
- package/test/unit/merge.test.ts +1 -0
- package/test/unit/pipeline/event-bus.test.ts +105 -0
- package/test/unit/pipeline/routing-partial-override.test.ts +1 -0
- package/test/unit/pipeline/runner-retry.test.ts +89 -0
- package/test/unit/pipeline/stages/autofix.test.ts +97 -0
- package/test/unit/pipeline/stages/rectify.test.ts +101 -0
- package/test/unit/pipeline/stages/regression-stage.test.ts +69 -0
- package/test/unit/pipeline/stages/verify.test.ts +1 -0
- package/test/unit/pipeline/subscribers/hooks.test.ts +45 -0
- package/test/unit/pipeline/subscribers/interaction.test.ts +31 -0
- package/test/unit/pipeline/subscribers/reporters.test.ts +90 -0
- package/test/unit/pipeline/verify-smart-runner.test.ts +2 -1
- package/test/unit/prd-auto-default.test.ts +3 -2
- package/test/unit/prd-failure-category.test.ts +1 -0
- package/test/unit/prd-get-next-story.test.ts +1 -0
- package/test/unit/precheck-checks.test.ts +1 -0
- package/test/unit/precheck-story-size-gate.test.ts +1 -0
- package/test/unit/precheck-types.test.ts +1 -0
- package/test/unit/prompts.test.ts +1 -0
- package/test/unit/rectification.test.ts +2 -1
- package/test/unit/registry.test.ts +1 -0
- package/test/unit/routing/routing-stability.test.ts +2 -1
- package/test/unit/routing/strategies/llm.test.ts +251 -0
- package/test/unit/routing-advanced.test.ts +313 -0
- package/test/unit/routing-core.test.ts +341 -0
- package/test/unit/routing-strategies.test.ts +442 -0
- package/test/unit/storyid-events.test.ts +1 -0
- package/test/{ui → unit/ui}/tui-controls.test.ts +8 -7
- package/test/{ui → unit/ui}/tui-cost-and-pty.test.ts +4 -3
- package/test/{ui → unit/ui}/tui-layout.test.ts +5 -4
- package/test/{ui → unit/ui}/tui-stories.test.ts +5 -4
- package/test/unit/{isolation.test.ts → unit-isolation.test.ts} +1 -0
- package/test/unit/{helpers.test.ts → utils-helpers.test.ts} +1 -0
- package/test/unit/verdict.test.ts +1 -0
- package/test/unit/verification/orchestrator-types.test.ts +54 -0
- package/test/unit/verification/orchestrator.test.ts +66 -0
- package/test/unit/verification/smart-runner-config.test.ts +1 -0
- package/test/unit/verification/smart-runner-discovery.test.ts +8 -7
- package/test/unit/verification/strategies/acceptance.test.ts +33 -0
- package/test/unit/verification/strategies/regression.test.ts +87 -0
- package/test/unit/verification/strategies/scoped.test.ts +100 -0
- package/test/unit/worktree-manager.test.ts +1 -0
- package/src/execution/lifecycle/story-hooks.ts +0 -38
- package/src/execution/post-verify.ts +0 -193
- package/src/execution/rectification.ts +0 -13
- package/src/execution/verification.ts +0 -72
- package/test/integration/rectification-flow.test.ts +0 -512
- package/test/integration/runner.test.ts +0 -1679
- package/test/integration/tdd-orchestrator.test.ts +0 -1762
- package/test/unit/execution/post-verify-regression.test.ts +0 -362
- package/test/unit/execution/post-verify.test.ts +0 -236
- package/test/unit/routing.test.ts +0 -1039
- /package/test/{integration → helpers}/helpers.test.ts +0 -0
- /package/test/integration/worktree/{merge.test.ts → worktree-merge.test.ts} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// RE-ARCH: keep
|
|
1
2
|
/**
|
|
2
3
|
* Smart Test Runner — 3-Pass Discovery Tests
|
|
3
4
|
*
|
|
@@ -115,7 +116,7 @@ describe("Pass 2: importGrepFallback", () => {
|
|
|
115
116
|
test("matches test file that imports the source by basename path", async () => {
|
|
116
117
|
mockGlob(["test/unit/routing.test.ts"]);
|
|
117
118
|
mockFileContent({
|
|
118
|
-
"/repo/test/unit/routing.test.ts": `import { route } from "
|
|
119
|
+
"/repo/test/unit/routing.test.ts": `import { route } from "../../../src/routing/strategies/llm";`,
|
|
119
120
|
});
|
|
120
121
|
|
|
121
122
|
const result = await importGrepFallback(
|
|
@@ -145,7 +146,7 @@ describe("Pass 2: importGrepFallback", () => {
|
|
|
145
146
|
test("does not match test file with no import reference", async () => {
|
|
146
147
|
mockGlob(["test/unit/other.test.ts"]);
|
|
147
148
|
mockFileContent({
|
|
148
|
-
"/repo/test/unit/other.test.ts": `import { something } from "
|
|
149
|
+
"/repo/test/unit/other.test.ts": `import { something } from "../../../src/other/module";`,
|
|
149
150
|
});
|
|
150
151
|
|
|
151
152
|
const result = await importGrepFallback(
|
|
@@ -160,8 +161,8 @@ describe("Pass 2: importGrepFallback", () => {
|
|
|
160
161
|
test("returns multiple matching test files", async () => {
|
|
161
162
|
mockGlob(["test/unit/a.test.ts", "test/unit/b.test.ts"]);
|
|
162
163
|
mockFileContent({
|
|
163
|
-
"/repo/test/unit/a.test.ts": `import { fn } from "
|
|
164
|
-
"/repo/test/unit/b.test.ts": `import { fn } from "
|
|
164
|
+
"/repo/test/unit/a.test.ts": `import { fn } from "../../../src/utils/helper";`,
|
|
165
|
+
"/repo/test/unit/b.test.ts": `import { fn } from "../../../src/utils/helper";`,
|
|
165
166
|
});
|
|
166
167
|
|
|
167
168
|
const result = await importGrepFallback(
|
|
@@ -182,7 +183,7 @@ describe("Pass 2: importGrepFallback", () => {
|
|
|
182
183
|
exists: () => Promise.resolve(true),
|
|
183
184
|
text: () => {
|
|
184
185
|
if (path.includes("broken")) throw new Error("read error");
|
|
185
|
-
return Promise.resolve(`import { fn } from "
|
|
186
|
+
return Promise.resolve(`import { fn } from "../../../src/utils/helper";`);
|
|
186
187
|
},
|
|
187
188
|
});
|
|
188
189
|
|
|
@@ -200,7 +201,7 @@ describe("Pass 2: importGrepFallback", () => {
|
|
|
200
201
|
mockGlob(["test/unit/routing.test.ts"]);
|
|
201
202
|
// Content contains both "/llm" and "routing/strategies/llm"
|
|
202
203
|
mockFileContent({
|
|
203
|
-
"/repo/test/unit/routing.test.ts": `import { classify } from "
|
|
204
|
+
"/repo/test/unit/routing.test.ts": `import { classify } from "../../../src/routing/strategies/llm";`,
|
|
204
205
|
});
|
|
205
206
|
|
|
206
207
|
const result = await importGrepFallback(
|
|
@@ -273,7 +274,7 @@ describe("Pass 3: full-suite fallback (empty return from both passes)", () => {
|
|
|
273
274
|
};
|
|
274
275
|
// biome-ignore lint/suspicious/noExplicitAny: mocking
|
|
275
276
|
(Bun as any).file = (_path: string) => ({
|
|
276
|
-
text: () => Promise.resolve(`import { x } from "
|
|
277
|
+
text: () => Promise.resolve(`import { x } from "../../../src/completely/different";`),
|
|
277
278
|
});
|
|
278
279
|
|
|
279
280
|
const result = await importGrepFallback(
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// RE-ARCH: keep
|
|
2
|
+
import { describe, expect, test } from "bun:test";
|
|
3
|
+
import { AcceptanceStrategy } from "../../../../src/verification/strategies/acceptance";
|
|
4
|
+
import type { VerifyContext } from "../../../../src/verification/orchestrator-types";
|
|
5
|
+
|
|
6
|
+
function makeCtx(overrides: Partial<VerifyContext> = {}): VerifyContext {
|
|
7
|
+
return {
|
|
8
|
+
workdir: "/tmp/test-repo",
|
|
9
|
+
testCommand: "bun test",
|
|
10
|
+
timeoutSeconds: 60,
|
|
11
|
+
storyId: "US-001",
|
|
12
|
+
...overrides,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe("AcceptanceStrategy", () => {
|
|
17
|
+
test("name is acceptance", () => {
|
|
18
|
+
expect(new AcceptanceStrategy().name).toBe("acceptance");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test("returns SKIPPED when no acceptanceTestPath", async () => {
|
|
22
|
+
const result = await new AcceptanceStrategy().execute(makeCtx());
|
|
23
|
+
expect(result.status).toBe("SKIPPED");
|
|
24
|
+
expect(result.success).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("returns SKIPPED when test file does not exist", async () => {
|
|
28
|
+
const result = await new AcceptanceStrategy().execute(
|
|
29
|
+
makeCtx({ acceptanceTestPath: "/nonexistent/path/acceptance.test.ts" }),
|
|
30
|
+
);
|
|
31
|
+
expect(result.status).toBe("SKIPPED");
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// RE-ARCH: keep
|
|
2
|
+
import { describe, expect, test } from "bun:test";
|
|
3
|
+
import { RegressionStrategy, _regressionStrategyDeps } from "../../../../src/verification/strategies/regression";
|
|
4
|
+
import type { VerifyContext } from "../../../../src/verification/orchestrator-types";
|
|
5
|
+
import { DEFAULT_CONFIG } from "../../../../src/config";
|
|
6
|
+
|
|
7
|
+
function makeCtx(overrides: Partial<VerifyContext> = {}): VerifyContext {
|
|
8
|
+
return {
|
|
9
|
+
workdir: "/tmp/test-repo",
|
|
10
|
+
testCommand: "bun test",
|
|
11
|
+
timeoutSeconds: 120,
|
|
12
|
+
storyId: "US-001",
|
|
13
|
+
acceptOnTimeout: true,
|
|
14
|
+
config: DEFAULT_CONFIG,
|
|
15
|
+
...overrides,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe("RegressionStrategy", () => {
|
|
20
|
+
test("name is regression", () => {
|
|
21
|
+
expect(new RegressionStrategy().name).toBe("regression");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("returns SKIPPED when gate disabled", async () => {
|
|
25
|
+
const config = {
|
|
26
|
+
...DEFAULT_CONFIG,
|
|
27
|
+
execution: {
|
|
28
|
+
...DEFAULT_CONFIG.execution,
|
|
29
|
+
regressionGate: { enabled: false, timeoutSeconds: 120, mode: "inline" as const },
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
const result = await new RegressionStrategy().execute(makeCtx({ config }));
|
|
33
|
+
expect(result.status).toBe("SKIPPED");
|
|
34
|
+
expect(result.success).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("returns PASS when tests pass", async () => {
|
|
38
|
+
const saved = { ...(_regressionStrategyDeps as any) };
|
|
39
|
+
_regressionStrategyDeps.runVerification = async () => ({
|
|
40
|
+
success: true,
|
|
41
|
+
status: "SUCCESS" as const,
|
|
42
|
+
countsTowardEscalation: false,
|
|
43
|
+
output: "10 pass",
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const result = await new RegressionStrategy().execute(makeCtx());
|
|
47
|
+
|
|
48
|
+
Object.assign(_regressionStrategyDeps, saved);
|
|
49
|
+
|
|
50
|
+
expect(result.success).toBe(true);
|
|
51
|
+
expect(result.status).toBe("PASS");
|
|
52
|
+
expect(result.strategy).toBe("regression");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("accepts TIMEOUT as pass when acceptOnTimeout=true", async () => {
|
|
56
|
+
const saved = { ...(_regressionStrategyDeps as any) };
|
|
57
|
+
_regressionStrategyDeps.runVerification = async () => ({
|
|
58
|
+
success: false,
|
|
59
|
+
status: "TIMEOUT" as const,
|
|
60
|
+
countsTowardEscalation: false,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const result = await new RegressionStrategy().execute(makeCtx({ acceptOnTimeout: true }));
|
|
64
|
+
|
|
65
|
+
Object.assign(_regressionStrategyDeps, saved);
|
|
66
|
+
|
|
67
|
+
expect(result.success).toBe(true);
|
|
68
|
+
expect(result.status).toBe("PASS");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("returns TEST_FAILURE when tests fail", async () => {
|
|
72
|
+
const saved = { ...(_regressionStrategyDeps as any) };
|
|
73
|
+
_regressionStrategyDeps.runVerification = async () => ({
|
|
74
|
+
success: false,
|
|
75
|
+
status: "TEST_FAILURE" as const,
|
|
76
|
+
countsTowardEscalation: true,
|
|
77
|
+
output: "(fail) x > y\n2 fail",
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const result = await new RegressionStrategy().execute(makeCtx({ acceptOnTimeout: false }));
|
|
81
|
+
|
|
82
|
+
Object.assign(_regressionStrategyDeps, saved);
|
|
83
|
+
|
|
84
|
+
expect(result.success).toBe(false);
|
|
85
|
+
expect(result.status).toBe("TEST_FAILURE");
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// RE-ARCH: keep
|
|
2
|
+
import { describe, expect, test } from "bun:test";
|
|
3
|
+
import { ScopedStrategy, _scopedDeps } from "../../../../src/verification/strategies/scoped";
|
|
4
|
+
import type { VerifyContext } from "../../../../src/verification/orchestrator-types";
|
|
5
|
+
|
|
6
|
+
function makeCtx(overrides: Partial<VerifyContext> = {}): VerifyContext {
|
|
7
|
+
return {
|
|
8
|
+
workdir: "/tmp/test-repo",
|
|
9
|
+
testCommand: "bun test",
|
|
10
|
+
timeoutSeconds: 60,
|
|
11
|
+
storyId: "US-001",
|
|
12
|
+
storyGitRef: "abc123",
|
|
13
|
+
regressionMode: "deferred",
|
|
14
|
+
acceptOnTimeout: true,
|
|
15
|
+
...overrides,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
describe("ScopedStrategy", () => {
|
|
20
|
+
test("name is scoped", () => {
|
|
21
|
+
expect(new ScopedStrategy().name).toBe("scoped");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("returns SKIPPED when deferred mode and no mapped tests", async () => {
|
|
25
|
+
const saved = { ..._scopedDeps };
|
|
26
|
+
_scopedDeps.getChangedSourceFiles = async () => [];
|
|
27
|
+
_scopedDeps.mapSourceToTests = async () => [];
|
|
28
|
+
_scopedDeps.importGrepFallback = async () => [];
|
|
29
|
+
|
|
30
|
+
const result = await new ScopedStrategy().execute(makeCtx({ regressionMode: "deferred" }));
|
|
31
|
+
|
|
32
|
+
Object.assign(_scopedDeps, saved);
|
|
33
|
+
|
|
34
|
+
expect(result.status).toBe("SKIPPED");
|
|
35
|
+
expect(result.success).toBe(true);
|
|
36
|
+
expect(result.countsTowardEscalation).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("runs full suite when inline mode and no mapped tests", async () => {
|
|
40
|
+
const saved = { ..._scopedDeps };
|
|
41
|
+
_scopedDeps.getChangedSourceFiles = async () => [];
|
|
42
|
+
_scopedDeps.mapSourceToTests = async () => [];
|
|
43
|
+
_scopedDeps.importGrepFallback = async () => [];
|
|
44
|
+
_scopedDeps.regression = async () => ({
|
|
45
|
+
success: true,
|
|
46
|
+
status: "SUCCESS" as const,
|
|
47
|
+
countsTowardEscalation: false,
|
|
48
|
+
output: "1 pass",
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const result = await new ScopedStrategy().execute(makeCtx({ regressionMode: "inline" }));
|
|
52
|
+
|
|
53
|
+
Object.assign(_scopedDeps, saved);
|
|
54
|
+
|
|
55
|
+
expect(result.success).toBe(true);
|
|
56
|
+
expect(result.status).toBe("PASS");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("returns PASS when tests pass", async () => {
|
|
60
|
+
const saved = { ..._scopedDeps };
|
|
61
|
+
_scopedDeps.getChangedSourceFiles = async () => ["src/foo.ts"];
|
|
62
|
+
_scopedDeps.mapSourceToTests = async () => ["test/unit/foo.test.ts"];
|
|
63
|
+
_scopedDeps.buildSmartTestCommand = (_files: string[], cmd: string) => `${cmd} test/unit/foo.test.ts`;
|
|
64
|
+
_scopedDeps.regression = async () => ({
|
|
65
|
+
success: true,
|
|
66
|
+
status: "SUCCESS" as const,
|
|
67
|
+
countsTowardEscalation: false,
|
|
68
|
+
output: "5 pass\n0 fail",
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const result = await new ScopedStrategy().execute(makeCtx());
|
|
72
|
+
|
|
73
|
+
Object.assign(_scopedDeps, saved);
|
|
74
|
+
|
|
75
|
+
expect(result.success).toBe(true);
|
|
76
|
+
expect(result.status).toBe("PASS");
|
|
77
|
+
expect(result.strategy).toBe("scoped");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("returns TEST_FAILURE when tests fail", async () => {
|
|
81
|
+
const saved = { ..._scopedDeps };
|
|
82
|
+
_scopedDeps.getChangedSourceFiles = async () => ["src/foo.ts"];
|
|
83
|
+
_scopedDeps.mapSourceToTests = async () => ["test/unit/foo.test.ts"];
|
|
84
|
+
_scopedDeps.buildSmartTestCommand = (_files: string[], cmd: string) => cmd;
|
|
85
|
+
_scopedDeps.regression = async () => ({
|
|
86
|
+
success: false,
|
|
87
|
+
status: "TEST_FAILURE" as const,
|
|
88
|
+
countsTowardEscalation: true,
|
|
89
|
+
output: "(fail) foo > bar\n1 fail",
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const result = await new ScopedStrategy().execute(makeCtx());
|
|
93
|
+
|
|
94
|
+
Object.assign(_scopedDeps, saved);
|
|
95
|
+
|
|
96
|
+
expect(result.success).toBe(false);
|
|
97
|
+
expect(result.status).toBe("TEST_FAILURE");
|
|
98
|
+
expect(result.countsTowardEscalation).toBe(true);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Story Lifecycle Hooks
|
|
3
|
-
*
|
|
4
|
-
* Centralizes reporter notification boilerplate for story lifecycle events:
|
|
5
|
-
* - onStoryComplete (completed/paused/skipped/failed)
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { getSafeLogger } from "../../logger";
|
|
9
|
-
import type { IReporter } from "../../plugins/types";
|
|
10
|
-
|
|
11
|
-
export interface StoryCompleteEvent {
|
|
12
|
-
runId: string;
|
|
13
|
-
storyId: string;
|
|
14
|
-
status: "completed" | "paused" | "skipped" | "failed";
|
|
15
|
-
durationMs: number;
|
|
16
|
-
cost: number;
|
|
17
|
-
tier: string;
|
|
18
|
-
testStrategy: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Emit onStoryComplete event to all reporters
|
|
23
|
-
*
|
|
24
|
-
* Handles error recovery for individual reporter failures.
|
|
25
|
-
*/
|
|
26
|
-
export async function emitStoryComplete(reporters: IReporter[], event: StoryCompleteEvent): Promise<void> {
|
|
27
|
-
const logger = getSafeLogger();
|
|
28
|
-
|
|
29
|
-
for (const reporter of reporters) {
|
|
30
|
-
if (reporter.onStoryComplete) {
|
|
31
|
-
try {
|
|
32
|
-
await reporter.onStoryComplete(event);
|
|
33
|
-
} catch (error) {
|
|
34
|
-
logger?.warn("plugins", `Reporter '${reporter.name}' onStoryComplete failed`, { error });
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Post-Agent Verification (ADR-003)
|
|
3
|
-
*
|
|
4
|
-
* Runs verification after the agent completes, reverts story state on failure.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { NaxConfig } from "../config";
|
|
8
|
-
import { getSafeLogger } from "../logger";
|
|
9
|
-
import type { StoryMetrics } from "../metrics";
|
|
10
|
-
import type { PRD, StructuredFailure, UserStory, VerificationStage } from "../prd";
|
|
11
|
-
import { getExpectedFiles, savePRD } from "../prd";
|
|
12
|
-
import type { VerificationResult } from "../verification";
|
|
13
|
-
import { parseBunTestOutput } from "../verification";
|
|
14
|
-
import { revertStoriesOnFailure, runRectificationLoop } from "./post-verify-rectification";
|
|
15
|
-
import { runVerification } from "./verification";
|
|
16
|
-
|
|
17
|
-
/** Build a StructuredFailure from verification result and test output. */
|
|
18
|
-
function buildStructuredFailure(
|
|
19
|
-
story: UserStory,
|
|
20
|
-
stage: VerificationStage,
|
|
21
|
-
verificationResult: VerificationResult,
|
|
22
|
-
summary: string,
|
|
23
|
-
): StructuredFailure {
|
|
24
|
-
const testFailures =
|
|
25
|
-
verificationResult.status === "TEST_FAILURE" && verificationResult.output
|
|
26
|
-
? _postVerifyDeps.parseBunTestOutput(verificationResult.output).failures.map((f) => ({
|
|
27
|
-
file: f.file,
|
|
28
|
-
testName: f.testName,
|
|
29
|
-
error: f.error,
|
|
30
|
-
stackTrace: f.stackTrace,
|
|
31
|
-
}))
|
|
32
|
-
: undefined;
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
attempt: (story.attempts ?? 0) + 1,
|
|
36
|
-
modelTier: story.routing?.modelTier ?? "unknown",
|
|
37
|
-
stage,
|
|
38
|
-
summary,
|
|
39
|
-
testFailures: testFailures && testFailures.length > 0 ? testFailures : undefined,
|
|
40
|
-
timestamp: new Date().toISOString(),
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface PostVerifyOptions {
|
|
45
|
-
config: NaxConfig;
|
|
46
|
-
prd: PRD;
|
|
47
|
-
prdPath: string;
|
|
48
|
-
workdir: string;
|
|
49
|
-
featureDir?: string;
|
|
50
|
-
story: UserStory;
|
|
51
|
-
storiesToExecute: UserStory[];
|
|
52
|
-
allStoryMetrics: StoryMetrics[];
|
|
53
|
-
timeoutRetryCountMap: Map<string, number>;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export interface PostVerifyResult {
|
|
57
|
-
passed: boolean;
|
|
58
|
-
prd: PRD;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Run post-agent verification and handle failure state.
|
|
63
|
-
*
|
|
64
|
-
* @design Shell command in config.quality.commands.test is operator-controlled,
|
|
65
|
-
* not user/PRD input. No shell injection risk from untrusted sources.
|
|
66
|
-
*/
|
|
67
|
-
export async function runPostAgentVerification(opts: PostVerifyOptions): Promise<PostVerifyResult> {
|
|
68
|
-
const { config, prd, prdPath, workdir, featureDir, story, storiesToExecute, allStoryMetrics } = opts;
|
|
69
|
-
|
|
70
|
-
if (!config.quality.commands.test) return { passed: true, prd };
|
|
71
|
-
|
|
72
|
-
const rectificationEnabled = config.execution.rectification?.enabled ?? false;
|
|
73
|
-
const regressionMode = config.execution.regressionGate?.mode;
|
|
74
|
-
|
|
75
|
-
// Skip per-story regression gate only when explicitly set to deferred
|
|
76
|
-
if (regressionMode === "deferred") {
|
|
77
|
-
return { passed: true, prd };
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Run full-suite regression gate (per-story mode)
|
|
81
|
-
const regressionGateResult = await runRegressionGate(config, workdir, story, rectificationEnabled);
|
|
82
|
-
|
|
83
|
-
if (regressionGateResult.status === "passed" || regressionGateResult.status === "skipped") {
|
|
84
|
-
return { passed: true, prd };
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Regression failed -- build StructuredFailure and revert stories
|
|
88
|
-
// verificationResult is always set when status === "failed" (see RegressionGateResult)
|
|
89
|
-
const regressionVerificationResult = regressionGateResult.verificationResult ?? {
|
|
90
|
-
status: "TEST_FAILURE" as const,
|
|
91
|
-
success: false,
|
|
92
|
-
countsTowardEscalation: true,
|
|
93
|
-
};
|
|
94
|
-
const regressionFailure = buildStructuredFailure(
|
|
95
|
-
story,
|
|
96
|
-
"regression",
|
|
97
|
-
regressionVerificationResult,
|
|
98
|
-
"Full-suite regression detected",
|
|
99
|
-
);
|
|
100
|
-
const updatedPrd = await _postVerifyDeps.revertStoriesOnFailure({
|
|
101
|
-
prd,
|
|
102
|
-
prdPath,
|
|
103
|
-
story,
|
|
104
|
-
storiesToExecute,
|
|
105
|
-
allStoryMetrics,
|
|
106
|
-
featureDir,
|
|
107
|
-
diagnosticContext: "REGRESSION: full-suite regression detected",
|
|
108
|
-
countsTowardEscalation: true,
|
|
109
|
-
priorFailure: regressionFailure,
|
|
110
|
-
});
|
|
111
|
-
return { passed: false, prd: updatedPrd };
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
interface RegressionGateResult {
|
|
115
|
-
status: "passed" | "skipped" | "failed";
|
|
116
|
-
verificationResult?: VerificationResult;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/** Run full-suite regression gate. */
|
|
120
|
-
async function runRegressionGate(
|
|
121
|
-
config: NaxConfig,
|
|
122
|
-
workdir: string,
|
|
123
|
-
story: UserStory,
|
|
124
|
-
rectificationEnabled: boolean,
|
|
125
|
-
): Promise<RegressionGateResult> {
|
|
126
|
-
const logger = getSafeLogger();
|
|
127
|
-
const regressionGateEnabled = config.execution.regressionGate?.enabled ?? true;
|
|
128
|
-
|
|
129
|
-
if (!regressionGateEnabled) {
|
|
130
|
-
return { status: "skipped" };
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
logger?.info("regression-gate", "Running full-suite regression gate");
|
|
134
|
-
const fullSuiteCommand = config.quality.commands.test ?? "bun test";
|
|
135
|
-
const regressionResult = await _postVerifyDeps.runVerification({
|
|
136
|
-
workingDirectory: workdir,
|
|
137
|
-
expectedFiles: _postVerifyDeps.getExpectedFiles(story),
|
|
138
|
-
command: fullSuiteCommand,
|
|
139
|
-
timeoutSeconds: config.execution.regressionGate.timeoutSeconds,
|
|
140
|
-
forceExit: config.quality.forceExit,
|
|
141
|
-
detectOpenHandles: config.quality.detectOpenHandles,
|
|
142
|
-
detectOpenHandlesRetries: config.quality.detectOpenHandlesRetries,
|
|
143
|
-
timeoutRetryCount: 0,
|
|
144
|
-
gracePeriodMs: config.quality.gracePeriodMs,
|
|
145
|
-
drainTimeoutMs: config.quality.drainTimeoutMs,
|
|
146
|
-
shell: config.quality.shell,
|
|
147
|
-
stripEnvVars: config.quality.stripEnvVars,
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
if (regressionResult.success) {
|
|
151
|
-
logger?.info("regression-gate", "Full-suite regression gate passed");
|
|
152
|
-
return { status: "passed" };
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Handle timeout: accept as pass if configured (BUG-026)
|
|
156
|
-
const acceptOnTimeout = config.execution.regressionGate?.acceptOnTimeout ?? true;
|
|
157
|
-
if (regressionResult.status === "TIMEOUT" && acceptOnTimeout) {
|
|
158
|
-
logger?.warn("regression-gate", "[BUG-026] Full-suite regression gate timed out (accepted as pass)");
|
|
159
|
-
return { status: "passed" };
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
logger?.warn("regression-gate", "Full-suite regression detected", { status: regressionResult.status });
|
|
163
|
-
|
|
164
|
-
// Attempt rectification on regression failures
|
|
165
|
-
const isTestFailure = regressionResult.status === "TEST_FAILURE" && regressionResult.output;
|
|
166
|
-
if (rectificationEnabled && isTestFailure && regressionResult.output) {
|
|
167
|
-
const fixed = await _postVerifyDeps.runRectificationLoop({
|
|
168
|
-
config,
|
|
169
|
-
workdir,
|
|
170
|
-
story,
|
|
171
|
-
testCommand: fullSuiteCommand,
|
|
172
|
-
timeoutSeconds: config.execution.regressionGate.timeoutSeconds,
|
|
173
|
-
testOutput: regressionResult.output,
|
|
174
|
-
promptPrefix:
|
|
175
|
-
"# REGRESSION: Full-Suite Test Failures\n\nYour changes broke tests in the full suite. Fix these regressions.",
|
|
176
|
-
});
|
|
177
|
-
if (fixed) return { status: "passed" };
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return { status: "failed", verificationResult: regressionResult };
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Swappable dependencies for testing (avoids mock.module() which leaks in Bun 1.x).
|
|
185
|
-
*/
|
|
186
|
-
export const _postVerifyDeps = {
|
|
187
|
-
parseBunTestOutput,
|
|
188
|
-
runVerification,
|
|
189
|
-
getExpectedFiles,
|
|
190
|
-
savePRD,
|
|
191
|
-
revertStoriesOnFailure,
|
|
192
|
-
runRectificationLoop,
|
|
193
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Rectification Core Logic (v0.11)
|
|
3
|
-
*
|
|
4
|
-
* DEPRECATED: Use src/verification/rectification.ts instead.
|
|
5
|
-
* This file is kept for backward compatibility only.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// Re-export from unified verification layer
|
|
9
|
-
export {
|
|
10
|
-
type RectificationState,
|
|
11
|
-
shouldRetryRectification,
|
|
12
|
-
createRectificationPrompt,
|
|
13
|
-
} from "../verification/rectification";
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ADR-003: Robust Orchestration Feedback Loop - Verification Module
|
|
3
|
-
*
|
|
4
|
-
* DEPRECATED: Use src/verification/ unified layer instead.
|
|
5
|
-
* This file is kept for backward compatibility only.
|
|
6
|
-
*
|
|
7
|
-
* Implements Decisions 3-6:
|
|
8
|
-
* - Pre-Flight Asset Verification
|
|
9
|
-
* - Execution Guard (Verification Timeout)
|
|
10
|
-
* - Smart Exit-Code Analysis
|
|
11
|
-
* - Environment Normalization
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
// Re-export from unified verification layer
|
|
15
|
-
export {
|
|
16
|
-
type AssetVerificationResult,
|
|
17
|
-
type TestExecutionResult as TimeoutExecutionResult,
|
|
18
|
-
type TestOutputAnalysis,
|
|
19
|
-
type VerificationResult,
|
|
20
|
-
type VerificationStatus,
|
|
21
|
-
verifyAssets,
|
|
22
|
-
executeWithTimeout,
|
|
23
|
-
parseTestOutput,
|
|
24
|
-
getEnvironmentalEscalationThreshold,
|
|
25
|
-
normalizeEnvironment,
|
|
26
|
-
appendOpenHandlesFlag,
|
|
27
|
-
appendForceExitFlag,
|
|
28
|
-
buildTestCommand,
|
|
29
|
-
} from "../verification";
|
|
30
|
-
|
|
31
|
-
// Adapter function for backward compatibility
|
|
32
|
-
import { fullSuite } from "../verification";
|
|
33
|
-
import type { VerificationGateOptions } from "../verification/types";
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Run complete verification flow with all ADR-003 safety checks.
|
|
37
|
-
*
|
|
38
|
-
* @deprecated Use fullSuite() from src/verification/gate.ts instead
|
|
39
|
-
*/
|
|
40
|
-
export async function runVerification(options: {
|
|
41
|
-
workingDirectory: string;
|
|
42
|
-
expectedFiles?: string[];
|
|
43
|
-
command: string;
|
|
44
|
-
timeoutSeconds: number;
|
|
45
|
-
forceExit?: boolean;
|
|
46
|
-
detectOpenHandles?: boolean;
|
|
47
|
-
detectOpenHandlesRetries?: number;
|
|
48
|
-
timeoutRetryCount?: number;
|
|
49
|
-
gracePeriodMs?: number;
|
|
50
|
-
drainTimeoutMs?: number;
|
|
51
|
-
shell?: string;
|
|
52
|
-
stripEnvVars?: string[];
|
|
53
|
-
cwd?: string;
|
|
54
|
-
}) {
|
|
55
|
-
// Map old options to new VerificationGateOptions
|
|
56
|
-
const gateOptions: VerificationGateOptions = {
|
|
57
|
-
workdir: options.workingDirectory,
|
|
58
|
-
expectedFiles: options.expectedFiles,
|
|
59
|
-
command: options.command,
|
|
60
|
-
timeoutSeconds: options.timeoutSeconds,
|
|
61
|
-
forceExit: options.forceExit,
|
|
62
|
-
detectOpenHandles: options.detectOpenHandles,
|
|
63
|
-
detectOpenHandlesRetries: options.detectOpenHandlesRetries,
|
|
64
|
-
timeoutRetryCount: options.timeoutRetryCount,
|
|
65
|
-
gracePeriodMs: options.gracePeriodMs,
|
|
66
|
-
drainTimeoutMs: options.drainTimeoutMs,
|
|
67
|
-
shell: options.shell,
|
|
68
|
-
stripEnvVars: options.stripEnvVars,
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
return fullSuite(gateOptions);
|
|
72
|
-
}
|