macro-agent 0.1.8 → 0.1.11

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 (306) hide show
  1. package/CLAUDE.md +263 -33
  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 +192 -7
  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/adapters/tasks-adapter.d.ts.map +1 -1
  14. package/dist/adapters/tasks-adapter.js +3 -0
  15. package/dist/adapters/tasks-adapter.js.map +1 -1
  16. package/dist/adapters/types.d.ts +1 -0
  17. package/dist/adapters/types.d.ts.map +1 -1
  18. package/dist/agent/agent-manager-v2.d.ts +21 -0
  19. package/dist/agent/agent-manager-v2.d.ts.map +1 -1
  20. package/dist/agent/agent-manager-v2.js +308 -54
  21. package/dist/agent/agent-manager-v2.js.map +1 -1
  22. package/dist/agent/agent-manager.d.ts +12 -0
  23. package/dist/agent/agent-manager.d.ts.map +1 -1
  24. package/dist/agent/agent-manager.js.map +1 -1
  25. package/dist/agent/agent-store.d.ts +10 -0
  26. package/dist/agent/agent-store.d.ts.map +1 -1
  27. package/dist/agent/agent-store.js +22 -0
  28. package/dist/agent/agent-store.js.map +1 -1
  29. package/dist/agent/types.d.ts +15 -2
  30. package/dist/agent/types.d.ts.map +1 -1
  31. package/dist/agent/types.js.map +1 -1
  32. package/dist/boot-v2.d.ts +129 -1
  33. package/dist/boot-v2.d.ts.map +1 -1
  34. package/dist/boot-v2.js +359 -8
  35. package/dist/boot-v2.js.map +1 -1
  36. package/dist/cli/acp.js +4 -0
  37. package/dist/cli/acp.js.map +1 -1
  38. package/dist/cli/index.js +56 -0
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/cognitive/macro-agent-backend.d.ts.map +1 -1
  41. package/dist/cognitive/macro-agent-backend.js +40 -22
  42. package/dist/cognitive/macro-agent-backend.js.map +1 -1
  43. package/dist/integrations/skilltree.d.ts.map +1 -1
  44. package/dist/integrations/skilltree.js +1 -0
  45. package/dist/integrations/skilltree.js.map +1 -1
  46. package/dist/lifecycle/cascade.d.ts +25 -2
  47. package/dist/lifecycle/cascade.d.ts.map +1 -1
  48. package/dist/lifecycle/cascade.js +70 -2
  49. package/dist/lifecycle/cascade.js.map +1 -1
  50. package/dist/lifecycle/cleanup.d.ts +33 -2
  51. package/dist/lifecycle/cleanup.d.ts.map +1 -1
  52. package/dist/lifecycle/cleanup.js +28 -6
  53. package/dist/lifecycle/cleanup.js.map +1 -1
  54. package/dist/lifecycle/handlers-v2.d.ts +7 -0
  55. package/dist/lifecycle/handlers-v2.d.ts.map +1 -1
  56. package/dist/lifecycle/handlers-v2.js +28 -2
  57. package/dist/lifecycle/handlers-v2.js.map +1 -1
  58. package/dist/lifecycle/types.d.ts +11 -0
  59. package/dist/lifecycle/types.d.ts.map +1 -1
  60. package/dist/lifecycle/types.js.map +1 -1
  61. package/dist/map/acp-bridge.d.ts +9 -0
  62. package/dist/map/acp-bridge.d.ts.map +1 -1
  63. package/dist/map/acp-bridge.js +15 -2
  64. package/dist/map/acp-bridge.js.map +1 -1
  65. package/dist/map/cascade-action-handler.d.ts +24 -0
  66. package/dist/map/cascade-action-handler.d.ts.map +1 -0
  67. package/dist/map/cascade-action-handler.js +170 -0
  68. package/dist/map/cascade-action-handler.js.map +1 -0
  69. package/dist/map/cascade-bridge.d.ts +44 -0
  70. package/dist/map/cascade-bridge.d.ts.map +1 -0
  71. package/dist/map/cascade-bridge.js +294 -0
  72. package/dist/map/cascade-bridge.js.map +1 -0
  73. package/dist/map/coordination-handler.d.ts.map +1 -1
  74. package/dist/map/coordination-handler.js +12 -1
  75. package/dist/map/coordination-handler.js.map +1 -1
  76. package/dist/map/lifecycle-bridge.d.ts +1 -1
  77. package/dist/map/lifecycle-bridge.d.ts.map +1 -1
  78. package/dist/map/lifecycle-bridge.js +58 -23
  79. package/dist/map/lifecycle-bridge.js.map +1 -1
  80. package/dist/map/server.d.ts.map +1 -1
  81. package/dist/map/server.js +219 -7
  82. package/dist/map/server.js.map +1 -1
  83. package/dist/map/sidecar.d.ts.map +1 -1
  84. package/dist/map/sidecar.js +49 -2
  85. package/dist/map/sidecar.js.map +1 -1
  86. package/dist/map/types.d.ts +22 -0
  87. package/dist/map/types.d.ts.map +1 -1
  88. package/dist/mcp/tools/done-v2.d.ts.map +1 -1
  89. package/dist/mcp/tools/done-v2.js +8 -0
  90. package/dist/mcp/tools/done-v2.js.map +1 -1
  91. package/dist/teams/team-manager-v2.d.ts.map +1 -1
  92. package/dist/teams/team-manager-v2.js +26 -0
  93. package/dist/teams/team-manager-v2.js.map +1 -1
  94. package/dist/teams/team-runtime-v2.d.ts.map +1 -1
  95. package/dist/teams/team-runtime-v2.js +16 -3
  96. package/dist/teams/team-runtime-v2.js.map +1 -1
  97. package/dist/workspace/config.d.ts +10 -10
  98. package/dist/workspace/config.d.ts.map +1 -1
  99. package/dist/workspace/config.js +4 -4
  100. package/dist/workspace/config.js.map +1 -1
  101. package/dist/workspace/git-cascade-adapter.d.ts +510 -0
  102. package/dist/workspace/git-cascade-adapter.d.ts.map +1 -0
  103. package/dist/workspace/git-cascade-adapter.js +934 -0
  104. package/dist/workspace/git-cascade-adapter.js.map +1 -0
  105. package/dist/workspace/index.d.ts +3 -3
  106. package/dist/workspace/index.d.ts.map +1 -1
  107. package/dist/workspace/index.js +4 -4
  108. package/dist/workspace/index.js.map +1 -1
  109. package/dist/workspace/landing/direct-push.d.ts +20 -0
  110. package/dist/workspace/landing/direct-push.d.ts.map +1 -0
  111. package/dist/workspace/landing/direct-push.js +74 -0
  112. package/dist/workspace/landing/direct-push.js.map +1 -0
  113. package/dist/workspace/landing/index.d.ts +29 -0
  114. package/dist/workspace/landing/index.d.ts.map +1 -0
  115. package/dist/workspace/landing/index.js +37 -0
  116. package/dist/workspace/landing/index.js.map +1 -0
  117. package/dist/workspace/landing/merge-to-parent.d.ts +41 -0
  118. package/dist/workspace/landing/merge-to-parent.d.ts.map +1 -0
  119. package/dist/workspace/landing/merge-to-parent.js +186 -0
  120. package/dist/workspace/landing/merge-to-parent.js.map +1 -0
  121. package/dist/workspace/landing/optimistic-push.d.ts +16 -0
  122. package/dist/workspace/landing/optimistic-push.d.ts.map +1 -0
  123. package/dist/workspace/landing/optimistic-push.js +27 -0
  124. package/dist/workspace/landing/optimistic-push.js.map +1 -0
  125. package/dist/workspace/landing/queue-to-branch.d.ts +24 -0
  126. package/dist/workspace/landing/queue-to-branch.d.ts.map +1 -0
  127. package/dist/workspace/landing/queue-to-branch.js +79 -0
  128. package/dist/workspace/landing/queue-to-branch.js.map +1 -0
  129. package/dist/workspace/merge-queue/merge-queue.d.ts +10 -0
  130. package/dist/workspace/merge-queue/merge-queue.d.ts.map +1 -1
  131. package/dist/workspace/merge-queue/merge-queue.js +10 -0
  132. package/dist/workspace/merge-queue/merge-queue.js.map +1 -1
  133. package/dist/workspace/merge-queue/types.d.ts +16 -2
  134. package/dist/workspace/merge-queue/types.d.ts.map +1 -1
  135. package/dist/workspace/merge-queue/types.js +9 -0
  136. package/dist/workspace/merge-queue/types.js.map +1 -1
  137. package/dist/workspace/pool/types.d.ts +1 -0
  138. package/dist/workspace/pool/types.d.ts.map +1 -1
  139. package/dist/workspace/pool/worktree-pool.d.ts.map +1 -1
  140. package/dist/workspace/pool/worktree-pool.js +1 -0
  141. package/dist/workspace/pool/worktree-pool.js.map +1 -1
  142. package/dist/workspace/recovery/abandon.d.ts +15 -0
  143. package/dist/workspace/recovery/abandon.d.ts.map +1 -0
  144. package/dist/workspace/recovery/abandon.js +45 -0
  145. package/dist/workspace/recovery/abandon.js.map +1 -0
  146. package/dist/workspace/recovery/auto-resolve.d.ts +27 -0
  147. package/dist/workspace/recovery/auto-resolve.d.ts.map +1 -0
  148. package/dist/workspace/recovery/auto-resolve.js +99 -0
  149. package/dist/workspace/recovery/auto-resolve.js.map +1 -0
  150. package/dist/workspace/recovery/defer.d.ts +15 -0
  151. package/dist/workspace/recovery/defer.d.ts.map +1 -0
  152. package/dist/workspace/recovery/defer.js +16 -0
  153. package/dist/workspace/recovery/defer.js.map +1 -0
  154. package/dist/workspace/recovery/escalate.d.ts +16 -0
  155. package/dist/workspace/recovery/escalate.d.ts.map +1 -0
  156. package/dist/workspace/recovery/escalate.js +24 -0
  157. package/dist/workspace/recovery/escalate.js.map +1 -0
  158. package/dist/workspace/recovery/index.d.ts +32 -0
  159. package/dist/workspace/recovery/index.d.ts.map +1 -0
  160. package/dist/workspace/recovery/index.js +45 -0
  161. package/dist/workspace/recovery/index.js.map +1 -0
  162. package/dist/workspace/recovery/spawn-resolver.d.ts +45 -0
  163. package/dist/workspace/recovery/spawn-resolver.d.ts.map +1 -0
  164. package/dist/workspace/recovery/spawn-resolver.js +118 -0
  165. package/dist/workspace/recovery/spawn-resolver.js.map +1 -0
  166. package/dist/workspace/recovery/types.d.ts +63 -0
  167. package/dist/workspace/recovery/types.d.ts.map +1 -0
  168. package/dist/workspace/recovery/types.js +12 -0
  169. package/dist/workspace/recovery/types.js.map +1 -0
  170. package/dist/workspace/topology/index.d.ts +9 -0
  171. package/dist/workspace/topology/index.d.ts.map +1 -0
  172. package/dist/workspace/topology/index.js +8 -0
  173. package/dist/workspace/topology/index.js.map +1 -0
  174. package/dist/workspace/topology/no-workspace.d.ts +18 -0
  175. package/dist/workspace/topology/no-workspace.d.ts.map +1 -0
  176. package/dist/workspace/topology/no-workspace.js +25 -0
  177. package/dist/workspace/topology/no-workspace.js.map +1 -0
  178. package/dist/workspace/topology/types.d.ts +97 -0
  179. package/dist/workspace/topology/types.d.ts.map +1 -0
  180. package/dist/workspace/topology/types.js +20 -0
  181. package/dist/workspace/topology/types.js.map +1 -0
  182. package/dist/workspace/topology/yaml-driven.d.ts +69 -0
  183. package/dist/workspace/topology/yaml-driven.d.ts.map +1 -0
  184. package/dist/workspace/topology/yaml-driven.js +273 -0
  185. package/dist/workspace/topology/yaml-driven.js.map +1 -0
  186. package/dist/workspace/types-v3.d.ts +117 -0
  187. package/dist/workspace/types-v3.d.ts.map +1 -0
  188. package/dist/workspace/types-v3.js +20 -0
  189. package/dist/workspace/types-v3.js.map +1 -0
  190. package/dist/workspace/types.d.ts +162 -17
  191. package/dist/workspace/types.d.ts.map +1 -1
  192. package/dist/workspace/workspace-manager.d.ts +101 -13
  193. package/dist/workspace/workspace-manager.d.ts.map +1 -1
  194. package/dist/workspace/workspace-manager.js +416 -13
  195. package/dist/workspace/workspace-manager.js.map +1 -1
  196. package/dist/workspace/yaml-schema.d.ts +254 -0
  197. package/dist/workspace/yaml-schema.d.ts.map +1 -0
  198. package/dist/workspace/yaml-schema.js +170 -0
  199. package/dist/workspace/yaml-schema.js.map +1 -0
  200. package/docs/conflict-recovery.md +472 -0
  201. package/docs/design/task-dispatcher.md +880 -0
  202. package/docs/git-cascade-integration-gaps.md +678 -0
  203. package/docs/workspace-interfaces.md +731 -0
  204. package/docs/workspace-redesign-plan.md +302 -0
  205. package/package.json +6 -5
  206. package/src/__tests__/boot-v2.test.ts +435 -0
  207. package/src/__tests__/e2e/acp-over-map.e2e.test.ts +92 -0
  208. package/src/__tests__/e2e/auto-sync.e2e.test.ts +257 -0
  209. package/src/__tests__/e2e/bootstrap.e2e.test.ts +319 -0
  210. package/src/__tests__/e2e/cascade-rebase.e2e.test.ts +254 -0
  211. package/src/__tests__/e2e/cli-run.e2e.test.ts +167 -0
  212. package/src/__tests__/e2e/dispatch-coordination.e2e.test.ts +495 -0
  213. package/src/__tests__/e2e/dispatch-live.e2e.test.ts +564 -0
  214. package/src/__tests__/e2e/dispatch-opentasks.e2e.test.ts +496 -0
  215. package/src/__tests__/e2e/dispatch-phase2-live.e2e.test.ts +456 -0
  216. package/src/__tests__/e2e/dispatch-phase2.e2e.test.ts +386 -0
  217. package/src/__tests__/e2e/dispatch.e2e.test.ts +376 -0
  218. package/src/__tests__/e2e/self-driving-v3.e2e.test.ts +197 -0
  219. package/src/__tests__/e2e/spawn-resolver.e2e.test.ts +200 -0
  220. package/src/__tests__/e2e/workspace-lifecycle.e2e.test.ts +30 -22
  221. package/src/__tests__/e2e/workspace-v3.e2e.test.ts +413 -0
  222. package/src/acp/__tests__/claude-code-replay.test.ts +225 -0
  223. package/src/acp/__tests__/macro-agent.test.ts +39 -1
  224. package/src/acp/claude-code-replay.ts +208 -0
  225. package/src/acp/macro-agent.ts +203 -10
  226. package/src/acp/types.ts +10 -0
  227. package/src/adapters/__tests__/tasks-adapter.test.ts +1 -0
  228. package/src/adapters/tasks-adapter.ts +3 -0
  229. package/src/adapters/types.ts +1 -0
  230. package/src/agent/__tests__/agent-manager-topology.test.ts +73 -0
  231. package/src/agent/__tests__/agent-manager-v2.test.ts +66 -0
  232. package/src/agent/__tests__/agent-store.test.ts +52 -0
  233. package/src/agent/__tests__/task-ref-resolution.test.ts +231 -0
  234. package/src/agent/agent-manager-v2.ts +372 -59
  235. package/src/agent/agent-manager.ts +14 -0
  236. package/src/agent/agent-store.ts +24 -0
  237. package/src/agent/types.ts +16 -2
  238. package/src/boot-v2.ts +589 -35
  239. package/src/cli/acp.ts +4 -0
  240. package/src/cli/index.ts +61 -0
  241. package/src/cognitive/macro-agent-backend.ts +45 -29
  242. package/src/integrations/skilltree.ts +1 -0
  243. package/src/lifecycle/__tests__/cascade-consolidation.test.ts +240 -0
  244. package/src/lifecycle/cascade.ts +77 -2
  245. package/src/lifecycle/cleanup.ts +52 -3
  246. package/src/lifecycle/handlers-v2.ts +40 -3
  247. package/src/lifecycle/types.ts +12 -0
  248. package/src/map/__tests__/cascade-bridge.test.ts +229 -0
  249. package/src/map/__tests__/emit-event.test.ts +71 -0
  250. package/src/map/__tests__/lifecycle-bridge.test.ts +86 -10
  251. package/src/map/acp-bridge.ts +26 -3
  252. package/src/map/cascade-action-handler.ts +205 -0
  253. package/src/map/cascade-bridge.ts +339 -0
  254. package/src/map/coordination-handler.ts +13 -1
  255. package/src/map/lifecycle-bridge.ts +52 -17
  256. package/src/map/server.ts +225 -7
  257. package/src/map/sidecar.ts +48 -1
  258. package/src/map/types.ts +23 -0
  259. package/src/mcp/tools/done-v2.ts +9 -0
  260. package/src/teams/team-manager-v2.ts +37 -0
  261. package/src/teams/team-runtime-v2.ts +23 -3
  262. package/src/workspace/__tests__/{dataplane-adapter.test.ts → git-cascade-adapter.test.ts} +209 -14
  263. package/src/workspace/__tests__/land-dispatch.test.ts +214 -0
  264. package/src/workspace/__tests__/self-driving-yaml.test.ts +114 -0
  265. package/src/workspace/__tests__/shared-worktree-refcount.test.ts +154 -0
  266. package/src/workspace/__tests__/standalone-mode.test.ts +118 -0
  267. package/src/workspace/__tests__/workspace-manager-v3.test.ts +245 -0
  268. package/src/workspace/__tests__/yaml-schema.test.ts +210 -0
  269. package/src/workspace/config.ts +11 -11
  270. package/src/workspace/git-cascade-adapter.ts +1213 -0
  271. package/src/workspace/index.ts +11 -11
  272. package/src/workspace/landing/__tests__/strategies.test.ts +184 -0
  273. package/src/workspace/landing/direct-push.ts +91 -0
  274. package/src/workspace/landing/index.ts +40 -0
  275. package/src/workspace/landing/merge-to-parent.ts +229 -0
  276. package/src/workspace/landing/optimistic-push.ts +36 -0
  277. package/src/workspace/landing/queue-to-branch.ts +108 -0
  278. package/src/workspace/merge-queue/merge-queue.ts +10 -0
  279. package/src/workspace/merge-queue/types.ts +16 -2
  280. package/src/workspace/pool/__tests__/worktree-pool.integration.test.ts +5 -5
  281. package/src/workspace/pool/types.ts +1 -0
  282. package/src/workspace/pool/worktree-pool.ts +1 -0
  283. package/src/workspace/recovery/__tests__/auto-resolve-integration.test.ts +127 -0
  284. package/src/workspace/recovery/__tests__/spawn-resolver.test.ts +139 -0
  285. package/src/workspace/recovery/__tests__/strategies.test.ts +145 -0
  286. package/src/workspace/recovery/abandon.ts +51 -0
  287. package/src/workspace/recovery/auto-resolve.ts +119 -0
  288. package/src/workspace/recovery/defer.ts +23 -0
  289. package/src/workspace/recovery/escalate.ts +30 -0
  290. package/src/workspace/recovery/index.ts +58 -0
  291. package/src/workspace/recovery/spawn-resolver.ts +152 -0
  292. package/src/workspace/recovery/types.ts +54 -0
  293. package/src/workspace/topology/__tests__/yaml-driven.test.ts +345 -0
  294. package/src/workspace/topology/index.ts +18 -0
  295. package/src/workspace/topology/no-workspace.ts +39 -0
  296. package/src/workspace/topology/types.ts +116 -0
  297. package/src/workspace/topology/yaml-driven.ts +316 -0
  298. package/src/workspace/types-v3.ts +162 -0
  299. package/src/workspace/types.ts +211 -20
  300. package/src/workspace/workspace-manager.ts +533 -19
  301. package/src/workspace/yaml-schema.ts +216 -0
  302. package/dist/workspace/dataplane-adapter.d.ts +0 -260
  303. package/dist/workspace/dataplane-adapter.d.ts.map +0 -1
  304. package/dist/workspace/dataplane-adapter.js +0 -416
  305. package/dist/workspace/dataplane-adapter.js.map +0 -1
  306. package/src/workspace/dataplane-adapter.ts +0 -546
