agent-coord-mcp 0.26.18 → 0.26.20

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 (84) hide show
  1. package/README.md +82 -0
  2. package/dist/build.js +113 -0
  3. package/dist/build.js.map +1 -0
  4. package/dist/capabilities.js +214 -0
  5. package/dist/capabilities.js.map +1 -0
  6. package/dist/prefix.js +64 -0
  7. package/dist/prefix.js.map +1 -0
  8. package/dist/roles.js +132 -0
  9. package/dist/roles.js.map +1 -0
  10. package/dist/server-identity.js +82 -0
  11. package/dist/server-identity.js.map +1 -0
  12. package/dist/server.js +668 -0
  13. package/dist/server.js.map +1 -0
  14. package/dist/store.js +553 -0
  15. package/dist/store.js.map +1 -0
  16. package/dist/tools/admin.js +323 -0
  17. package/dist/tools/admin.js.map +1 -0
  18. package/dist/tools/attention.js +73 -0
  19. package/dist/tools/attention.js.map +1 -0
  20. package/dist/tools/away.js +285 -0
  21. package/dist/tools/away.js.map +1 -0
  22. package/dist/tools/board-ref.js +208 -0
  23. package/dist/tools/board-ref.js.map +1 -0
  24. package/dist/tools/event-kinds.js +39 -0
  25. package/dist/tools/event-kinds.js.map +1 -0
  26. package/dist/tools/events.js +234 -0
  27. package/dist/tools/events.js.map +1 -0
  28. package/dist/tools/index.js +14 -0
  29. package/dist/tools/index.js.map +1 -0
  30. package/dist/tools/logwatch.js +85 -0
  31. package/dist/tools/logwatch.js.map +1 -0
  32. package/dist/tools/messaging.js +706 -0
  33. package/dist/tools/messaging.js.map +1 -0
  34. package/dist/tools/record-events.js +380 -0
  35. package/dist/tools/record-events.js.map +1 -0
  36. package/dist/tools/records.js +1205 -0
  37. package/dist/tools/records.js.map +1 -0
  38. package/dist/tools/registry.js +529 -0
  39. package/dist/tools/registry.js.map +1 -0
  40. package/dist/tools/render.js +2 -0
  41. package/dist/tools/render.js.map +1 -0
  42. package/dist/tools/rooms.js +210 -0
  43. package/dist/tools/rooms.js.map +1 -0
  44. package/dist/tools/rotate.js +143 -0
  45. package/dist/tools/rotate.js.map +1 -0
  46. package/dist/tools/scopes.js +126 -0
  47. package/dist/tools/scopes.js.map +1 -0
  48. package/dist/tools/shared.js +104 -0
  49. package/dist/tools/shared.js.map +1 -0
  50. package/dist/tools/stall.js +415 -0
  51. package/dist/tools/stall.js.map +1 -0
  52. package/dist/tools/transport.js +1918 -0
  53. package/dist/tools/transport.js.map +1 -0
  54. package/dist/tools/work.js +465 -0
  55. package/dist/tools/work.js.map +1 -0
  56. package/dist/tools/worktrees.js +581 -0
  57. package/dist/tools/worktrees.js.map +1 -0
  58. package/dist/transports/config.js +82 -0
  59. package/dist/transports/config.js.map +1 -0
  60. package/dist/transports/index.js +113 -0
  61. package/dist/transports/index.js.map +1 -0
  62. package/dist/transports/tmux.js +140 -0
  63. package/dist/transports/tmux.js.map +1 -0
  64. package/dist/transports/types.js +86 -0
  65. package/dist/transports/types.js.map +1 -0
  66. package/dist/typed-records.js +174 -0
  67. package/dist/typed-records.js.map +1 -0
  68. package/dist/work.js +2 -0
  69. package/dist/work.js.map +1 -0
  70. package/hooks/tmux-pusher.mjs +33 -3
  71. package/package.json +1 -1
  72. package/src/capabilities.ts +104 -1
  73. package/src/server.ts +30 -1
  74. package/src/tools/records.ts +221 -34
  75. package/src/tools/registry.ts +36 -5
  76. package/src/tools/shared.ts +12 -36
  77. package/src/tools/stall.ts +2 -1
  78. package/src/tools/transport.ts +96 -43
  79. package/src/tools/work.ts +95 -3
  80. package/src/tools/worktrees.ts +234 -32
  81. package/src/transports/config.ts +110 -0
  82. package/src/transports/index.ts +126 -0
  83. package/src/transports/tmux.ts +177 -0
  84. package/src/transports/types.ts +201 -0
