agent-coord-mcp 0.19.0 → 0.19.1

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.
@@ -3,7 +3,7 @@ import { promises as fsp } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { z } from "zod";
5
5
  import { WORK_DIR, workFile, readJson } from "../store.js";
6
- import { boardRowsOf, doneEntriesOf, parseWorkDoc, queueItemsOf, renderWorkDoc, } from "../work.js";
6
+ import { boardRowsOf, doneEntriesOf, parseWorkDoc, queueItemsOf, renderWorkDoc, workDocIssues, } from "../work.js";
7
7
  import { loadScopes, ownsDocument } from "./scopes.js";
8
8
  import { AGENTS_FILE } from "../store.js";
9
9
  // ---------- work state as data (Phase 8 Task 5) ----------
@@ -76,18 +76,28 @@ export async function importWorkTool(args) {
76
76
  }
77
77
  const state = { project: args.project, repo, importedAt: Date.now(), docs };
78
78
  await saveState(state);
79
+ const allIssues = docs.flatMap((d) => workDocIssues(d.doc).map((issue) => `${d.path}: ${issue}`));
79
80
  return {
80
81
  ok: true,
81
82
  project: args.project,
82
83
  repo,
83
84
  file: workFile(args.project),
84
- imported: docs.map((d) => ({
85
- path: d.path,
86
- kind: d.kind,
87
- queue: queueItemsOf(d.doc).length,
88
- done: doneEntriesOf(d.doc).length,
89
- board: boardRowsOf(d.doc).length,
90
- })),
85
+ imported: docs.map((d) => {
86
+ const issues = workDocIssues(d.doc);
87
+ return {
88
+ path: d.path,
89
+ kind: d.kind,
90
+ queue: queueItemsOf(d.doc).length,
91
+ done: doneEntriesOf(d.doc).length,
92
+ board: boardRowsOf(d.doc).length,
93
+ ...(issues.length ? { issues } : {}),
94
+ };
95
+ }),
96
+ ...(allIssues.length
97
+ ? {
98
+ warning: `${allIssues.length} table row(s) were refused a record (wrong column count) and kept verbatim — the documents round-trip unchanged, but these rows are invisible to board consumers until fixed. See imported[].issues.`,
99
+ }
100
+ : {}),
91
101
  note: "the markdown remains authoritative — this store is a derived index",
92
102
  };
93
103
  }
@@ -117,10 +127,12 @@ export async function listWorkTool(args) {
117
127
  const queue = [];
118
128
  const done = [];
119
129
  const board = [];
130
+ const issues = [];
120
131
  for (const d of state.docs) {
121
132
  queue.push(...queueItemsOf(d.doc));
122
133
  done.push(...doneEntriesOf(d.doc));
123
134
  board.push(...boardRowsOf(d.doc));
135
+ issues.push(...workDocIssues(d.doc).map((issue) => `${d.path}: ${issue}`));
124
136
  }
125
137
  const openQueue = args.includeDone ? queue : queue.filter((q) => !q.done);
126
138
  const filtered = args.priority ? openQueue.filter((q) => q.priority === args.priority) : openQueue;
@@ -132,6 +144,9 @@ export async function listWorkTool(args) {
132
144
  ...(args.kind === "queue" || args.kind === undefined ? { queue: filtered } : {}),
133
145
  ...(args.kind === "done" || args.kind === undefined ? { done } : {}),
134
146
  ...(args.kind === "board" || args.kind === undefined ? { board } : {}),
147
+ // A row refused for wrong arity is absent from `board` — say so rather
148
+ // than let the absence read as "that lane doesn't exist".
149
+ ...(issues.length ? { issues } : {}),
135
150
  };
136
151
  }
137
152
  // Parse the documents without persisting — used by the list fallback so a
