oh-my-claude-sisyphus 3.5.8 → 3.6.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/agents/executor-high.md +2 -0
- package/agents/executor-low.md +2 -0
- package/agents/executor.md +2 -0
- package/agents/templates/base-agent.md +9 -0
- package/commands/cancel.md +8 -8
- package/commands/swarm.md +350 -148
- package/dist/__tests__/hooks.test.js +10 -9
- package/dist/__tests__/hooks.test.js.map +1 -1
- package/dist/agents/codex-agents.d.ts +20 -0
- package/dist/agents/codex-agents.d.ts.map +1 -0
- package/dist/agents/codex-agents.js +36 -0
- package/dist/agents/codex-agents.js.map +1 -0
- package/dist/agents/preamble.d.ts +14 -0
- package/dist/agents/preamble.d.ts.map +1 -0
- package/dist/agents/preamble.js +26 -0
- package/dist/agents/preamble.js.map +1 -0
- package/dist/hooks/autopilot/__tests__/cancel.test.js +14 -4
- package/dist/hooks/autopilot/__tests__/cancel.test.js.map +1 -1
- package/dist/hooks/autopilot/__tests__/state.test.js +1 -0
- package/dist/hooks/autopilot/__tests__/state.test.js.map +1 -1
- package/dist/hooks/autopilot/__tests__/summary.test.js +38 -3
- package/dist/hooks/autopilot/__tests__/summary.test.js.map +1 -1
- package/dist/hooks/autopilot/state.d.ts +1 -1
- package/dist/hooks/autopilot/state.d.ts.map +1 -1
- package/dist/hooks/autopilot/state.js +15 -8
- package/dist/hooks/autopilot/state.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +7 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/mode-registry/index.d.ts +135 -0
- package/dist/hooks/mode-registry/index.d.ts.map +1 -0
- package/dist/hooks/mode-registry/index.js +445 -0
- package/dist/hooks/mode-registry/index.js.map +1 -0
- package/dist/hooks/mode-registry/types.d.ts +31 -0
- package/dist/hooks/mode-registry/types.d.ts.map +1 -0
- package/dist/hooks/mode-registry/types.js +7 -0
- package/dist/hooks/mode-registry/types.js.map +1 -0
- package/dist/hooks/ralph/loop.js +6 -6
- package/dist/hooks/ralph/loop.js.map +1 -1
- package/dist/hooks/swarm/__tests__/claiming.test.d.ts +2 -0
- package/dist/hooks/swarm/__tests__/claiming.test.d.ts.map +1 -0
- package/dist/hooks/swarm/__tests__/claiming.test.js +170 -0
- package/dist/hooks/swarm/__tests__/claiming.test.js.map +1 -0
- package/dist/hooks/swarm/__tests__/index.test.d.ts +2 -0
- package/dist/hooks/swarm/__tests__/index.test.d.ts.map +1 -0
- package/dist/hooks/swarm/__tests__/index.test.js +157 -0
- package/dist/hooks/swarm/__tests__/index.test.js.map +1 -0
- package/dist/hooks/swarm/__tests__/mode-registry.test.d.ts +2 -0
- package/dist/hooks/swarm/__tests__/mode-registry.test.d.ts.map +1 -0
- package/dist/hooks/swarm/__tests__/mode-registry.test.js +177 -0
- package/dist/hooks/swarm/__tests__/mode-registry.test.js.map +1 -0
- package/dist/hooks/swarm/claiming.d.ts +101 -0
- package/dist/hooks/swarm/claiming.d.ts.map +1 -0
- package/dist/hooks/swarm/claiming.js +460 -0
- package/dist/hooks/swarm/claiming.js.map +1 -0
- package/dist/hooks/swarm/index.d.ts +221 -0
- package/dist/hooks/swarm/index.d.ts.map +1 -0
- package/dist/hooks/swarm/index.js +413 -0
- package/dist/hooks/swarm/index.js.map +1 -0
- package/dist/hooks/swarm/state.d.ts +94 -0
- package/dist/hooks/swarm/state.d.ts.map +1 -0
- package/dist/hooks/swarm/state.js +530 -0
- package/dist/hooks/swarm/state.js.map +1 -0
- package/dist/hooks/swarm/types.d.ts +116 -0
- package/dist/hooks/swarm/types.d.ts.map +1 -0
- package/dist/hooks/swarm/types.js +22 -0
- package/dist/hooks/swarm/types.js.map +1 -0
- package/dist/hooks/ultrapilot/decomposer.d.ts +141 -0
- package/dist/hooks/ultrapilot/decomposer.d.ts.map +1 -0
- package/dist/hooks/ultrapilot/decomposer.js +377 -0
- package/dist/hooks/ultrapilot/decomposer.js.map +1 -0
- package/dist/hooks/ultrapilot/index.d.ts +31 -0
- package/dist/hooks/ultrapilot/index.d.ts.map +1 -1
- package/dist/hooks/ultrapilot/index.js +43 -2
- package/dist/hooks/ultrapilot/index.js.map +1 -1
- package/dist/hooks/ultrapilot/state.d.ts +1 -1
- package/dist/hooks/ultrapilot/state.d.ts.map +1 -1
- package/dist/hooks/ultrapilot/state.js +7 -0
- package/dist/hooks/ultrapilot/state.js.map +1 -1
- package/dist/hooks/ultraqa/index.js +5 -5
- package/dist/hooks/ultraqa/index.js.map +1 -1
- package/dist/hooks/ultrawork/index.js +3 -3
- package/dist/hooks/ultrawork/index.js.map +1 -1
- package/package.json +3 -1
- package/skills/autopilot/SKILL.md +18 -0
- package/skills/cancel/SKILL.md +166 -141
- package/skills/ecomode/SKILL.md +14 -0
- package/skills/pipeline/SKILL.md +13 -0
- package/skills/ralph/SKILL.md +22 -1
- package/skills/swarm/SKILL.md +521 -197
- package/skills/ultrapilot/SKILL.md +82 -13
- package/skills/ultraqa/SKILL.md +13 -0
- package/skills/ultrawork/SKILL.md +14 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
|
+
import { mkdtempSync, rmSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { tmpdir } from 'os';
|
|
5
|
+
import { initDb, closeDb, initSession, addTasks, getHeartbeats } from '../state.js';
|
|
6
|
+
import { claimTask, cleanupStaleClaims, heartbeat } from '../claiming.js';
|
|
7
|
+
describe('Swarm Claiming', () => {
|
|
8
|
+
let testDir;
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
testDir = mkdtempSync(join(tmpdir(), 'swarm-claiming-test-'));
|
|
11
|
+
await initDb(testDir);
|
|
12
|
+
});
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
closeDb();
|
|
15
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
16
|
+
});
|
|
17
|
+
describe('claimTask', () => {
|
|
18
|
+
it('should successfully claim a pending task', () => {
|
|
19
|
+
initSession('test-session', 3);
|
|
20
|
+
addTasks([
|
|
21
|
+
{ id: 'task-1', description: 'First task' }
|
|
22
|
+
]);
|
|
23
|
+
const result = claimTask('agent-1');
|
|
24
|
+
expect(result.success).toBe(true);
|
|
25
|
+
expect(result.taskId).toBe('task-1');
|
|
26
|
+
expect(result.description).toBe('First task');
|
|
27
|
+
});
|
|
28
|
+
it('should allow sequential claims for different tasks', () => {
|
|
29
|
+
initSession('test-session', 3);
|
|
30
|
+
addTasks([
|
|
31
|
+
{ id: 'task-1', description: 'First task' },
|
|
32
|
+
{ id: 'task-2', description: 'Second task' },
|
|
33
|
+
{ id: 'task-3', description: 'Third task' }
|
|
34
|
+
]);
|
|
35
|
+
const result1 = claimTask('agent-1');
|
|
36
|
+
const result2 = claimTask('agent-2');
|
|
37
|
+
const result3 = claimTask('agent-3');
|
|
38
|
+
expect(result1.success).toBe(true);
|
|
39
|
+
expect(result1.taskId).toBe('task-1');
|
|
40
|
+
expect(result2.success).toBe(true);
|
|
41
|
+
expect(result2.taskId).toBe('task-2');
|
|
42
|
+
expect(result3.success).toBe(true);
|
|
43
|
+
expect(result3.taskId).toBe('task-3');
|
|
44
|
+
});
|
|
45
|
+
it('should handle duplicate claims correctly when only one task available', () => {
|
|
46
|
+
initSession('test-session', 2);
|
|
47
|
+
addTasks([
|
|
48
|
+
{ id: 'task-1', description: 'Only task' }
|
|
49
|
+
]);
|
|
50
|
+
const result1 = claimTask('agent-1');
|
|
51
|
+
const result2 = claimTask('agent-2');
|
|
52
|
+
expect(result1.success).toBe(true);
|
|
53
|
+
expect(result1.taskId).toBe('task-1');
|
|
54
|
+
expect(result2.success).toBe(false);
|
|
55
|
+
expect(result2.taskId).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
it('should fail with appropriate message when no pending tasks available', () => {
|
|
58
|
+
initSession('test-session', 2);
|
|
59
|
+
// No tasks added
|
|
60
|
+
const result = claimTask('agent-1');
|
|
61
|
+
expect(result.success).toBe(false);
|
|
62
|
+
expect(result.taskId).toBeNull();
|
|
63
|
+
expect(result.reason).toBe('No pending tasks available');
|
|
64
|
+
});
|
|
65
|
+
it('should update heartbeat when claiming a task', () => {
|
|
66
|
+
initSession('test-session', 1);
|
|
67
|
+
addTasks([
|
|
68
|
+
{ id: 'task-1', description: 'First task' }
|
|
69
|
+
]);
|
|
70
|
+
claimTask('agent-1');
|
|
71
|
+
const heartbeats = getHeartbeats();
|
|
72
|
+
expect(heartbeats).toHaveLength(1);
|
|
73
|
+
expect(heartbeats[0].agentId).toBe('agent-1');
|
|
74
|
+
expect(heartbeats[0].currentTaskId).toBe('task-1');
|
|
75
|
+
expect(heartbeats[0].lastHeartbeat).toBeGreaterThan(Date.now() - 1000);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
describe('cleanupStaleClaims', () => {
|
|
79
|
+
it('should return 0 when no stale claims exist', () => {
|
|
80
|
+
initSession('test-session', 1);
|
|
81
|
+
addTasks([
|
|
82
|
+
{ id: 'task-1', description: 'First task' }
|
|
83
|
+
]);
|
|
84
|
+
const released = cleanupStaleClaims(5 * 60 * 1000); // 5 minutes
|
|
85
|
+
expect(released).toBe(0);
|
|
86
|
+
});
|
|
87
|
+
it('should release stale claim without heartbeat', () => {
|
|
88
|
+
vi.useFakeTimers();
|
|
89
|
+
const now = Date.now();
|
|
90
|
+
vi.setSystemTime(now);
|
|
91
|
+
initSession('test-session', 1);
|
|
92
|
+
addTasks([
|
|
93
|
+
{ id: 'task-1', description: 'First task' }
|
|
94
|
+
]);
|
|
95
|
+
// Claim task
|
|
96
|
+
claimTask('agent-1');
|
|
97
|
+
// Advance time by 6 minutes
|
|
98
|
+
vi.setSystemTime(now + 6 * 60 * 1000);
|
|
99
|
+
// Cleanup stale claims
|
|
100
|
+
const released = cleanupStaleClaims(5 * 60 * 1000);
|
|
101
|
+
expect(released).toBe(1);
|
|
102
|
+
vi.useRealTimers();
|
|
103
|
+
});
|
|
104
|
+
it('should not release claim with fresh heartbeat', () => {
|
|
105
|
+
vi.useFakeTimers();
|
|
106
|
+
const now = Date.now();
|
|
107
|
+
vi.setSystemTime(now);
|
|
108
|
+
initSession('test-session', 1);
|
|
109
|
+
addTasks([
|
|
110
|
+
{ id: 'task-1', description: 'First task' }
|
|
111
|
+
]);
|
|
112
|
+
// Claim task
|
|
113
|
+
claimTask('agent-1');
|
|
114
|
+
// Advance time by 3 minutes
|
|
115
|
+
vi.setSystemTime(now + 3 * 60 * 1000);
|
|
116
|
+
// Send heartbeat
|
|
117
|
+
heartbeat('agent-1');
|
|
118
|
+
// Advance time by another 3 minutes (6 minutes total, but heartbeat is only 3 minutes old)
|
|
119
|
+
vi.setSystemTime(now + 6 * 60 * 1000);
|
|
120
|
+
// Cleanup stale claims
|
|
121
|
+
const released = cleanupStaleClaims(5 * 60 * 1000);
|
|
122
|
+
expect(released).toBe(0);
|
|
123
|
+
vi.useRealTimers();
|
|
124
|
+
});
|
|
125
|
+
it('should release multiple stale claims', () => {
|
|
126
|
+
vi.useFakeTimers();
|
|
127
|
+
const now = Date.now();
|
|
128
|
+
vi.setSystemTime(now);
|
|
129
|
+
initSession('test-session', 3);
|
|
130
|
+
addTasks([
|
|
131
|
+
{ id: 'task-1', description: 'First task' },
|
|
132
|
+
{ id: 'task-2', description: 'Second task' },
|
|
133
|
+
{ id: 'task-3', description: 'Third task' }
|
|
134
|
+
]);
|
|
135
|
+
// All agents claim tasks
|
|
136
|
+
claimTask('agent-1');
|
|
137
|
+
claimTask('agent-2');
|
|
138
|
+
claimTask('agent-3');
|
|
139
|
+
// Advance time by 6 minutes
|
|
140
|
+
vi.setSystemTime(now + 6 * 60 * 1000);
|
|
141
|
+
// Cleanup stale claims
|
|
142
|
+
const released = cleanupStaleClaims(5 * 60 * 1000);
|
|
143
|
+
expect(released).toBe(3);
|
|
144
|
+
vi.useRealTimers();
|
|
145
|
+
});
|
|
146
|
+
it('should remove stale heartbeat records during cleanup', () => {
|
|
147
|
+
vi.useFakeTimers();
|
|
148
|
+
const now = Date.now();
|
|
149
|
+
vi.setSystemTime(now);
|
|
150
|
+
initSession('test-session', 1);
|
|
151
|
+
addTasks([
|
|
152
|
+
{ id: 'task-1', description: 'First task' }
|
|
153
|
+
]);
|
|
154
|
+
// Claim task
|
|
155
|
+
claimTask('agent-1');
|
|
156
|
+
// Verify heartbeat exists
|
|
157
|
+
let heartbeats = getHeartbeats();
|
|
158
|
+
expect(heartbeats).toHaveLength(1);
|
|
159
|
+
// Advance time by 6 minutes
|
|
160
|
+
vi.setSystemTime(now + 6 * 60 * 1000);
|
|
161
|
+
// Cleanup stale claims
|
|
162
|
+
cleanupStaleClaims(5 * 60 * 1000);
|
|
163
|
+
// Verify heartbeat was removed
|
|
164
|
+
heartbeats = getHeartbeats();
|
|
165
|
+
expect(heartbeats).toHaveLength(0);
|
|
166
|
+
vi.useRealTimers();
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
//# sourceMappingURL=claiming.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claiming.test.js","sourceRoot":"","sources":["../../../../src/hooks/swarm/__tests__/claiming.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../../src/hooks/swarm/__tests__/index.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { mkdtempSync, rmSync, existsSync, writeFileSync, mkdirSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { tmpdir } from 'os';
|
|
5
|
+
import { startSwarm, stopSwarm, getSwarmStatus, isSwarmActive } from '../index.js';
|
|
6
|
+
describe('Swarm Lifecycle', () => {
|
|
7
|
+
let testDir;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
testDir = mkdtempSync(join(tmpdir(), 'swarm-test-'));
|
|
10
|
+
});
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
// Clean up any active swarm before removing directory
|
|
13
|
+
try {
|
|
14
|
+
stopSwarm(true);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Ignore errors if swarm was not active
|
|
18
|
+
}
|
|
19
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
20
|
+
});
|
|
21
|
+
describe('startSwarm', () => {
|
|
22
|
+
it('should start swarm with valid config and create db and marker', async () => {
|
|
23
|
+
const success = await startSwarm({
|
|
24
|
+
agentCount: 3,
|
|
25
|
+
tasks: ['task 1', 'task 2', 'task 3'],
|
|
26
|
+
cwd: testDir
|
|
27
|
+
});
|
|
28
|
+
expect(success).toBe(true);
|
|
29
|
+
// Verify database exists
|
|
30
|
+
const dbPath = join(testDir, '.omc', 'state', 'swarm.db');
|
|
31
|
+
expect(existsSync(dbPath)).toBe(true);
|
|
32
|
+
// Verify marker file exists
|
|
33
|
+
const markerPath = join(testDir, '.omc', 'state', 'swarm-active.marker');
|
|
34
|
+
expect(existsSync(markerPath)).toBe(true);
|
|
35
|
+
// Verify state is active
|
|
36
|
+
const status = getSwarmStatus();
|
|
37
|
+
expect(status).not.toBeNull();
|
|
38
|
+
expect(status?.active).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
it('should fail with empty tasks array', async () => {
|
|
41
|
+
const success = await startSwarm({
|
|
42
|
+
agentCount: 3,
|
|
43
|
+
tasks: [],
|
|
44
|
+
cwd: testDir
|
|
45
|
+
});
|
|
46
|
+
expect(success).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
it('should fail with agentCount less than 1', async () => {
|
|
49
|
+
const success = await startSwarm({
|
|
50
|
+
agentCount: 0,
|
|
51
|
+
tasks: ['task 1'],
|
|
52
|
+
cwd: testDir
|
|
53
|
+
});
|
|
54
|
+
expect(success).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
it('should fail when another exclusive mode is active', async () => {
|
|
57
|
+
// Create autopilot state file to simulate active autopilot
|
|
58
|
+
const stateDir = join(testDir, '.omc', 'state');
|
|
59
|
+
mkdirSync(stateDir, { recursive: true });
|
|
60
|
+
const autopilotStatePath = join(stateDir, 'autopilot-state.json');
|
|
61
|
+
writeFileSync(autopilotStatePath, JSON.stringify({
|
|
62
|
+
active: true,
|
|
63
|
+
phase: 'execution',
|
|
64
|
+
originalIdea: 'test',
|
|
65
|
+
created_at: Date.now()
|
|
66
|
+
}));
|
|
67
|
+
// Attempt to start swarm should fail
|
|
68
|
+
const success = await startSwarm({
|
|
69
|
+
agentCount: 3,
|
|
70
|
+
tasks: ['task 1'],
|
|
71
|
+
cwd: testDir
|
|
72
|
+
});
|
|
73
|
+
expect(success).toBe(false);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe('stopSwarm', () => {
|
|
77
|
+
it('should clean up properly and remove marker', async () => {
|
|
78
|
+
// Start swarm
|
|
79
|
+
await startSwarm({
|
|
80
|
+
agentCount: 2,
|
|
81
|
+
tasks: ['task 1', 'task 2'],
|
|
82
|
+
cwd: testDir
|
|
83
|
+
});
|
|
84
|
+
const markerPath = join(testDir, '.omc', 'state', 'swarm-active.marker');
|
|
85
|
+
expect(existsSync(markerPath)).toBe(true);
|
|
86
|
+
// Stop swarm without deleting database
|
|
87
|
+
const success = stopSwarm(false);
|
|
88
|
+
expect(success).toBe(true);
|
|
89
|
+
// Marker should be removed
|
|
90
|
+
expect(existsSync(markerPath)).toBe(false);
|
|
91
|
+
// Database should still exist
|
|
92
|
+
const dbPath = join(testDir, '.omc', 'state', 'swarm.db');
|
|
93
|
+
expect(existsSync(dbPath)).toBe(true);
|
|
94
|
+
});
|
|
95
|
+
it('should remove database when deleteDatabase=true', async () => {
|
|
96
|
+
await startSwarm({
|
|
97
|
+
agentCount: 2,
|
|
98
|
+
tasks: ['task 1'],
|
|
99
|
+
cwd: testDir
|
|
100
|
+
});
|
|
101
|
+
const dbPath = join(testDir, '.omc', 'state', 'swarm.db');
|
|
102
|
+
expect(existsSync(dbPath)).toBe(true);
|
|
103
|
+
// Stop with deleteDatabase flag
|
|
104
|
+
stopSwarm(true);
|
|
105
|
+
// Database should be deleted
|
|
106
|
+
expect(existsSync(dbPath)).toBe(false);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe('getSwarmStatus', () => {
|
|
110
|
+
it('should return null when swarm is not active', () => {
|
|
111
|
+
const status = getSwarmStatus();
|
|
112
|
+
expect(status).toBeNull();
|
|
113
|
+
});
|
|
114
|
+
it('should return correct state when swarm is active', async () => {
|
|
115
|
+
await startSwarm({
|
|
116
|
+
agentCount: 5,
|
|
117
|
+
tasks: ['task 1', 'task 2'],
|
|
118
|
+
cwd: testDir
|
|
119
|
+
});
|
|
120
|
+
const status = getSwarmStatus();
|
|
121
|
+
expect(status).not.toBeNull();
|
|
122
|
+
expect(status?.active).toBe(true);
|
|
123
|
+
expect(status?.agentCount).toBe(5);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
describe('isSwarmActive', () => {
|
|
127
|
+
it('should detect running swarm', async () => {
|
|
128
|
+
await startSwarm({
|
|
129
|
+
agentCount: 3,
|
|
130
|
+
tasks: ['task 1'],
|
|
131
|
+
cwd: testDir
|
|
132
|
+
});
|
|
133
|
+
expect(isSwarmActive(testDir)).toBe(true);
|
|
134
|
+
});
|
|
135
|
+
it('should return false when swarm is not running', () => {
|
|
136
|
+
expect(isSwarmActive(testDir)).toBe(false);
|
|
137
|
+
});
|
|
138
|
+
it('should detect inactive state after swarm is stopped with database preserved', async () => {
|
|
139
|
+
await startSwarm({
|
|
140
|
+
agentCount: 2,
|
|
141
|
+
tasks: ['task 1'],
|
|
142
|
+
cwd: testDir
|
|
143
|
+
});
|
|
144
|
+
expect(isSwarmActive(testDir)).toBe(true);
|
|
145
|
+
stopSwarm(false);
|
|
146
|
+
// After stopSwarm(false), database file still exists
|
|
147
|
+
const dbPath = join(testDir, '.omc', 'state', 'swarm.db');
|
|
148
|
+
expect(existsSync(dbPath)).toBe(true);
|
|
149
|
+
// isSwarmActive checks if db file exists (not if it's truly active)
|
|
150
|
+
// This is expected behavior - database is preserved for analysis
|
|
151
|
+
// For true active detection, use marker file (removed by stopSwarm)
|
|
152
|
+
const markerPath = join(testDir, '.omc', 'state', 'swarm-active.marker');
|
|
153
|
+
expect(existsSync(markerPath)).toBe(false);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
//# sourceMappingURL=index.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../../src/hooks/swarm/__tests__/index.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mode-registry.test.d.ts","sourceRoot":"","sources":["../../../../src/hooks/swarm/__tests__/mode-registry.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { mkdtempSync, rmSync, existsSync, writeFileSync, mkdirSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { tmpdir } from 'os';
|
|
5
|
+
import { canStartMode, createModeMarker, removeModeMarker, isModeActive, readModeMarker } from '../../mode-registry/index.js';
|
|
6
|
+
describe('Mode Registry Integration', () => {
|
|
7
|
+
let testDir;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
testDir = mkdtempSync(join(tmpdir(), 'mode-registry-test-'));
|
|
10
|
+
});
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
13
|
+
});
|
|
14
|
+
describe('canStartMode', () => {
|
|
15
|
+
it('should allow mode when no conflicts exist', () => {
|
|
16
|
+
const result = canStartMode('swarm', testDir);
|
|
17
|
+
expect(result.allowed).toBe(true);
|
|
18
|
+
expect(result.blockedBy).toBeUndefined();
|
|
19
|
+
expect(result.message).toBeUndefined();
|
|
20
|
+
});
|
|
21
|
+
it('should block when exclusive mode is active', () => {
|
|
22
|
+
// Create autopilot state to simulate active mode
|
|
23
|
+
const stateDir = join(testDir, '.omc', 'state');
|
|
24
|
+
mkdirSync(stateDir, { recursive: true });
|
|
25
|
+
const autopilotStatePath = join(stateDir, 'autopilot-state.json');
|
|
26
|
+
writeFileSync(autopilotStatePath, JSON.stringify({
|
|
27
|
+
active: true,
|
|
28
|
+
phase: 'execution',
|
|
29
|
+
originalIdea: 'test',
|
|
30
|
+
created_at: Date.now()
|
|
31
|
+
}));
|
|
32
|
+
const result = canStartMode('swarm', testDir);
|
|
33
|
+
expect(result.allowed).toBe(false);
|
|
34
|
+
expect(result.blockedBy).toBe('autopilot');
|
|
35
|
+
expect(result.message).toContain('Cannot start Swarm');
|
|
36
|
+
expect(result.message).toContain('Autopilot is active');
|
|
37
|
+
});
|
|
38
|
+
it('should block when ultrapilot is active', () => {
|
|
39
|
+
// Create ultrapilot state
|
|
40
|
+
const stateDir = join(testDir, '.omc', 'state');
|
|
41
|
+
mkdirSync(stateDir, { recursive: true });
|
|
42
|
+
const ultrapilotStatePath = join(stateDir, 'ultrapilot-state.json');
|
|
43
|
+
writeFileSync(ultrapilotStatePath, JSON.stringify({
|
|
44
|
+
active: true,
|
|
45
|
+
created_at: Date.now()
|
|
46
|
+
}));
|
|
47
|
+
const result = canStartMode('swarm', testDir);
|
|
48
|
+
expect(result.allowed).toBe(false);
|
|
49
|
+
expect(result.blockedBy).toBe('ultrapilot');
|
|
50
|
+
});
|
|
51
|
+
it('should allow non-exclusive modes when swarm is active', () => {
|
|
52
|
+
// Create swarm marker
|
|
53
|
+
const stateDir = join(testDir, '.omc', 'state');
|
|
54
|
+
mkdirSync(stateDir, { recursive: true });
|
|
55
|
+
createModeMarker('swarm', testDir, { agentCount: 3 });
|
|
56
|
+
// Ralph is not exclusive, so it should be allowed
|
|
57
|
+
const result = canStartMode('ralph', testDir);
|
|
58
|
+
expect(result.allowed).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe('createModeMarker', () => {
|
|
62
|
+
it('should create marker file with metadata', () => {
|
|
63
|
+
const markerPath = join(testDir, '.omc', 'state', 'swarm-active.marker');
|
|
64
|
+
const success = createModeMarker('swarm', testDir, {
|
|
65
|
+
agentCount: 5,
|
|
66
|
+
taskCount: 10
|
|
67
|
+
});
|
|
68
|
+
expect(success).toBe(true);
|
|
69
|
+
expect(existsSync(markerPath)).toBe(true);
|
|
70
|
+
const marker = readModeMarker('swarm', testDir);
|
|
71
|
+
expect(marker).not.toBeNull();
|
|
72
|
+
expect(marker?.mode).toBe('swarm');
|
|
73
|
+
expect(marker?.agentCount).toBe(5);
|
|
74
|
+
expect(marker?.taskCount).toBe(10);
|
|
75
|
+
expect(marker?.startedAt).toBeDefined();
|
|
76
|
+
});
|
|
77
|
+
it('should create directory if it does not exist', () => {
|
|
78
|
+
const markerPath = join(testDir, '.omc', 'state', 'swarm-active.marker');
|
|
79
|
+
// Ensure directory doesn't exist
|
|
80
|
+
expect(existsSync(join(testDir, '.omc'))).toBe(false);
|
|
81
|
+
const success = createModeMarker('swarm', testDir, {});
|
|
82
|
+
expect(success).toBe(true);
|
|
83
|
+
expect(existsSync(markerPath)).toBe(true);
|
|
84
|
+
});
|
|
85
|
+
it('should fail for modes without marker file', () => {
|
|
86
|
+
// autopilot uses JSON state file, not marker
|
|
87
|
+
const success = createModeMarker('autopilot', testDir, {});
|
|
88
|
+
expect(success).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe('removeModeMarker', () => {
|
|
92
|
+
it('should delete marker file', () => {
|
|
93
|
+
const markerPath = join(testDir, '.omc', 'state', 'swarm-active.marker');
|
|
94
|
+
createModeMarker('swarm', testDir, {});
|
|
95
|
+
expect(existsSync(markerPath)).toBe(true);
|
|
96
|
+
const success = removeModeMarker('swarm', testDir);
|
|
97
|
+
expect(success).toBe(true);
|
|
98
|
+
expect(existsSync(markerPath)).toBe(false);
|
|
99
|
+
});
|
|
100
|
+
it('should succeed if marker does not exist', () => {
|
|
101
|
+
const success = removeModeMarker('swarm', testDir);
|
|
102
|
+
expect(success).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
it('should succeed for modes without marker file', () => {
|
|
105
|
+
const success = removeModeMarker('autopilot', testDir);
|
|
106
|
+
expect(success).toBe(true);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe('isModeActive', () => {
|
|
110
|
+
it('should detect active marker-based mode', () => {
|
|
111
|
+
createModeMarker('swarm', testDir, {});
|
|
112
|
+
expect(isModeActive('swarm', testDir)).toBe(true);
|
|
113
|
+
});
|
|
114
|
+
it('should detect active JSON-based mode', () => {
|
|
115
|
+
const stateDir = join(testDir, '.omc', 'state');
|
|
116
|
+
mkdirSync(stateDir, { recursive: true });
|
|
117
|
+
writeFileSync(join(stateDir, 'autopilot-state.json'), JSON.stringify({
|
|
118
|
+
active: true,
|
|
119
|
+
phase: 'execution',
|
|
120
|
+
originalIdea: 'test',
|
|
121
|
+
created_at: Date.now()
|
|
122
|
+
}));
|
|
123
|
+
expect(isModeActive('autopilot', testDir)).toBe(true);
|
|
124
|
+
});
|
|
125
|
+
it('should return false when mode is not active', () => {
|
|
126
|
+
expect(isModeActive('swarm', testDir)).toBe(false);
|
|
127
|
+
expect(isModeActive('autopilot', testDir)).toBe(false);
|
|
128
|
+
});
|
|
129
|
+
it('should return false when JSON mode is inactive', () => {
|
|
130
|
+
const stateDir = join(testDir, '.omc', 'state');
|
|
131
|
+
mkdirSync(stateDir, { recursive: true });
|
|
132
|
+
writeFileSync(join(stateDir, 'autopilot-state.json'), JSON.stringify({
|
|
133
|
+
active: false,
|
|
134
|
+
phase: 'complete',
|
|
135
|
+
originalIdea: 'test',
|
|
136
|
+
created_at: Date.now(),
|
|
137
|
+
completed_at: Date.now()
|
|
138
|
+
}));
|
|
139
|
+
expect(isModeActive('autopilot', testDir)).toBe(false);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
describe('Stale marker detection', () => {
|
|
143
|
+
it('should auto-remove stale markers older than 1 hour', () => {
|
|
144
|
+
// Create marker with old timestamp (simulating stale marker)
|
|
145
|
+
const stateDir = join(testDir, '.omc', 'state');
|
|
146
|
+
mkdirSync(stateDir, { recursive: true });
|
|
147
|
+
const markerPath = join(stateDir, 'swarm-active.marker');
|
|
148
|
+
// Create marker with timestamp from 2 hours ago (exceeds 1-hour threshold)
|
|
149
|
+
const twoHoursAgo = new Date(Date.now() - 2 * 60 * 60 * 1000).toISOString();
|
|
150
|
+
writeFileSync(markerPath, JSON.stringify({
|
|
151
|
+
mode: 'swarm',
|
|
152
|
+
startedAt: twoHoursAgo,
|
|
153
|
+
agentCount: 3
|
|
154
|
+
}));
|
|
155
|
+
// Verify marker file exists
|
|
156
|
+
expect(existsSync(markerPath)).toBe(true);
|
|
157
|
+
// isModeActive should detect stale marker and auto-remove it
|
|
158
|
+
expect(isModeActive('swarm', testDir)).toBe(false);
|
|
159
|
+
// Marker should be deleted after staleness check
|
|
160
|
+
expect(existsSync(markerPath)).toBe(false);
|
|
161
|
+
});
|
|
162
|
+
it('should handle marker files without timestamp', () => {
|
|
163
|
+
const stateDir = join(testDir, '.omc', 'state');
|
|
164
|
+
mkdirSync(stateDir, { recursive: true });
|
|
165
|
+
const markerPath = join(stateDir, 'swarm-active.marker');
|
|
166
|
+
// Create marker without startedAt
|
|
167
|
+
writeFileSync(markerPath, JSON.stringify({
|
|
168
|
+
mode: 'swarm',
|
|
169
|
+
agentCount: 3
|
|
170
|
+
}));
|
|
171
|
+
expect(isModeActive('swarm', testDir)).toBe(true);
|
|
172
|
+
const marker = readModeMarker('swarm', testDir);
|
|
173
|
+
expect(marker?.startedAt).toBeUndefined();
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
//# sourceMappingURL=mode-registry.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mode-registry.test.js","sourceRoot":"","sources":["../../../../src/hooks/swarm/__tests__/mode-registry.test.ts"],"names":[],"mappings":"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"}
|