@@ -0,0 +1,234 @@
1
+ /*
2
+ * Event subscriptions — stop relying on someone CHOOSING to tell you.
3
+ *
4
+ * The bus is almost entirely direct messaging: an agent learns something
5
+ * happened because another agent decided to say so. Every miss this week was a
6
+ * missing NOTIFICATION rather than a missing capability — two mergeable PRs sat
7
+ * 17 hours because nobody told the coordinator to gate, the console's trigger
8
+ * ran zero times because nothing woke it, and `stall_check` runs only when a
9
+ * human types it.
10
+ */
11
+ import { createHash, randomUUID } from "node:crypto";
12
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
13
+ import path from "node:path";
14
+ import { z } from "zod";
15
+ import { ROOT } from "../store.js";
16
+ import { EVENT_KINDS, EVENT_KIND_IDS } from "./event-kinds.js";
17
+ const subsFile = () => path.join(ROOT, "subscriptions.json");
18
+ // Re-exported so every existing importer keeps its import path. The vocabulary
19
+ // itself is defined beside the emitters (record-events.ts) — Task 9.2: a kind
20
+ // that can be subscribed to but never emitted is unsatisfiable BY CONSTRUCTION
21
+ // only if the enum cannot be widened without an emitter.
22
+ export { EVENT_KINDS, EVENT_KIND_IDS };
23
+ export function readSubs() {
24
+ const f = subsFile();
25
+ if (!existsSync(f))
26
+ return [];
27
+ try {
28
+ return (JSON.parse(readFileSync(f, "utf8")).subscriptions ?? []);
29
+ }
30
+ catch {
31
+ return [];
32
+ }
33
+ }
34
+ function writeSubs(subs) {
35
+ mkdirSync(ROOT, { recursive: true });
36
+ writeFileSync(subsFile(), `${JSON.stringify({ subscriptions: subs }, null, 2)}\n`);
37
+ }
38
+ /**
39
+ * 6.3 — A SUBSCRIPTION THAT NEVER FIRES MUST BE DISTINGUISHABLE FROM ONE NEVER
40
+ * REGISTERED, so never-evaluated is an ERROR rather than a quiet zero.
41
+ *
42
+ * We hit the absence of this rule twice in two days: the console's standing
43
+ * trigger and `stall_check`'s clock both looked healthy while never running. A
44
+ * subscription with no last-evaluated mark has produced no evidence of
45
+ * anything, and "no events" is the same output a broken subscription gives.
46
+ */
47
+ export function subscriptionHealth(s) {
48
+ const iso = (n) => new Date(n).toISOString();
49
+ // THREE STATES, BECAUSE THERE ARE THREE FACTS. They were two, and the
50
+ // collapse cost a week: an `item` subscriber read `error — never evaluated`
51
+ // the whole time, because `evaluate()` only touches subscriptions whose kind
52
+ // matches the event and no `item` event had fired. The wiring was fine. The
53
+ // health field said it was dead, and the agent holding it believed the field.
54
+ //
55
+ // Same shape as `alive` swallowing `heartbeatFresh`, and as
56
+ // `stall_clock_status` reporting green while covering nothing: one field
57
+ // answering two questions always answers the easier one.
58
+ if (s.lastScannedAt === undefined && s.lastEvaluatedAt === null) {
59
+ // Written before this field existed AND never evaluated. Absent is UNKNOWN,
60
+ // never "never scanned" — inventing a scan nobody observed is the failure
61
+ // this phase is about, and asserting one never happened is the same error
62
+ // pointed the other way.
63
+ return {
64
+ level: "unknown",
65
+ detail: "predates scan tracking and has never been evaluated — whether the machinery has run for it CANNOT be determined from this record. " +
66
+ "It will resolve to ok or error on the next scan; until then this is an absence of evidence, not evidence of absence.",
67
+ };
68
+ }
69
+ if (!s.lastScannedAt) {
70
+ return {
71
+ level: "error",
72
+ detail: "NEVER SCANNED — no scan has run with this subscription registered, so it has produced no evidence of being wired to anything. " +
73
+ "This is the state that means broken.",
74
+ };
75
+ }
76
+ if (s.lastEvaluatedAt === null) {
77
+ // THE STATE THAT USED TO READ AS BROKEN. The machinery ran and nothing of
78
+ // this kind happened, which is a healthy idle watch.
79
+ return {
80
+ level: "ok",
81
+ detail: `scanned ${iso(s.lastScannedAt)}, never evaluated — the machinery RAN and no '${s.kind}' event has occurred yet. ` +
82
+ "Scanned-and-quiet is healthy; it is not the same as never run, and those shared a field until now.",
83
+ };
84
+ }
85
+ return {
86
+ level: "ok",
87
+ detail: s.lastEventAt
88
+ ? `scanned ${iso(s.lastScannedAt)}, last evaluated ${iso(s.lastEvaluatedAt)}, last event ${iso(s.lastEventAt)}`
89
+ : `scanned ${iso(s.lastScannedAt)}, last evaluated ${iso(s.lastEvaluatedAt)}, no events yet`,
90
+ };
91
+ }
92
+ /**
93
+ * 6.4 — DELIVERY IS AT-LEAST-ONCE BY DESIGN. Safe for a reader, DOUBLE
94
+ * EXECUTION for an executor: a callback that triggers work must carry a key, or
95
+ * the same merge lands twice. The key is derived from the EVENT, never from the
96
+ * delivery attempt, so a retry produces the same key.
97
+ */
98
+ export const eventKey = (kind, target, ref) => createHash("sha256").update(`${kind}:${target}:${ref}`).digest("hex").slice(0, 16);
99
+ /**
100
+ * 6.2 — EVENTS ARE DERIVED FROM THE RECORD, NEVER PARALLEL TO IT.
101
+ *
102
+ * Enforced here rather than promised in a comment: the event's `ref` must
103
+ * already be present in the record document before anything is emitted. An
104
+ * event stream that can say "task X complete" while DONE.md does not is a
105
+ * second source of truth, and record-vs-state divergence is the defect this
106
+ * fleet hit most this week. ADR-003 keeps markdown authoritative, and this must
107
+ * not quietly reopen it.
108
+ *
109
+ * So the ordering is not a convention: emission READS the record, and an event
110
+ * whose cause is not in the record cannot be emitted at all.
111
+ */
112
+ export function eventIsDerived(recordText, ev) {
113
+ if (!ev.ref)
114
+ return { ok: false, error: `event for ${ev.kind} ${ev.target} carries no ref — nothing ties it to a record entry` };
115
+ if (!String(recordText).includes(ev.ref))
116
+ return {
117
+ ok: false,
118
+ error: `refusing to emit ${ev.kind} ${ev.target}: its ref ${ev.ref} is NOT in the record. ` +
119
+ `An event that exists without the record change that caused it is a second source of truth — ` +
120
+ `the stream would claim something the authoritative document does not.`,
121
+ };
122
+ return { ok: true };
123
+ }
124
+ /** Subscriptions matching an event. Exact target match; no wildcards yet. */
125
+ export const matching = (subs, ev) => subs.filter((s) => s.kind === ev.kind && s.target === ev.target);
126
+ /**
127
+ * Evaluate every subscription against one event and return what to deliver.
128
+ *
129
+ * EVALUATION IS RECORDED EVEN WHEN NOTHING MATCHES — that is 6.3's whole point.
130
+ * A subscription only learns it is alive by being evaluated, so the mark is
131
+ * written for every subscription of that kind, not only the ones that fired.
132
+ */
133
+ /**
134
+ * Record that a scan RAN, for every live subscription regardless of kind.
135
+ *
136
+ * Called once per scan — including a scan that produced NO events, which is
137
+ * exactly the case that starved the old field: no events of your kind means
138
+ * `evaluate` never touches you, and a subscription that is never touched cannot
139
+ * be told from one that is not wired to anything.
140
+ */
141
+ export function markScanned(subs, now) {
142
+ return subs.map((s) => ({ ...s, lastScannedAt: now }));
143
+ }
144
+ export function evaluate(subs, ev, now) {
145
+ const key = eventKey(ev.kind, ev.target, ev.ref);
146
+ const deliveries = [];
147
+ const next = subs.map((s) => {
148
+ // Every subscription observed this scan, whatever its kind.
149
+ const scanned = { ...s, lastScannedAt: now };
150
+ if (s.kind !== ev.kind)
151
+ return scanned;
152
+ const evaluated = { ...scanned, lastEvaluatedAt: now };
153
+ if (s.target !== ev.target)
154
+ return evaluated;
155
+ if (s.delivered.includes(key)) {
156
+ deliveries.push({ subscriptionId: s.id, agentId: s.agentId, key, status: "duplicate-suppressed" });
157
+ return evaluated;
158
+ }
159
+ deliveries.push({ subscriptionId: s.id, agentId: s.agentId, key, status: "delivered" });
160
+ return { ...evaluated, lastEventAt: now, delivered: [...s.delivered, key].slice(-200) };
161
+ });
162
+ return { subs: next, deliveries };
163
+ }
164
+ /* ── verbs ─────────────────────────────────────────────────────────────────── */
165
+ export const subscribeSchema = {
166
+ agentId: z.string().min(1),
167
+ kind: z.enum(EVENT_KIND_IDS),
168
+ target: z.string().min(1),
169
+ };
170
+ export async function subscribeTool(args) {
171
+ const subs = readSubs();
172
+ const dupe = subs.find((s) => s.agentId === args.agentId && s.kind === args.kind && s.target === args.target);
173
+ if (dupe)
174
+ return { ok: true, subscription: dupe, note: "already subscribed — returning the existing registration rather than a second one" };
175
+ const sub = {
176
+ id: randomUUID(),
177
+ agentId: args.agentId,
178
+ kind: args.kind,
179
+ target: args.target,
180
+ createdAt: Date.now(),
181
+ // EXPLICIT null, never left absent. `null` means "we know no scan has run
182
+ // for this"; `undefined` means "this record predates the field and we
183
+ // cannot say". A subscription created now is the first case, and writing it
184
+ // explicitly is what keeps a brand-new registration from being reported as
185
+ // unknowable.
186
+ lastScannedAt: null,
187
+ lastEvaluatedAt: null,
188
+ lastEventAt: null,
189
+ delivered: [],
190
+ };
191
+ writeSubs([...subs, sub]);
192
+ return { ok: true, subscription: sub, health: subscriptionHealth(sub) };
193
+ }
194
+ export const unsubscribeSchema = { agentId: z.string().min(1), id: z.string().min(1) };
195
+ export async function unsubscribeTool(args) {
196
+ const subs = readSubs();
197
+ const sub = subs.find((s) => s.id === args.id);
198
+ if (!sub)
199
+ return { ok: false, error: `no subscription '${args.id}'` };
200
+ // Another agent's subscription is not yours to remove: silently dropping
201
+ // someone else's notification is how a miss is manufactured.
202
+ if (sub.agentId !== args.agentId)
203
+ return { ok: false, error: `subscription '${args.id}' belongs to '${sub.agentId}', not '${args.agentId}'` };
204
+ writeSubs(subs.filter((s) => s.id !== args.id));
205
+ return { ok: true, removed: sub };
206
+ }
207
+ export const listSubscriptionsSchema = { agentId: z.string().optional() };
208
+ export async function listSubscriptionsTool(args) {
209
+ const all = readSubs();
210
+ const subs = args.agentId ? all.filter((s) => s.agentId === args.agentId) : all;
211
+ const rows = subs.map((s) => ({ ...s, health: subscriptionHealth(s) }));
212
+ const neverEvaluated = rows.filter((r) => r.health.level === "error");
213
+ const undetermined = rows.filter((r) => r.health.level === "unknown");
214
+ return {
215
+ ok: neverEvaluated.length === 0,
216
+ // Population beside the verdict, always: "no subscriptions" and "none
217
+ // listed for you" are different claims.
218
+ population: { listed: rows.length, total: all.length },
219
+ subscriptions: rows,
220
+ ...(neverEvaluated.length
221
+ ? { error: `${neverEvaluated.length} of ${rows.length} subscription(s) have NEVER BEEN SCANNED — no scan has run with them registered, so they have produced no evidence of being wired to anything.` }
222
+ : {}),
223
+ ...(undetermined.length
224
+ ? {
225
+ undetermined: `${undetermined.length} of ${rows.length} subscription(s) predate scan tracking and cannot be judged yet — they resolve on the next scan. Reported rather than counted as either healthy or broken.`,
226
+ }
227
+ : {}),
228
+ };
229
+ }
230
+ /** Persist an evaluation. Callers do this after a record write, never before. */
231
+ export function commitEvaluation(next) {
232
+ writeSubs(next);
233
+ }
234
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/tools/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export * from "./shared.js";
2
+ export * from "./registry.js";
3
+ export * from "./rooms.js";
4
+ export * from "./messaging.js";
5
+ export * from "./transport.js";
6
+ export * from "./admin.js";
7
+ export * from "./scopes.js";
8
+ export * from "./work.js";
9
+ export * from "./records.js";
10
+ export * from "./worktrees.js";
11
+ export * from "./stall.js";
12
+ export * from "./events.js";
13
+ export * from "./record-events.js";
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,85 @@
1
+ /*
2
+ * Task 8 — a watch over an append-only log, keyed on FILE OFFSET.
3
+ *
4
+ * A WATCH MUST NOT BE ABLE TO CONSUME. This is Task 7.1's rule at its second
5
+ * caller, not a second fix: the read cursor records what the AGENT has taken
6
+ * delivery of, and only the agent reading may advance it. A pusher typing into
7
+ * a pane is a reader; a watch waiting for traffic is a reader; neither may
8
+ * consume on the agent's behalf.
9
+ *
10
+ * So this keeps its OWN position — `lastLineSeen` — and never touches
11
+ * `cursors/<id>.json`. A watch that advanced the read cursor would reproduce
12
+ * exactly the defect Task 7 removed, one component over: the message would be
13
+ * marked consumed by something that only looked at it.
14
+ *
15
+ * WHY THIS DOES NOT VIOLATE 6.2 (8.5). "Events are derived from the record,
16
+ * never parallel to it." The room and inbox JSONL logs ARE the record — they
17
+ * are the authoritative store, not a projection of one. `land`'s events are
18
+ * derived from a document write; these are derived from the log itself. Both
19
+ * read the authoritative artifact and neither maintains a second source of
20
+ * truth. The test for a violation is whether the stream could assert something
21
+ * the record does not, and it cannot: every event here IS a line in the log,
22
+ * identified by its offset in that log.
23
+ *
24
+ * Keyed on OFFSET rather than timestamp or id, because an offset is a property
25
+ * of the log itself. Two lines can share a `ts`, an id can be rewritten, and a
26
+ * clock can disagree with another clock — a line's position cannot.
27
+ */
28
+ import { existsSync, readFileSync } from "node:fs";
29
+ import path from "node:path";
30
+ import { z } from "zod";
31
+ import { ROOT } from "../store.js";
32
+ export const logFileFor = (kind, target) => kind === "room" ? path.join(ROOT, "rooms", `${target}.jsonl`) : path.join(ROOT, "inbox", `${target}.jsonl`);
33
+ /** Parsed lines of a log. Malformed lines are SKIPPED but still counted. */
34
+ export function readLog(file) {
35
+ if (!existsSync(file))
36
+ return { entries: [], total: 0 };
37
+ const lines = readFileSync(file, "utf8").split("\n").filter((l) => l.trim());
38
+ const entries = [];
39
+ for (const l of lines) {
40
+ try {
41
+ entries.push(JSON.parse(l));
42
+ }
43
+ catch {
44
+ // A malformed line still OCCUPIES an offset. Skipping it without counting
45
+ // would shift every subsequent line's position by one and silently
46
+ // re-report the whole tail.
47
+ entries.push(null);
48
+ }
49
+ }
50
+ return { entries, total: lines.length };
51
+ }
52
+ /**
53
+ * Lines appended since `lastLineSeen`.
54
+ *
55
+ * A TRUNCATED LOG IS NOT A QUIET ONE. If the file is SHORTER than the watch's
56
+ * position, something rewrote or pruned it — reporting "no new lines" would be
57
+ * indistinguishable from a healthy quiet period. It is surfaced instead.
58
+ */
59
+ export function newLines(watch, log) {
60
+ if (log.total < watch.lastLineSeen)
61
+ return { events: [], truncated: true, total: log.total };
62
+ const events = [];
63
+ for (let i = watch.lastLineSeen; i < log.total; i++) {
64
+ events.push({ kind: watch.kind, target: watch.target, offset: i, line: log.entries[i] ?? null });
65
+ }
66
+ return { events, truncated: false, total: log.total };
67
+ }
68
+ /** 8.3 — health, identical in shape to the record subscriptions, plus lastLineSeen. */
69
+ export function watchHealth(w) {
70
+ if (w.lastEvaluatedAt === null)
71
+ return {
72
+ level: "error",
73
+ detail: `never evaluated — this watch has produced no evidence it is attached to anything. "No lines yet" and "never ran" are the same output, and only one of them is healthy.`,
74
+ };
75
+ return {
76
+ level: "ok",
77
+ detail: `last evaluated ${new Date(w.lastEvaluatedAt).toISOString()}, reported up to line ${w.lastLineSeen}`,
78
+ };
79
+ }
80
+ export const logWatchSchema = {
81
+ agentId: z.string().min(1),
82
+ kind: z.enum(["room", "inbox"]),
83
+ target: z.string().min(1),
84
+ };
85
+ //# sourceMappingURL=logwatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logwatch.js","sourceRoot":"","sources":["../../src/tools/logwatch.ts"],"names":[],"mappings":"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"}