@mclawnet/swarm 0.1.4 → 0.1.5

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 (224) hide show
  1. package/README.md +118 -0
  2. package/dist/__tests__/action-parser.test.js +29 -82
  3. package/dist/__tests__/action-parser.test.js.map +1 -1
  4. package/dist/__tests__/coordinator-create-tx.test.d.ts +2 -0
  5. package/dist/__tests__/coordinator-create-tx.test.d.ts.map +1 -0
  6. package/dist/__tests__/coordinator-create-tx.test.js +114 -0
  7. package/dist/__tests__/coordinator-create-tx.test.js.map +1 -0
  8. package/dist/__tests__/coordinator-inbox-migration.test.d.ts +2 -0
  9. package/dist/__tests__/coordinator-inbox-migration.test.d.ts.map +1 -0
  10. package/dist/__tests__/coordinator-inbox-migration.test.js +56 -0
  11. package/dist/__tests__/coordinator-inbox-migration.test.js.map +1 -0
  12. package/dist/__tests__/inbox-integration.test.d.ts +2 -0
  13. package/dist/__tests__/inbox-integration.test.d.ts.map +1 -0
  14. package/dist/__tests__/inbox-integration.test.js +120 -0
  15. package/dist/__tests__/inbox-integration.test.js.map +1 -0
  16. package/dist/__tests__/inbox-persistence-recovery.test.d.ts +2 -0
  17. package/dist/__tests__/inbox-persistence-recovery.test.d.ts.map +1 -0
  18. package/dist/__tests__/inbox-persistence-recovery.test.js +139 -0
  19. package/dist/__tests__/inbox-persistence-recovery.test.js.map +1 -0
  20. package/dist/__tests__/inbox-relay-interceptor.test.d.ts +2 -0
  21. package/dist/__tests__/inbox-relay-interceptor.test.d.ts.map +1 -0
  22. package/dist/__tests__/inbox-relay-interceptor.test.js +156 -0
  23. package/dist/__tests__/inbox-relay-interceptor.test.js.map +1 -0
  24. package/dist/__tests__/inbox-relay.test.d.ts +2 -0
  25. package/dist/__tests__/inbox-relay.test.d.ts.map +1 -0
  26. package/dist/__tests__/inbox-relay.test.js +318 -0
  27. package/dist/__tests__/inbox-relay.test.js.map +1 -0
  28. package/dist/__tests__/inbox-store.test.d.ts +2 -0
  29. package/dist/__tests__/inbox-store.test.d.ts.map +1 -0
  30. package/dist/__tests__/inbox-store.test.js +129 -0
  31. package/dist/__tests__/inbox-store.test.js.map +1 -0
  32. package/dist/__tests__/inbox-watcher.test.d.ts +2 -0
  33. package/dist/__tests__/inbox-watcher.test.d.ts.map +1 -0
  34. package/dist/__tests__/inbox-watcher.test.js +104 -0
  35. package/dist/__tests__/inbox-watcher.test.js.map +1 -0
  36. package/dist/__tests__/persistence-path.test.d.ts +2 -0
  37. package/dist/__tests__/persistence-path.test.d.ts.map +1 -0
  38. package/dist/__tests__/persistence-path.test.js +79 -0
  39. package/dist/__tests__/persistence-path.test.js.map +1 -0
  40. package/dist/__tests__/persistence-robust.test.d.ts +2 -0
  41. package/dist/__tests__/persistence-robust.test.d.ts.map +1 -0
  42. package/dist/__tests__/persistence-robust.test.js +125 -0
  43. package/dist/__tests__/persistence-robust.test.js.map +1 -0
  44. package/dist/__tests__/persistence.test.d.ts +2 -0
  45. package/dist/__tests__/persistence.test.d.ts.map +1 -0
  46. package/dist/__tests__/persistence.test.js +105 -0
  47. package/dist/__tests__/persistence.test.js.map +1 -0
  48. package/dist/__tests__/phase4-5-e2e.test.d.ts +2 -0
  49. package/dist/__tests__/phase4-5-e2e.test.d.ts.map +1 -0
  50. package/dist/__tests__/phase4-5-e2e.test.js +203 -0
  51. package/dist/__tests__/phase4-5-e2e.test.js.map +1 -0
  52. package/dist/__tests__/phase6-7-e2e.test.d.ts +2 -0
  53. package/dist/__tests__/phase6-7-e2e.test.d.ts.map +1 -0
  54. package/dist/__tests__/phase6-7-e2e.test.js +93 -0
  55. package/dist/__tests__/phase6-7-e2e.test.js.map +1 -0
  56. package/dist/__tests__/recovery-cross-project.test.d.ts +2 -0
  57. package/dist/__tests__/recovery-cross-project.test.d.ts.map +1 -0
  58. package/dist/__tests__/recovery-cross-project.test.js +87 -0
  59. package/dist/__tests__/recovery-cross-project.test.js.map +1 -0
  60. package/dist/__tests__/recovery-forwards-to-coordinator.test.d.ts +2 -0
  61. package/dist/__tests__/recovery-forwards-to-coordinator.test.d.ts.map +1 -0
  62. package/dist/__tests__/recovery-forwards-to-coordinator.test.js +59 -0
  63. package/dist/__tests__/recovery-forwards-to-coordinator.test.js.map +1 -0
  64. package/dist/__tests__/recovery-resume.test.d.ts +2 -0
  65. package/dist/__tests__/recovery-resume.test.d.ts.map +1 -0
  66. package/dist/__tests__/recovery-resume.test.js +132 -0
  67. package/dist/__tests__/recovery-resume.test.js.map +1 -0
  68. package/dist/__tests__/retrospective.test.js +1 -0
  69. package/dist/__tests__/retrospective.test.js.map +1 -1
  70. package/dist/__tests__/role-loader-preamble-all.test.d.ts +2 -0
  71. package/dist/__tests__/role-loader-preamble-all.test.d.ts.map +1 -0
  72. package/dist/__tests__/role-loader-preamble-all.test.js +38 -0
  73. package/dist/__tests__/role-loader-preamble-all.test.js.map +1 -0
  74. package/dist/__tests__/role-loader-tools.test.d.ts +2 -0
  75. package/dist/__tests__/role-loader-tools.test.d.ts.map +1 -0
  76. package/dist/__tests__/role-loader-tools.test.js +39 -0
  77. package/dist/__tests__/role-loader-tools.test.js.map +1 -0
  78. package/dist/__tests__/role-loader.test.js +116 -1
  79. package/dist/__tests__/role-loader.test.js.map +1 -1
  80. package/dist/__tests__/role-prompt-no-legacy-protocol.test.d.ts +2 -0
  81. package/dist/__tests__/role-prompt-no-legacy-protocol.test.d.ts.map +1 -0
  82. package/dist/__tests__/role-prompt-no-legacy-protocol.test.js +37 -0
  83. package/dist/__tests__/role-prompt-no-legacy-protocol.test.js.map +1 -0
  84. package/dist/__tests__/role-tools.test.d.ts +2 -0
  85. package/dist/__tests__/role-tools.test.d.ts.map +1 -0
  86. package/dist/__tests__/role-tools.test.js +80 -0
  87. package/dist/__tests__/role-tools.test.js.map +1 -0
  88. package/dist/__tests__/spawn-role-injects-briefings.test.d.ts +2 -0
  89. package/dist/__tests__/spawn-role-injects-briefings.test.d.ts.map +1 -0
  90. package/dist/__tests__/spawn-role-injects-briefings.test.js +182 -0
  91. package/dist/__tests__/spawn-role-injects-briefings.test.js.map +1 -0
  92. package/dist/__tests__/spawn-role-tool-policy.test.d.ts +2 -0
  93. package/dist/__tests__/spawn-role-tool-policy.test.d.ts.map +1 -0
  94. package/dist/__tests__/spawn-role-tool-policy.test.js +96 -0
  95. package/dist/__tests__/spawn-role-tool-policy.test.js.map +1 -0
  96. package/dist/__tests__/swarm-coordinator-inbox-watcher.test.d.ts +2 -0
  97. package/dist/__tests__/swarm-coordinator-inbox-watcher.test.d.ts.map +1 -0
  98. package/dist/__tests__/swarm-coordinator-inbox-watcher.test.js +61 -0
  99. package/dist/__tests__/swarm-coordinator-inbox-watcher.test.js.map +1 -0
  100. package/dist/__tests__/swarm-coordinator-inbox.test.d.ts +2 -0
  101. package/dist/__tests__/swarm-coordinator-inbox.test.d.ts.map +1 -0
  102. package/dist/__tests__/swarm-coordinator-inbox.test.js +182 -0
  103. package/dist/__tests__/swarm-coordinator-inbox.test.js.map +1 -0
  104. package/dist/__tests__/swarm-coordinator-init.test.js +36 -8
  105. package/dist/__tests__/swarm-coordinator-init.test.js.map +1 -1
  106. package/dist/__tests__/swarm-coordinator-legacy-plan-review-warn.test.d.ts +2 -0
  107. package/dist/__tests__/swarm-coordinator-legacy-plan-review-warn.test.d.ts.map +1 -0
  108. package/dist/__tests__/swarm-coordinator-legacy-plan-review-warn.test.js +113 -0
  109. package/dist/__tests__/swarm-coordinator-legacy-plan-review-warn.test.js.map +1 -0
  110. package/dist/__tests__/swarm-coordinator-plan-review-intercept.test.d.ts +2 -0
  111. package/dist/__tests__/swarm-coordinator-plan-review-intercept.test.d.ts.map +1 -0
  112. package/dist/__tests__/swarm-coordinator-plan-review-intercept.test.js +465 -0
  113. package/dist/__tests__/swarm-coordinator-plan-review-intercept.test.js.map +1 -0
  114. package/dist/__tests__/swarm-coordinator-plan-review-recovery.test.d.ts +2 -0
  115. package/dist/__tests__/swarm-coordinator-plan-review-recovery.test.d.ts.map +1 -0
  116. package/dist/__tests__/swarm-coordinator-plan-review-recovery.test.js +284 -0
  117. package/dist/__tests__/swarm-coordinator-plan-review-recovery.test.js.map +1 -0
  118. package/dist/__tests__/swarm-coordinator-plan-review.test.d.ts +2 -0
  119. package/dist/__tests__/swarm-coordinator-plan-review.test.d.ts.map +1 -0
  120. package/dist/__tests__/swarm-coordinator-plan-review.test.js +294 -0
  121. package/dist/__tests__/swarm-coordinator-plan-review.test.js.map +1 -0
  122. package/dist/__tests__/swarm-coordinator-resume.test.d.ts +2 -0
  123. package/dist/__tests__/swarm-coordinator-resume.test.d.ts.map +1 -0
  124. package/dist/__tests__/swarm-coordinator-resume.test.js +93 -0
  125. package/dist/__tests__/swarm-coordinator-resume.test.js.map +1 -0
  126. package/dist/__tests__/swarm-coordinator-roleId.test.js +2 -2
  127. package/dist/__tests__/swarm-coordinator-roleId.test.js.map +1 -1
  128. package/dist/__tests__/swarm-destroy-detach.test.d.ts +2 -0
  129. package/dist/__tests__/swarm-destroy-detach.test.d.ts.map +1 -0
  130. package/dist/__tests__/swarm-destroy-detach.test.js +135 -0
  131. package/dist/__tests__/swarm-destroy-detach.test.js.map +1 -0
  132. package/dist/action-parser.d.ts +0 -9
  133. package/dist/action-parser.d.ts.map +1 -1
  134. package/dist/action-parser.js +0 -114
  135. package/dist/action-parser.js.map +1 -1
  136. package/dist/inbox-relay.d.ts +50 -0
  137. package/dist/inbox-relay.d.ts.map +1 -0
  138. package/dist/inbox-relay.js +168 -0
  139. package/dist/inbox-relay.js.map +1 -0
  140. package/dist/inbox-store.d.ts +25 -0
  141. package/dist/inbox-store.d.ts.map +1 -0
  142. package/dist/inbox-store.js +95 -0
  143. package/dist/inbox-store.js.map +1 -0
  144. package/dist/inbox-watcher.d.ts +13 -0
  145. package/dist/inbox-watcher.d.ts.map +1 -0
  146. package/dist/inbox-watcher.js +89 -0
  147. package/dist/inbox-watcher.js.map +1 -0
  148. package/dist/index.d.ts +4 -3
  149. package/dist/index.d.ts.map +1 -1
  150. package/dist/index.js +3 -2
  151. package/dist/index.js.map +1 -1
  152. package/dist/persistence.d.ts +19 -5
  153. package/dist/persistence.d.ts.map +1 -1
  154. package/dist/persistence.js +97 -22
  155. package/dist/persistence.js.map +1 -1
  156. package/dist/recovery.d.ts +12 -0
  157. package/dist/recovery.d.ts.map +1 -1
  158. package/dist/recovery.js +14 -19
  159. package/dist/recovery.js.map +1 -1
  160. package/dist/roles/role-loader.d.ts +28 -1
  161. package/dist/roles/role-loader.d.ts.map +1 -1
  162. package/dist/roles/role-loader.js +73 -1
  163. package/dist/roles/role-loader.js.map +1 -1
  164. package/dist/roles/role-tools.d.ts +16 -0
  165. package/dist/roles/role-tools.d.ts.map +1 -0
  166. package/dist/roles/role-tools.js +25 -0
  167. package/dist/roles/role-tools.js.map +1 -0
  168. package/dist/roles/types.d.ts +4 -0
  169. package/dist/roles/types.d.ts.map +1 -1
  170. package/dist/swarm-coordinator.d.ts +176 -12
  171. package/dist/swarm-coordinator.d.ts.map +1 -1
  172. package/dist/swarm-coordinator.js +863 -370
  173. package/dist/swarm-coordinator.js.map +1 -1
  174. package/dist/types.d.ts +26 -0
  175. package/dist/types.d.ts.map +1 -1
  176. package/package.json +9 -6
  177. package/roles/analyst-livermore.md +6 -30
  178. package/roles/designer-rams.md +2 -30
  179. package/roles/dev-torvalds.md +8 -44
  180. package/roles/developer.md +5 -21
  181. package/roles/director-jia.md +20 -49
  182. package/roles/editor-boyong.md +8 -40
  183. package/roles/macro-dalio.md +6 -30
  184. package/roles/planner-maoni.md +24 -53
  185. package/roles/pm-jobs.md +20 -71
  186. package/roles/preset-analyst-simons.md +2 -18
  187. package/roles/preset-architect-knuth.md +2 -18
  188. package/roles/preset-designer-norman.md +2 -18
  189. package/roles/preset-designer.md +2 -18
  190. package/roles/preset-dev-carmack.md +2 -18
  191. package/roles/preset-dev-gosling.md +2 -18
  192. package/roles/preset-developer.md +7 -23
  193. package/roles/preset-manager-grove.md +2 -18
  194. package/roles/preset-manager-musk.md +2 -18
  195. package/roles/preset-pm.md +7 -34
  196. package/roles/preset-researcher-feynman.md +2 -18
  197. package/roles/preset-reviewer.md +5 -21
  198. package/roles/preset-strategist-buffett.md +2 -18
  199. package/roles/preset-strategist-munger.md +2 -18
  200. package/roles/preset-strategist-sunzi.md +2 -18
  201. package/roles/preset-tester-beck.md +2 -18
  202. package/roles/preset-tester.md +5 -21
  203. package/roles/preset-writer-orwell.md +2 -18
  204. package/roles/preset-writer.md +2 -18
  205. package/roles/quant-simons.md +5 -32
  206. package/roles/queen.md +25 -41
  207. package/roles/reviewer-martin.md +11 -37
  208. package/roles/reviewer.md +20 -21
  209. package/roles/rhythm-tangsan.md +5 -29
  210. package/roles/risk-taleb.md +4 -32
  211. package/roles/script-shitiesheng.md +8 -31
  212. package/roles/storyboard-xuke.md +9 -29
  213. package/roles/strategist-soros.md +16 -73
  214. package/roles/tester-beck.md +4 -40
  215. package/roles/tester.md +5 -21
  216. package/roles/trader-jones.md +4 -32
  217. package/roles/vfx-guchangwei.md +8 -27
  218. package/roles/writer-zhouzi.md +7 -39
  219. package/templates/dev-team-pro.md +4 -1
  220. package/templates/dev-team.md +3 -1
  221. package/templates/minimal.md +2 -1
  222. package/templates/trading-team.md +6 -1
  223. package/templates/video-team.md +4 -1
  224. package/templates/writing-team.md +4 -1
