@@ -80,6 +80,64 @@ describe("dispatchAndStartWorkboardCards", () => {
|
80 | 80 | }); |
81 | 81 | }); |
82 | 82 | |
| 83 | +it("does not let review cards consume an agent running slot", async () => { |
| 84 | +const store = new WorkboardStore(createMemoryStore()); |
| 85 | +await store.create({ |
| 86 | +title: "Waiting for operator review", |
| 87 | +status: "review", |
| 88 | +priority: "normal", |
| 89 | +agentId: "codex-main", |
| 90 | +}); |
| 91 | +const ready = await store.create({ |
| 92 | +title: "Next ready card", |
| 93 | +status: "ready", |
| 94 | +priority: "high", |
| 95 | +agentId: "codex-main", |
| 96 | +}); |
| 97 | +const run = vi.fn().mockResolvedValue({ runId: "run-next" }); |
| 98 | + |
| 99 | +const result = await dispatchAndStartWorkboardCards({ |
| 100 | + store, |
| 101 | +subagent: { run }, |
| 102 | +options: { now: 10, maxStarts: 3 }, |
| 103 | +}); |
| 104 | + |
| 105 | +expect(result.started).toEqual([ |
| 106 | +expect.objectContaining({ |
| 107 | +cardId: ready.id, |
| 108 | +runId: "run-next", |
| 109 | +}), |
| 110 | +]); |
| 111 | +expect(run).toHaveBeenCalledOnce(); |
| 112 | +}); |
| 113 | + |
| 114 | +it("keeps claimed review cards in the owner running slot", async () => { |
| 115 | +const store = new WorkboardStore(createMemoryStore()); |
| 116 | +const review = await store.create({ |
| 117 | +title: "Claimed operator review", |
| 118 | +status: "review", |
| 119 | +priority: "normal", |
| 120 | +agentId: "codex-main", |
| 121 | +}); |
| 122 | +await store.claim(review.id, { ownerId: "codex-main", token: "review-token" }); |
| 123 | +await store.create({ |
| 124 | +title: "Next ready card", |
| 125 | +status: "ready", |
| 126 | +priority: "high", |
| 127 | +agentId: "codex-main", |
| 128 | +}); |
| 129 | +const run = vi.fn().mockResolvedValue({ runId: "run-next" }); |
| 130 | + |
| 131 | +const result = await dispatchAndStartWorkboardCards({ |
| 132 | + store, |
| 133 | +subagent: { run }, |
| 134 | +options: { now: 10, maxStarts: 3 }, |
| 135 | +}); |
| 136 | + |
| 137 | +expect(result.started).toEqual([]); |
| 138 | +expect(run).not.toHaveBeenCalled(); |
| 139 | +}); |
| 140 | + |
83 | 141 | it("blocks a card when worker start fails after claim", async () => { |
84 | 142 | const store = new WorkboardStore(createMemoryStore()); |
85 | 143 | const card = await store.create({ title: "Fail worker", status: "ready" }); |
|