@songsid/agend 2.1.7-beta.3 → 2.1.7-beta.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 (92) hide show
  1. package/README.md +2 -0
  2. package/README.zh-TW.md +2 -0
  3. package/dist/agent-cli-instructions.md +5 -0
  4. package/dist/agent-cli.js +13 -0
  5. package/dist/agent-cli.js.map +1 -1
  6. package/dist/agent-endpoint.d.ts +2 -0
  7. package/dist/agent-endpoint.js +48 -5
  8. package/dist/agent-endpoint.js.map +1 -1
  9. package/dist/backend/codex-session-lookup.d.ts +59 -0
  10. package/dist/backend/codex-session-lookup.js +139 -0
  11. package/dist/backend/codex-session-lookup.js.map +1 -0
  12. package/dist/backend/codex.d.ts +29 -0
  13. package/dist/backend/codex.js +183 -10
  14. package/dist/backend/codex.js.map +1 -1
  15. package/dist/backend/types.d.ts +21 -0
  16. package/dist/backend/types.js.map +1 -1
  17. package/dist/channel/mcp-operation-response.d.ts +3 -0
  18. package/dist/channel/mcp-operation-response.js +21 -0
  19. package/dist/channel/mcp-operation-response.js.map +1 -0
  20. package/dist/channel/mcp-operation-response.test.d.ts +1 -0
  21. package/dist/channel/mcp-operation-response.test.js +23 -0
  22. package/dist/channel/mcp-operation-response.test.js.map +1 -0
  23. package/dist/channel/mcp-server.js +20 -5
  24. package/dist/channel/mcp-server.js.map +1 -1
  25. package/dist/channel/mcp-tools.js +2 -0
  26. package/dist/channel/mcp-tools.js.map +1 -1
  27. package/dist/cli.js +68 -2
  28. package/dist/cli.js.map +1 -1
  29. package/dist/daemon.d.ts +34 -0
  30. package/dist/daemon.js +415 -41
  31. package/dist/daemon.js.map +1 -1
  32. package/dist/delivery-outbox.d.ts +174 -0
  33. package/dist/delivery-outbox.js +824 -0
  34. package/dist/delivery-outbox.js.map +1 -0
  35. package/dist/delivery-outbox.test.d.ts +1 -0
  36. package/dist/delivery-outbox.test.js +597 -0
  37. package/dist/delivery-outbox.test.js.map +1 -0
  38. package/dist/delivery-queue-evidence.d.ts +15 -0
  39. package/dist/delivery-queue-evidence.js +35 -0
  40. package/dist/delivery-queue-evidence.js.map +1 -0
  41. package/dist/delivery-queue-evidence.test.d.ts +1 -0
  42. package/dist/delivery-queue-evidence.test.js +23 -0
  43. package/dist/delivery-queue-evidence.test.js.map +1 -0
  44. package/dist/delivery-reconciliation.d.ts +49 -0
  45. package/dist/delivery-reconciliation.js +296 -0
  46. package/dist/delivery-reconciliation.js.map +1 -0
  47. package/dist/delivery-reconciliation.test.d.ts +1 -0
  48. package/dist/delivery-reconciliation.test.js +411 -0
  49. package/dist/delivery-reconciliation.test.js.map +1 -0
  50. package/dist/fleet-manager.d.ts +39 -1
  51. package/dist/fleet-manager.js +345 -50
  52. package/dist/fleet-manager.js.map +1 -1
  53. package/dist/instance-lifecycle.d.ts +18 -0
  54. package/dist/instance-lifecycle.js +116 -3
  55. package/dist/instance-lifecycle.js.map +1 -1
  56. package/dist/instructions.js +3 -0
  57. package/dist/instructions.js.map +1 -1
  58. package/dist/locale.js +6 -0
  59. package/dist/locale.js.map +1 -1
  60. package/dist/outbound-handlers.d.ts +25 -1
  61. package/dist/outbound-handlers.js +119 -8
  62. package/dist/outbound-handlers.js.map +1 -1
  63. package/dist/outbound-schemas.d.ts +7 -0
  64. package/dist/outbound-schemas.js +14 -0
  65. package/dist/outbound-schemas.js.map +1 -1
  66. package/dist/pane-write-lock.d.ts +2 -0
  67. package/dist/pane-write-lock.js +19 -0
  68. package/dist/pane-write-lock.js.map +1 -1
  69. package/dist/remote-credential-check.d.ts +39 -0
  70. package/dist/remote-credential-check.js +81 -0
  71. package/dist/remote-credential-check.js.map +1 -0
  72. package/dist/scheduler/scheduler.d.ts +5 -1
  73. package/dist/scheduler/scheduler.js +60 -20
  74. package/dist/scheduler/scheduler.js.map +1 -1
  75. package/dist/scheduler/scheduler.test.js +41 -2
  76. package/dist/scheduler/scheduler.test.js.map +1 -1
  77. package/dist/scheduler/types.d.ts +1 -1
  78. package/dist/tmux-manager.d.ts +3 -3
  79. package/dist/tmux-manager.js +6 -6
  80. package/dist/tmux-manager.js.map +1 -1
  81. package/dist/tool-permissions.js +6 -6
  82. package/dist/tool-permissions.js.map +1 -1
  83. package/dist/transcript-monitor.d.ts +3 -1
  84. package/dist/transcript-monitor.js +15 -0
  85. package/dist/transcript-monitor.js.map +1 -1
  86. package/dist/transcript-sources.d.ts +9 -0
  87. package/dist/transcript-sources.js +14 -0
  88. package/dist/transcript-sources.js.map +1 -1
  89. package/dist/usage/providers.d.ts +11 -6
  90. package/dist/usage/providers.js +17 -10
  91. package/dist/usage/providers.js.map +1 -1
  92. package/package.json +1 -1
