oh-my-claude-sisyphus 3.5.7 → 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.
Files changed (112) hide show
  1. package/agents/executor-high.md +2 -0
  2. package/agents/executor-low.md +2 -0
  3. package/agents/executor.md +2 -0
  4. package/agents/templates/base-agent.md +9 -0
  5. package/commands/cancel.md +8 -8
  6. package/commands/swarm.md +350 -148
  7. package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts +7 -0
  8. package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts.map +1 -0
  9. package/dist/__tests__/hooks/auto-slash-command/executor.test.js +374 -0
  10. package/dist/__tests__/hooks/auto-slash-command/executor.test.js.map +1 -0
  11. package/dist/__tests__/hooks/learner/bridge.test.d.ts +11 -0
  12. package/dist/__tests__/hooks/learner/bridge.test.d.ts.map +1 -0
  13. package/dist/__tests__/hooks/learner/bridge.test.js +199 -0
  14. package/dist/__tests__/hooks/learner/bridge.test.js.map +1 -0
  15. package/dist/__tests__/hooks.test.js +10 -9
  16. package/dist/__tests__/hooks.test.js.map +1 -1
  17. package/dist/__tests__/installer.test.js +1 -1
  18. package/dist/agents/codex-agents.d.ts +20 -0
  19. package/dist/agents/codex-agents.d.ts.map +1 -0
  20. package/dist/agents/codex-agents.js +36 -0
  21. package/dist/agents/codex-agents.js.map +1 -0
  22. package/dist/agents/preamble.d.ts +14 -0
  23. package/dist/agents/preamble.d.ts.map +1 -0
  24. package/dist/agents/preamble.js +26 -0
  25. package/dist/agents/preamble.js.map +1 -0
  26. package/dist/hooks/autopilot/__tests__/cancel.test.js +14 -4
  27. package/dist/hooks/autopilot/__tests__/cancel.test.js.map +1 -1
  28. package/dist/hooks/autopilot/__tests__/state.test.js +1 -0
  29. package/dist/hooks/autopilot/__tests__/state.test.js.map +1 -1
  30. package/dist/hooks/autopilot/__tests__/summary.test.js +38 -3
  31. package/dist/hooks/autopilot/__tests__/summary.test.js.map +1 -1
  32. package/dist/hooks/autopilot/state.d.ts +1 -1
  33. package/dist/hooks/autopilot/state.d.ts.map +1 -1
  34. package/dist/hooks/autopilot/state.js +15 -8
  35. package/dist/hooks/autopilot/state.js.map +1 -1
  36. package/dist/hooks/index.d.ts +2 -0
  37. package/dist/hooks/index.d.ts.map +1 -1
  38. package/dist/hooks/index.js +7 -0
  39. package/dist/hooks/index.js.map +1 -1
  40. package/dist/hooks/learner/bridge.d.ts +71 -0
  41. package/dist/hooks/learner/bridge.d.ts.map +1 -0
  42. package/dist/hooks/learner/bridge.js +426 -0
  43. package/dist/hooks/learner/bridge.js.map +1 -0
  44. package/dist/hooks/mode-registry/index.d.ts +135 -0
  45. package/dist/hooks/mode-registry/index.d.ts.map +1 -0
  46. package/dist/hooks/mode-registry/index.js +445 -0
  47. package/dist/hooks/mode-registry/index.js.map +1 -0
  48. package/dist/hooks/mode-registry/types.d.ts +31 -0
  49. package/dist/hooks/mode-registry/types.d.ts.map +1 -0
  50. package/dist/hooks/mode-registry/types.js +7 -0
  51. package/dist/hooks/mode-registry/types.js.map +1 -0
  52. package/dist/hooks/ralph/loop.js +6 -6
  53. package/dist/hooks/ralph/loop.js.map +1 -1
  54. package/dist/hooks/skill-bridge.cjs +349 -0
  55. package/dist/hooks/swarm/__tests__/claiming.test.d.ts +2 -0
  56. package/dist/hooks/swarm/__tests__/claiming.test.d.ts.map +1 -0
  57. package/dist/hooks/swarm/__tests__/claiming.test.js +170 -0
  58. package/dist/hooks/swarm/__tests__/claiming.test.js.map +1 -0
  59. package/dist/hooks/swarm/__tests__/index.test.d.ts +2 -0
  60. package/dist/hooks/swarm/__tests__/index.test.d.ts.map +1 -0
  61. package/dist/hooks/swarm/__tests__/index.test.js +157 -0
  62. package/dist/hooks/swarm/__tests__/index.test.js.map +1 -0
  63. package/dist/hooks/swarm/__tests__/mode-registry.test.d.ts +2 -0
  64. package/dist/hooks/swarm/__tests__/mode-registry.test.d.ts.map +1 -0
  65. package/dist/hooks/swarm/__tests__/mode-registry.test.js +177 -0
  66. package/dist/hooks/swarm/__tests__/mode-registry.test.js.map +1 -0
  67. package/dist/hooks/swarm/claiming.d.ts +101 -0
  68. package/dist/hooks/swarm/claiming.d.ts.map +1 -0
  69. package/dist/hooks/swarm/claiming.js +460 -0
  70. package/dist/hooks/swarm/claiming.js.map +1 -0
  71. package/dist/hooks/swarm/index.d.ts +221 -0
  72. package/dist/hooks/swarm/index.d.ts.map +1 -0
  73. package/dist/hooks/swarm/index.js +413 -0
  74. package/dist/hooks/swarm/index.js.map +1 -0
  75. package/dist/hooks/swarm/state.d.ts +94 -0
  76. package/dist/hooks/swarm/state.d.ts.map +1 -0
  77. package/dist/hooks/swarm/state.js +530 -0
  78. package/dist/hooks/swarm/state.js.map +1 -0
  79. package/dist/hooks/swarm/types.d.ts +116 -0
  80. package/dist/hooks/swarm/types.d.ts.map +1 -0
  81. package/dist/hooks/swarm/types.js +22 -0
  82. package/dist/hooks/swarm/types.js.map +1 -0
  83. package/dist/hooks/ultrapilot/decomposer.d.ts +141 -0
  84. package/dist/hooks/ultrapilot/decomposer.d.ts.map +1 -0
  85. package/dist/hooks/ultrapilot/decomposer.js +377 -0
  86. package/dist/hooks/ultrapilot/decomposer.js.map +1 -0
  87. package/dist/hooks/ultrapilot/index.d.ts +31 -0
  88. package/dist/hooks/ultrapilot/index.d.ts.map +1 -1
  89. package/dist/hooks/ultrapilot/index.js +43 -2
  90. package/dist/hooks/ultrapilot/index.js.map +1 -1
  91. package/dist/hooks/ultrapilot/state.d.ts +1 -1
  92. package/dist/hooks/ultrapilot/state.d.ts.map +1 -1
  93. package/dist/hooks/ultrapilot/state.js +7 -0
  94. package/dist/hooks/ultrapilot/state.js.map +1 -1
  95. package/dist/hooks/ultraqa/index.js +5 -5
  96. package/dist/hooks/ultraqa/index.js.map +1 -1
  97. package/dist/hooks/ultrawork/index.js +3 -3
  98. package/dist/hooks/ultrawork/index.js.map +1 -1
  99. package/dist/installer/index.d.ts +1 -1
  100. package/dist/installer/index.js +1 -1
  101. package/package.json +6 -2
  102. package/scripts/build-skill-bridge.mjs +32 -0
  103. package/scripts/skill-injector.mjs +77 -26
  104. package/skills/autopilot/SKILL.md +18 -0
  105. package/skills/cancel/SKILL.md +166 -141
  106. package/skills/ecomode/SKILL.md +14 -0
  107. package/skills/pipeline/SKILL.md +13 -0
  108. package/skills/ralph/SKILL.md +22 -1
  109. package/skills/swarm/SKILL.md +521 -197
  110. package/skills/ultrapilot/SKILL.md +82 -13
  111. package/skills/ultraqa/SKILL.md +13 -0
  112. package/skills/ultrawork/SKILL.md +14 -0
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mode-registry.test.d.ts.map
@@ -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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"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Swarm Task Claiming
3
+ *
4
+ * Atomic task claiming with lease-based ownership.
5
+ * Uses SQLite transactions to ensure only one agent can claim a task.
6
+ * Implements 5-minute lease timeout and heartbeat monitoring.
7
+ */
8
+ import type { ClaimResult, SwarmTask } from './types.js';
9
+ /**
10
+ * Atomically claim the next available task
11
+ *
12
+ * Uses a transaction to ensure only one agent can claim a task.
13
+ * Claims are lease-based with a 5-minute timeout.
14
+ *
15
+ * @param agentId - Unique identifier for the claiming agent
16
+ * @returns ClaimResult indicating success/failure and task details
17
+ */
18
+ export declare function claimTask(agentId: string): ClaimResult;
19
+ /**
20
+ * Release a claimed task back to the pending pool
21
+ *
22
+ * Used when an agent fails to complete a task or wants to give it up.
23
+ *
24
+ * @param agentId - Agent releasing the task
25
+ * @param taskId - Task to release
26
+ * @returns true if release was successful
27
+ */
28
+ export declare function releaseTask(agentId: string, taskId: string): boolean;
29
+ /**
30
+ * Mark a task as completed
31
+ *
32
+ * @param agentId - Agent that completed the task
33
+ * @param taskId - Completed task ID
34
+ * @param result - Optional result/output from the task
35
+ * @returns true if completion was recorded
36
+ */
37
+ export declare function completeTask(agentId: string, taskId: string, result?: string): boolean;
38
+ /**
39
+ * Mark a task as failed
40
+ *
41
+ * @param agentId - Agent that failed the task
42
+ * @param taskId - Failed task ID
43
+ * @param error - Error message/reason for failure
44
+ * @returns true if failure was recorded
45
+ */
46
+ export declare function failTask(agentId: string, taskId: string, error: string): boolean;
47
+ /**
48
+ * Record agent heartbeat
49
+ *
50
+ * Agents should call this every 60 seconds to indicate they're still alive.
51
+ * Used by cleanupStaleClaims to detect dead agents.
52
+ *
53
+ * @param agentId - Agent sending heartbeat
54
+ * @returns true if heartbeat was recorded
55
+ */
56
+ export declare function heartbeat(agentId: string): boolean;
57
+ /**
58
+ * Clean up stale claims from dead agents
59
+ *
60
+ * Releases tasks that have been claimed for longer than the lease timeout
61
+ * (default 5 minutes) by agents that haven't sent a heartbeat.
62
+ *
63
+ * @param leaseTimeout - Lease timeout in milliseconds (default: 5 minutes)
64
+ * @returns Number of tasks released
65
+ */
66
+ export declare function cleanupStaleClaims(leaseTimeout?: number): number;
67
+ /**
68
+ * Get tasks claimed by a specific agent
69
+ *
70
+ * @param agentId - Agent to query
71
+ * @returns Array of tasks claimed by the agent
72
+ */
73
+ export declare function getTasksClaimedBy(agentId: string): SwarmTask[];
74
+ /**
75
+ * Check if there are any pending tasks
76
+ *
77
+ * @returns true if there are pending tasks
78
+ */
79
+ export declare function hasPendingTasks(): boolean;
80
+ /**
81
+ * Check if all tasks are complete (done or failed)
82
+ *
83
+ * @returns true if all tasks are complete
84
+ */
85
+ export declare function allTasksComplete(): boolean;
86
+ /**
87
+ * Get the number of active agents (with recent heartbeats)
88
+ *
89
+ * @param heartbeatTimeout - How old a heartbeat can be to still be considered active
90
+ * @returns Number of active agents
91
+ */
92
+ export declare function getActiveAgentCount(heartbeatTimeout?: number): number;
93
+ /**
94
+ * Attempt to reclaim a failed task
95
+ *
96
+ * @param agentId - Agent attempting to reclaim
97
+ * @param taskId - Task to reclaim
98
+ * @returns ClaimResult
99
+ */
100
+ export declare function reclaimFailedTask(agentId: string, taskId: string): ClaimResult;
101
+ //# sourceMappingURL=claiming.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claiming.d.ts","sourceRoot":"","sources":["../../../src/hooks/swarm/claiming.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAazD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAqEtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAsCpE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAsCtF;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAsChF;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAgBlD;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,GAAE,MAA0C,GAAG,MAAM,CA2DnG;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,CAiC9D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAczC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAc1C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,gBAAgB,GAAE,MAA0C,GAAG,MAAM,CAexG;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAgE9E"}