macro-agent 0.1.7 → 0.1.10

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 (259) hide show
  1. package/CLAUDE.md +179 -38
  2. package/README.md +781 -131
  3. package/dist/acp/claude-code-replay.d.ts +11 -0
  4. package/dist/acp/claude-code-replay.d.ts.map +1 -0
  5. package/dist/acp/claude-code-replay.js +190 -0
  6. package/dist/acp/claude-code-replay.js.map +1 -0
  7. package/dist/acp/macro-agent.d.ts.map +1 -1
  8. package/dist/acp/macro-agent.js +155 -6
  9. package/dist/acp/macro-agent.js.map +1 -1
  10. package/dist/acp/types.d.ts +9 -0
  11. package/dist/acp/types.d.ts.map +1 -1
  12. package/dist/acp/types.js.map +1 -1
  13. package/dist/agent/agent-manager-v2.d.ts +21 -0
  14. package/dist/agent/agent-manager-v2.d.ts.map +1 -1
  15. package/dist/agent/agent-manager-v2.js +234 -71
  16. package/dist/agent/agent-manager-v2.js.map +1 -1
  17. package/dist/agent/agent-manager.d.ts +12 -0
  18. package/dist/agent/agent-manager.d.ts.map +1 -1
  19. package/dist/agent/agent-manager.js.map +1 -1
  20. package/dist/agent/types.d.ts +15 -2
  21. package/dist/agent/types.d.ts.map +1 -1
  22. package/dist/agent/types.js.map +1 -1
  23. package/dist/boot-v2.d.ts +41 -0
  24. package/dist/boot-v2.d.ts.map +1 -1
  25. package/dist/boot-v2.js +34 -37
  26. package/dist/boot-v2.js.map +1 -1
  27. package/dist/cli/index.js +56 -0
  28. package/dist/cli/index.js.map +1 -1
  29. package/dist/cognitive/macro-agent-backend.d.ts.map +1 -1
  30. package/dist/cognitive/macro-agent-backend.js +40 -22
  31. package/dist/cognitive/macro-agent-backend.js.map +1 -1
  32. package/dist/integrations/skilltree.d.ts.map +1 -1
  33. package/dist/integrations/skilltree.js +1 -0
  34. package/dist/integrations/skilltree.js.map +1 -1
  35. package/dist/lifecycle/cleanup.d.ts +33 -2
  36. package/dist/lifecycle/cleanup.d.ts.map +1 -1
  37. package/dist/lifecycle/cleanup.js +28 -6
  38. package/dist/lifecycle/cleanup.js.map +1 -1
  39. package/dist/lifecycle/handlers-v2.d.ts +7 -0
  40. package/dist/lifecycle/handlers-v2.d.ts.map +1 -1
  41. package/dist/lifecycle/handlers-v2.js +28 -2
  42. package/dist/lifecycle/handlers-v2.js.map +1 -1
  43. package/dist/lifecycle/types.d.ts +11 -0
  44. package/dist/lifecycle/types.d.ts.map +1 -1
  45. package/dist/lifecycle/types.js.map +1 -1
  46. package/dist/map/acp-bridge.d.ts +9 -0
  47. package/dist/map/acp-bridge.d.ts.map +1 -1
  48. package/dist/map/acp-bridge.js +15 -2
  49. package/dist/map/acp-bridge.js.map +1 -1
  50. package/dist/map/cascade-bridge.d.ts +44 -0
  51. package/dist/map/cascade-bridge.d.ts.map +1 -0
  52. package/dist/map/cascade-bridge.js +257 -0
  53. package/dist/map/cascade-bridge.js.map +1 -0
  54. package/dist/map/lifecycle-bridge.d.ts +1 -8
  55. package/dist/map/lifecycle-bridge.d.ts.map +1 -1
  56. package/dist/map/lifecycle-bridge.js +76 -22
  57. package/dist/map/lifecycle-bridge.js.map +1 -1
  58. package/dist/map/server.d.ts.map +1 -1
  59. package/dist/map/server.js +47 -6
  60. package/dist/map/server.js.map +1 -1
  61. package/dist/map/sidecar.d.ts.map +1 -1
  62. package/dist/map/sidecar.js +33 -4
  63. package/dist/map/sidecar.js.map +1 -1
  64. package/dist/map/types.d.ts +20 -0
  65. package/dist/map/types.d.ts.map +1 -1
  66. package/dist/mcp/tools/done-v2.d.ts.map +1 -1
  67. package/dist/mcp/tools/done-v2.js +8 -0
  68. package/dist/mcp/tools/done-v2.js.map +1 -1
  69. package/dist/teams/team-manager-v2.d.ts.map +1 -1
  70. package/dist/teams/team-manager-v2.js +26 -0
  71. package/dist/teams/team-manager-v2.js.map +1 -1
  72. package/dist/teams/team-runtime-v2.d.ts.map +1 -1
  73. package/dist/teams/team-runtime-v2.js +16 -3
  74. package/dist/teams/team-runtime-v2.js.map +1 -1
  75. package/dist/workspace/config.d.ts +10 -10
  76. package/dist/workspace/config.d.ts.map +1 -1
  77. package/dist/workspace/config.js +4 -4
  78. package/dist/workspace/config.js.map +1 -1
  79. package/dist/workspace/git-cascade-adapter.d.ts +510 -0
  80. package/dist/workspace/git-cascade-adapter.d.ts.map +1 -0
  81. package/dist/workspace/git-cascade-adapter.js +908 -0
  82. package/dist/workspace/git-cascade-adapter.js.map +1 -0
  83. package/dist/workspace/index.d.ts +3 -3
  84. package/dist/workspace/index.d.ts.map +1 -1
  85. package/dist/workspace/index.js +4 -4
  86. package/dist/workspace/index.js.map +1 -1
  87. package/dist/workspace/landing/direct-push.d.ts +20 -0
  88. package/dist/workspace/landing/direct-push.d.ts.map +1 -0
  89. package/dist/workspace/landing/direct-push.js +74 -0
  90. package/dist/workspace/landing/direct-push.js.map +1 -0
  91. package/dist/workspace/landing/index.d.ts +29 -0
  92. package/dist/workspace/landing/index.d.ts.map +1 -0
  93. package/dist/workspace/landing/index.js +37 -0
  94. package/dist/workspace/landing/index.js.map +1 -0
  95. package/dist/workspace/landing/merge-to-parent.d.ts +41 -0
  96. package/dist/workspace/landing/merge-to-parent.d.ts.map +1 -0
  97. package/dist/workspace/landing/merge-to-parent.js +185 -0
  98. package/dist/workspace/landing/merge-to-parent.js.map +1 -0
  99. package/dist/workspace/landing/optimistic-push.d.ts +16 -0
  100. package/dist/workspace/landing/optimistic-push.d.ts.map +1 -0
  101. package/dist/workspace/landing/optimistic-push.js +27 -0
  102. package/dist/workspace/landing/optimistic-push.js.map +1 -0
  103. package/dist/workspace/landing/queue-to-branch.d.ts +24 -0
  104. package/dist/workspace/landing/queue-to-branch.d.ts.map +1 -0
  105. package/dist/workspace/landing/queue-to-branch.js +79 -0
  106. package/dist/workspace/landing/queue-to-branch.js.map +1 -0
  107. package/dist/workspace/merge-queue/merge-queue.d.ts +10 -0
  108. package/dist/workspace/merge-queue/merge-queue.d.ts.map +1 -1
  109. package/dist/workspace/merge-queue/merge-queue.js +10 -0
  110. package/dist/workspace/merge-queue/merge-queue.js.map +1 -1
  111. package/dist/workspace/merge-queue/types.d.ts +16 -2
  112. package/dist/workspace/merge-queue/types.d.ts.map +1 -1
  113. package/dist/workspace/merge-queue/types.js +9 -0
  114. package/dist/workspace/merge-queue/types.js.map +1 -1
  115. package/dist/workspace/pool/types.d.ts +1 -0
  116. package/dist/workspace/pool/types.d.ts.map +1 -1
  117. package/dist/workspace/pool/worktree-pool.d.ts.map +1 -1
  118. package/dist/workspace/pool/worktree-pool.js +1 -0
  119. package/dist/workspace/pool/worktree-pool.js.map +1 -1
  120. package/dist/workspace/recovery/abandon.d.ts +15 -0
  121. package/dist/workspace/recovery/abandon.d.ts.map +1 -0
  122. package/dist/workspace/recovery/abandon.js +45 -0
  123. package/dist/workspace/recovery/abandon.js.map +1 -0
  124. package/dist/workspace/recovery/auto-resolve.d.ts +27 -0
  125. package/dist/workspace/recovery/auto-resolve.d.ts.map +1 -0
  126. package/dist/workspace/recovery/auto-resolve.js +99 -0
  127. package/dist/workspace/recovery/auto-resolve.js.map +1 -0
  128. package/dist/workspace/recovery/defer.d.ts +15 -0
  129. package/dist/workspace/recovery/defer.d.ts.map +1 -0
  130. package/dist/workspace/recovery/defer.js +16 -0
  131. package/dist/workspace/recovery/defer.js.map +1 -0
  132. package/dist/workspace/recovery/escalate.d.ts +16 -0
  133. package/dist/workspace/recovery/escalate.d.ts.map +1 -0
  134. package/dist/workspace/recovery/escalate.js +24 -0
  135. package/dist/workspace/recovery/escalate.js.map +1 -0
  136. package/dist/workspace/recovery/index.d.ts +32 -0
  137. package/dist/workspace/recovery/index.d.ts.map +1 -0
  138. package/dist/workspace/recovery/index.js +45 -0
  139. package/dist/workspace/recovery/index.js.map +1 -0
  140. package/dist/workspace/recovery/spawn-resolver.d.ts +45 -0
  141. package/dist/workspace/recovery/spawn-resolver.d.ts.map +1 -0
  142. package/dist/workspace/recovery/spawn-resolver.js +111 -0
  143. package/dist/workspace/recovery/spawn-resolver.js.map +1 -0
  144. package/dist/workspace/recovery/types.d.ts +63 -0
  145. package/dist/workspace/recovery/types.d.ts.map +1 -0
  146. package/dist/workspace/recovery/types.js +12 -0
  147. package/dist/workspace/recovery/types.js.map +1 -0
  148. package/dist/workspace/topology/index.d.ts +9 -0
  149. package/dist/workspace/topology/index.d.ts.map +1 -0
  150. package/dist/workspace/topology/index.js +8 -0
  151. package/dist/workspace/topology/index.js.map +1 -0
  152. package/dist/workspace/topology/no-workspace.d.ts +18 -0
  153. package/dist/workspace/topology/no-workspace.d.ts.map +1 -0
  154. package/dist/workspace/topology/no-workspace.js +25 -0
  155. package/dist/workspace/topology/no-workspace.js.map +1 -0
  156. package/dist/workspace/topology/types.d.ts +97 -0
  157. package/dist/workspace/topology/types.d.ts.map +1 -0
  158. package/dist/workspace/topology/types.js +20 -0
  159. package/dist/workspace/topology/types.js.map +1 -0
  160. package/dist/workspace/topology/yaml-driven.d.ts +69 -0
  161. package/dist/workspace/topology/yaml-driven.d.ts.map +1 -0
  162. package/dist/workspace/topology/yaml-driven.js +273 -0
  163. package/dist/workspace/topology/yaml-driven.js.map +1 -0
  164. package/dist/workspace/types-v3.d.ts +110 -0
  165. package/dist/workspace/types-v3.d.ts.map +1 -0
  166. package/dist/workspace/types-v3.js +20 -0
  167. package/dist/workspace/types-v3.js.map +1 -0
  168. package/dist/workspace/types.d.ts +145 -17
  169. package/dist/workspace/types.d.ts.map +1 -1
  170. package/dist/workspace/workspace-manager.d.ts +92 -13
  171. package/dist/workspace/workspace-manager.d.ts.map +1 -1
  172. package/dist/workspace/workspace-manager.js +373 -13
  173. package/dist/workspace/workspace-manager.js.map +1 -1
  174. package/dist/workspace/yaml-schema.d.ts +254 -0
  175. package/dist/workspace/yaml-schema.d.ts.map +1 -0
  176. package/dist/workspace/yaml-schema.js +170 -0
  177. package/dist/workspace/yaml-schema.js.map +1 -0
  178. package/docs/conflict-recovery.md +472 -0
  179. package/docs/git-cascade-integration-gaps.md +678 -0
  180. package/docs/workspace-interfaces.md +731 -0
  181. package/docs/workspace-redesign-plan.md +302 -0
  182. package/package.json +4 -4
  183. package/src/__tests__/e2e/auto-sync.e2e.test.ts +257 -0
  184. package/src/__tests__/e2e/cascade-rebase.e2e.test.ts +254 -0
  185. package/src/__tests__/e2e/cli-run.e2e.test.ts +167 -0
  186. package/src/__tests__/e2e/self-driving-v3.e2e.test.ts +197 -0
  187. package/src/__tests__/e2e/spawn-resolver.e2e.test.ts +200 -0
  188. package/src/__tests__/e2e/workspace-lifecycle.e2e.test.ts +30 -22
  189. package/src/__tests__/e2e/workspace-v3.e2e.test.ts +413 -0
  190. package/src/acp/__tests__/claude-code-replay.test.ts +225 -0
  191. package/src/acp/__tests__/macro-agent.test.ts +39 -1
  192. package/src/acp/claude-code-replay.ts +208 -0
  193. package/src/acp/macro-agent.ts +167 -9
  194. package/src/acp/types.ts +10 -0
  195. package/src/agent/__tests__/agent-manager-topology.test.ts +73 -0
  196. package/src/agent/__tests__/agent-manager-v2.test.ts +71 -11
  197. package/src/agent/__tests__/task-ref-resolution.test.ts +231 -0
  198. package/src/agent/agent-manager-v2.ts +293 -77
  199. package/src/agent/agent-manager.ts +14 -0
  200. package/src/agent/types.ts +16 -2
  201. package/src/boot-v2.ts +87 -36
  202. package/src/cli/index.ts +61 -0
  203. package/src/cognitive/__tests__/macro-agent-backend.test.ts +47 -5
  204. package/src/cognitive/macro-agent-backend.ts +45 -29
  205. package/src/integrations/skilltree.ts +1 -0
  206. package/src/lifecycle/cleanup.ts +52 -3
  207. package/src/lifecycle/handlers-v2.ts +40 -3
  208. package/src/lifecycle/types.ts +12 -0
  209. package/src/map/__tests__/cascade-bridge.test.ts +229 -0
  210. package/src/map/__tests__/lifecycle-bridge.test.ts +165 -22
  211. package/src/map/acp-bridge.ts +26 -3
  212. package/src/map/cascade-bridge.ts +301 -0
  213. package/src/map/lifecycle-bridge.ts +77 -27
  214. package/src/map/server.ts +47 -6
  215. package/src/map/sidecar.ts +31 -3
  216. package/src/map/types.ts +20 -0
  217. package/src/mcp/tools/done-v2.ts +9 -0
  218. package/src/teams/team-manager-v2.ts +37 -0
  219. package/src/teams/team-runtime-v2.ts +23 -3
  220. package/src/workspace/__tests__/{dataplane-adapter.test.ts → git-cascade-adapter.test.ts} +209 -14
  221. package/src/workspace/__tests__/self-driving-yaml.test.ts +114 -0
  222. package/src/workspace/__tests__/shared-worktree-refcount.test.ts +154 -0
  223. package/src/workspace/__tests__/standalone-mode.test.ts +118 -0
  224. package/src/workspace/__tests__/workspace-manager-v3.test.ts +245 -0
  225. package/src/workspace/__tests__/yaml-schema.test.ts +210 -0
  226. package/src/workspace/config.ts +11 -11
  227. package/src/workspace/git-cascade-adapter.ts +1186 -0
  228. package/src/workspace/index.ts +11 -11
  229. package/src/workspace/landing/__tests__/strategies.test.ts +142 -0
  230. package/src/workspace/landing/direct-push.ts +91 -0
  231. package/src/workspace/landing/index.ts +40 -0
  232. package/src/workspace/landing/merge-to-parent.ts +228 -0
  233. package/src/workspace/landing/optimistic-push.ts +36 -0
  234. package/src/workspace/landing/queue-to-branch.ts +108 -0
  235. package/src/workspace/merge-queue/merge-queue.ts +10 -0
  236. package/src/workspace/merge-queue/types.ts +16 -2
  237. package/src/workspace/pool/__tests__/worktree-pool.integration.test.ts +5 -5
  238. package/src/workspace/pool/types.ts +1 -0
  239. package/src/workspace/pool/worktree-pool.ts +1 -0
  240. package/src/workspace/recovery/__tests__/auto-resolve-integration.test.ts +127 -0
  241. package/src/workspace/recovery/__tests__/spawn-resolver.test.ts +139 -0
  242. package/src/workspace/recovery/__tests__/strategies.test.ts +145 -0
  243. package/src/workspace/recovery/abandon.ts +51 -0
  244. package/src/workspace/recovery/auto-resolve.ts +119 -0
  245. package/src/workspace/recovery/defer.ts +23 -0
  246. package/src/workspace/recovery/escalate.ts +30 -0
  247. package/src/workspace/recovery/index.ts +58 -0
  248. package/src/workspace/recovery/spawn-resolver.ts +145 -0
  249. package/src/workspace/recovery/types.ts +54 -0
  250. package/src/workspace/topology/__tests__/yaml-driven.test.ts +345 -0
  251. package/src/workspace/topology/index.ts +18 -0
  252. package/src/workspace/topology/no-workspace.ts +39 -0
  253. package/src/workspace/topology/types.ts +116 -0
  254. package/src/workspace/topology/yaml-driven.ts +316 -0
  255. package/src/workspace/types-v3.ts +155 -0
  256. package/src/workspace/types.ts +191 -20
  257. package/src/workspace/workspace-manager.ts +474 -19
  258. package/src/workspace/yaml-schema.ts +216 -0
  259. package/src/workspace/dataplane-adapter.ts +0 -546