@@ -0,0 +1,411 @@
1
+ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, describe, expect, it, vi } from "vitest";
5
+ import { DeliveryOutbox } from "./delivery-outbox.js";
6
+ import { queueResumePolicyForAttempt } from "./delivery-queue-evidence.js";
7
+ import { finishTargetReconciliation, transcriptDeltaHasDeliveryMarker } from "./delivery-reconciliation.js";
8
+ const id = "00000000-0000-4000-8000-000000000041";
9
+ const marker = `[agend-delivery-id:${id}]`;
10
+ const roots = [];
11
+ afterEach(() => {
12
+ for (const root of roots.splice(0))
13
+ rmSync(root, { recursive: true, force: true });
14
+ });
15
+ function makeAttempt(options = { enterStarted: true }) {
16
+ const root = mkdtempSync(join(tmpdir(), "agend-reconciliation-"));
17
+ roots.push(root);
18
+ const outbox = new DeliveryOutbox(join(root, "outbox.db"), "manager-1");
19
+ const row = outbox.admit({
20
+ operationId: "op-reconcile",
21
+ sourceKey: "source:op-reconcile:worker",
22
+ sourceInstance: "source",
23
+ sourceDaemonBootId: "source-boot",
24
+ targetInstance: "worker",
25
+ kind: options.kind ?? "fleet_inbound",
26
+ payload: { type: options.kind === "raw_paste" ? "raw_paste" : "fleet_inbound", content: options.payloadContent ?? "work", meta: {} },
27
+ }).delivery;
28
+ const claimed = outbox.claimNext("manager-1", () => "target-boot-1", new Set());
29
+ expect(outbox.begin(row.deliveryId, "target-boot-1", claimed.attemptNo, {
30
+ backend: options.backend ?? "claude-code",
31
+ backendVersion: null,
32
+ windowId: options.windowId === undefined ? "@old-worker" : options.windowId,
33
+ transcriptPath: options.transcriptPath ?? null,
34
+ transcriptOffset: options.transcriptOffset ?? null,
35
+ transcriptSessionId: options.transcriptPath ?? null,
36
+ submissionMode: options.submissionMode ?? "idle_submit",
37
+ queueResumePolicy: options.queueResumePolicy
38
+ ?? queueResumePolicyForAttempt(options.backend ?? "claude-code", null, options.submissionMode ?? "idle_submit"),
39
+ })).toBe("begun");
40
+ if (options.enterStarted)
41
+ expect(outbox.markEnterStarted(row.deliveryId, "target-boot-1", claimed.attemptNo)).toBe(true);
42
+ expect(outbox.recoverForBoot("manager-2").reconciliationPending).toBe(1);
43
+ return { outbox, row, candidate: outbox.getReconciliationCandidates("worker")[0] };
44
+ }
45
+ describe("durable transcript marker reconciliation", () => {
46
+ it("requires the exact marker at the beginning of a Claude user entry", () => {
47
+ expect(transcriptDeltaHasDeliveryMarker(JSON.stringify({
48
+ type: "user",
49
+ message: { role: "user", content: [{ type: "text", text: `${marker}\n[from:worker] do the work` }] },
50
+ }), "claude-code", id)).toBe(true);
51
+ });
52
+ it("requires the exact marker at the beginning of a Codex user entry", () => {
53
+ expect(transcriptDeltaHasDeliveryMarker(JSON.stringify({
54
+ type: "response_item",
55
+ payload: { type: "message", role: "user", content: [{ type: "input_text", text: `${marker}\n[from:worker] do the work` }] },
56
+ }), "codex", id)).toBe(true);
57
+ });
58
+ it("does not accept a marker after the first Claude user text item", () => {
59
+ const entry = JSON.stringify({
60
+ type: "user",
61
+ message: { role: "user", content: [
62
+ { type: "text", text: "preceding content" },
63
+ { type: "text", text: `${marker}\n[from:worker] do the work` },
64
+ ] },
65
+ });
66
+ expect(transcriptDeltaHasDeliveryMarker(entry, "claude-code", id)).toBe(false);
67
+ });
68
+ it("does not accept a marker after the first Codex user text item", () => {
69
+ const entry = JSON.stringify({
70
+ type: "response_item",
71
+ payload: { type: "message", role: "user", content: [
72
+ { type: "input_text", text: "preceding content" },
73
+ { type: "input_text", text: `${marker}\n[from:worker] do the work` },
74
+ ] },
75
+ });
76
+ expect(transcriptDeltaHasDeliveryMarker(entry, "codex", id)).toBe(false);
77
+ });
78
+ it("does not accept quoted, embedded, assistant, system, or tool-result occurrences", () => {
79
+ const entries = [
80
+ { type: "user", message: { role: "user", content: [{ type: "text", text: `quoted: ${marker}` }] } },
81
+ { type: "assistant", message: { role: "assistant", content: [{ type: "text", text: marker }] } },
82
+ { type: "user", message: { role: "user", content: [{ type: "tool_result", text: marker }] } },
83
+ { type: "response_item", payload: { type: "function_call_output", output: marker } },
84
+ ].map(entry => JSON.stringify(entry)).join("\n");
85
+ expect(transcriptDeltaHasDeliveryMarker(entries, "claude-code", id)).toBe(false);
86
+ expect(transcriptDeltaHasDeliveryMarker(entries, "codex", id)).toBe(false);
87
+ });
88
+ it("fails closed for unknown transcript backends and malformed lines", () => {
89
+ expect(transcriptDeltaHasDeliveryMarker(`not-json ${marker}`, "muse", id)).toBe(false);
90
+ expect(transcriptDeltaHasDeliveryMarker("{ truncated", "claude-code", id)).toBe(false);
91
+ });
92
+ it("uses a persisted Claude user-entry marker as positive proof only after the old CLI exits", async () => {
93
+ const root = mkdtempSync(join(tmpdir(), "agend-reconciliation-positive-"));
94
+ roots.push(root);
95
+ const transcriptPath = join(root, "session.jsonl");
96
+ const h = makeAttempt({ enterStarted: true, transcriptPath, transcriptOffset: 0 });
97
+ writeFileSync(transcriptPath, `${JSON.stringify({
98
+ type: "user",
99
+ message: { role: "user", content: [{ type: "text", text: `[agend-delivery-id:${h.row.deliveryId}]\n[from:worker] work` }] },
100
+ })}\n`);
101
+ const result = await finishTargetReconciliation(h.outbox, {
102
+ targetInstance: "worker",
103
+ sessionName: "test-session",
104
+ savedWindowId: "@old-worker",
105
+ attempts: [{ candidate: h.candidate, paneWindowId: "@old-worker", panePid: null, pane: "", paneCaptureError: null }],
106
+ }, true);
107
+ expect(result).toMatchObject({ delivered: 1, retry: 0, uncertain: 0, safeToStart: true });
108
+ expect(h.outbox.get(h.row.deliveryId)?.state).toBe("delivered");
109
+ h.outbox.close();
110
+ });
111
+ it("retries composer-only marker evidence only when the write-ahead fence proves Enter never started", async () => {
112
+ const h = makeAttempt({ enterStarted: false });
113
+ const result = await finishTargetReconciliation(h.outbox, {
114
+ targetInstance: "worker",
115
+ sessionName: "test-session",
116
+ savedWindowId: "@old-worker",
117
+ attempts: [{
118
+ candidate: h.candidate,
119
+ paneWindowId: "@old-worker",
120
+ panePid: null,
121
+ pane: `${marker}\n› [from:worker] work`,
122
+ paneCaptureError: null,
123
+ }],
124
+ }, true);
125
+ expect(result).toMatchObject({ delivered: 0, retry: 1, uncertain: 0, safeToStart: true });
126
+ expect(h.outbox.get(h.row.deliveryId)).toMatchObject({ state: "retry_wait", reconciliationPending: false });
127
+ h.outbox.close();
128
+ });
129
+ it("does not read a positive transcript as proof until window retirement is confirmed", async () => {
130
+ const root = mkdtempSync(join(tmpdir(), "agend-reconciliation-live-cli-"));
131
+ roots.push(root);
132
+ const transcriptPath = join(root, "session.jsonl");
133
+ const h = makeAttempt({ enterStarted: true, transcriptPath, transcriptOffset: 0 });
134
+ writeFileSync(transcriptPath, `${JSON.stringify({
135
+ type: "user",
136
+ message: { role: "user", content: [{ type: "text", text: `[agend-delivery-id:${h.row.deliveryId}]\n[from:worker] work` }] },
137
+ })}\n`);
138
+ const result = await finishTargetReconciliation(h.outbox, {
139
+ targetInstance: "worker",
140
+ sessionName: "test-session",
141
+ savedWindowId: "@old-worker",
142
+ attempts: [{ candidate: h.candidate, paneWindowId: "@old-worker", panePid: process.pid, pane: "", paneCaptureError: null }],
143
+ }, false);
144
+ expect(result).toMatchObject({ delivered: 0, retry: 0, uncertain: 1, safeToStart: false });
145
+ expect(h.outbox.get(h.row.deliveryId)?.state).toBe("uncertain");
146
+ h.outbox.close();
147
+ });
148
+ it("retries a stable transcript miss for an idle submit after the old CLI exits", async () => {
149
+ const root = mkdtempSync(join(tmpdir(), "agend-reconciliation-idle-miss-"));
150
+ roots.push(root);
151
+ const transcriptPath = join(root, "session.jsonl");
152
+ writeFileSync(transcriptPath, "");
153
+ const h = makeAttempt({
154
+ enterStarted: true,
155
+ backend: "codex",
156
+ submissionMode: "idle_submit",
157
+ transcriptPath,
158
+ transcriptOffset: 0,
159
+ });
160
+ const kill = vi.spyOn(process, "kill").mockImplementation(() => {
161
+ const err = new Error("no such process");
162
+ err.code = "ESRCH";
163
+ throw err;
164
+ });
165
+ try {
166
+ const result = await finishTargetReconciliation(h.outbox, {
167
+ targetInstance: "worker",
168
+ sessionName: "test-session",
169
+ savedWindowId: "@old-worker",
170
+ attempts: [{ candidate: h.candidate, paneWindowId: "@old-worker", panePid: 424242, pane: "", paneCaptureError: null }],
171
+ }, true);
172
+ expect(result).toMatchObject({ delivered: 0, retry: 1, uncertain: 0, safeToStart: true });
173
+ expect(h.outbox.get(h.row.deliveryId)).toMatchObject({ state: "retry_wait", reconciliationPending: false });
174
+ }
175
+ finally {
176
+ kill.mockRestore();
177
+ h.outbox.close();
178
+ }
179
+ });
180
+ it("retries raw_paste only when the exact bytes remain at the end of the pre-kill composer", async () => {
181
+ const raw = " /compact\n--keep-space ";
182
+ const h = makeAttempt({
183
+ enterStarted: false,
184
+ kind: "raw_paste",
185
+ payloadContent: raw,
186
+ submissionMode: "raw_paste",
187
+ });
188
+ const kill = vi.spyOn(process, "kill").mockImplementation(() => {
189
+ const err = new Error("no such process");
190
+ err.code = "ESRCH";
191
+ throw err;
192
+ });
193
+ try {
194
+ const result = await finishTargetReconciliation(h.outbox, {
195
+ targetInstance: "worker",
196
+ sessionName: "test-session",
197
+ savedWindowId: "@old-worker",
198
+ attempts: [{
199
+ candidate: h.candidate,
200
+ paneWindowId: "@old-worker",
201
+ panePid: 424242,
202
+ pane: `old transcript\n❯ ${raw}`,
203
+ paneCaptureError: null,
204
+ }],
205
+ }, true);
206
+ expect(result).toMatchObject({ delivered: 0, retry: 1, uncertain: 0, safeToStart: true });
207
+ expect(h.outbox.get(h.row.deliveryId)).toMatchObject({ state: "retry_wait" });
208
+ }
209
+ finally {
210
+ kill.mockRestore();
211
+ h.outbox.close();
212
+ }
213
+ });
214
+ it("keeps raw_paste uncertain when W1 says no Enter but the exact composer bytes are absent", async () => {
215
+ const raw = "/compact";
216
+ const h = makeAttempt({
217
+ enterStarted: false,
218
+ kind: "raw_paste",
219
+ payloadContent: raw,
220
+ submissionMode: "raw_paste",
221
+ });
222
+ const kill = vi.spyOn(process, "kill").mockImplementation(() => {
223
+ const err = new Error("no such process");
224
+ err.code = "ESRCH";
225
+ throw err;
226
+ });
227
+ try {
228
+ const result = await finishTargetReconciliation(h.outbox, {
229
+ targetInstance: "worker",
230
+ sessionName: "test-session",
231
+ savedWindowId: "@old-worker",
232
+ attempts: [{
233
+ candidate: h.candidate,
234
+ paneWindowId: "@old-worker",
235
+ panePid: 424242,
236
+ pane: "CLI resumed with a clean prompt",
237
+ paneCaptureError: null,
238
+ }],
239
+ }, true);
240
+ expect(result).toMatchObject({ delivered: 0, retry: 0, uncertain: 1, safeToStart: true });
241
+ expect(h.outbox.get(h.row.deliveryId)).toMatchObject({ state: "uncertain" });
242
+ }
243
+ finally {
244
+ kill.mockRestore();
245
+ h.outbox.close();
246
+ }
247
+ });
248
+ it("does not treat a raw command ending in newline as exact composer evidence", async () => {
249
+ const raw = "/compact\n";
250
+ const h = makeAttempt({
251
+ enterStarted: false,
252
+ kind: "raw_paste",
253
+ payloadContent: raw,
254
+ submissionMode: "raw_paste",
255
+ });
256
+ const kill = vi.spyOn(process, "kill").mockImplementation(() => {
257
+ const err = new Error("no such process");
258
+ err.code = "ESRCH";
259
+ throw err;
260
+ });
261
+ try {
262
+ const result = await finishTargetReconciliation(h.outbox, {
263
+ targetInstance: "worker",
264
+ sessionName: "test-session",
265
+ savedWindowId: "@old-worker",
266
+ attempts: [{
267
+ candidate: h.candidate,
268
+ paneWindowId: "@old-worker",
269
+ panePid: 424242,
270
+ pane: `old transcript\n❯ ${raw}\n`,
271
+ paneCaptureError: null,
272
+ }],
273
+ }, true);
274
+ expect(result).toMatchObject({ delivered: 0, retry: 0, uncertain: 1, safeToStart: true });
275
+ expect(h.outbox.get(h.row.deliveryId)).toMatchObject({ state: "uncertain" });
276
+ }
277
+ finally {
278
+ kill.mockRestore();
279
+ h.outbox.close();
280
+ }
281
+ });
282
+ it("keeps a transcript miss uncertain when the old CLI pid is unknown", async () => {
283
+ const root = mkdtempSync(join(tmpdir(), "agend-reconciliation-unknown-pid-"));
284
+ roots.push(root);
285
+ const transcriptPath = join(root, "session.jsonl");
286
+ writeFileSync(transcriptPath, "");
287
+ const h = makeAttempt({
288
+ enterStarted: true,
289
+ backend: "codex",
290
+ submissionMode: "idle_submit",
291
+ transcriptPath,
292
+ transcriptOffset: 0,
293
+ });
294
+ const result = await finishTargetReconciliation(h.outbox, {
295
+ targetInstance: "worker",
296
+ sessionName: "test-session",
297
+ savedWindowId: "@old-worker",
298
+ attempts: [{ candidate: h.candidate, paneWindowId: "@old-worker", panePid: null, pane: "", paneCaptureError: null }],
299
+ }, true);
300
+ expect(result).toMatchObject({ delivered: 0, retry: 0, uncertain: 1, safeToStart: true });
301
+ expect(h.outbox.get(h.row.deliveryId)).toMatchObject({ state: "uncertain", reconciliationPending: false });
302
+ h.outbox.close();
303
+ });
304
+ it.each([
305
+ ["Codex native queue", "codex", "native_queue_handoff", "unknown"],
306
+ ["Claude steering", "claude-code", "steer", "may_resume"],
307
+ ])("keeps %s uncertain when transcript has no marker and queue resume is not ruled out", async (_label, backend, submissionMode, queueResumePolicy) => {
308
+ const root = mkdtempSync(join(tmpdir(), "agend-reconciliation-queue-unknown-"));
309
+ roots.push(root);
310
+ const transcriptPath = join(root, "session.jsonl");
311
+ writeFileSync(transcriptPath, "");
312
+ const h = makeAttempt({
313
+ enterStarted: true,
314
+ backend,
315
+ submissionMode,
316
+ queueResumePolicy,
317
+ transcriptPath,
318
+ transcriptOffset: 0,
319
+ });
320
+ const result = await finishTargetReconciliation(h.outbox, {
321
+ targetInstance: "worker",
322
+ sessionName: "test-session",
323
+ savedWindowId: "@old-worker",
324
+ attempts: [{ candidate: h.candidate, paneWindowId: "@old-worker", panePid: 424242, pane: "", paneCaptureError: null }],
325
+ }, true);
326
+ expect(result).toMatchObject({ delivered: 0, retry: 0, uncertain: 1, safeToStart: true });
327
+ expect(h.outbox.get(h.row.deliveryId)).toMatchObject({ state: "uncertain", reconciliationPending: false });
328
+ h.outbox.close();
329
+ });
330
+ it("allows transcript absence to retry only for an exact policy that proves resume cannot replay a queue item", async () => {
331
+ const root = mkdtempSync(join(tmpdir(), "agend-reconciliation-queue-ephemeral-"));
332
+ roots.push(root);
333
+ const transcriptPath = join(root, "rollout.jsonl");
334
+ writeFileSync(transcriptPath, "");
335
+ const h = makeAttempt({
336
+ enterStarted: true,
337
+ backend: "codex",
338
+ submissionMode: "native_queue_handoff",
339
+ queueResumePolicy: "does_not_resume",
340
+ transcriptPath,
341
+ transcriptOffset: 0,
342
+ });
343
+ const kill = vi.spyOn(process, "kill").mockImplementation(() => {
344
+ const err = new Error("no such process");
345
+ err.code = "ESRCH";
346
+ throw err;
347
+ });
348
+ try {
349
+ const result = await finishTargetReconciliation(h.outbox, {
350
+ targetInstance: "worker",
351
+ sessionName: "test-session",
352
+ savedWindowId: "@old-worker",
353
+ attempts: [{ candidate: h.candidate, paneWindowId: "@old-worker", panePid: 424242, pane: "", paneCaptureError: null }],
354
+ }, true);
355
+ expect(result).toMatchObject({ delivered: 0, retry: 1, uncertain: 0, safeToStart: true });
356
+ expect(h.outbox.get(h.row.deliveryId)).toMatchObject({ state: "retry_wait" });
357
+ }
358
+ finally {
359
+ kill.mockRestore();
360
+ h.outbox.close();
361
+ }
362
+ });
363
+ it("keeps the target fenced when the tmux window is gone but its captured process is still alive", async () => {
364
+ const h = makeAttempt({ enterStarted: true });
365
+ const kill = vi.spyOn(process, "kill").mockImplementation(() => {
366
+ const err = new Error("permission denied");
367
+ err.code = "EPERM";
368
+ throw err;
369
+ });
370
+ try {
371
+ const result = await finishTargetReconciliation(h.outbox, {
372
+ targetInstance: "worker",
373
+ sessionName: "test-session",
374
+ savedWindowId: "@old-worker",
375
+ attempts: [{ candidate: h.candidate, paneWindowId: "@old-worker", panePid: 424242, pane: "", paneCaptureError: null }],
376
+ }, true);
377
+ expect(result).toMatchObject({ delivered: 0, retry: 0, uncertain: 1, safeToStart: false });
378
+ expect(h.outbox.get(h.row.deliveryId)?.state).toBe("uncertain");
379
+ }
380
+ finally {
381
+ kill.mockRestore();
382
+ h.outbox.close();
383
+ }
384
+ });
385
+ it("keeps the target fenced when a pending attempt has no window identity", async () => {
386
+ const h = makeAttempt({ enterStarted: true, windowId: null });
387
+ const result = await finishTargetReconciliation(h.outbox, {
388
+ targetInstance: "worker",
389
+ sessionName: "test-session",
390
+ savedWindowId: "@old-worker",
391
+ attempts: [{ candidate: h.candidate, paneWindowId: null, panePid: null, pane: null, paneCaptureError: "old window id unavailable" }],
392
+ }, true);
393
+ expect(result).toMatchObject({ delivered: 0, retry: 0, uncertain: 1, safeToStart: false });
394
+ expect(h.outbox.get(h.row.deliveryId)?.state).toBe("uncertain");
395
+ h.outbox.close();
396
+ });
397
+ it("allows an ordinary start when no reconciliation rows exist even if retirement is unconfirmed", async () => {
398
+ const root = mkdtempSync(join(tmpdir(), "agend-reconciliation-empty-"));
399
+ roots.push(root);
400
+ const outbox = new DeliveryOutbox(join(root, "outbox.db"), "manager-1");
401
+ const result = await finishTargetReconciliation(outbox, {
402
+ targetInstance: "worker",
403
+ sessionName: "test-session",
404
+ savedWindowId: "@old-worker",
405
+ attempts: [],
406
+ }, false);
407
+ expect(result).toMatchObject({ delivered: 0, retry: 0, uncertain: 0, safeToStart: true });
408
+ outbox.close();
409
+ });
410
+ });
411
+ //# sourceMappingURL=delivery-reconciliation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delivery-reconciliation.test.js","sourceRoot":"","sources":["../src/delivery-reconciliation.test.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,8 @@ import { InstanceLifecycle, type LifecycleContext } from "./instance-lifecycle.j
16
16
  import { type ArchiverContext } from "./topic-archiver.js";
