agent-coord-mcp 0.26.16 → 0.26.18

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 (79) hide show
  1. package/hooks/replay.mjs +107 -0
  2. package/hooks/tier.mjs +11 -0
  3. package/hooks/tmux-pusher.mjs +27 -0
  4. package/package.json +1 -1
  5. package/scripts/coord-pusher.mjs +16 -32
  6. package/src/server.ts +40 -20
  7. package/src/tools/admin.ts +8 -1
  8. package/src/tools/away.ts +48 -4
  9. package/src/tools/board-ref.ts +47 -2
  10. package/src/tools/messaging.ts +43 -2
  11. package/src/tools/records.ts +381 -25
  12. package/src/tools/registry.ts +5 -2
  13. package/src/tools/rooms.ts +2 -1
  14. package/src/tools/shared.ts +28 -0
  15. package/src/tools/stall.ts +29 -1
  16. package/src/tools/transport.ts +79 -10
  17. package/src/tools/work.ts +70 -4
  18. package/src/tools/worktrees.ts +64 -2
  19. package/src/work.ts +4 -0
  20. package/dist/build.js +0 -113
  21. package/dist/build.js.map +0 -1
  22. package/dist/capabilities.js +0 -158
  23. package/dist/capabilities.js.map +0 -1
  24. package/dist/prefix.js +0 -64
  25. package/dist/prefix.js.map +0 -1
  26. package/dist/roles.js +0 -132
  27. package/dist/roles.js.map +0 -1
  28. package/dist/server-identity.js +0 -82
  29. package/dist/server-identity.js.map +0 -1
  30. package/dist/server.js +0 -625
  31. package/dist/server.js.map +0 -1
  32. package/dist/store.js +0 -553
  33. package/dist/store.js.map +0 -1
  34. package/dist/tools/admin.js +0 -317
  35. package/dist/tools/admin.js.map +0 -1
  36. package/dist/tools/attention.js +0 -73
  37. package/dist/tools/attention.js.map +0 -1
  38. package/dist/tools/away.js +0 -243
  39. package/dist/tools/away.js.map +0 -1
  40. package/dist/tools/board-ref.js +0 -164
  41. package/dist/tools/board-ref.js.map +0 -1
  42. package/dist/tools/event-kinds.js +0 -39
  43. package/dist/tools/event-kinds.js.map +0 -1
  44. package/dist/tools/events.js +0 -234
  45. package/dist/tools/events.js.map +0 -1
  46. package/dist/tools/index.js +0 -14
  47. package/dist/tools/index.js.map +0 -1
  48. package/dist/tools/logwatch.js +0 -85
  49. package/dist/tools/logwatch.js.map +0 -1
  50. package/dist/tools/messaging.js +0 -667
  51. package/dist/tools/messaging.js.map +0 -1
  52. package/dist/tools/record-events.js +0 -380
  53. package/dist/tools/record-events.js.map +0 -1
  54. package/dist/tools/records.js +0 -686
  55. package/dist/tools/records.js.map +0 -1
  56. package/dist/tools/registry.js +0 -497
  57. package/dist/tools/registry.js.map +0 -1
  58. package/dist/tools/render.js +0 -2
  59. package/dist/tools/render.js.map +0 -1
  60. package/dist/tools/rooms.js +0 -210
  61. package/dist/tools/rooms.js.map +0 -1
  62. package/dist/tools/rotate.js +0 -143
  63. package/dist/tools/rotate.js.map +0 -1
  64. package/dist/tools/scopes.js +0 -126
  65. package/dist/tools/scopes.js.map +0 -1
  66. package/dist/tools/shared.js +0 -86
  67. package/dist/tools/shared.js.map +0 -1
  68. package/dist/tools/stall.js +0 -387
  69. package/dist/tools/stall.js.map +0 -1
  70. package/dist/tools/transport.js +0 -1810
  71. package/dist/tools/transport.js.map +0 -1
  72. package/dist/tools/work.js +0 -319
  73. package/dist/tools/work.js.map +0 -1
  74. package/dist/tools/worktrees.js +0 -339
  75. package/dist/tools/worktrees.js.map +0 -1
  76. package/dist/typed-records.js +0 -174
  77. package/dist/typed-records.js.map +0 -1
  78. package/dist/work.js +0 -2
  79. package/dist/work.js.map +0 -1
