import { readFileSync } from "node:fs"; import path from "node:path"; /* * ⛔⛆⛆ TWO SEATS RAN THE SAME VERB, GOT `153` AND `138`, AND BOTH SERVERS HONESTLY * REPORTED `versionLabel 0.26.20` — `⟨q-cec42e20⟩`. * * Measured 2026-09-12: the aide's server (pid 61459, started 08:20:48Z) returned * `parsedOpen 153` with a `delivered` axis; the coordinator's (pid 65516, started * 2026-09-11T09:40:42Z) returned `open 138` and NO `delivered` axis at all. Identical * labels, different loaded code, both answering honestly. * * ⭐⭐ THE LABEL IS NOT MERELY UNINFORMATIVE — IT IS ACTIVELY MISLEADING, because it is * the ONE FIELD a seat reaches for to check exactly this, and it AGREES while the * behaviour differs. Nothing detected the spread; every seat had to VOLUNTEER it. Five * unprompted self-reports are why nothing broke that day, and a system that works * because its operators are honest is one incident away from working because they were. * * ⛔ SO THIS DOES NOT KEY ON `versionLabel`, AND IT DOES NOT KEY ON `serverBuildMtime` * EITHER — which is the near-miss worth recording, because that field LOOKS like the * answer. It is stamped at ATTACH, and measured across all six live transports it held * ONE distinct value (2026-09-11T09:27:20) for every seat. It would have reported the * fleet uniform while the spread was live: `versionLabel`'s failure in a different field. * * ⭐ THE AXIS THAT DISCRIMINATES IS START TIME AGAINST THE INSTALLED BUILD — BUT ONLY * FOR A SERVER THAT IS RUNNING THAT BUILD, AND THAT PROVISO IS NOT PEDANTRY. A server * loads its code once, at spawn, so one that started BEFORE the current install runs * different code from one that started AFTER it, whatever either calls itself. * * ⛔⛆ THE THIRD NEAR-MISS, AND THIS ONE WAS NOT A NEAR-MISS — IT WAS MEASURED ON THIS * FILE. When `agent-coord-mcp@0.26.21` was installed at 2026-09-14T11:19:30Z, the * time-only version of this module was run against the REAL population: * * SERVER SPREAD: AGREED — 12 seat(s) placed, 0 unreadable * pre-install: (all twelve) * * AGREED. Over a fleet loading THREE DISTINCT BUILDS: nine on the installed one, two on * a dev `dist/` in the primary checkout, and one on `0.19.1` from July. Every seat had * started before the install, so every seat landed in one cohort and the fleet read * uniform — `versionLabel`'s failure a THIRD time, now in the field this module chose * as its remedy. "Which side of the install did you start" is not even a question about * a server that never loads the installed build. * * ⭐ SO THE MODULE PATH IS THE PRIMARY KEY AND THE TIMESTAMP IS SUBORDINATE TO IT. A * seat on a different build is its own cohort and is never folded into `pre-install`; * a seat that does not publish a module path is UNCOMPARABLE, because it cannot be * shown to be running the installed build at all. Today that makes the honest answer * CANNOT_COMPARE for the whole fleet — which is the correct answer, and the one the * time-only axis was hiding behind a clean AGREED. */ /** What one seat publishes about the process actually answering for it. */ export type ServerIdentity = { agentId: string; /** The ANSWERING process. Never the pusher — that is a different process (⟨q-f14692ca⟩). */ serverPid?: number; /** Epoch ms at which that process began. Captured from uptime, not from a file. */ serverStartedAt?: number; /** * The module root the answering process is EXECUTING, resolved from its own location. * ⛔ Absent is not "the installed one" — it is unknown, and it makes the seat * uncomparable rather than silently placing it with the majority. */ serverModule?: string; }; /** What the answering process was installed from: both halves, or nothing. */ export type InstalledBuild = { mtime: number; module: string }; export type SpreadVerdict = | { state: "AGREED"; cohorts: Cohort[]; comparable: string[]; uncomparable: Uncomparable[] } | { state: "DIVERGED"; cohorts: Cohort[]; comparable: string[]; uncomparable: Uncomparable[] } | { state: "CANNOT_COMPARE"; why: string; cohorts: Cohort[]; comparable: string[]; uncomparable: Uncomparable[] }; export type Cohort = { side: "pre-install" | "post-install" | "other-build"; agents: string[]; module?: string }; export type Uncomparable = { agentId: string; why: string }; /** * Which side of the installed build a seat's server started on. * * ⚠ EXCLUSIVE ON PURPOSE: a server started at exactly the install's mtime is counted * POST. The boundary belongs to one side or the other and putting it with the newer * build is the direction that under-reports divergence rather than inventing it. */ const sideOf = (startedAt: number, installMtime: number): Cohort["side"] => startedAt < installMtime ? "pre-install" : "post-install"; /** * Do the live seats' servers disagree about what they are running? * * ⛔ THREE OUTCOMES, AND THE THIRD IS NOT A KIND OF AGREEMENT. A seat that publishes no * identity cannot be placed, and reporting AGREED over a population you could not read * is the defect this row exists to end — it is `exit 0` meaning "asked and resolved" and * "never reached the registry" at once, one layer up. * * ⭐ SO AN UNREADABLE SEAT POISONS THE VERDICT RATHER THAN BEING DROPPED FROM IT: with * any seat uncomparable the answer is CANNOT_COMPARE, even when every seat that COULD be * read agrees. The cohorts are still returned, so a reader sees what was established as * well as what was not. */ /** Is a stamped server pid still running? EPERM means it exists and is not ours. */ export function pidRunning(pid: number): boolean { if (!Number.isInteger(pid) || pid <= 0) return false; try { process.kill(pid, 0); return true; } catch (e) { return (e as NodeJS.ErrnoException).code === "EPERM"; } } export function detectSpread( identities: ServerIdentity[], installed: InstalledBuild | null, // PURE BY DEFAULT: the detector trusts a stamped pid unless the caller supplies a liveness // check. The production caller (`list_agents`) passes `pidRunning`; a fixture of a measured // incident, whose pids belong to processes long gone, is still placed by its stamps. { isRunning = () => true }: { isRunning?: (pid: number) => boolean } = {}, ): SpreadVerdict { const uncomparable: Uncomparable[] = []; const placed: { agentId: string; side: Cohort["side"]; module?: string }[] = []; for (const id of identities) { // ⛔ THE MODULE PATH IS READ FIRST, and a missing one is not a default. A seat that // does not say what it is running cannot be compared against the installed build, // and placing it by timestamp alone is exactly the AGREED-over-three-builds result. if (typeof id.serverModule !== "string" || !id.serverModule) { uncomparable.push({ agentId: id.agentId, why: "publishes no module path — it cannot be shown to be running the installed build at all, and a timestamp cannot answer that", }); continue; } if (typeof id.serverStartedAt !== "number" || !Number.isFinite(id.serverStartedAt)) { uncomparable.push({ agentId: id.agentId, why: "no serverStartedAt published — this seat's server has not stamped its identity since the field existed", }); continue; } // ⟨q-18a719c5⟩ A STAMP OUTLIVES ITS SERVER. If the process that stamped this entry is gone, // the module it names is what a DEAD process ran — not what serves the seat now. Unknown, // naming the pid, until the seat's next server binds and stamps over it. if (typeof id.serverPid === "number" && !isRunning(id.serverPid)) { uncomparable.push({ agentId: id.agentId, why: `stamped by server pid ${id.serverPid}, which is no longer running — the entry names a process that is gone, not the one serving this seat`, }); continue; } if (installed === null) continue; // ⭐ A DIFFERENT BUILD IS ITS OWN COHORT, never folded into `pre-install`: "which // side of the install did you start" is not a question about a process that does // not load the install. Measured 2026-09-14 — 3 of 12 seats were in this case. if (id.serverModule !== installed.module) { placed.push({ agentId: id.agentId, side: "other-build", module: id.serverModule }); continue; } placed.push({ agentId: id.agentId, side: sideOf(id.serverStartedAt, installed.mtime) }); } const cohorts: Cohort[] = []; for (const side of ["pre-install", "post-install"] as const) { const agents = placed.filter((p) => p.side === side).map((p) => p.agentId).sort(); if (agents.length) cohorts.push({ side, agents }); } // One cohort PER FOREIGN BUILD, so two seats on different foreign builds never read // as one group that agrees with itself. for (const module of [...new Set(placed.filter((p) => p.side === "other-build").map((p) => p.module!))].sort()) { cohorts.push({ side: "other-build", module, agents: placed.filter((p) => p.module === module).map((p) => p.agentId).sort(), }); } const comparable = placed.map((p) => p.agentId).sort(); if (installed === null) { return { state: "CANNOT_COMPARE", why: "the installed build could not be read, so no seat can be placed against it", cohorts, comparable, uncomparable, }; } // ⟨q-18a719c5⟩ UNKNOWNS BLOCK AGREEMENT, NOT DISAGREEMENT. Two readable seats on different // sides of the install is established whatever the unreadable ones run, so it is reported as // DIVERGED with the unknowns listed. Only AGREED needs every seat, and that rule (#293) stands. if (uncomparable.length && cohorts.length > 1) { return { state: "DIVERGED", cohorts, comparable, uncomparable }; } if (uncomparable.length) { return { state: "CANNOT_COMPARE", why: `${uncomparable.length} of ${identities.length} live seat(s) publish no usable server identity, so the fleet ` + `cannot be shown uniform — what the readable seats agree about is reported, but it is not an answer about the fleet`, cohorts, comparable, uncomparable, }; } if (comparable.length < 2) { return { state: "CANNOT_COMPARE", why: `only ${comparable.length} seat(s) could be placed — a disagreement needs two parties`, cohorts, comparable, uncomparable, }; } return { state: cohorts.length > 1 ? "DIVERGED" : "AGREED", cohorts, comparable, uncomparable }; } /** * What a reader is told. The POPULATION is mandatory for the same reason the replay * instrument's is (⟨q-a83b56af⟩): "0 diverged of 6 read" and "0 of 0" are different * facts and only the second is a reason to distrust the run. */ export function reportSpread(v: SpreadVerdict, installed: InstalledBuild | null): string { const iso = (ms: number) => new Date(ms).toISOString(); const lines = [ `SERVER SPREAD: ${v.state} — ${v.comparable.length} seat(s) placed, ${v.uncomparable.length} unreadable` + (installed === null ? " · installed build UNREADABLE" : ` · installed build ${iso(installed.mtime)} ${installed.module}`), ]; if ("why" in v) lines.push(` ⛔ ${v.why}`); for (const c of v.cohorts) { lines.push(` ${c.side}${c.module ? ` (${c.module})` : ""}: ${c.agents.join(", ")}`); } for (const u of v.uncomparable) lines.push(` ⚠ ${u.agentId}: ${u.why}`); if (v.state === "DIVERGED") { lines.push( ` These seats are running DIFFERENT CODE. A version label will agree anyway — it did`, ` on 2026-09-12 while one server answered 153 and the other 138.`, ); } return lines.join("\n"); } /** * The build this process was INSTALLED from — its module root AND its mtime — or null. * * ⛔ NULL IS A REAL ANSWER AND MUST STAY ONE. If this cannot be read, no seat can be * placed on either side of it and the only truthful verdict is CANNOT_COMPARE — * returning a 0 or a now() would place every seat on one side and report the fleet * uniform, which is the failure this whole row is about. * * Resolved from THIS module's own location rather than from a configured path: the * question is "what build is the answering process running", and the answering process * is the one executing this file. */ export const COORD_MCP_PACKAGE_NAME = "agent-coord-mcp"; export function installedBuild( fromUrl: string, statSync: (p: string) => { mtimeMs: number }, readFile: (p: string) => string = (p) => readFileSync(p, "utf8"), ): InstalledBuild | null { // ⟨q-18a719c5⟩ THE ROOT IS FOUND BY THE PACKAGE'S OWN IDENTITY, not by a depth. This used to // strip one level (`/dist/`), and both production callers live in // `dist/tools/registry.js`: the regex never matched, `statSync(".../registry.js/package.json")` // threw, and this returned null on every server — `serverSpread` read CANNOT_COMPARE on every // fleet and the heartbeat stamp wrote `serverModule: undefined`. A depth count, or the FIRST // package.json found, breaks in other layouts (a global npm or homebrew install nests the // package under node_modules, a workspace nests it under packages/); the package.json whose // `name` is agent-coord-mcp is the package in every one of them. Nothing found stays null. try { let dir = path.dirname(decodeURIComponent(new URL(fromUrl).pathname)); for (let hops = 0; hops < 12; hops++) { const pkg = path.join(dir, "package.json"); try { if (JSON.parse(readFile(pkg))?.name === COORD_MCP_PACKAGE_NAME) { return { mtime: statSync(pkg).mtimeMs, module: dir }; } } catch { /* no readable package.json here — keep walking */ } const up = path.dirname(dir); if (up === dir) break; dir = up; } return null; } catch { return null; } }