@principles/core 1.124.0 → 1.126.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/dist/runtime-v2/__tests__/architecture-regression.test.js +5 -1
- package/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
- package/dist/runtime-v2/__tests__/attack-e2e-pipeline-smoke.test.js +115 -21
- package/dist/runtime-v2/__tests__/attack-e2e-pipeline-smoke.test.js.map +1 -1
- package/dist/runtime-v2/__tests__/golden-path-diagnostician-e2e.test.js.map +1 -1
- package/dist/runtime-v2/__tests__/pain-signal-bridge-retried.test.js +7 -6
- package/dist/runtime-v2/__tests__/pain-signal-bridge-retried.test.js.map +1 -1
- package/dist/runtime-v2/__tests__/pain-signal-bridge-short-circuit.test.js.map +1 -1
- package/dist/runtime-v2/__tests__/pain-signal-bridge-workspace-dir.test.js.map +1 -1
- package/dist/runtime-v2/cli/diagnose.d.ts +2 -2
- package/dist/runtime-v2/cli/diagnose.d.ts.map +1 -1
- package/dist/runtime-v2/config/__tests__/pd-config-contract.test.js +3 -3
- package/dist/runtime-v2/config/__tests__/pd-config-contract.test.js.map +1 -1
- package/dist/runtime-v2/config/pd-config-defaults.js +2 -2
- package/dist/runtime-v2/config/pd-config-defaults.js.map +1 -1
- package/dist/runtime-v2/diagnostician-prompt-builder.d.ts +1 -64
- package/dist/runtime-v2/diagnostician-prompt-builder.d.ts.map +1 -1
- package/dist/runtime-v2/diagnostician-prompt-builder.js +0 -186
- package/dist/runtime-v2/diagnostician-prompt-builder.js.map +1 -1
- package/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js +17 -30
- package/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js.map +1 -1
- package/dist/runtime-v2/feature-flags/feature-flag-contract.d.ts.map +1 -1
- package/dist/runtime-v2/feature-flags/feature-flag-contract.js +3 -8
- package/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
- package/dist/runtime-v2/index.d.ts +8 -7
- package/dist/runtime-v2/index.d.ts.map +1 -1
- package/dist/runtime-v2/index.js +8 -5
- package/dist/runtime-v2/index.js.map +1 -1
- package/dist/runtime-v2/internalization/__tests__/diag-chain-e2e.test.js +108 -105
- package/dist/runtime-v2/internalization/__tests__/diag-chain-e2e.test.js.map +1 -1
- package/dist/runtime-v2/internalization/__tests__/runnerkind-seam.test.js +3 -3
- package/dist/runtime-v2/internalization/__tests__/runnerkind-seam.test.js.map +1 -1
- package/dist/runtime-v2/internalization/split-diagnostician-runner.d.ts.map +1 -1
- package/dist/runtime-v2/internalization/split-diagnostician-runner.js +121 -52
- package/dist/runtime-v2/internalization/split-diagnostician-runner.js.map +1 -1
- package/dist/runtime-v2/observer/__tests__/empathy-observer.real-e2e.test.js +28 -21
- package/dist/runtime-v2/observer/__tests__/empathy-observer.real-e2e.test.js.map +1 -1
- package/dist/runtime-v2/pain-signal-runtime-factory.d.ts +10 -1
- package/dist/runtime-v2/pain-signal-runtime-factory.d.ts.map +1 -1
- package/dist/runtime-v2/pain-signal-runtime-factory.js +42 -40
- package/dist/runtime-v2/pain-signal-runtime-factory.js.map +1 -1
- package/dist/runtime-v2/pain-to-principle-service.d.ts +1 -0
- package/dist/runtime-v2/pain-to-principle-service.d.ts.map +1 -1
- package/dist/runtime-v2/pain-to-principle-service.js.map +1 -1
- package/dist/runtime-v2/runner/__tests__/diagnose.test.js.map +1 -1
- package/package.json +1 -1
- package/dist/runtime-v2/__tests__/diagnostician-core-grounding.test.d.ts +0 -2
- package/dist/runtime-v2/__tests__/diagnostician-core-grounding.test.d.ts.map +0 -1
- package/dist/runtime-v2/__tests__/diagnostician-core-grounding.test.js +0 -122
- package/dist/runtime-v2/__tests__/diagnostician-core-grounding.test.js.map +0 -1
- package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.integration.test.d.ts +0 -2
- package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.integration.test.d.ts.map +0 -1
- package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.integration.test.js +0 -169
- package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.integration.test.js.map +0 -1
- package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.test.d.ts +0 -2
- package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.test.d.ts.map +0 -1
- package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.test.js +0 -462
- package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-builder.test.js.map +0 -1
- package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.d.ts +0 -13
- package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.d.ts.map +0 -1
- package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.js +0 -97
- package/dist/runtime-v2/diagnostician/__tests__/diagnostician-prompt-language.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/diagnostician-runner.integration.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/diagnostician-runner.integration.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/diagnostician-runner.integration.test.js +0 -378
- package/dist/runtime-v2/runner/__tests__/diagnostician-runner.integration.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/diagnostician-runner.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/diagnostician-runner.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/diagnostician-runner.test.js +0 -682
- package/dist/runtime-v2/runner/__tests__/diagnostician-runner.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/diagnostician-telemetry.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/diagnostician-telemetry.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/diagnostician-telemetry.test.js +0 -286
- package/dist/runtime-v2/runner/__tests__/diagnostician-telemetry.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/dual-track-e2e.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/dual-track-e2e.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/dual-track-e2e.test.js +0 -320
- package/dist/runtime-v2/runner/__tests__/dual-track-e2e.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/lease-expiration-recovery.integration.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/lease-expiration-recovery.integration.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/lease-expiration-recovery.integration.test.js +0 -261
- package/dist/runtime-v2/runner/__tests__/lease-expiration-recovery.integration.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m5-05-e2e.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/m5-05-e2e.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m5-05-e2e.test.js +0 -405
- package/dist/runtime-v2/runner/__tests__/m5-05-e2e.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m6-06-e2e.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/m6-06-e2e.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m6-06-e2e.test.js +0 -347
- package/dist/runtime-v2/runner/__tests__/m6-06-e2e.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m6-06-legacy.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/m6-06-legacy.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m6-06-legacy.test.js +0 -186
- package/dist/runtime-v2/runner/__tests__/m6-06-legacy.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m6-06-real-path.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/m6-06-real-path.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m6-06-real-path.test.js +0 -355
- package/dist/runtime-v2/runner/__tests__/m6-06-real-path.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m8-02-e2e.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/m8-02-e2e.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m8-02-e2e.test.js +0 -486
- package/dist/runtime-v2/runner/__tests__/m8-02-e2e.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m9-adapter-integration.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/m9-adapter-integration.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m9-adapter-integration.test.js +0 -171
- package/dist/runtime-v2/runner/__tests__/m9-adapter-integration.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m9-e2e.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/m9-e2e.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/m9-e2e.test.js +0 -175
- package/dist/runtime-v2/runner/__tests__/m9-e2e.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/max-attempts-exceeded.integration.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/max-attempts-exceeded.integration.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/max-attempts-exceeded.integration.test.js +0 -276
- package/dist/runtime-v2/runner/__tests__/max-attempts-exceeded.integration.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/retry-wait-recovery.integration.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/retry-wait-recovery.integration.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/retry-wait-recovery.integration.test.js +0 -272
- package/dist/runtime-v2/runner/__tests__/retry-wait-recovery.integration.test.js.map +0 -1
- package/dist/runtime-v2/runner/__tests__/start-run-input.test.d.ts +0 -2
- package/dist/runtime-v2/runner/__tests__/start-run-input.test.d.ts.map +0 -1
- package/dist/runtime-v2/runner/__tests__/start-run-input.test.js +0 -67
- package/dist/runtime-v2/runner/__tests__/start-run-input.test.js.map +0 -1
- package/dist/runtime-v2/runner/diagnostician-runner-options.d.ts +0 -57
- package/dist/runtime-v2/runner/diagnostician-runner-options.d.ts.map +0 -1
- package/dist/runtime-v2/runner/diagnostician-runner-options.js +0 -21
- package/dist/runtime-v2/runner/diagnostician-runner-options.js.map +0 -1
- package/dist/runtime-v2/runner/diagnostician-runner.d.ts +0 -89
- package/dist/runtime-v2/runner/diagnostician-runner.d.ts.map +0 -1
- package/dist/runtime-v2/runner/diagnostician-runner.js +0 -470
- package/dist/runtime-v2/runner/diagnostician-runner.js.map +0 -1
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dual-Track E2E Tests — M4 Exit Criteria Verification
|
|
3
|
-
*
|
|
4
|
-
* Tests the DiagnosticianRunner using TestDoubleRuntimeAdapter with real
|
|
5
|
-
* RuntimeStateManager (in-memory SQLite). Verifies all M4 exit criteria.
|
|
6
|
-
*
|
|
7
|
-
* Exit Criteria Covered:
|
|
8
|
-
* #1: Task completes through explicit run + validation WITHOUT heartbeat prompt injection
|
|
9
|
-
* #2: Runner uses SqliteContextAssembler for context building
|
|
10
|
-
* #3: Runner uses LeaseManager + RetryPolicy
|
|
11
|
-
* #6: Runner handles imported openclaw-history context without errors
|
|
12
|
-
* #8: Test coverage >= 80% for new runner code
|
|
13
|
-
* #9: No hidden dependence on heartbeat prompt path
|
|
14
|
-
* #10: Legacy heartbeat path remains functional (not modified by M4)
|
|
15
|
-
*/
|
|
16
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
17
|
-
import * as fs from 'fs';
|
|
18
|
-
import * as path from 'path';
|
|
19
|
-
import * as os from 'os';
|
|
20
|
-
import { RuntimeStateManager } from '../../store/runtime-state-manager.js';
|
|
21
|
-
import { SqliteContextAssembler } from '../../store/context/sqlite-context-assembler.js';
|
|
22
|
-
import { SqliteHistoryQuery } from '../../store/history/sqlite-history-query.js';
|
|
23
|
-
import { StoreEventEmitter } from '../../store/event-emitter.js';
|
|
24
|
-
import { DiagnosticianRunner } from '../diagnostician-runner.js';
|
|
25
|
-
import { PassThroughValidator } from '../diagnostician-validator.js';
|
|
26
|
-
import { TestDoubleRuntimeAdapter } from '../../adapter/test-double-runtime-adapter.js';
|
|
27
|
-
// -- Test fixtures --
|
|
28
|
-
function makeDiagnosticianOutput(taskId) {
|
|
29
|
-
return {
|
|
30
|
-
valid: true,
|
|
31
|
-
diagnosisId: `diag-e2e-${Date.now()}`,
|
|
32
|
-
taskId,
|
|
33
|
-
summary: 'E2E test diagnosis summary',
|
|
34
|
-
rootCause: 'E2E test root cause analysis',
|
|
35
|
-
violatedPrinciples: [],
|
|
36
|
-
evidence: [],
|
|
37
|
-
recommendations: [],
|
|
38
|
-
confidence: 0.85,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
function makeDiagnosticianTaskInput(options) {
|
|
42
|
-
const { taskId, workspaceDir, diagnostic, overrides } = options;
|
|
43
|
-
const diagnosticJson = JSON.stringify({
|
|
44
|
-
workspaceDir,
|
|
45
|
-
reasonSummary: diagnostic?.reasonSummary ?? 'E2E test task',
|
|
46
|
-
sourcePainId: diagnostic?.sourcePainId,
|
|
47
|
-
severity: diagnostic?.severity,
|
|
48
|
-
source: diagnostic?.source,
|
|
49
|
-
});
|
|
50
|
-
return {
|
|
51
|
-
taskId,
|
|
52
|
-
taskKind: 'diagnostician',
|
|
53
|
-
status: 'pending',
|
|
54
|
-
attemptCount: 0,
|
|
55
|
-
maxAttempts: 3,
|
|
56
|
-
...overrides,
|
|
57
|
-
diagnosticJson,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
// -- AlwaysInvalidValidator for Scenario 3 --
|
|
61
|
-
class AlwaysInvalidValidator {
|
|
62
|
-
// eslint-disable-next-line @typescript-eslint/class-methods-use-this
|
|
63
|
-
async validate(_output, _taskId) {
|
|
64
|
-
return {
|
|
65
|
-
valid: false,
|
|
66
|
-
errors: ['E2E test: always invalid'],
|
|
67
|
-
errorCategory: 'output_invalid',
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
// -- Test setup --
|
|
72
|
-
const TMP_ROOT = path.join(os.tmpdir(), `pd-dual-track-e2e-${process.pid}`);
|
|
73
|
-
describe('DiagnosticianRunner Dual-Track E2E', () => {
|
|
74
|
-
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
75
|
-
let testDir;
|
|
76
|
-
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
77
|
-
let stateManager;
|
|
78
|
-
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
79
|
-
let contextAssembler;
|
|
80
|
-
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
81
|
-
let historyQuery;
|
|
82
|
-
// eslint-disable-next-line @typescript-eslint/init-declarations
|
|
83
|
-
let eventEmitter;
|
|
84
|
-
beforeEach(async () => {
|
|
85
|
-
testDir = path.join(TMP_ROOT, `e2e-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
86
|
-
fs.mkdirSync(testDir, { recursive: true });
|
|
87
|
-
stateManager = new RuntimeStateManager({ workspaceDir: testDir });
|
|
88
|
-
await stateManager.initialize();
|
|
89
|
-
const sqliteConn = stateManager.connection;
|
|
90
|
-
historyQuery = new SqliteHistoryQuery(sqliteConn);
|
|
91
|
-
const taskStore = stateManager.taskStore;
|
|
92
|
-
const runStore = stateManager.runStore;
|
|
93
|
-
contextAssembler = new SqliteContextAssembler(taskStore, historyQuery, runStore);
|
|
94
|
-
eventEmitter = new StoreEventEmitter();
|
|
95
|
-
});
|
|
96
|
-
afterEach(() => {
|
|
97
|
-
stateManager.close();
|
|
98
|
-
try {
|
|
99
|
-
fs.rmSync(TMP_ROOT, { recursive: true, force: true });
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
// ignore cleanup errors on Windows
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
function createRunner(runtimeAdapter, validator = new PassThroughValidator(), committer = { commit: async () => ({ commitId: "mock-commit-id", artifactId: "mock-artifact-id", candidateCount: 0 }) }) {
|
|
106
|
-
return new DiagnosticianRunner({
|
|
107
|
-
stateManager,
|
|
108
|
-
contextAssembler,
|
|
109
|
-
runtimeAdapter,
|
|
110
|
-
eventEmitter,
|
|
111
|
-
validator,
|
|
112
|
-
committer,
|
|
113
|
-
}, {
|
|
114
|
-
owner: 'dual-track-e2e-runner',
|
|
115
|
-
runtimeKind: 'test-double',
|
|
116
|
-
pollIntervalMs: 50,
|
|
117
|
-
timeoutMs: 3000,
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
// ═══════════════════════════════════════════════════════════════
|
|
121
|
-
// SCENARIO 1: Happy Path (EXIT CRITERIA #1, #2, #3, #9, #10)
|
|
122
|
-
// ═══════════════════════════════════════════════════════════════
|
|
123
|
-
describe('Scenario 1: Happy Path', () => {
|
|
124
|
-
it('completes task through explicit run + validation flow', async () => {
|
|
125
|
-
const taskId = 'e2e-happy-001';
|
|
126
|
-
// Create task with diagnostic_json
|
|
127
|
-
await stateManager.createTask(makeDiagnosticianTaskInput({
|
|
128
|
-
taskId,
|
|
129
|
-
workspaceDir: testDir,
|
|
130
|
-
diagnostic: {
|
|
131
|
-
reasonSummary: 'E2E happy path test',
|
|
132
|
-
sourcePainId: 'pain-e2e-001',
|
|
133
|
-
severity: 'medium',
|
|
134
|
-
source: 'e2e-test',
|
|
135
|
-
},
|
|
136
|
-
}));
|
|
137
|
-
// Configure TestDoubleRuntimeAdapter to return success on first poll
|
|
138
|
-
const successfulOutput = makeDiagnosticianOutput(taskId);
|
|
139
|
-
const runtimeAdapter = new TestDoubleRuntimeAdapter({
|
|
140
|
-
onPollRun: (_runId) => ({ runId: 'td-poll-1', status: 'succeeded', startedAt: new Date().toISOString(), endedAt: new Date().toISOString() }),
|
|
141
|
-
onFetchOutput: (_runId) => ({ runId: 'td-fetch-1', payload: successfulOutput }),
|
|
142
|
-
});
|
|
143
|
-
const runner = createRunner(runtimeAdapter, new PassThroughValidator());
|
|
144
|
-
const result = await runner.run(taskId);
|
|
145
|
-
// Assertion 1: result.status === 'succeeded'
|
|
146
|
-
expect(result.status).toBe('succeeded');
|
|
147
|
-
// Assertion 2: task in store has status 'succeeded'
|
|
148
|
-
const task = await stateManager.getTask(taskId);
|
|
149
|
-
expect(task).not.toBeNull();
|
|
150
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
151
|
-
expect(task.status).toBe('succeeded');
|
|
152
|
-
// Assertion 3: output.payload.diagnosisId is set
|
|
153
|
-
expect(result.output).toBeDefined();
|
|
154
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
155
|
-
expect(result.output.diagnosisId).toBe(successfulOutput.diagnosisId);
|
|
156
|
-
// Assertion 4: contextHash is present (proves context assembly ran)
|
|
157
|
-
expect(result.contextHash).toBeDefined();
|
|
158
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
159
|
-
expect(result.contextHash.length).toBeGreaterThan(0);
|
|
160
|
-
// Assertion 5: runs exist with outputPayload
|
|
161
|
-
const runs = await stateManager.getRunsByTask(taskId);
|
|
162
|
-
expect(runs.length).toBeGreaterThan(0);
|
|
163
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
164
|
-
const latestRun = runs[runs.length - 1];
|
|
165
|
-
expect(latestRun.outputPayload).toBeDefined();
|
|
166
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
167
|
-
const parsed = JSON.parse(latestRun.outputPayload);
|
|
168
|
-
expect(parsed.diagnosisId).toBe(successfulOutput.diagnosisId);
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
// ═══════════════════════════════════════════════════════════════
|
|
172
|
-
// SCENARIO 2: Runtime Failure -> retry_wait (EXIT CRITERIA #3)
|
|
173
|
-
// ═══════════════════════════════════════════════════════════════
|
|
174
|
-
describe('Scenario 2: Runtime Failure -> retry_wait', () => {
|
|
175
|
-
it('transitions task to retry_wait on runtime failure', async () => {
|
|
176
|
-
const taskId = 'e2e-runtime-fail-001';
|
|
177
|
-
await stateManager.createTask(makeDiagnosticianTaskInput({
|
|
178
|
-
taskId,
|
|
179
|
-
workspaceDir: testDir,
|
|
180
|
-
diagnostic: { reasonSummary: 'E2E runtime failure test' },
|
|
181
|
-
}));
|
|
182
|
-
// Configure TestDoubleRuntimeAdapter.pollRun to return 'failed'
|
|
183
|
-
const runtimeAdapter = new TestDoubleRuntimeAdapter({
|
|
184
|
-
onPollRun: (_runId) => ({ runId: 'td-fail-1', status: 'failed', startedAt: new Date().toISOString(), endedAt: new Date().toISOString() }),
|
|
185
|
-
onFetchOutput: () => null,
|
|
186
|
-
});
|
|
187
|
-
const runner = createRunner(runtimeAdapter, new PassThroughValidator());
|
|
188
|
-
const result = await runner.run(taskId);
|
|
189
|
-
// Assertion 1: result.status === 'retried'
|
|
190
|
-
expect(result.status).toBe('retried');
|
|
191
|
-
// Assertion 2: result.errorCategory === 'execution_failed'
|
|
192
|
-
expect(result.errorCategory).toBe('execution_failed');
|
|
193
|
-
// Assertion 3: Verify task in store has status 'retry_wait'
|
|
194
|
-
const task = await stateManager.getTask(taskId);
|
|
195
|
-
expect(task).not.toBeNull();
|
|
196
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
197
|
-
expect(task.status).toBe('retry_wait');
|
|
198
|
-
// Assertion 4: Verify task attemptCount incremented
|
|
199
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
200
|
-
expect(task.attemptCount).toBe(1);
|
|
201
|
-
// Assertion 5: Verify run record has errorCategory 'execution_failed'
|
|
202
|
-
const runs = await stateManager.getRunsByTask(taskId);
|
|
203
|
-
expect(runs.length).toBeGreaterThan(0);
|
|
204
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
205
|
-
const latestRun = runs[runs.length - 1];
|
|
206
|
-
expect(latestRun.errorCategory).toBe('execution_failed');
|
|
207
|
-
// Assertion 6: Verify failureReason is present
|
|
208
|
-
expect(result.failureReason).toBeDefined();
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
// ═══════════════════════════════════════════════════════════════
|
|
212
|
-
// SCENARIO 3: Validation Failure (EXIT CRITERIA #4)
|
|
213
|
-
// ═══════════════════════════════════════════════════════════════
|
|
214
|
-
describe('Scenario 3: Validation Failure', () => {
|
|
215
|
-
it('transitions task to retry_wait on validation failure', async () => {
|
|
216
|
-
const taskId = 'e2e-validation-fail-001';
|
|
217
|
-
await stateManager.createTask(makeDiagnosticianTaskInput({
|
|
218
|
-
taskId,
|
|
219
|
-
workspaceDir: testDir,
|
|
220
|
-
diagnostic: { reasonSummary: 'E2E validation failure test' },
|
|
221
|
-
}));
|
|
222
|
-
// Configure TestDoubleRuntimeAdapter to return output that will fail validation
|
|
223
|
-
const validOutput = makeDiagnosticianOutput(taskId);
|
|
224
|
-
const runtimeAdapter = new TestDoubleRuntimeAdapter({
|
|
225
|
-
onPollRun: (_runId) => ({ runId: 'td-val-1', status: 'succeeded', startedAt: new Date().toISOString(), endedAt: new Date().toISOString() }),
|
|
226
|
-
onFetchOutput: (_runId) => ({ runId: 'td-val-fetch-1', payload: validOutput }),
|
|
227
|
-
});
|
|
228
|
-
// Use AlwaysInvalidValidator that always rejects output
|
|
229
|
-
const runner = createRunner(runtimeAdapter, new AlwaysInvalidValidator());
|
|
230
|
-
const result = await runner.run(taskId);
|
|
231
|
-
// Assertion 1: result.status === 'retried' (shouldRetry=true by default)
|
|
232
|
-
expect(result.status).toBe('retried');
|
|
233
|
-
// Assertion 2: result.errorCategory === 'output_invalid'
|
|
234
|
-
expect(result.errorCategory).toBe('output_invalid');
|
|
235
|
-
// Assertion 3: Verify task in store has status 'retry_wait'
|
|
236
|
-
const task = await stateManager.getTask(taskId);
|
|
237
|
-
expect(task).not.toBeNull();
|
|
238
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
239
|
-
expect(task.status).toBe('retry_wait');
|
|
240
|
-
// Assertion 4: Verify task attemptCount is 1
|
|
241
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
242
|
-
expect(task.attemptCount).toBe(1);
|
|
243
|
-
// Assertion 5: Verify failureReason mentions validation
|
|
244
|
-
expect(result.failureReason).toBeDefined();
|
|
245
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
246
|
-
expect(result.failureReason.toLowerCase()).toContain('validation');
|
|
247
|
-
// Assertion 6: Verify run record has errorCategory 'output_invalid'
|
|
248
|
-
const runs = await stateManager.getRunsByTask(taskId);
|
|
249
|
-
expect(runs.length).toBeGreaterThan(0);
|
|
250
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
251
|
-
const latestRun = runs[runs.length - 1];
|
|
252
|
-
expect(latestRun.errorCategory).toBe('output_invalid');
|
|
253
|
-
expect(latestRun.executionStatus).toBe('failed');
|
|
254
|
-
});
|
|
255
|
-
});
|
|
256
|
-
// ═══════════════════════════════════════════════════════════════
|
|
257
|
-
// SCENARIO 4: OpenClaw-History Compatibility (EXIT CRITERIA #6)
|
|
258
|
-
// ═══════════════════════════════════════════════════════════════
|
|
259
|
-
describe('Scenario 4: OpenClaw-History Compatibility', () => {
|
|
260
|
-
it('handles imported openclaw-history context without errors', async () => {
|
|
261
|
-
const taskId = 'e2e-openclaw-001';
|
|
262
|
-
// Create task
|
|
263
|
-
await stateManager.createTask(makeDiagnosticianTaskInput({
|
|
264
|
-
taskId,
|
|
265
|
-
workspaceDir: testDir,
|
|
266
|
-
diagnostic: { reasonSummary: 'E2E openclaw-history compat test' },
|
|
267
|
-
}));
|
|
268
|
-
// Acquire lease to create a real run record first (mimics imported history)
|
|
269
|
-
await stateManager.acquireLease({
|
|
270
|
-
taskId,
|
|
271
|
-
owner: 'setup-agent',
|
|
272
|
-
runtimeKind: 'openclaw-history',
|
|
273
|
-
});
|
|
274
|
-
// Mark as succeeded to have a completed run with output
|
|
275
|
-
await stateManager.markTaskSucceeded(taskId, 'run://setup-run');
|
|
276
|
-
// Now set up for runner: create a fresh task state
|
|
277
|
-
await stateManager.updateTask(taskId, {
|
|
278
|
-
status: 'pending',
|
|
279
|
-
attemptCount: 0,
|
|
280
|
-
lastError: null,
|
|
281
|
-
resultRef: null,
|
|
282
|
-
});
|
|
283
|
-
// Verify openclaw-history run exists
|
|
284
|
-
const runsBefore = await stateManager.getRunsByTask(taskId);
|
|
285
|
-
expect(runsBefore.length).toBeGreaterThan(0);
|
|
286
|
-
// Configure TestDoubleRuntimeAdapter for success
|
|
287
|
-
const successOutput = makeDiagnosticianOutput(taskId);
|
|
288
|
-
const runtimeAdapter = new TestDoubleRuntimeAdapter({
|
|
289
|
-
onPollRun: (_runId) => ({ runId: 'td-oc-1', status: 'succeeded', startedAt: new Date().toISOString(), endedAt: new Date().toISOString() }),
|
|
290
|
-
onFetchOutput: (_runId) => ({ runId: 'td-oc-fetch-1', payload: successOutput }),
|
|
291
|
-
});
|
|
292
|
-
const runner = createRunner(runtimeAdapter, new PassThroughValidator());
|
|
293
|
-
const result = await runner.run(taskId);
|
|
294
|
-
// Assertion 1: result.status === 'succeeded' (no errors from mixed runtime_kind)
|
|
295
|
-
expect(result.status).toBe('succeeded');
|
|
296
|
-
// Assertion 2: contextHash is present (context assembly succeeded)
|
|
297
|
-
expect(result.contextHash).toBeDefined();
|
|
298
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
299
|
-
expect(result.contextHash.length).toBeGreaterThan(0);
|
|
300
|
-
// Assertion 3: Verify task in store has status 'succeeded'
|
|
301
|
-
const task = await stateManager.getTask(taskId);
|
|
302
|
-
expect(task).not.toBeNull();
|
|
303
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
304
|
-
expect(task.status).toBe('succeeded');
|
|
305
|
-
// Assertion 4: Verify output is valid
|
|
306
|
-
expect(result.output).toBeDefined();
|
|
307
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
308
|
-
expect(result.output.valid).toBe(true);
|
|
309
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
310
|
-
expect(result.output.diagnosisId).toBe(successOutput.diagnosisId);
|
|
311
|
-
// Assertion 5: Verify openclaw-history run is in store (compatibility)
|
|
312
|
-
const allRuns = await stateManager.getRunsByTask(taskId);
|
|
313
|
-
const openclawHistoryRuns = allRuns.filter((r) => r.runtimeKind === 'openclaw-history');
|
|
314
|
-
expect(openclawHistoryRuns.length).toBeGreaterThan(0);
|
|
315
|
-
// Assertion 6: Verify result.taskId matches
|
|
316
|
-
expect(result.taskId).toBe(taskId);
|
|
317
|
-
});
|
|
318
|
-
});
|
|
319
|
-
});
|
|
320
|
-
//# sourceMappingURL=dual-track-e2e.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dual-track-e2e.test.js","sourceRoot":"","sources":["../../../../src/runtime-v2/runner/__tests__/dual-track-e2e.test.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime-v2/runner/__tests__/lease-expiration-recovery.integration.test.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lease-expiration-recovery.integration.test.d.ts","sourceRoot":"","sources":["../../../../src/runtime-v2/runner/__tests__/lease-expiration-recovery.integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Lease expiration recovery integration tests.
|
|
3
|
-
*
|
|
4
|
-
* Verifies forceExpire allows another runner to acquire a task whose lease became stale:
|
|
5
|
-
* 1. forceExpire clears the lease and returns task to 'pending'
|
|
6
|
-
* 2. Another runner can acquireLease without lease_conflict
|
|
7
|
-
* 3. Only one runner can hold a lease at any time (lease conflict)
|
|
8
|
-
* 4. The new runner's attempt completes successfully
|
|
9
|
-
*/
|
|
10
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
11
|
-
import * as fs from 'fs';
|
|
12
|
-
import * as path from 'path';
|
|
13
|
-
import * as os from 'os';
|
|
14
|
-
import { RuntimeStateManager } from '../../store/runtime-state-manager.js';
|
|
15
|
-
import { SqliteContextAssembler } from '../../store/context/sqlite-context-assembler.js';
|
|
16
|
-
import { SqliteHistoryQuery } from '../../store/history/sqlite-history-query.js';
|
|
17
|
-
import { StoreEventEmitter } from '../../store/event-emitter.js';
|
|
18
|
-
import { DiagnosticianRunner } from '../diagnostician-runner.js';
|
|
19
|
-
import { PassThroughValidator } from '../diagnostician-validator.js';
|
|
20
|
-
import { PDRuntimeError } from '../../error-categories.js';
|
|
21
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
22
|
-
// -- Test fixtures --
|
|
23
|
-
function makeDiagnosticianOutput(taskId) {
|
|
24
|
-
return {
|
|
25
|
-
valid: true,
|
|
26
|
-
diagnosisId: `diag-${Date.now()}`,
|
|
27
|
-
taskId,
|
|
28
|
-
summary: 'Integration test diagnosis summary',
|
|
29
|
-
rootCause: 'Test root cause analysis',
|
|
30
|
-
violatedPrinciples: [],
|
|
31
|
-
evidence: [],
|
|
32
|
-
recommendations: [],
|
|
33
|
-
confidence: 0.85,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
function makeDiagnosticianTaskInput(options) {
|
|
37
|
-
const { taskId, workspaceDir, diagnostic, overrides } = options;
|
|
38
|
-
const diagnosticJson = JSON.stringify({
|
|
39
|
-
workspaceDir,
|
|
40
|
-
reasonSummary: diagnostic?.reasonSummary ?? 'Integration test task',
|
|
41
|
-
sourcePainId: diagnostic?.sourcePainId,
|
|
42
|
-
severity: diagnostic?.severity,
|
|
43
|
-
source: diagnostic?.source,
|
|
44
|
-
});
|
|
45
|
-
return {
|
|
46
|
-
taskId,
|
|
47
|
-
taskKind: 'diagnostician',
|
|
48
|
-
status: 'pending',
|
|
49
|
-
attemptCount: 0,
|
|
50
|
-
maxAttempts: 3,
|
|
51
|
-
...overrides,
|
|
52
|
-
diagnosticJson,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
// -- StubRuntimeAdapter --
|
|
56
|
-
/* eslint-disable @typescript-eslint/class-methods-use-this */
|
|
57
|
-
class StubRuntimeAdapter {
|
|
58
|
-
kindValue;
|
|
59
|
-
nextOutput = null;
|
|
60
|
-
nextStatus = 'succeeded';
|
|
61
|
-
constructor(kindValue = 'test-double') {
|
|
62
|
-
this.kindValue = kindValue;
|
|
63
|
-
}
|
|
64
|
-
setOutput(output) {
|
|
65
|
-
this.nextOutput = output;
|
|
66
|
-
}
|
|
67
|
-
setRunStatus(status) {
|
|
68
|
-
this.nextStatus = status;
|
|
69
|
-
}
|
|
70
|
-
kind() {
|
|
71
|
-
return this.kindValue;
|
|
72
|
-
}
|
|
73
|
-
async getCapabilities() {
|
|
74
|
-
return {
|
|
75
|
-
supportsStructuredJsonOutput: true,
|
|
76
|
-
supportsToolUse: false,
|
|
77
|
-
supportsWorkingDirectory: false,
|
|
78
|
-
supportsModelSelection: false,
|
|
79
|
-
supportsLongRunningSessions: false,
|
|
80
|
-
supportsCancellation: true,
|
|
81
|
-
supportsArtifactWriteBack: false,
|
|
82
|
-
supportsConcurrentRuns: false,
|
|
83
|
-
supportsStreaming: false,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
async healthCheck() {
|
|
87
|
-
return {
|
|
88
|
-
healthy: true,
|
|
89
|
-
degraded: false,
|
|
90
|
-
warnings: [],
|
|
91
|
-
lastCheckedAt: new Date().toISOString(),
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
async startRun(_input) {
|
|
95
|
-
const runId = `stub-run-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
96
|
-
return {
|
|
97
|
-
runId,
|
|
98
|
-
runtimeKind: this.kindValue,
|
|
99
|
-
startedAt: new Date().toISOString(),
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
async pollRun(runId) {
|
|
103
|
-
return {
|
|
104
|
-
runId,
|
|
105
|
-
status: this.nextStatus,
|
|
106
|
-
startedAt: new Date().toISOString(),
|
|
107
|
-
endedAt: new Date().toISOString(),
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
async cancelRun(_runId) { }
|
|
111
|
-
async fetchOutput(runId) {
|
|
112
|
-
if (this.nextOutput === null)
|
|
113
|
-
return null;
|
|
114
|
-
return { runId, payload: this.nextOutput };
|
|
115
|
-
}
|
|
116
|
-
async fetchArtifacts(_runId) {
|
|
117
|
-
return [];
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
/* eslint-enable @typescript-eslint/class-methods-use-this */
|
|
121
|
-
// -- Integration test setup --
|
|
122
|
-
const TMP_ROOT = path.join(os.tmpdir(), `pd-m4-04-lease-expire-${process.pid}`);
|
|
123
|
-
describe('lease expiration recovery integration', () => {
|
|
124
|
-
let testDir = '';
|
|
125
|
-
let stateManager = null;
|
|
126
|
-
let contextAssembler = null;
|
|
127
|
-
let historyQuery = null;
|
|
128
|
-
let eventEmitter = null;
|
|
129
|
-
let runtimeAdapter = null;
|
|
130
|
-
beforeEach(async () => {
|
|
131
|
-
testDir = path.join(TMP_ROOT, `test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
132
|
-
fs.mkdirSync(testDir, { recursive: true });
|
|
133
|
-
stateManager = new RuntimeStateManager({ workspaceDir: testDir });
|
|
134
|
-
await stateManager.initialize();
|
|
135
|
-
const sqliteConn = stateManager.connection;
|
|
136
|
-
historyQuery = new SqliteHistoryQuery(sqliteConn);
|
|
137
|
-
const { taskStore } = stateManager;
|
|
138
|
-
const { runStore } = stateManager;
|
|
139
|
-
contextAssembler = new SqliteContextAssembler(taskStore, historyQuery, runStore);
|
|
140
|
-
eventEmitter = new StoreEventEmitter();
|
|
141
|
-
runtimeAdapter = new StubRuntimeAdapter();
|
|
142
|
-
});
|
|
143
|
-
afterEach(() => {
|
|
144
|
-
stateManager.close();
|
|
145
|
-
try {
|
|
146
|
-
fs.rmSync(TMP_ROOT, { recursive: true, force: true });
|
|
147
|
-
}
|
|
148
|
-
catch {
|
|
149
|
-
// ignore cleanup errors on Windows
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
function createRunner(validator = new PassThroughValidator(), committer = { commit: async () => ({ commitId: "mock-commit-id", artifactId: "mock-artifact-id", candidateCount: 0 }) }) {
|
|
153
|
-
return new DiagnosticianRunner({
|
|
154
|
-
stateManager,
|
|
155
|
-
contextAssembler,
|
|
156
|
-
runtimeAdapter,
|
|
157
|
-
eventEmitter,
|
|
158
|
-
validator,
|
|
159
|
-
committer,
|
|
160
|
-
}, {
|
|
161
|
-
owner: 'integration-test-runner',
|
|
162
|
-
runtimeKind: 'test-double',
|
|
163
|
-
pollIntervalMs: 50,
|
|
164
|
-
timeoutMs: 2000,
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
it('forceExpire clears stale lease allowing another runner to acquire', async () => {
|
|
168
|
-
const taskId = 'lease-expire-task-001';
|
|
169
|
-
// Create task with maxAttempts=3
|
|
170
|
-
await stateManager.createTask(makeDiagnosticianTaskInput({
|
|
171
|
-
taskId,
|
|
172
|
-
workspaceDir: testDir,
|
|
173
|
-
diagnostic: { reasonSummary: 'lease expiration recovery test' },
|
|
174
|
-
overrides: { maxAttempts: 3 },
|
|
175
|
-
}));
|
|
176
|
-
// Runner A acquires lease (attemptCount 0 → 1)
|
|
177
|
-
await stateManager.acquireLease({
|
|
178
|
-
taskId,
|
|
179
|
-
owner: 'runner-A',
|
|
180
|
-
runtimeKind: 'test-double',
|
|
181
|
-
});
|
|
182
|
-
let task = await stateManager.getTask(taskId);
|
|
183
|
-
expect(task.status).toBe('leased');
|
|
184
|
-
expect(task.leaseOwner).toBe('runner-A');
|
|
185
|
-
expect(task.attemptCount).toBe(1);
|
|
186
|
-
// Force-expire the lease (simulates runner-A crash)
|
|
187
|
-
await stateManager.forceExpireLease(taskId);
|
|
188
|
-
task = await stateManager.getTask(taskId);
|
|
189
|
-
expect(task.status).toBe('pending');
|
|
190
|
-
expect(task.leaseOwner).toBeFalsy();
|
|
191
|
-
expect(task.leaseExpiresAt).toBeFalsy();
|
|
192
|
-
// Runner B acquires the same task — should succeed without lease_conflict
|
|
193
|
-
await stateManager.acquireLease({
|
|
194
|
-
taskId,
|
|
195
|
-
owner: 'runner-B',
|
|
196
|
-
runtimeKind: 'test-double',
|
|
197
|
-
});
|
|
198
|
-
task = await stateManager.getTask(taskId);
|
|
199
|
-
expect(task.status).toBe('leased');
|
|
200
|
-
expect(task.leaseOwner).toBe('runner-B');
|
|
201
|
-
expect(task.attemptCount).toBe(2);
|
|
202
|
-
// Verify 2 run records (one from Runner A, one from Runner B)
|
|
203
|
-
const runs = await stateManager.getRunsByTask(taskId);
|
|
204
|
-
expect(runs).toHaveLength(2);
|
|
205
|
-
});
|
|
206
|
-
it('runner completes task after forceExpire recovery', async () => {
|
|
207
|
-
const taskId = 'lease-expire-task-002';
|
|
208
|
-
await stateManager.createTask(makeDiagnosticianTaskInput({
|
|
209
|
-
taskId,
|
|
210
|
-
workspaceDir: testDir,
|
|
211
|
-
diagnostic: { reasonSummary: 'runner recovery after force expire' },
|
|
212
|
-
overrides: { maxAttempts: 3 },
|
|
213
|
-
}));
|
|
214
|
-
// Runner A acquires lease then crashes
|
|
215
|
-
await stateManager.acquireLease({
|
|
216
|
-
taskId,
|
|
217
|
-
owner: 'runner-A',
|
|
218
|
-
runtimeKind: 'test-double',
|
|
219
|
-
});
|
|
220
|
-
await stateManager.forceExpireLease(taskId);
|
|
221
|
-
// Set up adapter for Runner B's successful attempt
|
|
222
|
-
const output = makeDiagnosticianOutput(taskId);
|
|
223
|
-
runtimeAdapter.setOutput(output);
|
|
224
|
-
// Runner B picks up the task via DiagnosticianRunner.run()
|
|
225
|
-
const runner = createRunner();
|
|
226
|
-
const result = await runner.run(taskId);
|
|
227
|
-
expect(result.status).toBe('succeeded');
|
|
228
|
-
expect(result.taskId).toBe(taskId);
|
|
229
|
-
const task = await stateManager.getTask(taskId);
|
|
230
|
-
expect(task.status).toBe('succeeded');
|
|
231
|
-
});
|
|
232
|
-
it('prevents concurrent lease holders — lease conflict enforced', async () => {
|
|
233
|
-
const taskId = 'lease-expire-task-003';
|
|
234
|
-
await stateManager.createTask(makeDiagnosticianTaskInput({
|
|
235
|
-
taskId,
|
|
236
|
-
workspaceDir: testDir,
|
|
237
|
-
diagnostic: { reasonSummary: 'concurrent lease conflict test' },
|
|
238
|
-
overrides: { maxAttempts: 3 },
|
|
239
|
-
}));
|
|
240
|
-
// Runner A acquires lease
|
|
241
|
-
await stateManager.acquireLease({
|
|
242
|
-
taskId,
|
|
243
|
-
owner: 'runner-A',
|
|
244
|
-
runtimeKind: 'test-double',
|
|
245
|
-
});
|
|
246
|
-
// Runner B tries to acquire while Runner A holds the lease → lease_conflict
|
|
247
|
-
await expect(stateManager.acquireLease({ taskId, owner: 'runner-B', runtimeKind: 'test-double' })).rejects.toThrow();
|
|
248
|
-
try {
|
|
249
|
-
await stateManager.acquireLease({ taskId, owner: 'runner-B', runtimeKind: 'test-double' });
|
|
250
|
-
}
|
|
251
|
-
catch (err) {
|
|
252
|
-
expect(err).toBeInstanceOf(PDRuntimeError);
|
|
253
|
-
expect(err.category).toBe('lease_conflict');
|
|
254
|
-
}
|
|
255
|
-
// Verify Runner A still holds the lease
|
|
256
|
-
const task = await stateManager.getTask(taskId);
|
|
257
|
-
expect(task.status).toBe('leased');
|
|
258
|
-
expect(task.leaseOwner).toBe('runner-A');
|
|
259
|
-
});
|
|
260
|
-
});
|
|
261
|
-
//# sourceMappingURL=lease-expiration-recovery.integration.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lease-expiration-recovery.integration.test.js","sourceRoot":"","sources":["../../../../src/runtime-v2/runner/__tests__/lease-expiration-recovery.integration.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAAE,sBAAsB,EAAE,MAAM,iDAAiD,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAerE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAE3D,6DAA6D;AAE7D,sBAAsB;AAEtB,SAAS,uBAAuB,CAAC,MAAc;IAC7C,OAAO;QACL,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,EAAE;QACjC,MAAM;QACN,OAAO,EAAE,oCAAoC;QAC7C,SAAS,EAAE,0BAA0B;QACrC,kBAAkB,EAAE,EAAE;QACtB,QAAQ,EAAE,EAAE;QACZ,eAAe,EAAE,EAAE;QACnB,UAAU,EAAE,IAAI;KACjB,CAAC;AACJ,CAAC;AAgBD,SAAS,0BAA0B,CACjC,OAA4B;IAE5B,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;IAChE,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC;QACpC,YAAY;QACZ,aAAa,EAAE,UAAU,EAAE,aAAa,IAAI,uBAAuB;QACnE,YAAY,EAAE,UAAU,EAAE,YAAY;QACtC,QAAQ,EAAE,UAAU,EAAE,QAAQ;QAC9B,MAAM,EAAE,UAAU,EAAE,MAAM;KAC3B,CAAC,CAAC;IAEH,OAAO;QACL,MAAM;QACN,QAAQ,EAAE,eAAe;QACzB,MAAM,EAAE,SAAS;QACjB,YAAY,EAAE,CAAC;QACf,WAAW,EAAE,CAAC;QACd,GAAG,SAAS;QACZ,cAAc;KACf,CAAC;AACJ,CAAC;AAED,2BAA2B;AAE3B,8DAA8D;AAC9D,MAAM,kBAAkB;IAIO;IAHrB,UAAU,GAAmC,IAAI,CAAC;IAClD,UAAU,GAAwB,WAAW,CAAC;IAEtD,YAA6B,YAAyB,aAAa;QAAtC,cAAS,GAAT,SAAS,CAA6B;IAAG,CAAC;IAEvE,SAAS,CAAC,MAAsC;QAC9C,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;IAC3B,CAAC;IAED,YAAY,CAAC,MAA2B;QACtC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;IAC3B,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,OAAO;YACL,4BAA4B,EAAE,IAAI;YAClC,eAAe,EAAE,KAAK;YACtB,wBAAwB,EAAE,KAAK;YAC/B,sBAAsB,EAAE,KAAK;YAC7B,2BAA2B,EAAE,KAAK;YAClC,oBAAoB,EAAE,IAAI;YAC1B,yBAAyB,EAAE,KAAK;YAChC,sBAAsB,EAAE,KAAK;YAC7B,iBAAiB,EAAE,KAAK;SACzB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,WAAW;QACf,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,KAAK;YACf,QAAQ,EAAE,EAAE;YACZ,aAAa,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACxC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAqB;QAClC,MAAM,KAAK,GAAG,YAAY,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACjF,OAAO;YACL,KAAK;YACL,WAAW,EAAE,IAAI,CAAC,SAAS;YAC3B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAa;QACzB,OAAO;YACL,KAAK;YACL,MAAM,EAAE,IAAI,CAAC,UAAU;YACvB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SAClC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,MAAc,IAA+B,CAAC;IAE9D,KAAK,CAAC,WAAW,CAAC,KAAa;QAC7B,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC1C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAAc;QACjC,OAAO,EAAE,CAAC;IACZ,CAAC;CACF;AACD,6DAA6D;AAE7D,+BAA+B;AAE/B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,yBAAyB,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AAEhF,QAAQ,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACrD,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,YAAY,GAAwB,IAAsC,CAAC;IAC/E,IAAI,gBAAgB,GAA2B,IAAyC,CAAC;IACzF,IAAI,YAAY,GAAuB,IAAqC,CAAC;IAC7E,IAAI,YAAY,GAAsB,IAAoC,CAAC;IAC3E,IAAI,cAAc,GAAuB,IAAqC,CAAC;IAE/E,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3F,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE3C,YAAY,GAAG,IAAI,mBAAmB,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC;QAClE,MAAM,YAAY,CAAC,UAAU,EAAE,CAAC;QAEhC,MAAM,UAAU,GAAI,YAAmD,CAAC,UAAU,CAAC;QACnF,YAAY,GAAG,IAAI,kBAAkB,CAAC,UAAmB,CAAC,CAAC;QAE3D,MAAM,EAAE,SAAS,EAAE,GAAI,YAAkD,CAAC;QAC1E,MAAM,EAAE,QAAQ,EAAE,GAAI,YAAiD,CAAC;QACxE,gBAAgB,GAAG,IAAI,sBAAsB,CAC3C,SAAkB,EAClB,YAAY,EACZ,QAAiB,CAClB,CAAC;QAEF,YAAY,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACvC,cAAc,GAAG,IAAI,kBAAkB,EAAE,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,YAAY,CAAC,KAAK,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;QAAC,MAAM,CAAC;YACP,mCAAmC;QACrC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,SAAS,YAAY,CAAC,YAAoC,IAAI,oBAAoB,EAAE,EAClF,YAAoC,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,kBAAkB,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,EAAE;QAC/I,OAAO,IAAI,mBAAmB,CAC5B;YACE,YAAY;YACZ,gBAAgB;YAChB,cAAc;YACd,YAAY;YACZ,SAAS;YACX,SAAS;SACR,EACD;YACE,KAAK,EAAE,yBAAyB;YAChC,WAAW,EAAE,aAAa;YAC1B,cAAc,EAAE,EAAE;YAClB,SAAS,EAAE,IAAI;SAChB,CACF,CAAC;IACJ,CAAC;IAED,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACjF,MAAM,MAAM,GAAG,uBAAuB,CAAC;QAEvC,iCAAiC;QACjC,MAAM,YAAY,CAAC,UAAU,CAC3B,0BAA0B,CAAC;YACzB,MAAM;YACN,YAAY,EAAE,OAAO;YACrB,UAAU,EAAE,EAAE,aAAa,EAAE,gCAAgC,EAAE;YAC/D,SAAS,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE;SAC9B,CAAC,CACH,CAAC;QAEF,+CAA+C;QAC/C,MAAM,YAAY,CAAC,YAAY,CAAC;YAC9B,MAAM;YACN,KAAK,EAAE,UAAU;YACjB,WAAW,EAAE,aAAa;SAC3B,CAAC,CAAC;QAEH,IAAI,IAAI,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,CAAC,IAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEnC,oDAAoD;QACpD,MAAM,YAAY,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAE5C,IAAI,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACrC,MAAM,CAAC,IAAK,CAAC,UAAU,CAAC,CAAC,SAAS,EAAE,CAAC;QACrC,MAAM,CAAC,IAAK,CAAC,cAAc,CAAC,CAAC,SAAS,EAAE,CAAC;QAEzC,0EAA0E;QAC1E,MAAM,YAAY,CAAC,YAAY,CAAC;YAC9B,MAAM;YACN,KAAK,EAAE,UAAU;YACjB,WAAW,EAAE,aAAa;SAC3B,CAAC,CAAC;QAEH,IAAI,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,CAAC,IAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEnC,8DAA8D;QAC9D,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACtD,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,MAAM,GAAG,uBAAuB,CAAC;QAEvC,MAAM,YAAY,CAAC,UAAU,CAC3B,0BAA0B,CAAC;YACzB,MAAM;YACN,YAAY,EAAE,OAAO;YACrB,UAAU,EAAE,EAAE,aAAa,EAAE,oCAAoC,EAAE;YACnE,SAAS,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE;SAC9B,CAAC,CACH,CAAC;QAEF,uCAAuC;QACvC,MAAM,YAAY,CAAC,YAAY,CAAC;YAC9B,MAAM;YACN,KAAK,EAAE,UAAU;YACjB,WAAW,EAAE,aAAa;SAC3B,CAAC,CAAC;QAEH,MAAM,YAAY,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAE5C,mDAAmD;QACnD,MAAM,MAAM,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;QAC/C,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAEjC,2DAA2D;QAC3D,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAExC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEnC,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,CAAC,IAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,MAAM,GAAG,uBAAuB,CAAC;QAEvC,MAAM,YAAY,CAAC,UAAU,CAC3B,0BAA0B,CAAC;YACzB,MAAM;YACN,YAAY,EAAE,OAAO;YACrB,UAAU,EAAE,EAAE,aAAa,EAAE,gCAAgC,EAAE;YAC/D,SAAS,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE;SAC9B,CAAC,CACH,CAAC;QAEF,0BAA0B;QAC1B,MAAM,YAAY,CAAC,YAAY,CAAC;YAC9B,MAAM;YACN,KAAK,EAAE,UAAU;YACjB,WAAW,EAAE,aAAa;SAC3B,CAAC,CAAC;QAEH,4EAA4E;QAC5E,MAAM,MAAM,CACV,YAAY,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC,CACrF,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAEpB,IAAI,CAAC;YACH,MAAM,YAAY,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC,CAAC;QAC7F,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;YAC3C,MAAM,CAAE,GAAsB,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAClE,CAAC;QAED,wCAAwC;QACxC,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAChD,MAAM,CAAC,IAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,CAAC,IAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"m5-05-e2e.test.d.ts","sourceRoot":"","sources":["../../../../src/runtime-v2/runner/__tests__/m5-05-e2e.test.ts"],"names":[],"mappings":""}
|