17
17
  import { type StatuslineWatcherContext } from "./statusline-watcher.js";
18
18
  import { type OutboundContext } from "./outbound-handlers.js";
19
+ import { DeliveryOutbox, type DeliveryStatusSelector, type DeliveryStatusPage } from "./delivery-outbox.js";
20
+ export declare const DURABLE_DELIVERY_LANE_ALERT_MS: number;
19
21
  import { type RawConfigPatch } from "./settings-api.js";
20
22
  import { type AgentEndpointContext } from "./agent-endpoint.js";
21
23
  import { ClassicChannelManager } from "./classic-channel-manager.js";
@@ -112,6 +114,14 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
112
114
  readonly spawnGate: SpawnGate;
113
115
  /** Fleet-level backend reachability memory (fed by pty_error / startup panes). */
114
116
  readonly backendOutage: BackendOutageTracker;
117
+ /** Stable for this FleetManager OS-process lifetime; Daemon objects have their own boot IDs. */
118
+ readonly managerBootId: `${string}-${string}-${string}-${string}-${string}`;
119
+ deliveryOutbox: DeliveryOutbox | null;
120
+ private deliveryOutboxRecovered;
121
+ private deliveryPumpScheduled;
122
+ private deliveryPumpRunning;
123
+ private deliveryPumpTimer;
124
+ private readonly activeDurableTargets;
115
125
  /** Live view of lifecycle.daemons — used throughout; not deprecated. */