@@ -189,11 +204,16 @@ export async function exportWorkTool(args) {
189
204
  : undefined;
190
205
  if (write && rendered !== current)
191
206
  await fsp.writeFile(target, rendered, "utf8");
207
+ const issues = workDocIssues(d.doc);
192
208
  files.push({
193
209
  path: d.path,
194
210
  bytes: Buffer.byteLength(rendered, "utf8"),
195
211
  identical: rendered === current,
196
212
  written: write && rendered !== current,
213
+ // Refused rows replay verbatim — the write is byte-faithful — but a
214
+ // caller rewriting a document should hear that some rows carry no
215
+ // record, rather than infer health from `identical:true`.
216
+ ...(issues.length ? { issues } : {}),
197
217
  ...(scope ? { scope } : {}),
198
218
  });
199
219
  }
@@ -1 +1 @@
1
- {"version":3,"file":"work.js","sourceRoot":"","sources":["../../src/tools/work.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"work.js","sourceRoot":"","sources":["../../src/tools/work.ts"],"names":[],"mappings":"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"}
package/dist/work.js CHANGED
@@ -20,6 +20,13 @@
20
20
  // replayed in place. Only lines it genuinely understands are re-rendered, so
21
21
  // an unmodelled construct can never be silently dropped.
22
22
  import { createHash } from "node:crypto";
23
+ // The one arity BoardRow can hold. boardCells() and the parser's arity guard
24
+ // both reference this constant so the two sides cannot drift; a test pins
25
+ // boardCells().length === BOARD_ARITY.
26
+ export const BOARD_ARITY = 5;
27
+ export function isMalformedRow(r) {
28
+ return r.malformed === true;
29
+ }
23
30
  // ---------- the glyph contract ----------
24
31
  //
25
32
  // Pinned in docs/DONE.md and consumed by external parsers: the ref splits on
@@ -116,11 +123,14 @@ function boardCells(r) {
116
123
  return [r.lane, r.owner, r.state, r.currentSlice, r.nextGo];
117
124
  }
118
125
  // Replay the original line when the fields still say what it said; re-render
119
- // once anything actually changed.
126
+ // once anything actually changed. A malformed row has no fields to have
127
+ // changed — it replays its bytes, always.
120
128
  export function renderBoardRow(r) {
129
+ if (isMalformedRow(r))
130
+ return r.verbatim;
121
131
  if (r.raw !== undefined) {
122
132
  const cells = splitRow(r.raw);
123
- if (cells.length === 5 && cells.every((c, i) => c === boardCells(r)[i]))
133
+ if (cells.length === BOARD_ARITY && cells.every((c, i) => c === boardCells(r)[i]))
124
134
  return r.raw;
125
135
  }
126
136
  return renderRow(boardCells(r));
@@ -216,7 +226,23 @@ export function parseWorkDoc(source) {
216
226
  let j = i + 2;
217
227
  for (; j < lines.length && TABLE_ROW.test(lines[j] ?? ""); j++) {
218
228
  const raw = lines[j] ?? "";
219
- const [lane = "", owner = "", state = "", currentSlice = "", nextGo = ""] = splitRow(raw);
229
+ const cells = splitRow(raw);
230
+ // Arity guard: a row BoardRow cannot hold is refused a record, kept
231
+ // verbatim, and named loudly — destructuring it into the 5-tuple is
232
+ // exactly the silent narrow/widen this exists to prevent. An empty
233
+ // trailing cell (`| a | b | c | d | |`) is still five columns and
234
+ // still a legitimate row.
235
+ if (cells.length !== BOARD_ARITY) {
236
+ rows.push({
237
+ malformed: true,
238
+ verbatim: raw,
239
+ issue: `board row at line ${j + 1} has ${cells.length} column(s), expected ${BOARD_ARITY} — ` +
240
+ `refused (kept verbatim, excluded from board records). Fix the row, or widen BoardRow ` +
241
+ `deliberately (BOARD_ARITY + boardCells + this guard together). Row: ${raw}`,
242
+ });
243
+ continue;
244
+ }
245
+ const [lane = "", owner = "", state = "", currentSlice = "", nextGo = ""] = cells;
220
246
  rows.push({ id: idFor("b", lane), lane, owner, state, currentSlice, nextGo, raw });
221
247
  }
222
248
  flushText();
@@ -255,6 +281,12 @@ export function doneEntriesOf(doc) {
255
281
  return doc.blocks.flatMap((b) => (b.kind === "done" ? b.entries : []));
256
282
  }
257
283
  export function boardRowsOf(doc) {
258
- return doc.blocks.flatMap((b) => (b.kind === "board" ? b.rows : []));
284
+ return doc.blocks.flatMap((b) => b.kind === "board" ? b.rows.filter((r) => !isMalformedRow(r)) : []);
285
+ }
286
+ // Every refused row's issue, in document order — what makes the parse-time
287
+ // rejection LOUD at the tool layer (import_work/list_work/export_work all
288
+ // surface it) instead of a filtered-out record nobody notices.
289
+ export function workDocIssues(doc) {
290
+ return doc.blocks.flatMap((b) => b.kind === "board" ? b.rows.filter(isMalformedRow).map((r) => r.issue) : []);
259
291
  }
260
292
  //# sourceMappingURL=work.js.map
package/dist/work.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"work.js","sourceRoot":"","sources":["../src/work.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"work.js","sourceRoot":"","sources":["../src/work.ts"],"names":[],"mappings":"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"}
@@ -461,6 +461,12 @@ function writeReceipts(msgs, outcome) {
461
461
  ts: Date.now(),
462
462
  from: m.from,
463
463
  control: m.control === true,
464
+ // Build identity of the pusher that did the typing/verifying — the
465
+ // same module-graph stamp the transport marker carries (SCRIPT_MTIME
466
+ // covers hooks/*.mjs, not just this file). Lets deliveryOutcome note
467
+ // a "confirmed" issued by pre-upgrade verification logic. Omitted
468
+ // when unknown: absence reads as UNKNOWN downstream, never as fresh.
469
+ ...(SCRIPT_MTIME !== undefined ? { scriptMtime: SCRIPT_MTIME } : {}),
464
470
  ...(outcome
465
471
  ? {
466
472
  submitted: outcome.submitted === true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-coord-mcp",
3
- "version": "0.19.0",
3
+ "version": "0.19.1",
4
4
  "description": "File-backed MCP server for coordinating multiple AI coding agents (Claude Code, Cursor, Cline, etc.). Local stdio or networked over Streamable HTTP.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,7 +22,7 @@
22
22
 
23
23
  import { spawn } from "node:child_process";
24
24
 
25
- const EXPECTED_TESTS = 226;
25
+ const EXPECTED_TESTS = 262;
26
26
 
27
27
  const expected = Number(process.env.AGENT_COORD_EXPECTED_TESTS ?? EXPECTED_TESTS);
28
28
  // Same glob the suite always used — `--test test/` would recurse differently
@@ -114,15 +114,41 @@ try {
114
114
  } catch (e) {
115
115
  die(`register failed: ${e?.message ?? e}`);
116
116
  }
117
- // Stamp the mtime of THIS process's loaded script so doctor() can spot a
118
- // stale remote pusher after a remote-side upgrade (see v0.8.2 stale-pusher
119
- // check — same hazard as the local tmux-pusher).
120
- let scriptMtime;
121
- try {
122
- const { statSync } = await import("node:fs");
123
- const { fileURLToPath } = await import("node:url");
124
- scriptMtime = statSync(fileURLToPath(import.meta.url)).mtimeMs;
125
- } catch { /* non-fatal */ }
117
+ // Build identity of THIS pusher process: newest mtime across the entry file
118
+ // AND its ../hooks/*.mjs imports, sampled once at startup. The entry file
119
+ // alone is not enough — the paste/submit pipeline lives in hooks/submit.mjs,
120
+ // so a fix landing there alone would leave a single-file stamp unchanged and
121
+ // a still-running pusher on the old code would read as fresh (#28's lesson,
122
+ // carried across the wire). Over-covering hooks siblings we don't import is
123
+ // the safe direction: a spurious stale flag is loud and cheap, a false fresh
124
+ // silently invalidates rollout verification. Stamped on the transport marker
125
+ // AND on every receipt this process reports; undefined on failure — an
126
+ // absent stamp reads as UNKNOWN downstream, never as fresh, and a partial
127
+ // (entry-only) value could read fresh while submit.mjs is exactly the stale
128
+ // part.
129
+ const scriptMtime = await (async () => {
130
+ try {
131
+ const { statSync, readdirSync } = await import("node:fs");
132
+ const { fileURLToPath } = await import("node:url");
133
+ const path = await import("node:path");
134
+ const self = fileURLToPath(import.meta.url);
135
+ let newest = statSync(self).mtimeMs;
136
+ const hooksDir = path.join(path.dirname(self), "..", "hooks");
137
+ for (const f of readdirSync(hooksDir)) {
138
+ if (!f.endsWith(".mjs")) continue;
139
+ let m;
140
+ try {
141
+ m = statSync(path.join(hooksDir, f)).mtimeMs;
142
+ } catch {
143
+ continue; // deleted mid-scan
144
+ }
145
+ if (m > newest) newest = m;
146
+ }
147
+ return newest;
148
+ } catch {
149
+ return undefined; // non-fatal — absence stays honest
150
+ }
151
+ })();
126
152
  try {
127
153
  await call(
128
154
  "report_transport",
@@ -323,6 +349,10 @@ async function reportReceipts(msgs, outcome) {
323
349
  id: m.id,
324
350
  ...(m.from !== undefined ? { from: m.from } : {}),
325
351
  control: m.control === true,
352
+ // Our build identity (module-graph mtime, see the startup stamp) —
353
+ // ties this receipt to the code that typed/verified the delivery.
354
+ // Omitted when unknown; the server must not default it.
355
+ ...(scriptMtime !== undefined ? { scriptMtime } : {}),
326
356
  ...(outcome
327
357
  ? {
328
358
  submitted: outcome.submitted === true,
package/src/server.ts CHANGED
@@ -4,8 +4,16 @@ import { createServer, IncomingMessage, ServerResponse } from "node:http";
4
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
6
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
7
- import { ensureDirs, getTokenMap, reloadTokenMapSync } from "./store.js";
7
+ import { unlinkSync, writeFileSync } from "node:fs";
8
8
  import {
9
+ ensureDirs,
10
+ getTokenMap,
11
+ reloadTokenMapSync,
12
+ sessionFile,
13
+ type SessionBinding,
14
+ } from "./store.js";
15
+ import {
16
+ liveClaimEvidence,
9
17
  attachAgentSchema,
10
18
  attachAgentTool,
11
19
  clearTransportSchema,
@@ -95,8 +103,103 @@ function jsonResult(data: unknown) {
95
103
  // switching (the PR #45 spoof shape) is rejected.
96
104
  // - rename_agent updates the binding to the new id on success so the
97
105
  // renamed session keeps working.
98
- function buildServer(initialBound?: string): McpServer {
106
+ // - First-claim guard (v0.20.0): TOFU no longer lets a fresh session claim
107
+ // an id that is currently LIVE on the bus (fresh heartbeat, live
108
+ // transport, or another live bound session) — that silently created a
109
+ // second session acting as an already-running agent (hit live 2026-07-06:
110
+ // a dev session bound itself to `disavow-liaison`). A live-id claim needs
111
+ // the agent's token or an explicit force (join/register params). See
112
+ // guardFirstClaim for how absent vs unreadable evidence is decided.
113
+ // - `trackSession` (stdio only): each successful bind writes a
114
+ // sessions/<id>.<pid>.<nonce>.json marker so doctor can SEE two live
115
+ // sessions bound to one id — closure state alone cannot be inspected
116
+ // from outside the process. Not tracked for HTTP sessions: tokens.json
117
+ // already enforces their identity and many share one pid, which would
118
+ // make pid-liveness meaningless.
119
+ function buildServer(initialBound?: string, opts: { trackSession?: boolean } = {}): McpServer {
99
120
  let bound = initialBound;
121
+ const trackSession = opts.trackSession ?? false;
122
+ let sessionMarker: string | undefined;
123
+ let exitHooksInstalled = false;
124
+
125
+ // Best-effort: a marker left behind by SIGKILL has a dead pid, which both
126
+ // the guard's evidence read and doctor's duplicate-session-binding check
127
+ // treat as garbage (doctor fix deletes it).
128
+ function recordSessionBinding(agentId: string, via: string): void {
129
+ if (!trackSession) return;
130
+ try {
131
+ const file = sessionFile(agentId, process.pid, randomUUID().slice(0, 8));
132
+ const marker: SessionBinding = {
133
+ agentId,
134
+ pid: process.pid,
135
+ boundAt: Date.now(),
136
+ via,
137
+ ...(process.env.TMUX_PANE ? { tmuxPane: process.env.TMUX_PANE } : {}),
138
+ };
139
+ writeFileSync(file, JSON.stringify(marker, null, 2) + "\n");
140
+ if (sessionMarker) {
141
+ try { unlinkSync(sessionMarker); } catch { /* already gone */ }
142
+ }
143
+ sessionMarker = file;
144
+ if (!exitHooksInstalled) {
145
+ exitHooksInstalled = true;
146
+ const cleanup = () => {
147
+ try { if (sessionMarker) unlinkSync(sessionMarker); } catch { /* already gone */ }
148
+ };
149
+ process.on("exit", cleanup);
150
+ // Default signal death skips 'exit' handlers; SIGHUP stays reserved
151
+ // for the token-map reload in loadTokenMap.
152
+ for (const sig of ["SIGTERM", "SIGINT"] as const) {
153
+ process.on(sig, () => { cleanup(); process.exit(0); });
154
+ }
155
+ }
156
+ } catch { /* marker is observability, never worth failing the bind */ }
157
+ }
158
+
159
+ // Decide whether a fresh session may claim `claimed` as its identity, and
160
+ // how. Returns the bind provenance ("tofu" | "token" | "force" |
161
+ // "same-pane") or throws. Ordering is deliberate:
162
+ // - a presented token must MATCH or the claim fails loudly, even when the
163
+ // id is not live — a wrong credential silently succeeding via the
164
+ // not-live path would teach callers that garbage tokens work;
165
+ // - force is an explicit human/agent decision, honored before evidence;
166
+ // - evidence that exists but cannot be read REFUSES (cannot-verify ≠
167
+ // verified-absent; unreadable state must not disable the guard);
168
+ // - a live id refuses, except when its live pusher types into THIS
169
+ // process's own tmux pane — two sessions cannot share a pane, so that
170
+ // is the same seat restarting (the routine fleet-restart case), not a
171
+ // second session. The exception never applies when another live
172
+ // session is already bound to the id.
173
+ // - verified-not-live binds freely: refusing absent evidence would break
174
+ // every first onboarding, and the guard exists to protect LIVE ids.
175
+ async function guardFirstClaim(claimed: string, args: Record<string, unknown>): Promise<string> {
176
+ const token = typeof args["token"] === "string" ? (args["token"] as string) : undefined;
177
+ if (token !== undefined) {
178
+ if (getTokenMap()?.get(token) === claimed) return "token";
179
+ throw new Error(
180
+ `token presented for '${claimed}' does not match tokens.json (or no token map is loaded). ` +
181
+ `Mint one with scripts/coord-token.mjs add ${claimed} (then SIGHUP the bus), or pass force:true if you are certain.`,
182
+ );
183
+ }
184
+ if (args["force"] === true) return "force";
185
+ const ev = await liveClaimEvidence(claimed, Date.now());
186
+ if (!ev.verifiable) {
187
+ throw new Error(
188
+ `cannot verify whether '${claimed}' is live: ${ev.reasons.join("; ")}. ` +
189
+ `Refusing to bind rather than treating unreadable evidence as absence. ` +
190
+ `Repair the state (doctor), or pass the agent's token or force:true (join/register).`,
191
+ );
192
+ }
193
+ if (ev.live) {
194
+ if (ev.samePane && ev.boundElsewhere === 0) return "same-pane";
195
+ throw new Error(
196
+ `agent '${claimed}' is live on this bus (${ev.reasons.join("; ")}) — refusing to bind this fresh session to it. ` +
197
+ `If you ARE '${claimed}' restarting, re-join from its tmux pane, or pass its token or force:true (join/register). ` +
198
+ `If you are diagnosing, use status/ping (read-only, they never bind) or your own id.`,
199
+ );
200
+ }
201
+ return "tofu";
202
+ }
100
203
 
101
204
  // Gate every tool that takes a caller identity. `field: null` (list_agents,
102
205
  // list_rooms, prune) bypasses the check entirely.
@@ -117,7 +220,12 @@ function buildServer(initialBound?: string): McpServer {
117
220
  if (typeof claimed === "string") {
118
221
  if (bound === undefined) {
119
222
  if (bindOnClaim) {
120
- bound = claimed; // TOFU: first claim wins, then sticky.
223
+ // TOFU: first claim wins, then sticky — but only after the
224
+ // first-claim guard agrees the id isn't someone else's live
225
+ // session (see guardFirstClaim).
226
+ const via = await guardFirstClaim(claimed, args);
227
+ bound = claimed;
228
+ recordSessionBinding(claimed, via);
121
229
  }
122
230
  } else if (bound !== claimed) {
123
231
  throw new Error(
@@ -137,7 +245,7 @@ function buildServer(initialBound?: string): McpServer {
137
245
 
138
246
  server.tool(
139
247
  "join",
140
- "Recommended session-start call. Does register + auto-attach (if running inside tmux) + read inbox in one round-trip. Pass attach=false to skip the transport, attach={...overrides} to customize, or omit it to let the server auto-detect $TMUX_PANE. Returns the registration, attach result, any unread inbox messages, and the default channel's topic + MOTD (room rules) so you see them on connect. Calling join binds this MCP process's identity to agentId for the lifetime of the session — no env var or config needed. Each Claude Code session runs its own stdio process so bindings are naturally isolated.",
248
+ "Recommended session-start call. Does register + auto-attach (if running inside tmux) + read inbox in one round-trip. Pass attach=false to skip the transport, attach={...overrides} to customize, or omit it to let the server auto-detect $TMUX_PANE. Returns the registration, attach result, any unread inbox messages, and the default channel's topic + MOTD (room rules) so you see them on connect. Calling join binds this MCP process's identity to agentId for the lifetime of the session — no env var or config needed. Each Claude Code session runs its own stdio process so bindings are naturally isolated. Claiming an id that is currently LIVE on the bus (fresh heartbeat, live pusher, or another bound session) is refused unless the claim comes from that agent's own tmux pane or carries the agent's token or force:true — diagnosing someone else's agent is what status/ping are for.",
141
249
  joinSchema,
142
250
  // join explicitly sets the session binding when unset, so each agent can
143
251
  // declare its identity via join rather than relying on env vars.
@@ -145,7 +253,9 @@ function buildServer(initialBound?: string): McpServer {
145
253
  const claimed = args["agentId"];
146
254
  if (typeof claimed === "string") {
147
255
  if (bound === undefined) {
256
+ const via = await guardFirstClaim(claimed, args);
148
257
  bound = claimed;
258
+ recordSessionBinding(claimed, via);
149
259
  } else if (bound !== claimed) {
150
260
  throw new Error(
151
261
  `identity bound to '${bound}'; rejected attempt to act as '${claimed}'`,
@@ -249,7 +359,7 @@ function buildServer(initialBound?: string): McpServer {
249
359
 
250
360
  server.tool(
251
361
  "prune",
252
- "Trim room/status/inbox JSONL to entries newer than `olderThanDays` (default 7); kind='decision' posts keep a longer `decisionDays` retention (default 30). Nothing is lost: aged-out entries are archived under archive/ (rooms/<chan>.jsonl, status.jsonl, inbox/<agent>.jsonl) — only receipts are truly deleted. Pass `room` to prune a single channel, or `targets` (rooms|status|inbox|receipts|members) to narrow the sweep. Sweeps room members that are unregistered or haven't heartbeated since the cutoff, and archives+removes non-default rooms left empty and inactive (disable via archiveEmptyRooms=false). Removes inbox files for agents no longer in the registry unless removeOrphanInboxes=false. Pass dryRun=true to preview.",
362
+ "Trim room/status/inbox JSONL to entries newer than `olderThanDays` (default 7); kind='decision' posts keep a longer `decisionDays` retention (default 30). Nothing is lost: aged-out entries are archived under archive/ (rooms/<chan>.jsonl, status.jsonl, inbox/<agent>.jsonl) — only receipts are truly deleted. `room` and `targets` compose: `room` scopes every sweep to that channel (and, alone, defaults the sweep to `rooms` only), while `targets` (rooms|status|inbox|receipts|members) selects which sweeps run and always wins over that default — so `{room, targets:['members']}` sweeps membership in that one channel. Sweeps room members that are unregistered or haven't heartbeated since the cutoff, and archives+removes non-default rooms left empty and inactive (disable via archiveEmptyRooms=false). Removes inbox files for agents no longer in the registry unless removeOrphanInboxes=false. Pass dryRun=true to preview.",
253
363
  pruneSchema,
254
364
  gate(null, pruneTool as (a: Record<string, unknown>) => Promise<unknown>),
255
365
  );
@@ -306,15 +416,23 @@ function buildServer(initialBound?: string): McpServer {
306
416
  async (args: Record<string, unknown>) => {
307
417
  const claimed = args.agentId;
308
418
  if (typeof claimed === "string") {
309
- if (bound === undefined) bound = claimed;
310
- else if (bound !== claimed) {
419
+ if (bound === undefined) {
420
+ // Renaming a live agent from a fresh session is still a first
421
+ // claim of that agent's identity — same guard as any other.
422
+ const via = await guardFirstClaim(claimed, args);
423
+ bound = claimed;
424
+ recordSessionBinding(claimed, via);
425
+ } else if (bound !== claimed) {
311
426
  throw new Error(`identity bound to '${bound}'; rejected attempt to act as '${claimed}'`);
312
427
  }
313
428
  }
314
429
  const result = await renameAgentTool(args as { agentId: string; newAgentId: string });
315
430
  if (result && typeof result === "object" && (result as { ok?: unknown }).ok === true) {
316
431
  const to = (result as { to?: unknown }).to;
317
- if (typeof to === "string") bound = to;
432
+ if (typeof to === "string") {
433
+ bound = to;
434
+ recordSessionBinding(to, "rename");
435
+ }
318
436
  }
319
437
  return jsonResult(result);
320
438
  },
@@ -404,6 +522,10 @@ function buildServer(initialBound?: string): McpServer {
404
522
  gate(null, forceUnregisterTool as (a: Record<string, unknown>) => Promise<unknown>),
405
523
  );
406
524
 
525
+ // An env pre-bound session is just as live as a TOFU-bound one — record it
526
+ // so doctor's duplicate check sees it too. (No-op unless trackSession.)
527
+ if (initialBound) recordSessionBinding(initialBound, "env");
528
+
407
529
  return server;
408
530
  }
409
531
 
@@ -452,7 +574,7 @@ async function main() {
452
574
  " unregister before restarting so the new name starts fresh.",
453
575
  );
454
576
  }
455
- const server = buildServer(boundAgent);
577
+ const server = buildServer(boundAgent, { trackSession: true });
456
578
  const transport = new StdioServerTransport();
457
579
  await server.connect(transport);
458
580
  }
package/src/store.ts CHANGED
@@ -55,6 +55,37 @@ export const ARCHIVE_ROOMS_DIR = path.join(ARCHIVE_DIR, "rooms");
55
55
  export const ARCHIVE_INBOX_DIR = path.join(ARCHIVE_DIR, "inbox");
56
56
  export const ARCHIVE_STATUS_FILE = path.join(ARCHIVE_DIR, "status.jsonl");
57
57
 
58
+ // Live session-binding markers (v0.20.0). One small file per *bound* stdio MCP
59
+ // session: which agentId the session claimed, which pid holds it, and how the
60
+ // bind was established. Written at bind time, removed on clean exit; a file
61
+ // whose pid is dead is garbage doctor can clean. This is what makes two live
62
+ // sessions bound to the same id VISIBLE (doctor `duplicate-session-binding`)
63
+ // — in-process closure state can't be, by definition. HTTP sessions are not
64
+ // tracked here: with tokens.json they are already identity-enforced, and many
65
+ // share one pid, so pid-liveness would be meaningless for them.
66
+ export const SESSIONS_DIR = path.join(ROOT, "sessions");
67
+
68
+ export type SessionBinding = {
69
+ agentId: string;
70
+ pid: number;
71
+ boundAt: number;
72
+ // How the bind was established: "tofu" (first claim, id verified not live),
73
+ // "env" (AGENT_COORD_BOUND_AGENT), "token", "force", "same-pane" (live
74
+ // marker types into this session's own tmux pane), "rename".
75
+ via: string;
76
+ tmuxPane?: string;
77
+ };
78
+
79
+ export function sessionFile(agentId: string, pid: number, nonce: string): string {
80
+ return path.join(SESSIONS_DIR, `${sanitize(agentId)}.${pid}.${nonce}.json`);
81
+ }
82
+
83
+ export async function listSessionFiles(): Promise<string[]> {
84
+ if (!existsSync(SESSIONS_DIR)) return [];
85
+ const names = await fs.readdir(SESSIONS_DIR);
86
+ return names.filter((n) => n.endsWith(".json")).map((n) => path.join(SESSIONS_DIR, n));
87
+ }
88
+
58
89
  // Per-agent token map for identity-bound bus auth (v0.7.0). Shape on disk:
59
90
  // { "alice": "tk_<random-secret>", "bob": "tk_<another-secret>" }
60
91
  // HTTP transport reverse-looks-up the bearer to bind the session to an
@@ -82,7 +113,7 @@ export function workFile(project: string): string {
82
113
  }
83
114
 
84
115
  export function ensureDirs(): void {
85
- for (const d of [ROOT, INBOX_DIR, CURSOR_DIR, TRANSPORT_DIR, PID_DIR, LOG_DIR, ROOMS_DIR, RECEIPTS_DIR, HISTORY_DIR, WORK_DIR]) {
116
+ for (const d of [ROOT, INBOX_DIR, CURSOR_DIR, TRANSPORT_DIR, PID_DIR, LOG_DIR, ROOMS_DIR, RECEIPTS_DIR, HISTORY_DIR, WORK_DIR, SESSIONS_DIR]) {
86
117
  if (!existsSync(d)) mkdirSync(d, { recursive: true });
87
118
  }
88
119
  for (const f of [ROOM_FILE, STATUS_FILE]) {
@@ -330,6 +361,19 @@ export async function readJson<T>(file: string, fallback: T): Promise<T> {
330
361
  }
331
362
  }
332
363
 
364
+ // Like readJson, but a file that EXISTS and cannot be parsed THROWS instead of
365
+ // silently returning the fallback. For callers whose decision flips on
366
+ // "verified absent" vs "cannot verify": the first-claim binding guard must
367
+ // refuse when evidence is unreadable, because a guard that treats unreadable
368
+ // evidence as absent is disabled by the very corruption it should be
369
+ // reporting (the absence-is-not-exemption class, #36).
370
+ export async function readJsonStrict<T>(file: string, fallback: T): Promise<T> {
371
+ if (!existsSync(file)) return fallback;
372
+ const raw = await fs.readFile(file, "utf8");
373
+ if (!raw.trim()) return fallback;
374
+ return JSON.parse(raw) as T;
375
+ }
376
+
333
377
  export async function writeJson(file: string, data: unknown): Promise<void> {
334
378
  await withLock(file, async () => {
335
379
  await fs.writeFile(file, JSON.stringify(data, null, 2), "utf8");