oh-my-codex 0.7.2 → 0.7.3
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/README.md +10 -2
- package/dist/cli/__tests__/session-scoped-runtime.test.js +1 -9
- package/dist/cli/__tests__/session-scoped-runtime.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.d.ts +2 -0
- package/dist/cli/__tests__/uninstall.test.d.ts.map +1 -0
- package/dist/cli/__tests__/uninstall.test.js +454 -0
- package/dist/cli/__tests__/uninstall.test.js.map +1 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +18 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/setup.d.ts +8 -0
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +1 -1
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/uninstall.d.ts +13 -0
- package/dist/cli/uninstall.d.ts.map +1 -0
- package/dist/cli/uninstall.js +317 -0
- package/dist/cli/uninstall.js.map +1 -0
- package/dist/config/__tests__/generator-idempotent.test.d.ts +2 -0
- package/dist/config/__tests__/generator-idempotent.test.d.ts.map +1 -0
- package/dist/config/__tests__/generator-idempotent.test.js +271 -0
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -0
- package/dist/config/generator.d.ts +14 -0
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +107 -2
- package/dist/config/generator.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +54 -0
- package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +78 -0
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +46 -4
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/task-size-detector.test.js +1 -7
- package/dist/hooks/__tests__/task-size-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/tmux-hook-engine.test.js +11 -0
- package/dist/hooks/__tests__/tmux-hook-engine.test.js.map +1 -1
- package/dist/hooks/keyword-detector.js +1 -1
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/keyword-registry.d.ts.map +1 -1
- package/dist/hooks/keyword-registry.js +0 -3
- package/dist/hooks/keyword-registry.js.map +1 -1
- package/dist/hooks/task-size-detector.d.ts.map +1 -1
- package/dist/hooks/task-size-detector.js +0 -2
- package/dist/hooks/task-size-detector.js.map +1 -1
- package/dist/hud/__tests__/index.test.js +0 -2
- package/dist/hud/__tests__/index.test.js.map +1 -1
- package/dist/hud/__tests__/render.test.js +5 -41
- package/dist/hud/__tests__/render.test.js.map +1 -1
- package/dist/hud/render.d.ts.map +1 -1
- package/dist/hud/render.js +0 -15
- package/dist/hud/render.js.map +1 -1
- package/dist/hud/state.d.ts +1 -3
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +2 -12
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/types.d.ts +0 -11
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/hud/types.js.map +1 -1
- package/dist/mcp/__tests__/state-server-schema.test.js +8 -14
- package/dist/mcp/__tests__/state-server-schema.test.js.map +1 -1
- package/dist/mcp/state-server.js +2 -2
- package/dist/mcp/state-server.js.map +1 -1
- package/dist/modes/base.d.ts +9 -2
- package/dist/modes/base.d.ts.map +1 -1
- package/dist/modes/base.js +17 -2
- package/dist/modes/base.js.map +1 -1
- package/dist/notifications/__tests__/template-engine.test.js +11 -0
- package/dist/notifications/__tests__/template-engine.test.js.map +1 -1
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +2 -0
- package/dist/notifications/index.js.map +1 -1
- package/dist/notifications/template-engine.d.ts.map +1 -1
- package/dist/notifications/template-engine.js +3 -0
- package/dist/notifications/template-engine.js.map +1 -1
- package/dist/openclaw/__tests__/dispatcher.test.js +22 -0
- package/dist/openclaw/__tests__/dispatcher.test.js.map +1 -1
- package/dist/openclaw/__tests__/index.test.js +127 -0
- package/dist/openclaw/__tests__/index.test.js.map +1 -1
- package/dist/openclaw/dispatcher.d.ts +3 -0
- package/dist/openclaw/dispatcher.d.ts.map +1 -1
- package/dist/openclaw/dispatcher.js +3 -0
- package/dist/openclaw/dispatcher.js.map +1 -1
- package/dist/openclaw/index.d.ts.map +1 -1
- package/dist/openclaw/index.js +36 -13
- package/dist/openclaw/index.js.map +1 -1
- package/dist/openclaw/types.d.ts +12 -0
- package/dist/openclaw/types.d.ts.map +1 -1
- package/dist/pipeline/__tests__/orchestrator.test.d.ts +2 -0
- package/dist/pipeline/__tests__/orchestrator.test.d.ts.map +1 -0
- package/dist/pipeline/__tests__/orchestrator.test.js +421 -0
- package/dist/pipeline/__tests__/orchestrator.test.js.map +1 -0
- package/dist/pipeline/__tests__/stages.test.d.ts +2 -0
- package/dist/pipeline/__tests__/stages.test.d.ts.map +1 -0
- package/dist/pipeline/__tests__/stages.test.js +199 -0
- package/dist/pipeline/__tests__/stages.test.js.map +1 -0
- package/dist/pipeline/index.d.ts +16 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +13 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/orchestrator.d.ts +50 -0
- package/dist/pipeline/orchestrator.d.ts.map +1 -0
- package/dist/pipeline/orchestrator.js +245 -0
- package/dist/pipeline/orchestrator.js.map +1 -0
- package/dist/pipeline/stages/ralph-verify.d.ts +40 -0
- package/dist/pipeline/stages/ralph-verify.d.ts.map +1 -0
- package/dist/pipeline/stages/ralph-verify.js +62 -0
- package/dist/pipeline/stages/ralph-verify.js.map +1 -0
- package/dist/pipeline/stages/ralplan.d.ts +20 -0
- package/dist/pipeline/stages/ralplan.d.ts.map +1 -0
- package/dist/pipeline/stages/ralplan.js +79 -0
- package/dist/pipeline/stages/ralplan.js.map +1 -0
- package/dist/pipeline/stages/team-exec.d.ts +43 -0
- package/dist/pipeline/stages/team-exec.d.ts.map +1 -0
- package/dist/pipeline/stages/team-exec.js +70 -0
- package/dist/pipeline/stages/team-exec.js.map +1 -0
- package/dist/pipeline/types.d.ts +115 -0
- package/dist/pipeline/types.d.ts.map +1 -0
- package/dist/pipeline/types.js +8 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/team/__tests__/state.test.js +47 -1
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +102 -11
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +64 -25
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +9 -1
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state.d.ts +1 -0
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +30 -7
- package/dist/team/state.js.map +1 -1
- package/dist/team/team-ops.d.ts +1 -0
- package/dist/team/team-ops.d.ts.map +1 -1
- package/dist/team/team-ops.js +2 -0
- package/dist/team/team-ops.js.map +1 -1
- package/dist/team/tmux-session.d.ts +7 -0
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +93 -8
- package/dist/team/tmux-session.js.map +1 -1
- package/package.json +1 -1
- package/scripts/notify-hook/team-dispatch.js +83 -2
- package/scripts/notify-hook/team-worker.js +78 -6
- package/scripts/tmux-hook-engine.js +12 -7
- package/skills/autopilot/SKILL.md +21 -0
- package/skills/pipeline/SKILL.md +86 -0
- package/skills/team/SKILL.md +22 -1
- package/templates/catalog-manifest.json +1 -1
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdtemp, rm, readFile } from 'fs/promises';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { tmpdir } from 'os';
|
|
6
|
+
import { existsSync } from 'fs';
|
|
7
|
+
import { runPipeline, canResumePipeline, readPipelineState, cancelPipeline, createAutopilotPipelineConfig, } from '../orchestrator.js';
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Helpers
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
function makeStage(name, result = {}, opts) {
|
|
12
|
+
return {
|
|
13
|
+
name,
|
|
14
|
+
canSkip: opts?.canSkip,
|
|
15
|
+
async run(_ctx) {
|
|
16
|
+
if (opts?.delay)
|
|
17
|
+
await new Promise((r) => setTimeout(r, opts.delay));
|
|
18
|
+
return {
|
|
19
|
+
status: 'completed',
|
|
20
|
+
artifacts: { produced_by: name },
|
|
21
|
+
duration_ms: 0,
|
|
22
|
+
...result,
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function makeFailingStage(name, error) {
|
|
28
|
+
return {
|
|
29
|
+
name,
|
|
30
|
+
async run() {
|
|
31
|
+
return {
|
|
32
|
+
status: 'failed',
|
|
33
|
+
artifacts: {},
|
|
34
|
+
duration_ms: 0,
|
|
35
|
+
error,
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function makeThrowingStage(name, message) {
|
|
41
|
+
return {
|
|
42
|
+
name,
|
|
43
|
+
async run() {
|
|
44
|
+
throw new Error(message);
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
let tempDir;
|
|
49
|
+
async function setup() {
|
|
50
|
+
tempDir = await mkdtemp(join(tmpdir(), 'omx-pipeline-test-'));
|
|
51
|
+
return tempDir;
|
|
52
|
+
}
|
|
53
|
+
async function cleanup() {
|
|
54
|
+
if (tempDir && existsSync(tempDir)) {
|
|
55
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
// Tests
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
describe('Pipeline Orchestrator', () => {
|
|
62
|
+
beforeEach(async () => {
|
|
63
|
+
await setup();
|
|
64
|
+
});
|
|
65
|
+
afterEach(async () => {
|
|
66
|
+
await cleanup();
|
|
67
|
+
});
|
|
68
|
+
describe('runPipeline', () => {
|
|
69
|
+
it('runs a single-stage pipeline to completion', async () => {
|
|
70
|
+
const config = {
|
|
71
|
+
name: 'test-single',
|
|
72
|
+
task: 'test task',
|
|
73
|
+
stages: [makeStage('stage-a')],
|
|
74
|
+
cwd: tempDir,
|
|
75
|
+
};
|
|
76
|
+
const result = await runPipeline(config);
|
|
77
|
+
assert.equal(result.status, 'completed');
|
|
78
|
+
assert.ok(result.stageResults['stage-a']);
|
|
79
|
+
assert.equal(result.stageResults['stage-a'].status, 'completed');
|
|
80
|
+
assert.ok(result.duration_ms >= 0);
|
|
81
|
+
});
|
|
82
|
+
it('runs a multi-stage pipeline sequentially', async () => {
|
|
83
|
+
const order = [];
|
|
84
|
+
const stages = ['a', 'b', 'c'].map((name) => ({
|
|
85
|
+
name: `stage-${name}`,
|
|
86
|
+
async run(ctx) {
|
|
87
|
+
order.push(`stage-${name}`);
|
|
88
|
+
return {
|
|
89
|
+
status: 'completed',
|
|
90
|
+
artifacts: { step: name, prevArtifacts: Object.keys(ctx.artifacts) },
|
|
91
|
+
duration_ms: 0,
|
|
92
|
+
};
|
|
93
|
+
},
|
|
94
|
+
}));
|
|
95
|
+
const result = await runPipeline({
|
|
96
|
+
name: 'test-multi',
|
|
97
|
+
task: 'multi-stage test',
|
|
98
|
+
stages,
|
|
99
|
+
cwd: tempDir,
|
|
100
|
+
});
|
|
101
|
+
assert.equal(result.status, 'completed');
|
|
102
|
+
assert.deepEqual(order, ['stage-a', 'stage-b', 'stage-c']);
|
|
103
|
+
assert.equal(Object.keys(result.stageResults).length, 3);
|
|
104
|
+
});
|
|
105
|
+
it('passes artifacts between stages', async () => {
|
|
106
|
+
let receivedArtifacts = {};
|
|
107
|
+
const stages = [
|
|
108
|
+
{
|
|
109
|
+
name: 'producer',
|
|
110
|
+
async run() {
|
|
111
|
+
return {
|
|
112
|
+
status: 'completed',
|
|
113
|
+
artifacts: { data: 'from-producer' },
|
|
114
|
+
duration_ms: 0,
|
|
115
|
+
};
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: 'consumer',
|
|
120
|
+
async run(ctx) {
|
|
121
|
+
receivedArtifacts = ctx.artifacts;
|
|
122
|
+
return { status: 'completed', artifacts: {}, duration_ms: 0 };
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
];
|
|
126
|
+
await runPipeline({ name: 'artifact-test', task: 'test', stages, cwd: tempDir });
|
|
127
|
+
assert.ok(receivedArtifacts['producer']);
|
|
128
|
+
assert.deepEqual(receivedArtifacts['producer'].data, 'from-producer');
|
|
129
|
+
});
|
|
130
|
+
it('stops pipeline on stage failure and reports failed stage', async () => {
|
|
131
|
+
const stages = [
|
|
132
|
+
makeStage('ok-stage'),
|
|
133
|
+
makeFailingStage('bad-stage', 'something broke'),
|
|
134
|
+
makeStage('never-reached'),
|
|
135
|
+
];
|
|
136
|
+
const result = await runPipeline({
|
|
137
|
+
name: 'fail-test',
|
|
138
|
+
task: 'test',
|
|
139
|
+
stages,
|
|
140
|
+
cwd: tempDir,
|
|
141
|
+
});
|
|
142
|
+
assert.equal(result.status, 'failed');
|
|
143
|
+
assert.equal(result.failedStage, 'bad-stage');
|
|
144
|
+
assert.equal(result.error, 'something broke');
|
|
145
|
+
assert.ok(result.stageResults['ok-stage']);
|
|
146
|
+
assert.ok(result.stageResults['bad-stage']);
|
|
147
|
+
assert.equal(result.stageResults['never-reached'], undefined);
|
|
148
|
+
});
|
|
149
|
+
it('catches thrown errors and converts to failed result', async () => {
|
|
150
|
+
const stages = [makeThrowingStage('throwing', 'kaboom')];
|
|
151
|
+
const result = await runPipeline({
|
|
152
|
+
name: 'throw-test',
|
|
153
|
+
task: 'test',
|
|
154
|
+
stages,
|
|
155
|
+
cwd: tempDir,
|
|
156
|
+
});
|
|
157
|
+
assert.equal(result.status, 'failed');
|
|
158
|
+
assert.equal(result.failedStage, 'throwing');
|
|
159
|
+
assert.match(result.error, /kaboom/);
|
|
160
|
+
});
|
|
161
|
+
it('skips stages when canSkip returns true', async () => {
|
|
162
|
+
const ran = [];
|
|
163
|
+
const stages = [
|
|
164
|
+
makeStage('always-run'),
|
|
165
|
+
{
|
|
166
|
+
name: 'skippable',
|
|
167
|
+
canSkip: () => true,
|
|
168
|
+
async run() {
|
|
169
|
+
ran.push('skippable');
|
|
170
|
+
return { status: 'completed', artifacts: {}, duration_ms: 0 };
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
name: 'after-skip',
|
|
175
|
+
async run() {
|
|
176
|
+
ran.push('after-skip');
|
|
177
|
+
return { status: 'completed', artifacts: {}, duration_ms: 0 };
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
];
|
|
181
|
+
const result = await runPipeline({
|
|
182
|
+
name: 'skip-test',
|
|
183
|
+
task: 'test',
|
|
184
|
+
stages,
|
|
185
|
+
cwd: tempDir,
|
|
186
|
+
});
|
|
187
|
+
assert.equal(result.status, 'completed');
|
|
188
|
+
assert.equal(result.stageResults['skippable'].status, 'skipped');
|
|
189
|
+
assert.ok(!ran.includes('skippable'));
|
|
190
|
+
assert.ok(ran.includes('after-skip'));
|
|
191
|
+
});
|
|
192
|
+
it('fires onStageTransition callback', async () => {
|
|
193
|
+
const transitions = [];
|
|
194
|
+
const stages = [makeStage('a'), makeStage('b'), makeStage('c')];
|
|
195
|
+
await runPipeline({
|
|
196
|
+
name: 'transition-test',
|
|
197
|
+
task: 'test',
|
|
198
|
+
stages,
|
|
199
|
+
cwd: tempDir,
|
|
200
|
+
onStageTransition: (from, to) => transitions.push([from, to]),
|
|
201
|
+
});
|
|
202
|
+
assert.deepEqual(transitions, [
|
|
203
|
+
['a', 'b'],
|
|
204
|
+
['b', 'c'],
|
|
205
|
+
]);
|
|
206
|
+
});
|
|
207
|
+
it('fires correct transitions when middle stage is skipped', async () => {
|
|
208
|
+
const transitions = [];
|
|
209
|
+
const stages = [
|
|
210
|
+
makeStage('a'),
|
|
211
|
+
{
|
|
212
|
+
name: 'b-skipped',
|
|
213
|
+
canSkip: () => true,
|
|
214
|
+
async run() {
|
|
215
|
+
return { status: 'completed', artifacts: {}, duration_ms: 0 };
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
makeStage('c'),
|
|
219
|
+
];
|
|
220
|
+
await runPipeline({
|
|
221
|
+
name: 'skip-transition-test',
|
|
222
|
+
task: 'test',
|
|
223
|
+
stages,
|
|
224
|
+
cwd: tempDir,
|
|
225
|
+
onStageTransition: (from, to) => transitions.push([from, to]),
|
|
226
|
+
});
|
|
227
|
+
assert.deepEqual(transitions, [
|
|
228
|
+
['a', 'b-skipped'],
|
|
229
|
+
['b-skipped', 'c'],
|
|
230
|
+
]);
|
|
231
|
+
});
|
|
232
|
+
it('passes previousStageResult to the next stage', async () => {
|
|
233
|
+
let receivedPrevResult;
|
|
234
|
+
const stages = [
|
|
235
|
+
{
|
|
236
|
+
name: 'first',
|
|
237
|
+
async run() {
|
|
238
|
+
return {
|
|
239
|
+
status: 'completed',
|
|
240
|
+
artifacts: { marker: 'first-stage' },
|
|
241
|
+
duration_ms: 42,
|
|
242
|
+
};
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
name: 'second',
|
|
247
|
+
async run(ctx) {
|
|
248
|
+
receivedPrevResult = ctx.previousStageResult;
|
|
249
|
+
return { status: 'completed', artifacts: {}, duration_ms: 0 };
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
];
|
|
253
|
+
await runPipeline({ name: 'prev-result-test', task: 'test', stages, cwd: tempDir });
|
|
254
|
+
assert.ok(receivedPrevResult);
|
|
255
|
+
assert.equal(receivedPrevResult.status, 'completed');
|
|
256
|
+
assert.deepEqual(receivedPrevResult.artifacts, { marker: 'first-stage' });
|
|
257
|
+
});
|
|
258
|
+
it('persists pipeline state to mode state file', async () => {
|
|
259
|
+
await runPipeline({
|
|
260
|
+
name: 'persist-test',
|
|
261
|
+
task: 'persistence check',
|
|
262
|
+
stages: [makeStage('only')],
|
|
263
|
+
cwd: tempDir,
|
|
264
|
+
});
|
|
265
|
+
const statePath = join(tempDir, '.omx', 'state', 'autopilot-state.json');
|
|
266
|
+
assert.ok(existsSync(statePath), 'pipeline state file should exist');
|
|
267
|
+
const raw = await readFile(statePath, 'utf-8');
|
|
268
|
+
const state = JSON.parse(raw);
|
|
269
|
+
assert.equal(state.active, false);
|
|
270
|
+
assert.equal(state.current_phase, 'complete');
|
|
271
|
+
assert.equal(state.pipeline_name, 'persist-test');
|
|
272
|
+
});
|
|
273
|
+
it('persists failed state with error', async () => {
|
|
274
|
+
await runPipeline({
|
|
275
|
+
name: 'fail-persist',
|
|
276
|
+
task: 'will fail',
|
|
277
|
+
stages: [makeFailingStage('failing', 'oops')],
|
|
278
|
+
cwd: tempDir,
|
|
279
|
+
});
|
|
280
|
+
const statePath = join(tempDir, '.omx', 'state', 'autopilot-state.json');
|
|
281
|
+
const raw = await readFile(statePath, 'utf-8');
|
|
282
|
+
const state = JSON.parse(raw);
|
|
283
|
+
assert.equal(state.active, false);
|
|
284
|
+
assert.equal(state.current_phase, 'failed');
|
|
285
|
+
assert.equal(state.error, 'oops');
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
describe('validation', () => {
|
|
289
|
+
it('rejects config with empty name', async () => {
|
|
290
|
+
await assert.rejects(() => runPipeline({ name: '', task: 'x', stages: [makeStage('a')], cwd: tempDir }), /non-empty name/);
|
|
291
|
+
});
|
|
292
|
+
it('rejects config with empty task', async () => {
|
|
293
|
+
await assert.rejects(() => runPipeline({ name: 'x', task: '', stages: [makeStage('a')], cwd: tempDir }), /non-empty task/);
|
|
294
|
+
});
|
|
295
|
+
it('rejects config with no stages', async () => {
|
|
296
|
+
await assert.rejects(() => runPipeline({ name: 'x', task: 'x', stages: [], cwd: tempDir }), /at least one stage/);
|
|
297
|
+
});
|
|
298
|
+
it('rejects duplicate stage names', async () => {
|
|
299
|
+
await assert.rejects(() => runPipeline({
|
|
300
|
+
name: 'x',
|
|
301
|
+
task: 'x',
|
|
302
|
+
stages: [makeStage('dup'), makeStage('dup')],
|
|
303
|
+
cwd: tempDir,
|
|
304
|
+
}), /Duplicate stage name/);
|
|
305
|
+
});
|
|
306
|
+
it('rejects non-positive maxRalphIterations', async () => {
|
|
307
|
+
await assert.rejects(() => runPipeline({
|
|
308
|
+
name: 'x',
|
|
309
|
+
task: 'x',
|
|
310
|
+
stages: [makeStage('a')],
|
|
311
|
+
cwd: tempDir,
|
|
312
|
+
maxRalphIterations: 0,
|
|
313
|
+
}), /maxRalphIterations must be a positive integer/);
|
|
314
|
+
});
|
|
315
|
+
it('rejects non-positive workerCount', async () => {
|
|
316
|
+
await assert.rejects(() => runPipeline({
|
|
317
|
+
name: 'x',
|
|
318
|
+
task: 'x',
|
|
319
|
+
stages: [makeStage('a')],
|
|
320
|
+
cwd: tempDir,
|
|
321
|
+
workerCount: -1,
|
|
322
|
+
}), /workerCount must be a positive integer/);
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
describe('canResumePipeline', () => {
|
|
326
|
+
it('returns false when no state exists', async () => {
|
|
327
|
+
assert.equal(await canResumePipeline(tempDir), false);
|
|
328
|
+
});
|
|
329
|
+
it('returns false after completed pipeline', async () => {
|
|
330
|
+
await runPipeline({
|
|
331
|
+
name: 'complete',
|
|
332
|
+
task: 'test',
|
|
333
|
+
stages: [makeStage('a')],
|
|
334
|
+
cwd: tempDir,
|
|
335
|
+
});
|
|
336
|
+
assert.equal(await canResumePipeline(tempDir), false);
|
|
337
|
+
});
|
|
338
|
+
it('returns false after failed pipeline', async () => {
|
|
339
|
+
await runPipeline({
|
|
340
|
+
name: 'fail',
|
|
341
|
+
task: 'test',
|
|
342
|
+
stages: [makeFailingStage('bad', 'err')],
|
|
343
|
+
cwd: tempDir,
|
|
344
|
+
});
|
|
345
|
+
assert.equal(await canResumePipeline(tempDir), false);
|
|
346
|
+
});
|
|
347
|
+
it('returns true when pipeline state is active and in-progress', async () => {
|
|
348
|
+
// Manually write an in-progress pipeline state
|
|
349
|
+
const { mkdir: mkdirFs, writeFile: writeFileFs } = await import('fs/promises');
|
|
350
|
+
const stateDir = join(tempDir, '.omx', 'state');
|
|
351
|
+
await mkdirFs(stateDir, { recursive: true });
|
|
352
|
+
await writeFileFs(join(stateDir, 'autopilot-state.json'), JSON.stringify({
|
|
353
|
+
active: true,
|
|
354
|
+
mode: 'autopilot',
|
|
355
|
+
iteration: 1,
|
|
356
|
+
max_iterations: 3,
|
|
357
|
+
current_phase: 'stage:team-exec',
|
|
358
|
+
pipeline_name: 'resume-test',
|
|
359
|
+
started_at: new Date().toISOString(),
|
|
360
|
+
}));
|
|
361
|
+
assert.equal(await canResumePipeline(tempDir), true);
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
describe('readPipelineState', () => {
|
|
365
|
+
it('returns null when no state exists', async () => {
|
|
366
|
+
assert.equal(await readPipelineState(tempDir), null);
|
|
367
|
+
});
|
|
368
|
+
it('returns extension fields after a run', async () => {
|
|
369
|
+
await runPipeline({
|
|
370
|
+
name: 'read-test',
|
|
371
|
+
task: 'read task',
|
|
372
|
+
stages: [makeStage('s1'), makeStage('s2')],
|
|
373
|
+
cwd: tempDir,
|
|
374
|
+
maxRalphIterations: 5,
|
|
375
|
+
workerCount: 3,
|
|
376
|
+
agentType: 'analyst',
|
|
377
|
+
});
|
|
378
|
+
const ext = await readPipelineState(tempDir);
|
|
379
|
+
assert.ok(ext);
|
|
380
|
+
assert.equal(ext.pipeline_name, 'read-test');
|
|
381
|
+
assert.deepEqual(ext.pipeline_stages, ['s1', 's2']);
|
|
382
|
+
assert.equal(ext.pipeline_max_ralph_iterations, 5);
|
|
383
|
+
assert.equal(ext.pipeline_worker_count, 3);
|
|
384
|
+
assert.equal(ext.pipeline_agent_type, 'analyst');
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
describe('cancelPipeline', () => {
|
|
388
|
+
it('does not throw when no state exists', async () => {
|
|
389
|
+
await assert.doesNotReject(() => cancelPipeline(tempDir));
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
describe('createAutopilotPipelineConfig', () => {
|
|
393
|
+
it('creates config with default values', () => {
|
|
394
|
+
const stages = [makeStage('a')];
|
|
395
|
+
const config = createAutopilotPipelineConfig('build feature X', { stages });
|
|
396
|
+
assert.equal(config.name, 'autopilot');
|
|
397
|
+
assert.equal(config.task, 'build feature X');
|
|
398
|
+
assert.equal(config.maxRalphIterations, 10);
|
|
399
|
+
assert.equal(config.workerCount, 2);
|
|
400
|
+
assert.equal(config.agentType, 'executor');
|
|
401
|
+
assert.equal(config.stages.length, 1);
|
|
402
|
+
});
|
|
403
|
+
it('accepts custom overrides', () => {
|
|
404
|
+
const stages = [makeStage('a'), makeStage('b')];
|
|
405
|
+
const config = createAutopilotPipelineConfig('task', {
|
|
406
|
+
stages,
|
|
407
|
+
maxRalphIterations: 20,
|
|
408
|
+
workerCount: 4,
|
|
409
|
+
agentType: 'architect',
|
|
410
|
+
cwd: '/tmp/test',
|
|
411
|
+
sessionId: 'session-1',
|
|
412
|
+
});
|
|
413
|
+
assert.equal(config.maxRalphIterations, 20);
|
|
414
|
+
assert.equal(config.workerCount, 4);
|
|
415
|
+
assert.equal(config.agentType, 'architect');
|
|
416
|
+
assert.equal(config.cwd, '/tmp/test');
|
|
417
|
+
assert.equal(config.sessionId, 'session-1');
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
//# sourceMappingURL=orchestrator.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.test.js","sourceRoot":"","sources":["../../../src/pipeline/__tests__/orchestrator.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stages.test.d.ts","sourceRoot":"","sources":["../../../src/pipeline/__tests__/stages.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdtemp, rm, mkdir, writeFile } from 'fs/promises';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { tmpdir } from 'os';
|
|
6
|
+
import { existsSync } from 'fs';
|
|
7
|
+
import { createRalplanStage } from '../stages/ralplan.js';
|
|
8
|
+
import { createTeamExecStage, buildTeamInstruction } from '../stages/team-exec.js';
|
|
9
|
+
import { createRalphVerifyStage, buildRalphInstruction } from '../stages/ralph-verify.js';
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// Helpers
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
let tempDir;
|
|
14
|
+
function makeCtx(overrides = {}) {
|
|
15
|
+
return {
|
|
16
|
+
task: 'test task',
|
|
17
|
+
artifacts: {},
|
|
18
|
+
cwd: tempDir,
|
|
19
|
+
...overrides,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async function setup() {
|
|
23
|
+
tempDir = await mkdtemp(join(tmpdir(), 'omx-stages-test-'));
|
|
24
|
+
return tempDir;
|
|
25
|
+
}
|
|
26
|
+
async function cleanup() {
|
|
27
|
+
if (tempDir && existsSync(tempDir)) {
|
|
28
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// RALPLAN stage tests
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
describe('RALPLAN Stage', () => {
|
|
35
|
+
beforeEach(async () => { await setup(); });
|
|
36
|
+
afterEach(async () => { await cleanup(); });
|
|
37
|
+
it('creates a stage with the correct name', () => {
|
|
38
|
+
const stage = createRalplanStage();
|
|
39
|
+
assert.equal(stage.name, 'ralplan');
|
|
40
|
+
});
|
|
41
|
+
it('runs successfully and produces artifacts', async () => {
|
|
42
|
+
const stage = createRalplanStage();
|
|
43
|
+
const result = await stage.run(makeCtx());
|
|
44
|
+
assert.equal(result.status, 'completed');
|
|
45
|
+
assert.equal(result.artifacts.stage, 'ralplan');
|
|
46
|
+
assert.ok(result.artifacts.instruction);
|
|
47
|
+
});
|
|
48
|
+
it('canSkip returns false when no plans directory exists', () => {
|
|
49
|
+
const stage = createRalplanStage();
|
|
50
|
+
assert.equal(stage.canSkip(makeCtx()), false);
|
|
51
|
+
});
|
|
52
|
+
it('canSkip returns false when plans directory is empty', async () => {
|
|
53
|
+
const plansDir = join(tempDir, '.omx', 'plans');
|
|
54
|
+
await mkdir(plansDir, { recursive: true });
|
|
55
|
+
const stage = createRalplanStage();
|
|
56
|
+
assert.equal(stage.canSkip(makeCtx()), false);
|
|
57
|
+
});
|
|
58
|
+
it('canSkip returns true when a prd- plan file exists', async () => {
|
|
59
|
+
const plansDir = join(tempDir, '.omx', 'plans');
|
|
60
|
+
await mkdir(plansDir, { recursive: true });
|
|
61
|
+
await writeFile(join(plansDir, 'prd-my-feature.md'), '# Plan\n');
|
|
62
|
+
const stage = createRalplanStage();
|
|
63
|
+
assert.equal(stage.canSkip(makeCtx()), true);
|
|
64
|
+
});
|
|
65
|
+
it('canSkip returns false for non-prd plan files', async () => {
|
|
66
|
+
const plansDir = join(tempDir, '.omx', 'plans');
|
|
67
|
+
await mkdir(plansDir, { recursive: true });
|
|
68
|
+
await writeFile(join(plansDir, 'autopilot-spec.md'), '# Spec\n');
|
|
69
|
+
const stage = createRalplanStage();
|
|
70
|
+
assert.equal(stage.canSkip(makeCtx()), false);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// Team exec stage tests
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
describe('Team Exec Stage', () => {
|
|
77
|
+
beforeEach(async () => { await setup(); });
|
|
78
|
+
afterEach(async () => { await cleanup(); });
|
|
79
|
+
it('creates a stage with the correct name', () => {
|
|
80
|
+
const stage = createTeamExecStage();
|
|
81
|
+
assert.equal(stage.name, 'team-exec');
|
|
82
|
+
});
|
|
83
|
+
it('uses default worker count and agent type', async () => {
|
|
84
|
+
const stage = createTeamExecStage();
|
|
85
|
+
const result = await stage.run(makeCtx());
|
|
86
|
+
assert.equal(result.status, 'completed');
|
|
87
|
+
const arts = result.artifacts;
|
|
88
|
+
assert.equal(arts.workerCount, 2);
|
|
89
|
+
assert.equal(arts.agentType, 'executor');
|
|
90
|
+
});
|
|
91
|
+
it('respects custom worker count and agent type', async () => {
|
|
92
|
+
const stage = createTeamExecStage({ workerCount: 4, agentType: 'architect' });
|
|
93
|
+
const result = await stage.run(makeCtx());
|
|
94
|
+
const arts = result.artifacts;
|
|
95
|
+
assert.equal(arts.workerCount, 4);
|
|
96
|
+
assert.equal(arts.agentType, 'architect');
|
|
97
|
+
});
|
|
98
|
+
it('includes ralplan artifacts in team task when available', async () => {
|
|
99
|
+
const stage = createTeamExecStage();
|
|
100
|
+
const ctx = makeCtx({
|
|
101
|
+
artifacts: {
|
|
102
|
+
ralplan: { data: 'plan-content', stage: 'ralplan' },
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
const result = await stage.run(ctx);
|
|
106
|
+
const descriptor = result.artifacts.teamDescriptor;
|
|
107
|
+
assert.ok(descriptor.task.includes('plan-content'));
|
|
108
|
+
});
|
|
109
|
+
it('falls back to raw task when no ralplan artifacts exist', async () => {
|
|
110
|
+
const stage = createTeamExecStage();
|
|
111
|
+
const result = await stage.run(makeCtx({ task: 'raw task description' }));
|
|
112
|
+
const descriptor = result.artifacts.teamDescriptor;
|
|
113
|
+
assert.equal(descriptor.task, 'raw task description');
|
|
114
|
+
});
|
|
115
|
+
describe('buildTeamInstruction', () => {
|
|
116
|
+
it('builds correct CLI instruction', () => {
|
|
117
|
+
const instruction = buildTeamInstruction({
|
|
118
|
+
task: 'implement feature',
|
|
119
|
+
workerCount: 3,
|
|
120
|
+
agentType: 'executor',
|
|
121
|
+
useWorktrees: false,
|
|
122
|
+
cwd: '/tmp/test',
|
|
123
|
+
});
|
|
124
|
+
assert.match(instruction, /^omx team 3:executor/);
|
|
125
|
+
assert.match(instruction, /implement feature/);
|
|
126
|
+
});
|
|
127
|
+
it('truncates long task descriptions', () => {
|
|
128
|
+
const longTask = 'a'.repeat(1000);
|
|
129
|
+
const instruction = buildTeamInstruction({
|
|
130
|
+
task: longTask,
|
|
131
|
+
workerCount: 1,
|
|
132
|
+
agentType: 'executor',
|
|
133
|
+
useWorktrees: false,
|
|
134
|
+
cwd: '/tmp',
|
|
135
|
+
});
|
|
136
|
+
// The instruction should contain a truncated version (500 chars max)
|
|
137
|
+
assert.ok(instruction.length < longTask.length);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
// ---------------------------------------------------------------------------
|
|
142
|
+
// Ralph verify stage tests
|
|
143
|
+
// ---------------------------------------------------------------------------
|
|
144
|
+
describe('Ralph Verify Stage', () => {
|
|
145
|
+
beforeEach(async () => { await setup(); });
|
|
146
|
+
afterEach(async () => { await cleanup(); });
|
|
147
|
+
it('creates a stage with the correct name', () => {
|
|
148
|
+
const stage = createRalphVerifyStage();
|
|
149
|
+
assert.equal(stage.name, 'ralph-verify');
|
|
150
|
+
});
|
|
151
|
+
it('uses default max iterations of 10', async () => {
|
|
152
|
+
const stage = createRalphVerifyStage();
|
|
153
|
+
const result = await stage.run(makeCtx());
|
|
154
|
+
assert.equal(result.status, 'completed');
|
|
155
|
+
const arts = result.artifacts;
|
|
156
|
+
assert.equal(arts.maxIterations, 10);
|
|
157
|
+
});
|
|
158
|
+
it('respects custom max iterations', async () => {
|
|
159
|
+
const stage = createRalphVerifyStage({ maxIterations: 25 });
|
|
160
|
+
const result = await stage.run(makeCtx());
|
|
161
|
+
const arts = result.artifacts;
|
|
162
|
+
assert.equal(arts.maxIterations, 25);
|
|
163
|
+
});
|
|
164
|
+
it('includes team-exec artifacts in verification context', async () => {
|
|
165
|
+
const stage = createRalphVerifyStage();
|
|
166
|
+
const ctx = makeCtx({
|
|
167
|
+
artifacts: {
|
|
168
|
+
'team-exec': { teamDescriptor: { task: 'completed work' } },
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
const result = await stage.run(ctx);
|
|
172
|
+
const descriptor = result.artifacts.verifyDescriptor;
|
|
173
|
+
const execArtifacts = descriptor.executionArtifacts;
|
|
174
|
+
assert.ok(execArtifacts.teamDescriptor);
|
|
175
|
+
});
|
|
176
|
+
describe('buildRalphInstruction', () => {
|
|
177
|
+
it('includes max iterations in instruction', () => {
|
|
178
|
+
const instruction = buildRalphInstruction({
|
|
179
|
+
task: 'verify feature',
|
|
180
|
+
maxIterations: 15,
|
|
181
|
+
cwd: '/tmp',
|
|
182
|
+
executionArtifacts: {},
|
|
183
|
+
});
|
|
184
|
+
assert.match(instruction, /max 15 iterations/);
|
|
185
|
+
assert.match(instruction, /verify feature/);
|
|
186
|
+
});
|
|
187
|
+
it('truncates long task descriptions', () => {
|
|
188
|
+
const longTask = 'b'.repeat(500);
|
|
189
|
+
const instruction = buildRalphInstruction({
|
|
190
|
+
task: longTask,
|
|
191
|
+
maxIterations: 10,
|
|
192
|
+
cwd: '/tmp',
|
|
193
|
+
executionArtifacts: {},
|
|
194
|
+
});
|
|
195
|
+
assert.ok(instruction.length < longTask.length);
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
//# sourceMappingURL=stages.test.js.map
|