@@ -0,0 +1,731 @@
1
+ # Workspace Interfaces (Draft)
2
+
3
+ Concrete TypeScript sketches for the redesigned workspace layer described in `docs/git-cascade-integration-gaps.md`. This file is the interface contract; the narrative doc is the rationale.
4
+
5
+ **Status**: draft for iteration. Not yet implemented. Not yet ported to call sites.
6
+
7
+ Three things are defined here:
8
+
9
+ 1. **`WorkspaceManager`** — stream-first API that sits above git-cascade. Used by programmatic consumers (cognitive-core), TopologyPolicy compilers, and MCP tool handlers.
10
+ 2. **`TopologyPolicy`** — compiles team YAML (`macro_agent.workspace`) into spawn-time workspace decisions and lifecycle hooks. The compiler is the only thing that reads YAML; everything downstream sees resolved policy objects.
11
+ 3. **`LandingStrategy`** — pluggable landing algorithm. Strategies register globally; YAML role config picks which strategy each stream uses.
12
+
13
+ Plus supporting surfaces:
14
+
15
+ - **YAML Zod schema** for `macro_agent.workspace` validation.
16
+ - **MCP tool schemas** for agent-facing workspace tools.
17
+ - **Built-in registrations** (5 landing strategies, 5 topology policies).
18
+
19
+ ---
20
+
21
+ ## 1. Core primitives
22
+
23
+ ```ts
24
+ // Identity types
25
+ export type AgentId = string;
26
+ export type StreamId = string;
27
+ export type ChangeId = string;
28
+ export type QueueEntryId = string;
29
+
30
+ // Pseudo-principals for entities that aren't real agents (team roots, system owners).
31
+ // Tagged via prefix; never terminates.
32
+ export type PseudoAgentId =
33
+ | `team:${string}`
34
+ | `system:${string}`;
35
+
36
+ export type Principal = AgentId | PseudoAgentId;
37
+
38
+ export const isPseudo = (p: Principal): p is PseudoAgentId =>
39
+ p.startsWith("team:") || p.startsWith("system:");
40
+ ```
41
+
42
+ ---
43
+
44
+ ## 2. Stream & worktree types
45
+
46
+ ```ts
47
+ export type StreamStatus = "active" | "merged" | "abandoned" | "conflicted" | "paused";
48
+
49
+ export interface Stream {
50
+ id: StreamId;
51
+ name: string;
52
+ ownerId: Principal;
53
+ parentStreamId?: StreamId;
54
+ baseCommit: string;
55
+ branch: string;
56
+ status: StreamStatus;
57
+ metadata: Record<string, unknown>;
58
+ createdAt: number;
59
+ }
60
+
61
+ export interface StreamNode {
62
+ stream: Stream;
63
+ children: StreamNode[];
64
+ activeTaskCount: number;
65
+ }
66
+
67
+ export interface Change {
68
+ id: ChangeId;
69
+ streamId: StreamId;
70
+ currentCommit: string;
71
+ historicalCommits: string[];
72
+ status: "active" | "merged" | "dropped";
73
+ createdAt: number;
74
+ }
75
+
76
+ export interface StreamSpec {
77
+ name: string;
78
+ ownerId: Principal;
79
+ parent?: StreamId; // fork from this stream (takes precedence)
80
+ forkFrom?: string; // otherwise fork from this branch
81
+ metadata?: Record<string, unknown>;
82
+ }
83
+
84
+ export interface Worktree {
85
+ agentId: Principal;
86
+ path: string;
87
+ streamId?: StreamId; // worktrees may be detached
88
+ branch: string;
89
+ pooled: boolean;
90
+ sharedWithAgents: AgentId[]; // ref-counted shares
91
+ createdAt: number;
92
+ }
93
+
94
+ export interface AllocateWorktreeOpts {
95
+ agentId: Principal;
96
+ streamId?: StreamId;
97
+ baseDir?: string;
98
+ pooled?: boolean;
99
+ sharedWithAgent?: AgentId; // if set, co-locates on that agent's worktree; ref-counted
100
+ }
101
+ ```
102
+
103
+ ---
104
+
105
+ ## 3. Results & conflict types
106
+
107
+ ```ts
108
+ export type ConflictStrategy = "abort" | "ours" | "theirs" | "defer" | "agent";
109
+ export type CascadeStrategy = "stop_on_conflict" | "skip_conflicting" | "defer_conflicts";
110
+
111
+ export interface MergeResult {
112
+ success: boolean;
113
+ mergeCommit?: string;
114
+ changeIds?: ChangeId[];
115
+ conflictId?: string;
116
+ }
117
+
118
+ export interface RebaseResult {
119
+ success: boolean;
120
+ rebasedCommits?: string[];
121
+ conflictId?: string;
122
+ }
123
+
124
+ export interface CascadeResult {
125
+ rootStreamId: StreamId;
126
+ succeeded: StreamId[];
127
+ failed: Array<{ streamId: StreamId; conflictId?: string; error?: string }>;
128
+ }
129
+
130
+ export interface ConflictRecord {
131
+ id: string;
132
+ streamId: StreamId;
133
+ sourceCommit?: string;
134
+ targetCommit?: string;
135
+ paths: string[];
136
+ createdAt: number;
137
+ resolvedAt?: number;
138
+ }
139
+
140
+ export interface ReconcileResult {
141
+ streamsChecked: number;
142
+ streamsFixed: number;
143
+ worktreesOrphaned: number;
144
+ worktreesCleaned: number;
145
+ poolEntriesPurged: number;
146
+ errors: Array<{ context: string; message: string }>;
147
+ }
148
+ ```
149
+
150
+ ---
151
+
152
+ ## 4. Events
153
+
154
+ All three control layers (YAML-compiled, MCP tools, programmatic) emit the same stream.
155
+
156
+ ```ts
157
+ export type WorkspaceEvent =
158
+ | { kind: "stream.created"; streamId: StreamId; ownerId: Principal; parentStreamId?: StreamId }
159
+ | { kind: "stream.committed"; streamId: StreamId; commit: string; changeId: ChangeId; agentId: Principal }
160
+ | { kind: "stream.merged"; sourceStreamId: StreamId; targetStreamId: StreamId; mergeCommit: string }
161
+ | { kind: "stream.conflicted"; streamId: StreamId; conflictId: string }
162
+ | { kind: "stream.abandoned"; streamId: StreamId; reason?: string }
163
+ | { kind: "stream.paused"; streamId: StreamId; reason?: string }
164
+ | { kind: "stream.resumed"; streamId: StreamId }
165
+ | { kind: "worktree.allocated"; agentId: Principal; path: string; streamId?: StreamId }
166
+ | { kind: "worktree.deallocated"; agentId: Principal; path: string }
167
+ | { kind: "worktree.shared"; ownerAgentId: AgentId; sharingAgentId: AgentId; path: string }
168
+ | { kind: "landing.started"; agentId: AgentId; streamId: StreamId; strategyName: string }
169
+ | { kind: "landing.completed"; agentId: AgentId; streamId: StreamId; result: MergeResult | RebaseResult }
170
+ | { kind: "cascade.started"; rootStreamId: StreamId }
171
+ | { kind: "cascade.completed"; result: CascadeResult };
172
+
173
+ export type WorkspaceEventCallback = (e: WorkspaceEvent) => void;
174
+ ```
175
+
176
+ ---
177
+
178
+ ## 5. `WorkspaceManager` interface
179
+
180
+ ```ts
181
+ export interface WorkspaceManager {
182
+ // ── Stream management ──────────────────────────────────────────
183
+ createStream(spec: StreamSpec): StreamId;
184
+
185
+ forkStream(opts: {
186
+ parentStreamId: StreamId;
187
+ name: string;
188
+ ownerId: Principal;
189
+ metadata?: Record<string, unknown>;
190
+ }): StreamId;
191
+
192
+ mergeStream(opts: {
193
+ sourceStreamId: StreamId;
194
+ targetStreamId: StreamId;
195
+ agentId: Principal;
196
+ worktree: string;
197
+ }): MergeResult;
198
+
199
+ syncWithParent(opts: {
200
+ streamId: StreamId;
201
+ agentId: Principal;
202
+ worktree: string;
203
+ onConflict?: ConflictStrategy;
204
+ }): RebaseResult;
205
+
206
+ rebaseOntoStream(opts: {
207
+ streamId: StreamId;
208
+ targetStreamId: StreamId;
209
+ agentId: Principal;
210
+ worktree: string;
211
+ onConflict?: ConflictStrategy;
212
+ }): RebaseResult;
213
+
214
+ cascadeRebase(opts: {
215
+ rootStreamId: StreamId;
216
+ strategy: CascadeStrategy;
217
+ worktreeProvider: (streamId: StreamId) => string | null;
218
+ }): CascadeResult;
219
+
220
+ abandonStream(streamId: StreamId, opts?: { cascade?: boolean; reason?: string }): void;
221
+ pauseStream(streamId: StreamId, reason?: string): void;
222
+ resumeStream(streamId: StreamId): void;
223
+
224
+ getStream(streamId: StreamId): Stream | null;
225
+ listStreams(filter?: { ownerId?: Principal; status?: StreamStatus; parentStreamId?: StreamId }): Stream[];
226
+ getStreamHierarchy(rootStreamId?: StreamId): StreamNode | StreamNode[];
227
+ getDependents(streamId: StreamId): StreamId[];
228
+
229
+ // ── Changes (Change-Id tracking) ───────────────────────────────
230
+ commitChanges(opts: {
231
+ agentId: Principal;
232
+ streamId: StreamId;
233
+ worktree: string;
234
+ message: string;
235
+ }): { commit: string; changeId: ChangeId };
236
+
237
+ markChangesMerged(changeIds: ChangeId[]): void;
238
+ getChange(changeId: ChangeId): Change | null;
239
+ getChangeByCommit(commit: string): Change | null;
240
+
241
+ // ── Worktree management ────────────────────────────────────────
242
+ allocateWorktree(opts: AllocateWorktreeOpts): Worktree;
243
+ deallocateWorktree(agentId: Principal): void;
244
+ getWorktreeForAgent(agentId: Principal): Worktree | null;
245
+ listWorktrees(): Worktree[];
246
+
247
+ // ── Conflicts ──────────────────────────────────────────────────
248
+ getConflictForStream(streamId: StreamId): ConflictRecord | null;
249
+ resolveConflict(opts: { conflictId: string; resolvedBy: Principal; resolutionCommit?: string }): void;
250
+
251
+ // ── Landing ────────────────────────────────────────────────────
252
+ registerLandingStrategy(strategy: LandingStrategy): void;
253
+ unregisterLandingStrategy(name: string): void;
254
+ getLandingStrategy(name: string): LandingStrategy | null;
255
+
256
+ land(opts: {
257
+ agentId: AgentId;
258
+ streamId: StreamId;
259
+ strategyName?: string;
260
+ targetStreamId?: StreamId;
261
+ strategyConfig?: Record<string, unknown>;
262
+ }): Promise<MergeResult>;
263
+
264
+ // ── Merge queue (delegates to git-cascade's built-in) ──────────
265
+ addToMergeQueue(opts: {
266
+ streamId: StreamId;
267
+ targetBranch: string;
268
+ priority?: number;
269
+ }): QueueEntryId;
270
+
271
+ getNextToMerge(targetBranch?: string): MergeQueueEntry | null;
272
+ markMergeQueueReady(entryId: QueueEntryId): void;
273
+ cancelMergeQueueEntry(entryId: QueueEntryId): void;
274
+ getMergeQueuePosition(streamId: StreamId, targetBranch?: string): number | null;
275
+
276
+ // ── Reconciliation & health ────────────────────────────────────
277
+ reconcile(): ReconcileResult;
278
+ healthCheck(): HealthCheckResult;
279
+
280
+ // ── Events ─────────────────────────────────────────────────────
281
+ onEvent(cb: WorkspaceEventCallback): () => void;
282
+
283
+ // ── Lifecycle ──────────────────────────────────────────────────
284
+ close(): void;
285
+ }
286
+
287
+ export interface MergeQueueEntry {
288
+ id: QueueEntryId;
289
+ streamId: StreamId;
290
+ targetBranch: string;
291
+ status: "pending" | "ready" | "in_progress" | "merged" | "cancelled" | "failed";
292
+ priority: number;
293
+ submittedAt: number;
294
+ }
295
+
296
+ export interface HealthCheckResult {
297
+ streamsActive: number;
298
+ streamsArchived: number;
299
+ agentsActive: number;
300
+ staleLocks: number;
301
+ incompleteOperations: number;
302
+ orphanedConflicts: number;
303
+ orphanedWorktrees: number;
304
+ }
305
+ ```
306
+
307
+ ---
308
+
309
+ ## 6. `LandingStrategy` interface
310
+
311
+ ```ts
312
+ export interface LandingContext {
313
+ agentId: AgentId;
314
+ streamId: StreamId;
315
+ sourceWorktree: string;
316
+ targetStreamId?: StreamId;
317
+ strategyConfig?: Record<string, unknown>; // from YAML `landing_config`
318
+ workspaceManager: WorkspaceManager;
319
+ }
320
+
321
+ export interface LandingStrategy {
322
+ readonly name: string;
323
+
324
+ // Optional: strategy decides if it applies given the context
325
+ canLand?(ctx: LandingContext): boolean;
326
+
327
+ // Execute the landing
328
+ land(ctx: LandingContext): Promise<MergeResult>;
329
+
330
+ // Optional lifecycle hooks
331
+ initialize?(): Promise<void>;
332
+ close?(): Promise<void>;
333
+ }
334
+ ```
335
+
336
+ ### 6.1 Built-in strategies
337
+
338
+ ```ts
339
+ // merge-to-parent: merge sourceStream → targetStream (or parent of source).
340
+ // On success: optionally cascadeRebase if strategyConfig.cascade === true.
341
+ // Used by: peer swarm, long-lived feature, solo stack.
342
+
343
+ // queue-to-branch: add to merge queue; return immediately. Actual merge is drained
344
+ // by an integrator-capable agent calling processMergeQueue / merge_stream.
345
+ // strategyConfig: { target: "stream:<id>" | "branch:<name>" | "role:<role>" }.
346
+ // Used by: triad (workers), pipeline (coders).
347
+
348
+ // cherry-pick-stack: createStackFromStream + cherryPickStackToTarget. Preserves
349
+ // commit identity via Change-Ids. strategyConfig: { target_branch: string }.
350
+ // Used by: stacked-diff review workflows.
351
+
352
+ // direct-push: rebase onto target + push. Raw execSync (current trunk strategy).
353
+ // strategyConfig: { target_branch: string; max_retries?: number }.
354
+ // Used by: trunk-based flows without a merge queue.
355
+
356
+ // optimistic-push: direct-push + emit `validation:requested` event.
357
+ // Validation delegated to a judge role.
358
+ // Used by: self-driving team today.
359
+ ```
360
+
361
+ Strategy registration happens once at boot; all 5 are registered by default. Teams pick via YAML `landing: <strategy_name>`.
362
+
363
+ ---
364
+
365
+ ## 7. `TopologyPolicy` interface
366
+
367
+ ```ts
368
+ export interface TopologyPolicy {
369
+ readonly name: string;
370
+
371
+ onTeamStart(ctx: TeamStartContext): Promise<TeamStartPlan>;
372
+ onAgentSpawn(ctx: SpawnContext): Promise<WorkspaceDecision>;
373
+ onAgentComplete(ctx: AgentCompleteContext): Promise<void>;
374
+ onTeamStop(ctx: TeamStopContext): Promise<void>;
375
+
376
+ // Optional: subscribed if the topology cares about parent stream updates
377
+ onParentStreamAdvanced?(ctx: ParentAdvancedContext): Promise<void>;
378
+ }
379
+
380
+ export interface TeamStartContext {
381
+ teamName: string;
382
+ teamId: string; // instance id
383
+ manifest: TeamManifest; // openteams-resolved
384
+ workspaceConfig: TeamWorkspaceConfig; // macro-agent's Zod-validated section
385
+ workspaceManager: WorkspaceManager;
386
+ inboxAdapter: InboxAdapter;
387
+ }
388
+
389
+ export interface TeamStartPlan {
390
+ teamStreamId?: StreamId; // the team's root stream if created
391
+ additionalStreams?: StreamId[];
392
+ }
393
+
394
+ export interface SpawnContext {
395
+ agentId: AgentId;
396
+ role: string;
397
+ roleConfig: RoleWorkspaceConfig; // parsed YAML for this role
398
+ parent?: AgentId;
399
+ parentStreamId?: StreamId;
400
+ teamStreamId?: StreamId;
401
+ workspaceManager: WorkspaceManager;
402
+ options: SpawnAgentOptions;
403
+ }
404
+
405
+ export type WorkspaceDecision =
406
+ | { kind: "none" }
407
+ | { kind: "share-parent-cwd" }
408
+ | { kind: "share-with-agent"; agentId: AgentId; worktreeRole?: "read" | "write" }
409
+ | { kind: "attach-to-stream"; streamId: StreamId; worktree: WorktreeOpts }
410
+ | { kind: "new-stream"; streamSpec: StreamSpec; worktree: WorktreeOpts };
411
+
412
+ export interface WorktreeOpts {
413
+ baseDir?: string;
414
+ pooled?: boolean;
415
+ }
416
+
417
+ export interface AgentCompleteContext {
418
+ agentId: AgentId;
419
+ role: string;
420
+ reason: "completed" | "failed" | "cascade" | "interrupted";
421
+ streamId?: StreamId;
422
+ workspaceManager: WorkspaceManager;
423
+ landingResult?: MergeResult;
424
+ }
425
+
426
+ export interface TeamStopContext {
427
+ teamName: string;
428
+ teamStreamId?: StreamId;
429
+ onTeamComplete: "keep" | "merge_to_main" | "abandon";
430
+ workspaceManager: WorkspaceManager;
431
+ }
432
+
433
+ export interface ParentAdvancedContext {
434
+ parentStreamId: StreamId;
435
+ childStreamIds: StreamId[];
436
+ workspaceManager: WorkspaceManager;
437
+ triggerSystem: TriggerSystemV2;
438
+ }
439
+ ```
440
+
441
+ ### 7.1 Built-in topology policies
442
+
443
+ ```ts
444
+ // YamlDrivenTopology: the default. Compiles TeamWorkspaceConfig into
445
+ // per-spawn decisions by looking up role config. Covers peer-swarm,
446
+ // triad, pipeline, research, long-lived, solo-stack via YAML alone.
447
+
448
+ // CognitiveCoreTopology: minimal policy for cognitive-core's analyst
449
+ // workflow; spawns analysts with no stream, allocates detached worktrees.
450
+ // Skips YAML; configured programmatically.
451
+
452
+ // NoWorkspaceTopology: returns { kind: "none" } for everything. Used when
453
+ // no workspace is needed but the team still needs structured spawning.
454
+ ```
455
+
456
+ `YamlDrivenTopology` is the primary; the others are escape hatches for library consumers.
457
+
458
+ ---
459
+
460
+ ## 8. YAML Zod schema (`macro_agent.workspace`)
461
+
462
+ ```ts
463
+ import { z } from "zod";
464
+
465
+ export const StreamLineageSchema = z.enum([
466
+ "from_team_root", // attach to existing team root (no new stream)
467
+ "fork_from_team_root", // fork new stream off team root
468
+ "fork_from_parent", // fork new stream off spawner's stream
469
+ "independent", // fork new stream off main branch
470
+ "track_existing_branch",// track an existing branch (no new stream/<id>)
471
+ ]);
472
+
473
+ export const LandingStrategyNameSchema = z.enum([
474
+ "merge_to_parent_stream",
475
+ "queue_to_branch",
476
+ "cherry_pick_stack",
477
+ "direct_push",
478
+ "optimistic_push",
479
+ "none",
480
+ ]);
481
+
482
+ export const ConflictStrategySchema = z.enum(["abort", "ours", "theirs", "defer", "agent"]);
483
+
484
+ export const WorkspaceKindSchema = z.enum([
485
+ "new_stream",
486
+ "attach_to_team_root",
487
+ "share_with_agent",
488
+ "share_parent_cwd",
489
+ "none",
490
+ ]);
491
+
492
+ export const AllocationSchema = z.enum([
493
+ "new_worktree",
494
+ "inherit_parent_cwd",
495
+ "pooled_worktree",
496
+ ]);
497
+
498
+ export const OnParentAdvancedSchema = z.enum([
499
+ "sync_with_parent",
500
+ "none",
501
+ ]);
502
+
503
+ export const OnTeamCompleteSchema = z.enum([
504
+ "keep",
505
+ "merge_to_main",
506
+ "abandon",
507
+ ]);
508
+
509
+ export const RoleWorkspaceConfigSchema = z.object({
510
+ workspace: WorkspaceKindSchema,
511
+ stream_lineage: StreamLineageSchema.optional(),
512
+ allocation: AllocationSchema.optional(),
513
+ landing: LandingStrategyNameSchema.optional(),
514
+ landing_config: z.record(z.unknown()).optional(),
515
+ on_conflict: ConflictStrategySchema.optional(),
516
+ cascade_on_parent_update: z.boolean().optional(),
517
+ on_parent_advanced: OnParentAdvancedSchema.optional(),
518
+ share_with: z.string().optional(), // role name — for workspace: share_with_agent
519
+ track_branch: z.string().optional(), // branch name — for stream_lineage: track_existing_branch
520
+ }).superRefine((val, ctx) => {
521
+ if (val.workspace === "share_with_agent" && !val.share_with) {
522
+ ctx.addIssue({ code: "custom", message: "share_with is required when workspace=share_with_agent" });
523
+ }
524
+ if (val.stream_lineage === "track_existing_branch" && !val.track_branch) {
525
+ ctx.addIssue({ code: "custom", message: "track_branch is required when stream_lineage=track_existing_branch" });
526
+ }
527
+ });
528
+
529
+ export const PoolConfigSchema = z.object({
530
+ enabled: z.boolean().default(true),
531
+ max_size: z.number().default(10),
532
+ reuse_across_streams: z.boolean().default(false),
533
+ }).optional();
534
+
535
+ export const DefaultStreamSchema = z.object({
536
+ fork_from: z.string().default("main"),
537
+ name_template: z.string().default("{team}"),
538
+ change_id_tracking: z.boolean().default(true),
539
+ }).optional();
540
+
541
+ export const TeamWorkspaceConfigSchema = z.object({
542
+ default_stream: DefaultStreamSchema,
543
+ on_team_complete: OnTeamCompleteSchema.default("keep"),
544
+ pool: PoolConfigSchema,
545
+ roles: z.record(z.string(), RoleWorkspaceConfigSchema),
546
+ capabilities: z.record(z.string(), z.array(z.string())).optional(),
547
+ });
548
+
549
+ export type TeamWorkspaceConfig = z.infer<typeof TeamWorkspaceConfigSchema>;
550
+ export type RoleWorkspaceConfig = z.infer<typeof RoleWorkspaceConfigSchema>;
551
+ ```
552
+
553
+ Loaded from `TeamManifest.macro_agent.workspace`. Validated once at team start; errors rejected loudly.
554
+
555
+ ---
556
+
557
+ ## 9. MCP tool schemas
558
+
559
+ Registered per-role based on capabilities in team YAML. Tool filtering already exists in `mcp-server-v2.ts` via `isToolAllowedForRole()`.
560
+
561
+ ```ts
562
+ import { z } from "zod";
563
+
564
+ // ── Capability: workspace.commit ──────────────────────────────────
565
+ export const commitToolInput = z.object({
566
+ message: z.string().min(1),
567
+ });
568
+ // Handler: commitChanges({ agentId, streamId: ctx.streamId, worktree: ctx.cwd, message })
569
+ // → returns { commit, changeId }
570
+
571
+ // ── Capability: workspace.land ────────────────────────────────────
572
+ export const landToolInput = z.object({
573
+ strategy: z.string().optional(), // override role default
574
+ targetStreamId: z.string().optional(),
575
+ strategyConfig: z.record(z.unknown()).optional(),
576
+ });
577
+ // Handler: workspaceManager.land({ agentId, streamId: ctx.streamId, ... })
578
+
579
+ // ── Capability: workspace.fork ────────────────────────────────────
580
+ export const forkStreamToolInput = z.object({
581
+ name: z.string().min(1),
582
+ parent: z.string().optional(), // defaults to current stream
583
+ });
584
+ // Handler: forkStream + allocateWorktree + implicitly moves agent's active stream
585
+
586
+ // ── Capability: workspace.sync ────────────────────────────────────
587
+ export const syncWithParentToolInput = z.object({
588
+ onConflict: ConflictStrategySchema.optional(),
589
+ });
590
+ // Handler: syncWithParent({ streamId: ctx.streamId, ... })
591
+
592
+ // ── Capability: workspace.merge ───────────────────────────────────
593
+ export const mergeStreamToolInput = z.object({
594
+ sourceStreamId: z.string(),
595
+ targetStreamId: z.string().optional(),
596
+ });
597
+ // Handler: mergeStream(...). For integrator roles draining queue.
598
+
599
+ // ── Capability: merge_queue.drain ─────────────────────────────────
600
+ export const nextMergeRequestToolInput = z.object({
601
+ targetBranch: z.string().optional(),
602
+ });
603
+ // Handler: getNextToMerge(targetBranch) + mark in_progress
604
+
605
+ export const markMergeCompleteToolInput = z.object({
606
+ entryId: z.string(),
607
+ mergeCommit: z.string().optional(),
608
+ success: z.boolean(),
609
+ error: z.string().optional(),
610
+ });
611
+ // Handler: updates queue entry state
612
+
613
+ // ── Capability: workspace.cascade ─────────────────────────────────
614
+ export const requestCascadeToolInput = z.object({
615
+ rootStreamId: z.string(),
616
+ strategy: z.enum(["stop_on_conflict", "skip_conflicting", "defer_conflicts"]).optional(),
617
+ });
618
+ // Handler: cascadeRebase({ rootStreamId, strategy, worktreeProvider })
619
+
620
+ // ── Capability: workspace.read (always available if role has any workspace cap) ─
621
+ export const streamStatusToolInput = z.object({
622
+ streamId: z.string().optional(), // defaults to agent's current stream
623
+ includeHierarchy: z.boolean().default(false),
624
+ });
625
+ // Handler: getStream + listStreams(filter) + optionally getStreamHierarchy
626
+
627
+ export const checkoutStreamToolInput = z.object({
628
+ streamId: z.string(),
629
+ });
630
+ // Handler: switches agent's active stream (for returning to parent after fork+land).
631
+ // Capability gate: workspace.fork OR workspace.sync.
632
+ ```
633
+
634
+ ### 9.1 Capability → tool mapping
635
+
636
+ | Capability | Tools registered |
637
+ |---|---|
638
+ | `workspace.commit` | `commit` |
639
+ | `workspace.land` | `land` |
640
+ | `workspace.fork` | `fork_stream`, `checkout_stream` |
641
+ | `workspace.sync` | `sync_with_parent` |
642
+ | `workspace.merge` | `merge_stream` |
643
+ | `workspace.cascade` | `request_cascade` |
644
+ | `workspace.read` | `stream_status` |
645
+ | `merge_queue.drain` | `next_merge_request`, `mark_merge_complete` |
646
+
647
+ ---
648
+
649
+ ## 10. Boot integration
650
+
651
+ ```ts
652
+ // boot-v2.ts — new path
653
+ export async function bootV2(config: BootV2Config): Promise<MacroAgentSystemV2> {
654
+ // ... existing setup (agentStore, inbox, tasks, etc.) ...
655
+
656
+ // Load team config if provided
657
+ let teamManifest: TeamManifest | null = null;
658
+ let workspaceConfig: TeamWorkspaceConfig | null = null;
659
+ if (config.team) {
660
+ teamManifest = await loadTeamManifest(config.team);
661
+ const rawWorkspace = teamManifest.macro_agent?.workspace;
662
+ if (rawWorkspace) {
663
+ workspaceConfig = TeamWorkspaceConfigSchema.parse(rawWorkspace);
664
+ }
665
+ }
666
+
667
+ // Construct WorkspaceManager if any role needs one
668
+ let workspaceManager: WorkspaceManager | undefined;
669
+ if (workspaceConfig || config.workspaceManager) {
670
+ workspaceManager = config.workspaceManager ?? createDefaultWorkspaceManager({
671
+ repoPath: config.cwd,
672
+ pool: workspaceConfig?.pool,
673
+ });
674
+
675
+ // Register built-in landing strategies
676
+ registerBuiltinLandingStrategies(workspaceManager);
677
+
678
+ // Reconcile on boot
679
+ const reconcileResult = workspaceManager.reconcile();
680
+ logReconcile(reconcileResult);
681
+ }
682
+
683
+ // Construct agent manager
684
+ const agentManager = createAgentManagerV2({
685
+ // ... existing args ...
686
+ workspaceManager,
687
+ });
688
+
689
+ // Construct topology policy
690
+ let topologyPolicy: TopologyPolicy | undefined;
691
+ if (workspaceConfig && workspaceManager) {
692
+ topologyPolicy = new YamlDrivenTopology(workspaceConfig);
693
+ agentManager.setTopologyPolicy(topologyPolicy);
694
+ }
695
+
696
+ // Start team if requested
697
+ if (config.team && teamManifest) {
698
+ const teamManager = new TeamManagerV2({
699
+ agentManager,
700
+ inboxAdapter,
701
+ tasksAdapter,
702
+ workspaceManager,
703
+ topologyPolicy,
704
+ });
705
+ await teamManager.startTeam(teamManifest);
706
+ }
707
+
708
+ // ... rest of boot ...
709
+ }
710
+ ```
711
+
712
+ Callers like `cognitive-core` continue to pass their own `workspaceManager` and skip team YAML entirely — they drive the API directly.
713
+
714
+ ---
715
+
716
+ ## 11. Open gaps in this draft
717
+
718
+ - **`checkout_stream` semantics** — moves agent's *context* (streamId in spawn env), but does it relocate cwd or re-allocate worktree? Needs concrete decision when we implement solo-stack.
719
+ - **`attach-to-stream` worktree** — when workspace kind is `attach_to_team_root`, does the agent get a fresh worktree on team_root's branch, or share with whoever already has one? Default: fresh worktree on the team_root branch.
720
+ - **Conflict recovery hook** — no interface method on `WorkspaceManager` yet for "escalate conflict to recovery strategy." Probably a pluggable `ConflictRecoveryStrategy` parallel to `LandingStrategy`. Deferred.
721
+ - **cascadeRebase triggering from events** — `YamlDrivenTopology` subscribes to `stream.committed` on parent streams when any child has `on_parent_advanced: sync_with_parent`. Needs WakeManager integration for coalescing. Deferred to migration step.
722
+ - **Backward compat shim for cognitive-core** — the existing `DefaultWorkspaceManager` needs to implement both old and new interfaces during migration. TBD once we start migration.
723
+
724
+ ---
725
+
726
+ ## 12. What's not defined here
727
+
728
+ - **Implementation** of `DefaultWorkspaceManager` — this doc is the interface only.
729
+ - **Migration order** — see `git-cascade-integration-gaps.md` §8.
730
+ - **Conflict recovery strategy interface** — parallel design, out of scope.
731
+ - **cc-swarm integration** — separate follow-up doc.