@@ -1,317 +0,0 @@
1
- import { z } from "zod";
2
- import path from "node:path";
3
- import { AGENTS_FILE, ARCHIVE_STATUS_FILE, CURSOR_DIR, DEFAULT_ROOM, INBOX_DIR, ROOMS_FILE, STATUS_FILE, archiveInboxFile, archiveJsonl, archiveRoomFile, deleteFile, getRooms, listCursorFiles, listInboxFiles, listReceiptFiles, normalizeRoom, pruneHistory, readJson, readJsonl, rewriteJsonl, roomFile, updateJson, } from "../store.js";
4
- import { isDecision, } from "./shared.js";
5
- // ---------- prune ----------
6
- export const PRUNE_TARGETS = ["rooms", "status", "inbox", "receipts", "members"];
7
- export const pruneSchema = {
8
- olderThanDays: z.number().positive().max(365).optional(),
9
- decisionDays: z.number().positive().max(365).optional(),
10
- room: z.string().optional(),
11
- targets: z.array(z.enum(PRUNE_TARGETS)).optional(),
12
- removeOrphanInboxes: z.boolean().optional(),
13
- archiveEmptyRooms: z.boolean().optional(),
14
- dryRun: z.boolean().optional(),
15
- };
16
- // Retention: decisions live by the (longer) decision cutoff; everything else
17
- // by the standard cutoff. What counts as a decision is `isDecision` — the
18
- // shared predicate, not a fourth copy of the comparison.
19
- function keepEntry(e, cutoff, decisionCutoff) {
20
- return isDecision(e) ? e.ts > decisionCutoff : e.ts > cutoff;
21
- }
22
- // Shift every agent's cursor offsets down by the number of entries removed
23
- // ahead of them (append-only + oldest-first removal ⇒ plain subtraction,
24
- // clamped at 0). Shared by prune and live compaction — without this, an
25
- // offset past the new file length makes read_messages return [] forever.
26
- export async function adjustCursors(removals) {
27
- const roomRemovedByChan = removals.roomRemovedByChan ?? {};
28
- const statusRemoved = removals.statusRemoved ?? 0;
29
- const perAgentInboxRemoved = removals.perAgentInboxRemoved ?? {};
30
- const cursorsAdjusted = [];
31
- for (const cname of await listCursorFiles()) {
32
- const id = cname.replace(/\.json$/, "");
33
- const cursorPath = path.join(CURSOR_DIR, cname);
34
- let touched = false;
35
- await updateJson(cursorPath, {}, (current) => {
36
- for (const [chan, removed] of Object.entries(roomRemovedByChan)) {
37
- if (chan === DEFAULT_ROOM) {
38
- if (current.roomOffset !== undefined) {
39
- current.roomOffset = Math.max(0, current.roomOffset - removed);
40
- touched = true;
41
- }
42
- }
43
- else if (current.roomOffsets?.[chan] !== undefined) {
44
- current.roomOffsets[chan] = Math.max(0, current.roomOffsets[chan] - removed);
45
- touched = true;
46
- }
47
- }
48
- if (current.statusOffset !== undefined && statusRemoved > 0) {
49
- current.statusOffset = Math.max(0, current.statusOffset - statusRemoved);
50
- touched = true;
51
- }
52
- const myInboxRemoved = perAgentInboxRemoved[id] ?? 0;
53
- if (current.inboxOffset !== undefined && myInboxRemoved > 0) {
54
- current.inboxOffset = Math.max(0, current.inboxOffset - myInboxRemoved);
55
- touched = true;
56
- }
57
- return current;
58
- });
59
- if (touched)
60
- cursorsAdjusted.push(id);
61
- }
62
- return cursorsAdjusted;
63
- }
64
- export async function pruneTool(args) {
65
- const days = args.olderThanDays ?? 7;
66
- const decisionDays = args.decisionDays ?? 30;
67
- const cutoff = Date.now() - days * 24 * 60 * 60 * 1000;
68
- const decisionCutoff = Date.now() - decisionDays * 24 * 60 * 60 * 1000;
69
- const dryRun = args.dryRun ?? false;
70
- // `room` scopes every sweep to that channel; `targets` narrows which sweeps
71
- // run. They compose: `room` only changes the DEFAULT target set, so an
72
- // explicit `targets` always wins.
73
- //
74
- // WHY (regression): this previously read `scopedRoom ? ["rooms"] : args.targets`,
75
- // which silently DISCARDED an explicit `targets` whenever `room` was passed.
76
- // `prune {room, targets:["members"], dryRun:true}` therefore reported
77
- // `orphanMembers: []` because the member sweep never ran — a caller asking
78
- // "which members are phantoms in this room" got a clean bill of health that
79
- // had not been computed, while `roomMessages` (the one target the override
80
- // left enabled) reported real messages a live run would have archived. Field
81
- // report: two members that `ping` called `unregistered` were invisible here.
82
- // A sweep must never answer a question it did not evaluate.
83
- const scopedRoom = args.room ? normalizeRoom(args.room) : undefined;
84
- const targets = new Set(args.targets ?? (scopedRoom ? ["rooms"] : [...PRUNE_TARGETS]));
85
- const keep = (e) => keepEntry(e, cutoff, decisionCutoff);
86
- const reg = await readJson(AGENTS_FILE, {});
87
- const knownAgents = new Set(Object.keys(reg));
88
- // A member is stale when its agent is gone from the registry (orphan) or
89
- // hasn't heartbeated since the cutoff (dead session).
90
- const staleAgent = (m) => !knownAgents.has(m) || (reg[m]?.lastHeartbeat ?? 0) <= cutoff;
91
- const channels = scopedRoom ? [scopedRoom] : Object.keys(await getRooms());
92
- // The membership sweeps walk the room registry rather than `channels`, so they
93
- // need the scope predicate explicitly — without it, `room` scoped the message
94
- // sweep while membership silently swept EVERY room.
95
- const inScope = (chan) => !scopedRoom || chan === scopedRoom;
96
- if (dryRun) {
97
- let roomMessages = 0;
98
- if (targets.has("rooms")) {
99
- for (const chan of channels) {
100
- const msgs = await readJsonl(roomFile(chan));
101
- roomMessages += msgs.filter((e) => !keep(e)).length;
102
- }
103
- }
104
- const status = targets.has("status") ? await readJsonl(STATUS_FILE) : [];
105
- let inboxRemoved = 0;
106
- const orphans = [];
107
- if (targets.has("inbox")) {
108
- for (const fname of await listInboxFiles()) {
109
- const id = fname.replace(/\.jsonl$/, "");
110
- if (!knownAgents.has(id) && (args.removeOrphanInboxes ?? true))
111
- orphans.push(fname);
112
- const entries = await readJsonl(path.join(INBOX_DIR, fname));
113
- inboxRemoved += entries.filter((e) => e.ts <= cutoff).length;
114
- }
115
- }
116
- const orphanMembers = new Set();
117
- const staleMembers = new Set();
118
- const emptyRooms = [];
119
- if (targets.has("members")) {
120
- const rooms = await getRooms();
121
- for (const [chan, e] of Object.entries(rooms)) {
122
- if (!inScope(chan))
123
- continue;
124
- const remaining = [];
125
- for (const m of e.members ?? []) {
126
- if (!knownAgents.has(m))
127
- orphanMembers.add(m);
128
- else if (staleAgent(m))
129
- staleMembers.add(m);
130
- else
131
- remaining.push(m);
132
- }
133
- if ((args.archiveEmptyRooms ?? true) &&
134
- chan !== DEFAULT_ROOM &&
135
- remaining.length === 0) {
136
- const msgs = await readJsonl(roomFile(chan));
137
- const lastTs = msgs[msgs.length - 1]?.ts ?? 0;
138
- if (lastTs <= cutoff)
139
- emptyRooms.push(chan);
140
- }
141
- }
142
- }
143
- let receiptsRemoved = 0;
144
- const orphanReceipts = [];
145
- if (targets.has("receipts")) {
146
- for (const filePath of await listReceiptFiles()) {
147
- const id = path.basename(filePath).replace(/\.jsonl$/, "");
148
- const entries = await readJsonl(filePath);
149
- if (!knownAgents.has(id) && (args.removeOrphanInboxes ?? true))
150
- orphanReceipts.push(id);
151
- receiptsRemoved += entries.filter((e) => e.ts <= cutoff).length;
152
- }
153
- }
154
- return {
155
- dryRun: true,
156
- cutoff,
157
- olderThanDays: days,
158
- decisionDays,
159
- ...(scopedRoom ? { room: scopedRoom } : {}),
160
- wouldRemove: {
161
- roomMessages,
162
- statusEntries: status.filter((e) => e.ts <= cutoff).length,
163
- inboxMessages: inboxRemoved,
164
- orphanInboxes: orphans,
165
- orphanMembers: [...orphanMembers],
166
- staleMembers: [...staleMembers],
167
- archivedRooms: emptyRooms,
168
- receipts: receiptsRemoved,
169
- orphanReceipts,
170
- },
171
- };
172
- }
173
- // Per-channel removed counts so we can shift the matching offset in each
174
- // cursor (default channel → roomOffset, others → roomOffsets[chan]).
175
- // Aged-out entries are archived to archive/rooms/<chan>.jsonl, never deleted.
176
- const roomRemovedByChan = {};
177
- let roomRemovedTotal = 0;
178
- if (targets.has("rooms")) {
179
- for (const chan of channels) {
180
- const r = await archiveJsonl(roomFile(chan), archiveRoomFile(chan), keep);
181
- if (r.removed > 0) {
182
- roomRemovedByChan[chan] = r.removed;
183
- roomRemovedTotal += r.removed;
184
- }
185
- }
186
- }
187
- const statusResult = targets.has("status")
188
- ? await archiveJsonl(STATUS_FILE, ARCHIVE_STATUS_FILE, (e) => e.ts > cutoff)
189
- : { kept: 0, removed: 0, archived: 0 };
190
- let inboxRemoved = 0;
191
- const deletedOrphans = [];
192
- // perAgentInboxRemoved: how many entries were stripped from each *kept* agent's
193
- // inbox, so we can shift only that agent's inboxOffset cursor below.
194
- const perAgentInboxRemoved = {};
195
- if (targets.has("inbox")) {
196
- for (const fname of await listInboxFiles()) {
197
- const id = fname.replace(/\.jsonl$/, "");
198
- const filePath = path.join(INBOX_DIR, fname);
199
- if (!knownAgents.has(id) && (args.removeOrphanInboxes ?? true)) {
200
- // Orphan inbox: archive everything it held, then drop the live file.
201
- const r = await archiveJsonl(filePath, archiveInboxFile(id), () => false);
202
- inboxRemoved += r.removed;
203
- await deleteFile(filePath);
204
- deletedOrphans.push(id);
205
- continue;
206
- }
207
- const r = await archiveJsonl(filePath, archiveInboxFile(id), (e) => e.ts > cutoff);
208
- inboxRemoved += r.removed;
209
- perAgentInboxRemoved[id] = r.removed;
210
- }
211
- }
212
- const cursorsAdjusted = await adjustCursors({
213
- roomRemovedByChan,
214
- statusRemoved: statusResult.removed,
215
- perAgentInboxRemoved,
216
- });
217
- // Membership sweep: drop orphans (not in registry) and stale members (no
218
- // heartbeat since cutoff) so list_rooms / joinedRooms() stop surfacing
219
- // ghosts. Then archive non-default rooms left with no members and no
220
- // activity since the cutoff: remaining messages move to the archive, the
221
- // room leaves the registry, and every cursor forgets its offset — the same
222
- // cleanup delete_room performs, minus the data loss.
223
- const orphanMembers = new Set();
224
- const staleMembers = new Set();
225
- const archivedRooms = [];
226
- if (targets.has("members")) {
227
- await updateJson(ROOMS_FILE, {}, (current) => {
228
- for (const [chan, e] of Object.entries(current)) {
229
- if (!inScope(chan))
230
- continue;
231
- if ((e.members?.length ?? 0) === 0)
232
- continue;
233
- e.members = (e.members ?? []).filter((m) => {
234
- if (!knownAgents.has(m)) {
235
- orphanMembers.add(m);
236
- return false;
237
- }
238
- if (staleAgent(m)) {
239
- staleMembers.add(m);
240
- return false;
241
- }
242
- return true;
243
- });
244
- }
245
- return current;
246
- });
247
- if (args.archiveEmptyRooms ?? true) {
248
- const rooms = await getRooms();
249
- for (const [chan, e] of Object.entries(rooms)) {
250
- if (chan === DEFAULT_ROOM || !inScope(chan) || (e.members?.length ?? 0) > 0)
251
- continue;
252
- const file = roomFile(chan);
253
- const msgs = await readJsonl(file);
254
- const lastTs = msgs[msgs.length - 1]?.ts ?? 0;
255
- if (lastTs > cutoff)
256
- continue;
257
- await archiveJsonl(file, archiveRoomFile(chan), () => false);
258
- await deleteFile(file);
259
- await updateJson(ROOMS_FILE, {}, (current) => {
260
- delete current[chan];
261
- return current;
262
- });
263
- for (const cname of await listCursorFiles()) {
264
- await updateJson(path.join(CURSOR_DIR, cname), {}, (current) => {
265
- if (current.roomOffsets?.[chan] !== undefined)
266
- delete current.roomOffsets[chan];
267
- return current;
268
- });
269
- }
270
- archivedRooms.push(chan);
271
- }
272
- }
273
- }
274
- // Receipts are out-of-band proof logs with no cursor and no analysis value —
275
- // trim old entries by ts and delete logs for agents no longer registered.
276
- // The one stream that is genuinely deleted, not archived.
277
- let receiptsRemoved = 0;
278
- const deletedOrphanReceipts = [];
279
- if (targets.has("receipts")) {
280
- for (const filePath of await listReceiptFiles()) {
281
- const id = path.basename(filePath).replace(/\.jsonl$/, "");
282
- if (!knownAgents.has(id) && (args.removeOrphanInboxes ?? true)) {
283
- const entries = await readJsonl(filePath);
284
- receiptsRemoved += entries.length;
285
- await deleteFile(filePath);
286
- deletedOrphanReceipts.push(id);
287
- continue;
288
- }
289
- const r = await rewriteJsonl(filePath, (e) => e.ts > cutoff);
290
- receiptsRemoved += r.removed;
291
- }
292
- }
293
- // Sweep expired reversible-history entries (TTL'd cache; also self-prunes on
294
- // every read, so this just catches entries on a server with few reads).
295
- await pruneHistory();
296
- return {
297
- dryRun: false,
298
- cutoff,
299
- olderThanDays: days,
300
- decisionDays,
301
- ...(scopedRoom ? { room: scopedRoom } : {}),
302
- removed: {
303
- roomMessages: roomRemovedTotal,
304
- statusEntries: statusResult.removed,
305
- inboxMessages: inboxRemoved,
306
- orphanInboxes: deletedOrphans,
307
- orphanMembers: [...orphanMembers],
308
- staleMembers: [...staleMembers],
309
- archivedRooms,
310
- receipts: receiptsRemoved,
311
- orphanReceipts: deletedOrphanReceipts,
312
- },
313
- archivedTo: "archive/ (rooms/<chan>.jsonl, status.jsonl, inbox/<agent>.jsonl; receipts deleted)",
314
- cursorsAdjusted,
315
- };
316
- }
317
- //# sourceMappingURL=admin.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"admin.js","sourceRoot":"","sources":["../../src/tools/admin.ts"],"names":[],"mappings":"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"}
@@ -1,73 +0,0 @@
1
- /*
2
- * Emit on the state that has twice cost hours: a PR that is MERGEABLE and
3
- * UNATTENDED.
4
- *
5
- * Two mergeable, CI-green PRs sat 17 hours; two more sat 40 minutes and 1h48
6
- * on the day the coordinator said it was checking for exactly that. Nothing in
7
- * the room said so — a worker went looking and found it. There is no mechanism
8
- * that reports "these PRs are mergeable and nobody is acting".
9
- *
10
- * 6.2 APPLIES HERE TOO: the event is DERIVED from observable state, never a
11
- * parallel claim. Everything below is computed from what GitHub actually
12
- * reports, and anything it has not answered yet is `unknown`.
13
- */
14
- import { normalizeChecks } from "./records.js";
15
- /**
16
- * UNKNOWN IS NOT UNATTENDED, and this is the clause the coordinator and I have
17
- * both been bitten by today.
18
- *
19
- * `mergeable` is `UNKNOWN` for a while after every push — GitHub computes it
20
- * asynchronously — and an empty check rollup is ambiguous between "not yet" and
21
- * "never will be". Reading either as "nobody is acting" invents an alert out of
22
- * a question GitHub has not answered, which is the fabrication class this fleet
23
- * has spent three days removing.
24
- */
25
- export function classifyPr(pr, nowMs, quietMs) {
26
- if (pr.state !== "OPEN")
27
- return { state: "attended", why: `#${pr.number} is ${pr.state}` };
28
- if (!pr.mergeable || pr.mergeable === "UNKNOWN")
29
- return {
30
- state: "unknown",
31
- why: `#${pr.number}: GitHub has not computed mergeability yet (frequently the case right after a push). UNKNOWN is not unattended — reporting it would invent an alert from an unanswered question.`,
32
- };
33
- if (pr.mergeable === "CONFLICTING")
34
- return { state: "attended", why: `#${pr.number} is CONFLICTING — it needs its author, not a gate` };
35
- const checks = normalizeChecks(pr.checks ?? []);
36
- if (checks.length === 0)
37
- return {
38
- state: "unknown",
39
- why: `#${pr.number} reports ZERO checks — ambiguous between "not started" and "never will". No checks is not passing checks, and it is not unattended either.`,
40
- };
41
- const pending = checks.filter((c) => c.verdict === "pending");
42
- if (pending.length)
43
- return { state: "unknown", why: `#${pr.number}: ${pending.length} check(s) still running — not yet a gate's turn` };
44
- const failed = checks.filter((c) => c.verdict === "fail");
45
- if (failed.length)
46
- return { state: "attended", why: `#${pr.number} has failing checks (${failed.map((c) => c.name).join(", ")}) — the author's move, not the gate's` };
47
- // Quiet is measured from the PR's own last update. A PR touched a minute ago
48
- // is not unattended; its author may still be pushing.
49
- const quietFor = nowMs - Date.parse(pr.updatedAt);
50
- if (!Number.isFinite(quietFor))
51
- return { state: "unknown", why: `#${pr.number}: unreadable updatedAt '${pr.updatedAt}' — cannot say how long it has waited` };
52
- if (quietFor < quietMs)
53
- return { state: "attended", why: `#${pr.number} was updated ${Math.round(quietFor / 60000)}m ago — still moving` };
54
- return {
55
- state: "unattended",
56
- why: `#${pr.number} is MERGEABLE, all ${checks.length} check(s) pass, and nothing has touched it for ${Math.round(quietFor / 60000)}m`,
57
- };
58
- }
59
- /** The three states are distinct on purpose; a caller must not collapse them. */
60
- export function partition(prs, nowMs, quietMs) {
61
- const out = { unattended: [], unknown: [], attended: 0 };
62
- for (const pr of prs) {
63
- const c = classifyPr(pr, nowMs, quietMs);
64
- if (c.state === "unattended")
65
- out.unattended.push({ pr, why: c.why });
66
- else if (c.state === "unknown")
67
- out.unknown.push({ pr, why: c.why });
68
- else
69
- out.attended++;
70
- }
71
- return out;
72
- }
73
- //# sourceMappingURL=attention.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"attention.js","sourceRoot":"","sources":["../../src/tools/attention.ts"],"names":[],"mappings":"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"}