116
126
  get daemons(): Map<string, import("./daemon.js").Daemon>;
117
127
  fleetConfig: FleetConfig | null;
@@ -330,6 +340,31 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
330
340
  private viewToken;
331
341
  private healthServerListening;
332
342
  constructor(dataDir: string);
343
+ private ensureDeliveryOutbox;
344
+ /** Synchronous SQLite admission; the caller may acknowledge only after this returns. */
345
+ admitDurableDelivery(input: {
346
+ operationId: string;
347
+ sourceDaemonBootId?: string;
348
+ sourceInstance: string;
349
+ targetInstance: string;
350
+ targetSession?: string;
351
+ kind: string;
352
+ correlationId: string;
353
+ payload: Record<string, unknown>;
354
+ }): {
355
+ deliveryId: string;
356
+ state: string;
357
+ duplicate: boolean;
358
+ };
359
+ queryDurableDeliveryStatus(callerInstance: string, selector: DeliveryStatusSelector): DeliveryStatusPage;
360
+ getDaemonBootId(instanceName: string): string | undefined;
361
+ markDurableResponseDelivered(sourceInstance: string, operationId: string): void;
362
+ /** Called after a replacement Daemon object is installed in lifecycle.daemons. */
363
+ onDaemonReady(name: string, daemonBootId: string): void;
364
+ private scheduleDeliveryOutboxPump;
365
+ private runDeliveryOutboxPump;
366
+ private dispatchDurableDelivery;
367
+ private waitForDurableLaneRelease;
333
368
  private spawnConcurrency;