@@ -0,0 +1,200 @@
1
+ /**
2
+ * SpawnResolverStrategy real-spawn e2e.
3
+ *
4
+ * Exercises the full conflict recovery flow:
5
+ * 1. Set up a real conflict (two streams with conflicting changes)
6
+ * 2. SpawnResolverStrategy.recover() actually spawns a resolver agent
7
+ * via AgentManager (mocked Claude Code)
8
+ * 3. The resolver calls workspaceManager.resolveConflict() which emits
9
+ * conflict:resolved
10
+ * 4. The awaiting recover() Promise resolves
11
+ *
12
+ * Uses mocked acp-factory — focus is on the orchestration, not on an LLM
13
+ * actually resolving conflicts.
14
+ *
15
+ * REQUIRES: RUN_E2E_TESTS=true
16
+ */
17
+
18
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
19
+ import * as fs from 'fs';
20
+ import * as path from 'path';
21
+ import * as os from 'os';
22
+ import { execSync } from 'child_process';
23
+ import { bootV2, type MacroAgentSystemV2 } from '../../boot-v2.js';
24
+ import { GitCascadeAdapter } from '../../workspace/git-cascade-adapter.js';
25
+ import {
26
+ DefaultWorkspaceManager,
27
+ createWorkspaceManagerWithAdapter,
28
+ } from '../../workspace/workspace-manager.js';
29
+ import { createSpawnResolverStrategy } from '../../workspace/recovery/spawn-resolver.js';
30
+ import type { ConflictContext } from '../../workspace/recovery/types.js';
31
+
32
+ const RUN_E2E = !!process.env.RUN_E2E_TESTS;
33
+ const describeFn = RUN_E2E ? describe : describe.skip;
34
+
35
+ vi.mock('acp-factory', () => ({
36
+ AgentFactory: {
37
+ spawn: vi.fn().mockResolvedValue({
38
+ createSession: vi.fn().mockResolvedValue({
39
+ id: `session-${Date.now()}`,
40
+ prompt: vi.fn().mockReturnValue({
41
+ [Symbol.asyncIterator]: () => ({
42
+ next: () => Promise.resolve({ done: true, value: undefined }),
43
+ }),
44
+ }),
45
+ forkWithFlush: vi.fn().mockResolvedValue({ id: `forked-${Date.now()}` }),
46
+ }),
47
+ loadSession: vi.fn().mockResolvedValue({ id: `loaded-${Date.now()}` }),
48
+ close: vi.fn().mockResolvedValue(undefined),
49
+ isRunning: vi.fn().mockReturnValue(true),
50
+ }),
51
+ },
52
+ }));
53
+
54
+ vi.mock('opentasks', () => ({
55
+ OpenTasksClient: vi.fn().mockImplementation(() => ({
56
+ connect: vi.fn().mockRejectedValue(new Error('No daemon')),
57
+ disconnect: vi.fn(),
58
+ query: vi.fn().mockResolvedValue({ items: [] }),
59
+ link: vi.fn().mockResolvedValue({ success: true }),
60
+ task: vi.fn().mockResolvedValue({ id: 't-1' }),
61
+ })),
62
+ }));
63
+
64
+ describeFn('SpawnResolver real-spawn e2e', () => {
65
+ let system: MacroAgentSystemV2;
66
+ let testDir: string;
67
+ let repoPath: string;
68
+ let adapter: GitCascadeAdapter;
69
+ let workspaceManager: DefaultWorkspaceManager;
70
+
71
+ beforeEach(async () => {
72
+ testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'spawn-resolver-e2e-'));
73
+ repoPath = path.join(testDir, 'repo');
74
+ fs.mkdirSync(repoPath);
75
+
76
+ execSync('git init -b main', { cwd: repoPath, stdio: 'pipe' });
77
+ execSync('git config user.email "t@t.com"', { cwd: repoPath, stdio: 'pipe' });
78
+ execSync('git config user.name "T"', { cwd: repoPath, stdio: 'pipe' });
79
+ fs.writeFileSync(path.join(repoPath, 'README.md'), '# test');
80
+ execSync('git add .', { cwd: repoPath, stdio: 'pipe' });
81
+ execSync('git commit -m "init"', { cwd: repoPath, stdio: 'pipe' });
82
+
83
+ adapter = new GitCascadeAdapter({
84
+ enabled: true,
85
+ repoPath,
86
+ dbPath: path.join(testDir, 'gc.db'),
87
+ skipRecovery: true,
88
+ });
89
+ workspaceManager = createWorkspaceManagerWithAdapter(adapter, {
90
+ worktreeBaseDir: path.join(repoPath, '.worktrees'),
91
+ }) as DefaultWorkspaceManager;
92
+
93
+ system = await bootV2({
94
+ cwd: repoPath,
95
+ baseDir: testDir,
96
+ inbox: { socketPath: path.join(testDir, 'inbox.sock') },
97
+ workspaceManager,
98
+ });
99
+ });
100
+
101
+ afterEach(async () => {
102
+ if (system) await system.shutdown();
103
+ if (workspaceManager) workspaceManager.close();
104
+ if (adapter) adapter.close();
105
+ if (fs.existsSync(testDir)) fs.rmSync(testDir, { recursive: true, force: true });
106
+ });
107
+
108
+ it('spawns a real resolver agent and resolves via workspaceManager.resolveConflict', async () => {
109
+ // Set up: conflicted stream
110
+ const streamId = workspaceManager.createStreamV3({
111
+ name: 'conflicted-feature',
112
+ ownerId: 'team:test',
113
+ forkFrom: 'main',
114
+ });
115
+ const conflictId = adapter.createConflict({
116
+ streamId,
117
+ conflictingCommit: '0'.repeat(40),
118
+ targetCommit: '0'.repeat(40),
119
+ conflictedFiles: ['auth.ts'],
120
+ });
121
+
122
+ // Construct the strategy with AgentManager injection
123
+ const strategy = createSpawnResolverStrategy({
124
+ agentManager: system.agentManager,
125
+ defaultRole: 'worker', // using built-in worker role (has spawn capability)
126
+ defaultTimeoutMs: 10_000,
127
+ });
128
+
129
+ const ctx: ConflictContext = {
130
+ conflictId,
131
+ streamId,
132
+ paths: ['auth.ts'],
133
+ operation: 'merge',
134
+ recoveryDepth: 0,
135
+ workspaceManager,
136
+ strategyConfig: { role: 'worker', timeout_ms: 10_000 },
137
+ };
138
+
139
+ // Kick off recovery. Strategy spawns a resolver agent, then awaits
140
+ // conflict:resolved. We simulate the resolver's tool call by invoking
141
+ // workspaceManager.resolveConflict directly after a small delay.
142
+ const recoveryPromise = strategy.recover(ctx);
143
+
144
+ // Give the strategy time to spawn + subscribe
145
+ await new Promise((r) => setTimeout(r, 100));
146
+
147
+ // Simulate resolver finishing its work
148
+ workspaceManager.resolveConflict({
149
+ conflictId,
150
+ resolvedBy: 'agent_resolver_stub',
151
+ resolutionCommit: 'abc123def456',
152
+ });
153
+
154
+ const resolution = await recoveryPromise;
155
+ expect(resolution.kind).toBe('resolved');
156
+ if (resolution.kind === 'resolved') {
157
+ expect(resolution.resolutionCommit).toBe('abc123def456');
158
+ }
159
+
160
+ // A resolver agent should have actually been spawned by AgentManager
161
+ const agents = system.agentStore.listAgents({});
162
+ const resolverAgents = agents.filter((a) => a.role === 'worker');
163
+ expect(resolverAgents.length).toBeGreaterThan(0);
164
+ });
165
+
166
+ it('escalates to human on timeout (no resolve_conflict call)', async () => {
167
+ const streamId = workspaceManager.createStreamV3({
168
+ name: 'timeout-feature',
169
+ ownerId: 'team:test',
170
+ forkFrom: 'main',
171
+ });
172
+ const conflictId = adapter.createConflict({
173
+ streamId,
174
+ conflictingCommit: '0'.repeat(40),
175
+ targetCommit: '0'.repeat(40),
176
+ conflictedFiles: ['x.ts'],
177
+ });
178
+
179
+ const strategy = createSpawnResolverStrategy({
180
+ agentManager: system.agentManager,
181
+ defaultRole: 'worker',
182
+ defaultTimeoutMs: 200, // short timeout to force escalation
183
+ });
184
+
185
+ const resolution = await strategy.recover({
186
+ conflictId,
187
+ streamId,
188
+ paths: ['x.ts'],
189
+ operation: 'merge',
190
+ recoveryDepth: 0,
191
+ workspaceManager,
192
+ strategyConfig: { role: 'worker' },
193
+ });
194
+
195
+ expect(resolution.kind).toBe('escalated');
196
+ if (resolution.kind === 'escalated') {
197
+ expect(resolution.escalatedTo).toBe('human');
198
+ }
199
+ });
200
+ });
@@ -1,17 +1,25 @@
1
1
  /**
2
- * Workspace Lifecycle E2E Tests
2
+ * Workspace Lifecycle E2E Tests — LEGACY capability-dispatch path.
3
3
  *
4
- * Tests workspace isolation infrastructure through the V2 stack:
4
+ * These tests exercise the programmatic/capability-based spawn flow:
5
+ * callers pass `capabilities: ["workspace.worktree"|"workspace.stream"|
6
+ * "workspace.integrate"]` + `streamId`/`streamConfig` to `agentManager.spawn`,
7
+ * and AgentManagerV2's `legacyCapabilityDispatch` allocates workspaces via
8
+ * `WorkspaceManager.createWorkerWorkspace` / `createIntegratorWorkspace` /
9
+ * `createCoordinatorWorkspace`.
10
+ *
11
+ * This path remains supported for programmatic callers that don't use team
12
+ * YAML (e.g., tools, libraries). The V3 YAML-driven path is covered by
13
+ * `workspace-v3.e2e.test.ts`.
14
+ *
15
+ * Scenarios verified:
5
16
  * - Boot with WorkspaceManager wired correctly
6
- * - Worker spawn creates worktree
7
- * - Worker terminate submits merge request
8
- * - Cascade terminate cleans up worktrees
9
- * - Coordinator creates integration stream
17
+ * - Worker spawn creates worktree (capability-based)
18
+ * - Worker terminate submits merge request to (legacy) MergeQueue
19
+ * - Cascade terminate cleans up child worktrees
20
+ * - Coordinator creates integration stream via `workspace.stream` capability
10
21
  *
11
22
  * REQUIRES: RUN_E2E_TESTS=true (no real Claude Code agents)
12
- *
13
- * Run with:
14
- * RUN_E2E_TESTS=true npx vitest run --config vitest.e2e.config.ts src/__tests__/e2e/workspace-lifecycle.e2e.test.ts
15
23
  */