@@ -0,0 +1,284 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { mkdtempSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { randomUUID } from "node:crypto";
6
+ // Capture warns + infos so the I1 gate test can assert the "refusing to apply"
7
+ // log fires instead of the "proceeding anyway" branch we replaced.
8
+ const { warnSpy, infoSpy } = vi.hoisted(() => ({
9
+ warnSpy: vi.fn(),
10
+ infoSpy: vi.fn(),
11
+ }));
12
+ vi.mock("@mclawnet/logger", () => ({
13
+ createLogger: () => ({
14
+ info: infoSpy,
15
+ warn: warnSpy,
16
+ error: vi.fn(),
17
+ debug: vi.fn(),
18
+ }),
19
+ }));
20
+ // I2 needs to drive recover() with controllable snapshot data.
21
+ const loadSwarmSnapshotMock = vi.fn();
22
+ const listRecoverableSwarmIdsMock = vi.fn();
23
+ vi.mock("../persistence.js", () => ({
24
+ saveSwarmSnapshot: vi.fn(),
25
+ deleteSwarmSnapshot: vi.fn(),
26
+ appendMessageLog: vi.fn(),
27
+ loadSwarmSnapshot: (...args) => loadSwarmSnapshotMock(...args),
28
+ listRecoverableSwarmIds: (...args) => listRecoverableSwarmIdsMock(...args),
29
+ readMessageLog: vi.fn(() => []),
30
+ }));
31
+ vi.mock("../retrospective.js", () => ({
32
+ runRetrospective: vi.fn(async () => ({})),
33
+ }));
34
+ import { SwarmCoordinator } from "../swarm-coordinator.js";
35
+ import { InboxStore } from "../inbox-store.js";
36
+ function adapters() {
37
+ const session = {
38
+ createSession: vi.fn(async () => ""),
39
+ sendInput: vi.fn(),
40
+ closeSession: vi.fn(async () => { }),
41
+ };
42
+ const hub = { send: vi.fn() };
43
+ return { session, hub };
44
+ }
45
+ let HOME;
46
+ let WORK;
47
+ beforeEach(() => {
48
+ warnSpy.mockReset();
49
+ infoSpy.mockReset();
50
+ loadSwarmSnapshotMock.mockReset();
51
+ listRecoverableSwarmIdsMock.mockReset();
52
+ HOME = mkdtempSync(join(tmpdir(), "swarm-pr-recovery-home-"));
53
+ WORK = mkdtempSync(join(tmpdir(), "swarm-pr-recovery-work-"));
54
+ process.env.CLAWNET_HOME = HOME;
55
+ });
56
+ afterEach(() => {
57
+ rmSync(HOME, { recursive: true, force: true });
58
+ rmSync(WORK, { recursive: true, force: true });
59
+ delete process.env.CLAWNET_HOME;
60
+ });
61
+ async function setupSwarm(swarmId) {
62
+ const { session, hub } = adapters();
63
+ const coord = new SwarmCoordinator(session, hub);
64
+ await coord.create(swarmId, {
65
+ workDir: WORK,
66
+ roles: [
67
+ { roleName: "queen", count: 1, eager: true },
68
+ { roleName: "reviewer", count: 1, eager: true },
69
+ ],
70
+ });
71
+ // Allow fire-and-forget post-create deliveries to settle on the real clock
72
+ // before any test logic. Mirrors the pattern used in other plan-review
73
+ // tests so the queen-check / inbox-watcher startup writes don't race
74
+ // assertions.
75
+ await new Promise((r) => setTimeout(r, 30));
76
+ // Suppress the 5min queen-check timer so it can never accidentally race
77
+ // I3's manual reconcilePlanStatusForQueen invocation.
78
+ const swarm = coord.getSwarm(swarmId);
79
+ if (swarm.checkTimer) {
80
+ clearTimeout(swarm.checkTimer);
81
+ swarm.checkTimer = undefined;
82
+ }
83
+ return { coord, swarm };
84
+ }
85
+ // ─────────────────────────────────────────────────────────────────────────────
86
+ // I1: submitPlanReview must refuse to apply a verdict unless planStatus is
87
+ // exactly "reviewing". Premature submissions (planStatus === "none" / "draft")
88
+ // previously logged "proceeding anyway" and clobbered state. Now they no-op.
89
+ // ─────────────────────────────────────────────────────────────────────────────
90
+ describe("I1: submitPlanReview gate (planStatus === reviewing only)", () => {
91
+ it("planStatus='draft': verdict is refused, status stays draft, no inbox write", async () => {
92
+ const swarmId = "sw-i1-draft";
93
+ const { coord, swarm } = await setupSwarm(swarmId);
94
+ swarm.planStatus = "draft";
95
+ const store = new InboxStore(WORK, swarmId);
96
+ const before = await store.readAll("queen-0");
97
+ const beforeCount = before.length;
98
+ await coord.submitPlanReview({
99
+ swarmId,
100
+ from: "reviewer-0",
101
+ verdict: "approved",
102
+ body: "premature",
103
+ });
104
+ expect(swarm.planStatus).toBe("draft");
105
+ const after = await store.readAll("queen-0");
106
+ expect(after.length).toBe(beforeCount);
107
+ const matched = warnSpy.mock.calls.find(([_ctx, msg]) => typeof msg === "string" &&
108
+ msg.includes("planStatus !== reviewing"));
109
+ expect(matched).toBeDefined();
110
+ });
111
+ it("planStatus='none': verdict is refused, status stays none, no inbox write", async () => {
112
+ const swarmId = "sw-i1-none";
113
+ const { coord, swarm } = await setupSwarm(swarmId);
114
+ swarm.planStatus = "none";
115
+ const store = new InboxStore(WORK, swarmId);
116
+ const beforeCount = (await store.readAll("queen-0")).length;
117
+ await coord.submitPlanReview({
118
+ swarmId,
119
+ from: "reviewer-0",
120
+ verdict: "rejected",
121
+ body: "premature reject",
122
+ });
123
+ expect(swarm.planStatus).toBe("none");
124
+ expect((await store.readAll("queen-0")).length).toBe(beforeCount);
125
+ });
126
+ });
127
+ // ─────────────────────────────────────────────────────────────────────────────
128
+ // I2: recover() must re-arm the plan_review timeout when the snapshot says
129
+ // planStatus === "reviewing". planReviewTimer is runtime-only — without this,
130
+ // a process restart mid-review deadlocks forever (the very bug PR #98 fixes).
131
+ // ─────────────────────────────────────────────────────────────────────────────
132
+ describe("I2: recover() re-arms plan_review timeout", () => {
133
+ it("snapshot.planStatus='reviewing' → planReviewTimer is set", async () => {
134
+ listRecoverableSwarmIdsMock.mockReturnValue([{ workDir: WORK, swarmId: "sw-i2-reviewing" }]);
135
+ loadSwarmSnapshotMock.mockReturnValue({
136
+ id: "sw-i2-reviewing",
137
+ hubSessionId: "sw-i2-reviewing",
138
+ workDir: WORK,
139
+ teamName: "default",
140
+ roles: [
141
+ { instanceId: "queen-0", roleName: "queen", status: "active" },
142
+ { instanceId: "reviewer-0", roleName: "reviewer", status: "active" },
143
+ ],
144
+ plan: { goal: "x" },
145
+ nextInstanceSeq: { queen: 1, reviewer: 1 },
146
+ savedAt: Date.now(),
147
+ status: "paused",
148
+ planStatus: "reviewing",
149
+ });
150
+ const { session, hub } = adapters();
151
+ const coord = new SwarmCoordinator(session, hub);
152
+ await coord.recover("sw-i2-reviewing");
153
+ const swarm = coord.getSwarm("sw-i2-reviewing");
154
+ expect(swarm.planStatus).toBe("reviewing");
155
+ expect(swarm.planReviewTimer).toBeDefined();
156
+ // Cleanup so we don't leak a 10-minute timer into the worker and stall
157
+ // vitest's process-exit detection.
158
+ clearTimeout(swarm.planReviewTimer);
159
+ swarm.planReviewTimer = undefined;
160
+ if (swarm.checkTimer) {
161
+ clearTimeout(swarm.checkTimer);
162
+ swarm.checkTimer = undefined;
163
+ }
164
+ });
165
+ it("snapshot.planStatus='approved' → planReviewTimer is NOT set", async () => {
166
+ listRecoverableSwarmIdsMock.mockReturnValue([{ workDir: WORK, swarmId: "sw-i2-approved" }]);
167
+ loadSwarmSnapshotMock.mockReturnValue({
168
+ id: "sw-i2-approved",
169
+ hubSessionId: "sw-i2-approved",
170
+ workDir: WORK,
171
+ teamName: "default",
172
+ roles: [
173
+ { instanceId: "queen-0", roleName: "queen", status: "active" },
174
+ ],
175
+ plan: { goal: "x" },
176
+ nextInstanceSeq: { queen: 1 },
177
+ savedAt: Date.now(),
178
+ status: "paused",
179
+ planStatus: "approved",
180
+ });
181
+ const { session, hub } = adapters();
182
+ const coord = new SwarmCoordinator(session, hub);
183
+ await coord.recover("sw-i2-approved");
184
+ const swarm = coord.getSwarm("sw-i2-approved");
185
+ expect(swarm.planStatus).toBe("approved");
186
+ expect(swarm.planReviewTimer).toBeUndefined();
187
+ if (swarm.checkTimer) {
188
+ clearTimeout(swarm.checkTimer);
189
+ swarm.checkTimer = undefined;
190
+ }
191
+ });
192
+ it("snapshot.planStatus='none' → planReviewTimer is NOT set", async () => {
193
+ listRecoverableSwarmIdsMock.mockReturnValue([{ workDir: WORK, swarmId: "sw-i2-none" }]);
194
+ loadSwarmSnapshotMock.mockReturnValue({
195
+ id: "sw-i2-none",
196
+ hubSessionId: "sw-i2-none",
197
+ workDir: WORK,
198
+ teamName: "default",
199
+ roles: [{ instanceId: "queen-0", roleName: "queen", status: "active" }],
200
+ plan: null,
201
+ nextInstanceSeq: { queen: 1 },
202
+ savedAt: Date.now(),
203
+ status: "paused",
204
+ planStatus: "none",
205
+ });
206
+ const { session, hub } = adapters();
207
+ const coord = new SwarmCoordinator(session, hub);
208
+ await coord.recover("sw-i2-none");
209
+ const swarm = coord.getSwarm("sw-i2-none");
210
+ expect(swarm.planReviewTimer).toBeUndefined();
211
+ if (swarm.checkTimer) {
212
+ clearTimeout(swarm.checkTimer);
213
+ swarm.checkTimer = undefined;
214
+ }
215
+ });
216
+ });
217
+ // ─────────────────────────────────────────────────────────────────────────────
218
+ // I3: reconcilePlanStatusForQueen must re-emit plan_approved / plan_rejected
219
+ // when planStatus is finalised but the queen inbox lacks the corresponding
220
+ // system envelope. Idempotent when the envelope is already present.
221
+ // Triggered from the queen check-in tick to recover from a swallowed
222
+ // deliverInbox() failure inside the deferred submitPlanReview chain.
223
+ // ─────────────────────────────────────────────────────────────────────────────
224
+ describe("I3: queen check-in reconciles missing plan_* envelopes", () => {
225
+ it("planStatus='approved' + queen has no plan_approved → re-emits one", async () => {
226
+ const swarmId = "sw-i3-approved";
227
+ const { coord, swarm } = await setupSwarm(swarmId);
228
+ swarm.planStatus = "approved";
229
+ const store = new InboxStore(WORK, swarmId);
230
+ const before = await store.readAll("queen-0");
231
+ expect(before.find((m) => m.type === "plan_approved")).toBeUndefined();
232
+ await coord.reconcilePlanStatusForQueen(swarm, "queen-0");
233
+ const after = await store.readAll("queen-0");
234
+ const reissued = after.find((m) => m.type === "plan_approved" && m.from === "system");
235
+ expect(reissued).toBeDefined();
236
+ expect(reissued.data).toContain("[reconcile]");
237
+ expect(reissued.data).toContain("approved");
238
+ });
239
+ it("planStatus='rejected' + queen has no plan_rejected → re-emits one", async () => {
240
+ const swarmId = "sw-i3-rejected";
241
+ const { coord, swarm } = await setupSwarm(swarmId);
242
+ swarm.planStatus = "rejected";
243
+ await coord.reconcilePlanStatusForQueen(swarm, "queen-0");
244
+ const store = new InboxStore(WORK, swarmId);
245
+ const after = await store.readAll("queen-0");
246
+ const reissued = after.find((m) => m.type === "plan_rejected" && m.from === "system");
247
+ expect(reissued).toBeDefined();
248
+ expect(reissued.data).toContain("[reconcile]");
249
+ });
250
+ it("planStatus='approved' + queen ALREADY has plan_approved → idempotent (no duplicate)", async () => {
251
+ const swarmId = "sw-i3-idem";
252
+ const { coord, swarm } = await setupSwarm(swarmId);
253
+ swarm.planStatus = "approved";
254
+ // Pre-seed the queen inbox with a system plan_approved as if the
255
+ // legitimate submitPlanReview had succeeded.
256
+ const store = new InboxStore(WORK, swarmId);
257
+ const seeded = {
258
+ id: randomUUID(),
259
+ from: "system",
260
+ type: "plan_approved",
261
+ data: JSON.stringify({ verdict: "approved", body: "lgtm", from: "reviewer-0" }),
262
+ timestamp: Date.now(),
263
+ delivered: false,
264
+ };
265
+ await store.append("queen-0", seeded);
266
+ const beforeCount = (await store.readAll("queen-0")).length;
267
+ await coord.reconcilePlanStatusForQueen(swarm, "queen-0");
268
+ const after = await store.readAll("queen-0");
269
+ expect(after.length).toBe(beforeCount); // No re-emit.
270
+ });
271
+ it("planStatus='reviewing' → reconcile is a no-op (in-flight, nothing to recover)", async () => {
272
+ const swarmId = "sw-i3-reviewing";
273
+ const { coord, swarm } = await setupSwarm(swarmId);
274
+ swarm.planStatus = "reviewing";
275
+ const store = new InboxStore(WORK, swarmId);
276
+ const beforeCount = (await store.readAll("queen-0")).length;
277
+ await coord.reconcilePlanStatusForQueen(swarm, "queen-0");
278
+ const after = await store.readAll("queen-0");
279
+ expect(after.length).toBe(beforeCount);
280
+ expect(after.find((m) => m.type === "plan_approved")).toBeUndefined();
281
+ expect(after.find((m) => m.type === "plan_rejected")).toBeUndefined();
282
+ });
283
+ });
284
+ //# sourceMappingURL=swarm-coordinator-plan-review-recovery.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swarm-coordinator-plan-review-recovery.test.js","sourceRoot":"","sources":["../../src/__tests__/swarm-coordinator-plan-review-recovery.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=swarm-coordinator-plan-review.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swarm-coordinator-plan-review.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/swarm-coordinator-plan-review.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,294 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { mkdtempSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ // Mock logger
6
+ vi.mock("@mclawnet/logger", () => ({
7
+ createLogger: () => ({
8
+ info: vi.fn(),
9
+ warn: vi.fn(),
10
+ error: vi.fn(),
11
+ debug: vi.fn(),
12
+ }),
13
+ }));
14
+ // Mock persistence — keep in-memory; submitPlanReview's saveSwarmSnapshot is a no-op.
15
+ vi.mock("../persistence.js", () => ({
16
+ saveSwarmSnapshot: vi.fn(),
17
+ deleteSwarmSnapshot: vi.fn(),
18
+ appendMessageLog: vi.fn(),
19
+ loadSwarmSnapshot: vi.fn(),
20
+ readMessageLog: vi.fn(() => []),
21
+ }));
22
+ vi.mock("../retrospective.js", () => ({
23
+ runRetrospective: vi.fn(async () => ({})),
24
+ }));
25
+ import { SwarmCoordinator } from "../swarm-coordinator.js";
26
+ import { InboxStore } from "../inbox-store.js";
27
+ function createMockSessionAdapter() {
28
+ const calls = [];
29
+ const inputs = [];
30
+ const adapter = {
31
+ _calls: calls,
32
+ _inputs: inputs,
33
+ createSession: vi.fn(async (options) => {
34
+ calls.push(options);
35
+ return `proc-${options.sessionId}`;
36
+ }),
37
+ sendInput: vi.fn((sessionId, input) => {
38
+ inputs.push({ sessionId, input });
39
+ }),
40
+ closeSession: vi.fn(async () => { }),
41
+ };
42
+ return adapter;
43
+ }
44
+ function createMockHubAdapter() {
45
+ const msgs = [];
46
+ const adapter = {
47
+ _msgs: msgs,
48
+ send: vi.fn((msg) => msgs.push(msg)),
49
+ };
50
+ return adapter;
51
+ }
52
+ let HOME;
53
+ let WORK;
54
+ beforeEach(() => {
55
+ HOME = mkdtempSync(join(tmpdir(), "swarm-pr-"));
56
+ WORK = mkdtempSync(join(tmpdir(), "swarm-pr-work-"));
57
+ process.env.CLAWNET_HOME = HOME;
58
+ });
59
+ afterEach(() => {
60
+ rmSync(HOME, { recursive: true, force: true });
61
+ rmSync(WORK, { recursive: true, force: true });
62
+ delete process.env.CLAWNET_HOME;
63
+ });
64
+ async function setupSwarmWithReviewer(swarmId) {
65
+ const sessionAdapter = createMockSessionAdapter();
66
+ const hubAdapter = createMockHubAdapter();
67
+ const coord = new SwarmCoordinator(sessionAdapter, hubAdapter);
68
+ await coord.create(swarmId, {
69
+ workDir: WORK,
70
+ roles: [
71
+ { roleName: "queen", count: 1, eager: true },
72
+ { roleName: "reviewer", count: 1, eager: true },
73
+ ],
74
+ });
75
+ // Allow fire-and-forget post-create deliveries to settle.
76
+ await new Promise((r) => setTimeout(r, 30));
77
+ return { coord, sessionAdapter, hubAdapter };
78
+ }
79
+ /**
80
+ * Drain microtasks + setImmediate cycles until either the predicate succeeds
81
+ * or maxIters is exhausted. Used after fake-timer fires to let the chained
82
+ * async work (lockfile + fs writes) settle. Predicate may return a boolean or
83
+ * a Promise<boolean>.
84
+ */
85
+ async function flushUntil(predicate, maxIters = 20) {
86
+ for (let i = 0; i < maxIters; i++) {
87
+ const ok = await predicate();
88
+ if (ok)
89
+ return;
90
+ await new Promise((r) => setImmediate(r));
91
+ }
92
+ }
93
+ describe("SwarmCoordinator.submitPlanReview", () => {
94
+ it("flips planStatus to approved + notifies queen via inbox", async () => {
95
+ const swarmId = "sw-pr-approve";
96
+ const { coord } = await setupSwarmWithReviewer(swarmId);
97
+ const swarm = coord.getSwarm(swarmId);
98
+ swarm.planStatus = "reviewing";
99
+ await coord.submitPlanReview({
100
+ swarmId,
101
+ from: "reviewer-0",
102
+ verdict: "approved",
103
+ body: "lgtm",
104
+ });
105
+ expect(swarm.planStatus).toBe("approved");
106
+ const store = new InboxStore(WORK, swarmId);
107
+ const queenInbox = await store.readAll("queen-0");
108
+ const last = queenInbox[queenInbox.length - 1];
109
+ expect(last.type).toBe("plan_approved");
110
+ expect(last.from).toBe("system");
111
+ expect(last.data).toContain("lgtm");
112
+ expect(last.data).toContain("approved");
113
+ });
114
+ it("flips planStatus to rejected + forwards body to queen", async () => {
115
+ const swarmId = "sw-pr-reject";
116
+ const { coord } = await setupSwarmWithReviewer(swarmId);
117
+ const swarm = coord.getSwarm(swarmId);
118
+ swarm.planStatus = "reviewing";
119
+ await coord.submitPlanReview({
120
+ swarmId,
121
+ from: "reviewer-0",
122
+ verdict: "rejected",
123
+ body: "缺并发处理",
124
+ });
125
+ expect(swarm.planStatus).toBe("rejected");
126
+ const store = new InboxStore(WORK, swarmId);
127
+ const queenInbox = await store.readAll("queen-0");
128
+ const last = queenInbox[queenInbox.length - 1];
129
+ expect(last.type).toBe("plan_rejected");
130
+ expect(last.data).toContain("缺并发处理");
131
+ });
132
+ it("clears planReviewTimer when verdict received in time", async () => {
133
+ vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout"] });
134
+ try {
135
+ const swarmId = "sw-pr-timer";
136
+ const sessionAdapter = createMockSessionAdapter();
137
+ const hubAdapter = createMockHubAdapter();
138
+ const coord = new SwarmCoordinator(sessionAdapter, hubAdapter);
139
+ await coord.create(swarmId, {
140
+ workDir: WORK,
141
+ roles: [
142
+ { roleName: "queen", count: 1, eager: true },
143
+ { roleName: "reviewer", count: 1, eager: true },
144
+ ],
145
+ });
146
+ const swarm = coord.getSwarm(swarmId);
147
+ // Drive requestPlanReview directly (private) to set up the timer.
148
+ await coord.requestPlanReview(swarm, { goal: "test plan" });
149
+ expect(swarm.planStatus).toBe("reviewing");
150
+ expect(swarm.planReviewTimer).toBeDefined();
151
+ await coord.submitPlanReview({
152
+ swarmId,
153
+ from: "reviewer-0",
154
+ verdict: "approved",
155
+ body: "ok",
156
+ });
157
+ expect(swarm.planReviewTimer).toBeUndefined();
158
+ }
159
+ finally {
160
+ vi.useRealTimers();
161
+ }
162
+ });
163
+ it("throws when swarm not found", async () => {
164
+ const sessionAdapter = createMockSessionAdapter();
165
+ const hubAdapter = createMockHubAdapter();
166
+ const coord = new SwarmCoordinator(sessionAdapter, hubAdapter);
167
+ await expect(coord.submitPlanReview({ swarmId: "ghost", from: "reviewer-0", verdict: "approved" })).rejects.toThrow(/swarm not found: ghost/);
168
+ });
169
+ it("idempotent when planStatus is already approved (no-op)", async () => {
170
+ const swarmId = "sw-pr-idem";
171
+ const { coord } = await setupSwarmWithReviewer(swarmId);
172
+ const swarm = coord.getSwarm(swarmId);
173
+ swarm.planStatus = "approved";
174
+ const store = new InboxStore(WORK, swarmId);
175
+ const before = await store.readAll("queen-0");
176
+ const beforeCount = before.length;
177
+ await coord.submitPlanReview({
178
+ swarmId,
179
+ from: "reviewer-0",
180
+ verdict: "rejected",
181
+ body: "trying again",
182
+ });
183
+ expect(swarm.planStatus).toBe("approved"); // unchanged
184
+ const after = await store.readAll("queen-0");
185
+ expect(after.length).toBe(beforeCount);
186
+ });
187
+ it("auto-approves after timeout with warning body to queen", async () => {
188
+ const swarmId = "sw-pr-timeout";
189
+ const sessionAdapter = createMockSessionAdapter();
190
+ const hubAdapter = createMockHubAdapter();
191
+ const coord = new SwarmCoordinator(sessionAdapter, hubAdapter);
192
+ await coord.create(swarmId, {
193
+ workDir: WORK,
194
+ roles: [
195
+ { roleName: "queen", count: 1, eager: true },
196
+ { roleName: "reviewer", count: 1, eager: true },
197
+ ],
198
+ });
199
+ const swarm = coord.getSwarm(swarmId);
200
+ // Allow post-create deliveries to settle on the real clock before any
201
+ // fake-timer manipulation so we don't trap proper-lockfile retries.
202
+ await new Promise((r) => setTimeout(r, 30));
203
+ // Suppress the 5min queen-check timer for this test — it would race the
204
+ // plan-review timer and fire its own deliveries inside the same window.
205
+ if (swarm.checkTimer) {
206
+ clearTimeout(swarm.checkTimer);
207
+ swarm.checkTimer = undefined;
208
+ }
209
+ vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout"] });
210
+ let realTimersRestored = false;
211
+ try {
212
+ await coord.requestPlanReview(swarm, { goal: "test plan" });
213
+ expect(swarm.planStatus).toBe("reviewing");
214
+ expect(swarm.planReviewTimer).toBeDefined();
215
+ // advanceTimersByTimeAsync awaits the microtask queue between fires so
216
+ // our `void submitPlanReview(...)` chain can settle before the next
217
+ // expectation. We then drop back to real timers for any straggler I/O.
218
+ await vi.advanceTimersByTimeAsync(10 * 60 * 1000 + 100);
219
+ vi.useRealTimers();
220
+ realTimersRestored = true;
221
+ // Wait for the chained deliverInbox to land the message.
222
+ const store = new InboxStore(WORK, swarmId);
223
+ let timeoutMsg;
224
+ await flushUntil(async () => {
225
+ const all = await store.readAll("queen-0");
226
+ timeoutMsg = all.find((m) => m.type === "plan_approved" &&
227
+ typeof m.data === "string" &&
228
+ m.data.includes("[timeout]"));
229
+ return Boolean(timeoutMsg);
230
+ }, 100);
231
+ expect(swarm.planStatus).toBe("approved");
232
+ expect(swarm.planReviewTimer).toBeUndefined();
233
+ expect(timeoutMsg).toBeDefined();
234
+ expect(timeoutMsg.data).toContain("[timeout]");
235
+ expect(timeoutMsg.data).toContain("未在 10 分钟内");
236
+ }
237
+ finally {
238
+ if (!realTimersRestored)
239
+ vi.useRealTimers();
240
+ }
241
+ });
242
+ it("late submission after timeout-approved is no-op (idempotency)", async () => {
243
+ const swarmId = "sw-pr-late";
244
+ const sessionAdapter = createMockSessionAdapter();
245
+ const hubAdapter = createMockHubAdapter();
246
+ const coord = new SwarmCoordinator(sessionAdapter, hubAdapter);
247
+ await coord.create(swarmId, {
248
+ workDir: WORK,
249
+ roles: [
250
+ { roleName: "queen", count: 1, eager: true },
251
+ { roleName: "reviewer", count: 1, eager: true },
252
+ ],
253
+ });
254
+ const swarm = coord.getSwarm(swarmId);
255
+ await new Promise((r) => setTimeout(r, 30));
256
+ if (swarm.checkTimer) {
257
+ clearTimeout(swarm.checkTimer);
258
+ swarm.checkTimer = undefined;
259
+ }
260
+ vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout"] });
261
+ let realTimersRestored = false;
262
+ try {
263
+ await coord.requestPlanReview(swarm, { goal: "test plan" });
264
+ await vi.advanceTimersByTimeAsync(10 * 60 * 1000 + 100);
265
+ vi.useRealTimers();
266
+ realTimersRestored = true;
267
+ // Wait until the timeout-approve message has landed.
268
+ const store = new InboxStore(WORK, swarmId);
269
+ await flushUntil(async () => {
270
+ const all = await store.readAll("queen-0");
271
+ return all.some((m) => m.type === "plan_approved" &&
272
+ (m.data ?? "").includes("[timeout]"));
273
+ }, 100);
274
+ expect(swarm.planStatus).toBe("approved");
275
+ const beforeCount = (await store.readAll("queen-0")).length;
276
+ expect(beforeCount).toBeGreaterThan(0);
277
+ // Reviewer finally submits late.
278
+ await coord.submitPlanReview({
279
+ swarmId,
280
+ from: "reviewer-0",
281
+ verdict: "rejected",
282
+ body: "late",
283
+ });
284
+ expect(swarm.planStatus).toBe("approved"); // still
285
+ const afterLate = await store.readAll("queen-0");
286
+ expect(afterLate.length).toBe(beforeCount);
287
+ }
288
+ finally {
289
+ if (!realTimersRestored)
290
+ vi.useRealTimers();
291
+ }
292
+ });
293
+ });
294
+ //# sourceMappingURL=swarm-coordinator-plan-review.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swarm-coordinator-plan-review.test.js","sourceRoot":"","sources":["../../src/__tests__/swarm-coordinator-plan-review.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=swarm-coordinator-resume.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swarm-coordinator-resume.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/swarm-coordinator-resume.test.ts"],"names":[],"mappings":""}