334
369
  /** Wire the one fleet-wide storm into notification and recovery surfaces. */
335
370
  private bindStormWindowEvents;
@@ -535,7 +570,7 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
535
570
  /** Whether this target already has an ordinary non-user delivery in its FIFO. */
536
571
  hasPendingIdleGatedDelivery(instanceName: string): boolean;
537
572
  /** Single delivery facade: wake paused CLIs and serialize non-user work behind idle. */
538
- deliverToInstance(instanceName: string, payload: Record<string, unknown>, options?: DeliveryOptions): Promise<void>;
573
+ deliverToInstance(instanceName: string, payload: Record<string, unknown>, options?: DeliveryOptions): Promise<boolean | void>;
539
574
  /** Fleet admin is an explicit config allowlist entry, not merely an open/paired user. */
540
575
  isFleetAdmin(userId: string, adapterId?: string): boolean;
541
576
  changeInstancePauseState(name: string, action: "pause" | "wake"): Promise<"paused" | "awake" | "not_idle">;
@@ -653,6 +688,7 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
653
688
  restartSingleInstance(name: string, opts?: {
654
689
  freshStart?: boolean;
655
690
  }): Promise<void>;
691
+ isInstanceRestarting(name: string): boolean;
656
692
  private doRestartSingleInstance;
657
693
  /**
658
694
  * Mark an instance so its next daemon start skips session resume. Written AFTER
@@ -1030,6 +1066,8 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1030
1066
  * the chain drains, so idle messages hold no memory.
1031
1067
  */
1032
1068
  private deliveryStatusChains;
1069
+ /** #725: in-flight CLI env probes, keyed by backend name. Coalesces concurrent /model requests. */
1070
+ private pendingCliEnvProbes;
1033
1071
  reactMessageStatus(instanceName: string, chatId: string, messageId: string, emoji: string, threadId?: string): void;
1034
1072
  /**
1035
1073
  * Apply a terminal delivery verdict. Telegram maps ✅ to 👀 and ❌ to 👎 in