16
24
 
17
25
  import {
@@ -27,7 +35,7 @@ import * as os from "os";
27
35
  import * as fs from "fs";
28
36
  import { execSync } from "child_process";
29
37
  import { bootV2, type MacroAgentSystemV2 } from "../../boot-v2.js";
30
- import { DataplaneAdapter } from "../../workspace/dataplane-adapter.js";
38
+ import { GitCascadeAdapter } from "../../workspace/git-cascade-adapter.js";
31
39
  import {
32
40
  DefaultWorkspaceManager,
33
41
  createWorkspaceManagerWithAdapter,
@@ -121,17 +129,17 @@ describeFn("Workspace Lifecycle E2E", () => {
121
129
  let system: MacroAgentSystemV2;
122
130
  let testDir: string;
123
131
  let repoPath: string;
124
- let adapter: DataplaneAdapter;
132
+ let adapter: GitCascadeAdapter;
125
133
  let workspaceManager: DefaultWorkspaceManager;
126
134
 
127
135
  beforeEach(async () => {
128
136
  testDir = createTestDir();
129
137
  repoPath = createGitRepo(testDir);
130
138
 
131
- const dbPath = path.join(testDir, "dataplane.db");
139
+ const dbPath = path.join(testDir, "git-cascade.db");
132
140
 
133
- // Create DataplaneAdapter and WorkspaceManager
134
- adapter = new DataplaneAdapter({
141
+ // Create GitCascadeAdapter and WorkspaceManager
142
+ adapter = new GitCascadeAdapter({
135
143
  enabled: true,
136
144
  repoPath,
137
145
  dbPath,
@@ -191,17 +199,17 @@ describeFn("Workspace Lifecycle E2E", () => {
191
199
  });
192
200
  expect(streamId).toBeDefined();
193
201
 
194
- // Pre-create a dataplane task so the claimTask call can find it
202
+ // Pre-create a git-cascade task so the claimTask call can find it
195
203
  const dpTaskId = workspaceManager.createTask(streamId, {
196
204
  title: "Implement feature",
197
205
  });
198
206
 
199
- // Spawn a worker with the streamId and dataplaneTaskId
207
+ // Spawn a worker with the streamId and gitCascadeTaskId
200
208
  const worker = await system.agentManager.spawn({
201
209
  task: "Implement feature",
202
210
  role: "worker",
203
211
  streamId,
204
- dataplaneTaskId: dpTaskId,
212
+ gitCascadeTaskId: dpTaskId,
205
213
  capabilities: ["workspace.worktree"],
206
214
  });
207
215
 
@@ -234,7 +242,7 @@ describeFn("Workspace Lifecycle E2E", () => {
234
242
  name: "merge-feature",
235
243
  });
236
244
 
237
- // Pre-create dataplane task
245
+ // Pre-create git-cascade task
238
246
  const dpTaskId = workspaceManager.createTask(streamId, {
239
247
  title: "Do work for merge",
240
248
  });
@@ -244,7 +252,7 @@ describeFn("Workspace Lifecycle E2E", () => {
244
252
  task: "Do work for merge",
245
253
  role: "worker",
246
254
  streamId,
247
- dataplaneTaskId: dpTaskId,
255
+ gitCascadeTaskId: dpTaskId,
248
256
  capabilities: ["workspace.worktree"],
249
257
  });
250
258
 
@@ -294,7 +302,7 @@ describeFn("Workspace Lifecycle E2E", () => {
294
302
  { name: "cascade-feature" }
295
303
  );
296
304
 
297
- // Pre-create dataplane tasks
305
+ // Pre-create git-cascade tasks
298
306
  const dpTaskId1 = workspaceManager.createTask(streamId, {
299
307
  title: "Child 1",
300
308
  });
@@ -308,7 +316,7 @@ describeFn("Workspace Lifecycle E2E", () => {
308
316
  role: "worker",
309
317
  parent: coordinator.id,
310
318
  streamId,
311
- dataplaneTaskId: dpTaskId1,
319
+ gitCascadeTaskId: dpTaskId1,
312
320
  capabilities: ["workspace.worktree"],
313
321
  });
314
322
  const child2 = await system.agentManager.spawn({
@@ -316,7 +324,7 @@ describeFn("Workspace Lifecycle E2E", () => {
316
324
  role: "worker",
317
325
  parent: coordinator.id,
318
326
  streamId,
319
- dataplaneTaskId: dpTaskId2,
327
+ gitCascadeTaskId: dpTaskId2,
320
328
  capabilities: ["workspace.worktree"],
321
329
  });
322
330