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,158 +0,0 @@
1
- /*
2
- * Phase 5.1 Task 11 — CLOSE THE LOOP: answer a capability question by
3
- * EXERCISING the capability, in the process that would serve it.
4
- *
5
- * 11.1: NO TIMESTAMP ON THIS BOX CAN ANSWER A CAPABILITY QUESTION. Every
6
- * artefact people reach for is a proxy that fails differently:
7
- *
8
- * an mtime tracks WRITES. A reinstall of byte-identical code moves
9
- * it, and an edit that never got built does not.
10
- * serverBuildMtime is stamped at ATTACH, so it tells you when a transport
11
- * started, not what the running process contains.
12
- * a version string is a LABEL someone typed into package.json. Measured
13
- * today: a tarball published as 0.5.23 contained a change
14
- * the version numbering said it could not, and the number
15
- * was believed over the artefact for an hour.
16
- * `npm view` answers from a cache, and told this fleet the wrong
17
- * published version twice in one morning.
18
- *
19
- * Each is honest about something and dishonest about capability, and the
20
- * failure is always the same shape: an ANSWER ABOUT A LABEL read as an answer
21
- * about behaviour.
22
- *
23
- * 11.2: A RELEASE IS NOT DELIVERED UNTIL A SERVER THAT RESTARTED ANSWERS.
24
- * `merged · published · installed · restarted · observed` — five states, and
25
- * the last two are the ones that keep being skipped. A probe run INSIDE the
26
- * server process is the only artefact that speaks for the loaded code: it
27
- * cannot be satisfied by a file that exists, a version that matches, or a
28
- * package that installed, because it calls the code and reports what happened.
29
- *
30
- * WHY A PROBE MAY NEVER READ A VERSION: if a probe branched on a version
31
- * string it would inherit that string's dishonesty, and a fleet would then
32
- * have a capability check that passes on a restarted-but-not-upgraded server.
33
- * Probes call behaviour. The version travels beside the answer as CONTEXT and
34
- * is labelled as such.
35
- */
36
- import { prRefsIn } from "./tools/record-events.js";
37
- import { EVENT_KIND_IDS } from "./tools/event-kinds.js";
38
- import { suggestRecordType, typedRecordMode } from "./typed-records.js";
39
- import { LEAD_REFUSED, PARKED_CATEGORIES } from "./tools/away.js";
40
- import { recordAuthorityFor } from "./roles.js";
41
- import { subscriptionHealth } from "./tools/events.js";
42
- /**
43
- * Each probe calls a behaviour that did not exist before its release and
44
- * reports what it observed. A probe that could pass without the code being
45
- * loaded is not a probe — it is a restatement of the version.
46
- */
47
- const PROBES = [
48
- {
49
- id: "typed-records-obligatory",
50
- since: "0.26.10",
51
- run: () => {
52
- const s = suggestRecordType("DONE: shipped it", []);
53
- const mode = typedRecordMode();
54
- return {
55
- present: s.type === "done" && (mode === "warn" || mode === "refuse"),
56
- evidence: `suggestRecordType("DONE: …") -> '${s.type}', policy mode '${mode}'`,
57
- };
58
- },
59
- },
60
- {
61
- id: "record-events-all-kinds",
62
- since: "0.26.12",
63
- run: () => {
64
- const kinds = [...EVENT_KIND_IDS].sort();
65
- const present = ["item", "phase", "pr", "task"].every((k) => kinds.includes(k));
66
- return { present, evidence: `subscribable kinds: ${kinds.join(", ")}` };
67
- },
68
- },
69
- {
70
- id: "multi-pr-citation",
71
- since: "0.26.14",
72
- run: () => {
73
- const refs = prRefsIn("owner/repo#170, #173");
74
- return {
75
- present: refs.length === 2 && refs[1] === "owner/repo#173",
76
- evidence: `prRefsIn("owner/repo#170, #173") -> [${refs.join(", ")}]`,
77
- };
78
- },
79
- },
80
- {
81
- id: "away-means-david-away",
82
- since: "0.26.13",
83
- run: () => {
84
- const present = "merge" in LEAD_REFUSED && PARKED_CATEGORIES.includes("licence");
85
- return {
86
- present,
87
- evidence: `coord_away refuses [${Object.keys(LEAD_REFUSED).join(", ")}] for the lead; parks ${PARKED_CATEGORIES.length} categories`,
88
- };
89
- },
90
- },
91
- {
92
- id: "subscription-scanned-vs-evaluated",
93
- since: "0.26.15",
94
- run: () => {
95
- // The capability is that "the machinery ran" and "your kind fired" are
96
- // separable. Probed by asking for the state that used to be reported as
97
- // broken: scanned, never evaluated — a healthy idle watch.
98
- const base = { id: "p", agentId: "p", kind: "item", target: "t", createdAt: 0, lastEvaluatedAt: null, lastEventAt: null, delivered: [] };
99
- const quiet = subscriptionHealth({ ...base, lastScannedAt: Date.now() });
100
- const unscanned = subscriptionHealth({ ...base, lastScannedAt: null });
101
- return {
102
- present: quiet.level === "ok" && unscanned.level === "error",
103
- evidence: `scanned+quiet -> '${quiet.level}', never-scanned -> '${unscanned.level}'`,
104
- };
105
- },
106
- },
107
- {
108
- id: "record-authority",
109
- since: "0.24.0",
110
- run: () => {
111
- const worker = recordAuthorityFor({ roleId: "worker" });
112
- return {
113
- present: worker.mayNotEmit.includes("verdict"),
114
- evidence: `a worker mayNotEmit: [${worker.mayNotEmit.join(", ")}]`,
115
- };
116
- },
117
- },
118
- ];
119
- export function probeCapabilities(context) {
120
- const probes = PROBES.map((p) => {
121
- try {
122
- const r = p.run();
123
- return { id: p.id, since: p.since, present: r.present, evidence: r.evidence };
124
- }
125
- catch (e) {
126
- // A THROWN PROBE IS AN ABSENT CAPABILITY, NOT A BROKEN CHECK. Older code
127
- // that lacks the symbol throws exactly here, and reporting that as an
128
- // error rather than an absence would make the common case look like a
129
- // malfunction.
130
- return { id: p.id, since: p.since, present: false, evidence: `probe threw: ${e.message}` };
131
- }
132
- });
133
- const missing = probes.filter((p) => !p.present).map((p) => p.id);
134
- return {
135
- answeredBy: {
136
- pid: process.pid,
137
- startedAtIso: new Date(Date.now() - Math.round(process.uptime() * 1000)).toISOString(),
138
- module: context.module,
139
- versionLabel: context.versionLabel,
140
- },
141
- probes,
142
- missing,
143
- ok: missing.length === 0,
144
- note: "Every line above was produced by CALLING the code in this process. `versionLabel` is a label someone typed " +
145
- "into package.json and is context, never evidence — a published tarball has already been observed carrying a " +
146
- "change its version said it could not. THIS ANSWER IS ABOUT ONE PROCESS: a release is delivered when every " +
147
- "live agent's OWN server answers, which is the fifth state (merged · published · installed · restarted · observed). " +
148
- "A server that has not restarted answers honestly about the old code it is still running.",
149
- };
150
- }
151
- /* ── the verb ──────────────────────────────────────────────────────────────── */
152
- import { resolveServerIdentity } from "./server-identity.js";
153
- export const capabilitiesSchema = {};
154
- export async function capabilitiesTool() {
155
- const id = resolveServerIdentity();
156
- return probeCapabilities({ module: id.path, versionLabel: id.version });
157
- }
158
- //# sourceMappingURL=capabilities.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../src/capabilities.ts"],"names":[],"mappings":"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"}
package/dist/prefix.js DELETED
@@ -1,64 +0,0 @@
1
- /*
2
- * WHERE WILL A NEW GLOBAL INSTALL LAND, AND IS IT WHERE THE FLEET LOADS FROM?
3
- *
4
- * These are two different questions and neither answers the other. The
5
- * `server-build-drift` check names which copy is RUNNING; this names where the
6
- * NEXT copy will be written. A run of `npm i -g agent-coord-mcp` that prints
7
- * "added 1 package" is not evidence it landed anywhere that runs.
8
- *
9
- * MEASURED ON THIS BOX, 2026-08-28 — the divergence is not hypothetical:
10
- * npm prefix -g -> .../node/v22.22.2
11
- * every live fleet server-> .../node/v22.21.1/lib/node_modules/agent-coord-mcp
12
- * Three prefixes exist here (two nvm, one /opt/homebrew), `npm prefix -g` is
13
- * PATH-dependent, and nvm switches it per shell. So the install target and the
14
- * load target had silently diverged, and a successful install would have
15
- * updated a copy nothing loads. That gap cost the fleet a day.
16
- */
17
- import path from "node:path";
18
- /**
19
- * The global root a module path sits under, or null if it is not in one.
20
- * `/p/lib/node_modules/agent-coord-mcp/dist` -> `/p`
21
- */
22
- export function prefixOf(modulePath) {
23
- if (!modulePath)
24
- return null;
25
- // Split on the LAST occurrence: a global prefix can itself live under a path
26
- // containing `node_modules`, and taking the first match would name an
27
- // ancestor that installs nothing.
28
- const marker = `${path.sep}lib${path.sep}node_modules${path.sep}`;
29
- const i = modulePath.lastIndexOf(marker);
30
- if (i === -1)
31
- return null;
32
- return modulePath.slice(0, i);
33
- }
34
- /**
35
- * `loadPrefix` is where THIS server was loaded from; `installPrefix` is what
36
- * `npm prefix -g` answered, and `npmPath` is which npm answered it — because a
37
- * prefix without the binary that reported it cannot be reproduced by anyone.
38
- */
39
- export function prefixVerdict(loadPrefix, installPrefix, npmPath) {
40
- const via = npmPath ? ` (asked: ${npmPath})` : "";
41
- // NOT DETERMINED IS NOT MATCHING. Both unknown branches are warnings that say
42
- // what could not be established, never an "ok" over an unasked question.
43
- // NOT APPLICABLE IS NOT THE SAME AS UNCHECKED, and conflating them is how a
44
- // check earns its way into being ignored. A dev checkout has no load prefix
45
- // BY CONSTRUCTION: this process is not the copy the fleet loads, so there is
46
- // no divergence for it to have. Warning on every dev run would fire on every
47
- // test run and every local session — noise, which is what a denylist does.
48
- //
49
- // The question is still ASKED where it can be answered: a session running
50
- // from a global install has a load prefix, and that is where the fleet lives.
51
- if (!loadPrefix)
52
- return { level: "ok", detail: `not applicable: this server runs from a dev checkout, not a global install${via}, so it is not the copy the fleet loads and has no prefix to diverge from. Run \`doctor\` in an installed session to compare install target against load target.` };
53
- if (!installPrefix)
54
- return { level: "warn", detail: `could not determine the global install prefix${via} — \`npm prefix -g\` gave no answer, so where a new copy would land is UNKNOWN. Running from ${loadPrefix}.` };
55
- if (path.resolve(loadPrefix) === path.resolve(installPrefix))
56
- return { level: "ok", detail: `a global install would land where this server loads from (${loadPrefix})${via}` };
57
- return {
58
- level: "error",
59
- detail: `INSTALL PREFIX AND LOAD PREFIX DIVERGE. A global install from this shell writes to ${installPrefix}${via}, but this server is running from ${loadPrefix}. ` +
60
- `A successful "added 1 package" would update a copy nothing loads, and every check that reads a VERSION would keep reporting the old one truthfully. ` +
61
- `Install with an explicit prefix (\`npm i -g --prefix ${loadPrefix} <pkg>\`) or switch node/nvm to the version owning ${loadPrefix} before installing.`,
62
- };
63
- }
64
- //# sourceMappingURL=prefix.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prefix.js","sourceRoot":"","sources":["../src/prefix.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,UAA8B;IACrD,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAC7B,6EAA6E;IAC7E,sEAAsE;IACtE,kCAAkC;IAClC,MAAM,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG,eAAe,IAAI,CAAC,GAAG,EAAE,CAAC;IAClE,MAAM,CAAC,GAAG,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAChC,CAAC;AAOD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,UAAyB,EAAE,aAA4B,EAAE,OAAgB;IACrG,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,YAAY,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAElD,8EAA8E;IAC9E,yEAAyE;IACzE,4EAA4E;IAC5E,4EAA4E;IAC5E,6EAA6E;IAC7E,6EAA6E;IAC7E,2EAA2E;IAC3E,EAAE;IACF,0EAA0E;IAC1E,8EAA8E;IAC9E,IAAI,CAAC,UAAU;QACb,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,6EAA6E,GAAG,kKAAkK,EAAE,CAAC;IACrR,IAAI,CAAC,aAAa;QAChB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,gDAAgD,GAAG,gGAAgG,UAAU,GAAG,EAAE,CAAC;IAErM,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;QAC1D,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,6DAA6D,UAAU,IAAI,GAAG,EAAE,EAAE,CAAC;IAEnH,OAAO;QACL,KAAK,EAAE,OAAO;QACd,MAAM,EACJ,sFAAsF,aAAa,GAAG,GAAG,qCAAqC,UAAU,IAAI;YAC5J,sJAAsJ;YACtJ,wDAAwD,UAAU,sDAAsD,UAAU,qBAAqB;KAC1J,CAAC;AACJ,CAAC"}
package/dist/roles.js DELETED
@@ -1,132 +0,0 @@
1
- // Canonical role identity, server side (Phase 8 Task 4).
2
- //
3
- // MIRROR of hooks/roles.mjs — tsconfig's rootDir is `src`, so this cannot
4
- // import the hook copy, and the hook copy must stay build-free (the pusher
5
- // loads it from a bare checkout). test/roles.test.mjs asserts the two agree;
6
- // change one, change the other.
7
- //
8
- // See hooks/roles.mjs for the rationale behind `explicit` and the word-match
9
- // fallback.
10
- import { z } from "zod";
11
- export function slugifyRole(role) {
12
- return String(role ?? "")
13
- .trim()
14
- .toLowerCase()
15
- .replace(/[^a-z0-9]+/g, "-")
16
- .replace(/^-+|-+$/g, "");
17
- }
18
- export const GATE_RUNNER_ROLE_IDS = new Set(["qa", "quality", "coordinator", "gate"]);
19
- export const COORDINATOR_ROLE_IDS = new Set(["coordinator"]);
20
- // CI receives express-lane DONE: wake. Not a gate-runner — must not grant verdict.
21
- export const CI_ROLE_IDS = new Set(["ci"]);
22
- // Console / watchers. May send prefixed messages. Not a gate-runner.
23
- export const AUTOMATION_ROLE_IDS = new Set(["automation"]);
24
- // A HUMAN READER. The one carve-out in the typed-record rule (Phase 5.1 Task
25
- // 12.3): canon already rules "David-facing messages may use normal prose", and
26
- // a blanket requirement would break the single channel whose reader is a
27
- // person. `david` is here as well as `human` because the registry entry that
28
- // exists on this bus today declares role "David" — the id derives to `david`,
29
- // and a rule that only recognised the canonical spelling would have refused
30
- // the exact traffic it is written to protect.
31
- export const HUMAN_ROLE_IDS = new Set(["human", "david"]);
32
- export function resolveRole(role) {
33
- if (role === null || role === undefined)
34
- return undefined;
35
- if (typeof role === "string") {
36
- const roleId = slugifyRole(role);
37
- return roleId ? { roleId, displayName: role, explicit: false } : undefined;
38
- }
39
- if (typeof role === "object") {
40
- const declared = typeof role.roleId === "string" ? slugifyRole(role.roleId) : "";
41
- const name = typeof role.displayName === "string" && role.displayName
42
- ? role.displayName
43
- : typeof role.role === "string" && role.role
44
- ? role.role
45
- : undefined;
46
- if (declared)
47
- return { roleId: declared, displayName: name ?? declared, explicit: true };
48
- if (name)
49
- return resolveRole(name);
50
- }
51
- return undefined;
52
- }
53
- export function roleMatches(role, allowedIds) {
54
- const resolved = resolveRole(role);
55
- if (!resolved)
56
- return false;
57
- if (allowedIds.has(resolved.roleId))
58
- return true;
59
- // Word-split applies to DECLARED ids too. It used to be derived-only ("frozen
60
- // ids match exactly"), which made precision cost authority: {roleId:"coord-qa"}
61
- // was refused `verdict` while the vaguer bare string "coord-qa" passed via the
62
- // split — a consumer fleet's QA verdicts were never machine-authorized (2026-08-21).
63
- // Freezing still governs identity (the id cannot change); it must never grant
64
- // LESS than the derived twin of the same spelling.
65
- return resolved.roleId.split("-").some((word) => allowedIds.has(word));
66
- }
67
- // The canonical role vocabulary — every authority set plus the classes the
68
- // cards register. Not an allowlist: any roleId may register; a non-canonical
69
- // one gets a warning naming this set so the next card uses the exact spelling.
70
- export const CANONICAL_ROLE_IDS = new Set([
71
- "coordinator",
72
- "worker",
73
- "aide",
74
- "qa",
75
- "quality",
76
- "gate",
77
- "ci",
78
- "audit",
79
- "automation",
80
- "human",
81
- ]);
82
- export function isGateRunner(role) {
83
- return roleMatches(role, GATE_RUNNER_ROLE_IDS);
84
- }
85
- export function isCoordinator(role) {
86
- return roleMatches(role, COORDINATOR_ROLE_IDS);
87
- }
88
- export function isCi(role) {
89
- return roleMatches(role, CI_ROLE_IDS);
90
- }
91
- export function isAutomation(role) {
92
- return roleMatches(role, AUTOMATION_ROLE_IDS);
93
- }
94
- export function isHuman(role) {
95
- return roleMatches(role, HUMAN_ROLE_IDS);
96
- }
97
- // Which roles may emit which record.type at the send path. Enforcement lives
98
- // in messaging.ts (checkRecordAuthority); the table lives here so register/join
99
- // can ECHO the consequence back at onboarding — a role that cannot emit `go`
100
- // should learn it when it registers, not when it sends its first work order.
101
- //
102
- // NOT A TRUST BOUNDARY — roles are self-declared. See checkRecordAuthority.
103
- export const RECORD_AUTHORITY = {
104
- verdict: { roles: GATE_RUNNER_ROLE_IDS, label: "gate-runner" },
105
- go: { roles: COORDINATOR_ROLE_IDS, label: "coordinator" },
106
- scope: { roles: COORDINATOR_ROLE_IDS, label: "coordinator" },
107
- };
108
- // Split the restricted record types into what this role may and may not emit.
109
- // Unrestricted types are omitted from both lists — they are nobody's business.
110
- export function recordAuthorityFor(role) {
111
- const mayEmit = [];
112
- const mayNotEmit = [];
113
- for (const [type, rule] of Object.entries(RECORD_AUTHORITY)) {
114
- (roleMatches(role, rule.roles) ? mayEmit : mayNotEmit).push(type);
115
- }
116
- return { mayEmit, mayNotEmit };
117
- }
118
- // Wire shape for `role` on register/join. Either free text (v1: `role: "qa
119
- // lead"`) or a declared identity (`{roleId: "qa", displayName: "QA gate"}`).
120
- // Both are supported forever — the string form is not deprecated, it just
121
- // leaves the id derived rather than frozen.
122
- //
123
- // Lives here rather than in tools/ because registry.ts and transport.ts import
124
- // each other; a schema in either would be a temporal-dead-zone hazard.
125
- export const roleInputSchema = z.union([
126
- z.string(),
127
- z.object({
128
- roleId: z.string().min(1).optional(),
129
- displayName: z.string().min(1).optional(),
130
- }),
131
- ]);
132
- //# sourceMappingURL=roles.js.map
package/dist/roles.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"roles.js","sourceRoot":"","sources":["../src/roles.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,EAAE;AACF,0EAA0E;AAC1E,2EAA2E;AAC3E,6EAA6E;AAC7E,gCAAgC;AAChC,EAAE;AACF,6EAA6E;AAC7E,YAAY;AAEZ,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAexB,MAAM,UAAU,WAAW,CAAC,IAAa;IACvC,OAAO,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;SACtB,IAAI,EAAE;SACN,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;AACtF,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;AAC7D,mFAAmF;AACnF,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,qEAAqE;AACrE,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;AAC3D,6EAA6E;AAC7E,+EAA+E;AAC/E,yEAAyE;AACzE,6EAA6E;AAC7E,8EAA8E;AAC9E,4EAA4E;AAC5E,8CAA8C;AAC9C,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAE1D,MAAM,UAAU,WAAW,CAAC,IAAe;IACzC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1D,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QACjC,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7E,CAAC;IACD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACjF,MAAM,IAAI,GACR,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ,IAAI,IAAI,CAAC,WAAW;YACtD,CAAC,CAAC,IAAI,CAAC,WAAW;YAClB,CAAC,CAAC,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI;gBAC1C,CAAC,CAAC,IAAI,CAAC,IAAI;gBACX,CAAC,CAAC,SAAS,CAAC;QAClB,IAAI,QAAQ;YAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,IAAI,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QACzF,IAAI,IAAI;YAAE,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAe,EAAE,UAAuB;IAClE,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5B,IAAI,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACjD,8EAA8E;IAC9E,gFAAgF;IAChF,+EAA+E;IAC/E,qFAAqF;IACrF,8EAA8E;IAC9E,mDAAmD;IACnD,OAAO,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,2EAA2E;AAC3E,6EAA6E;AAC7E,+EAA+E;AAC/E,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACxC,aAAa;IACb,QAAQ;IACR,MAAM;IACN,IAAI;IACJ,SAAS;IACT,MAAM;IACN,IAAI;IACJ,OAAO;IACP,YAAY;IACZ,OAAO;CACR,CAAC,CAAC;AAEH,MAAM,UAAU,YAAY,CAAC,IAAe;IAC1C,OAAO,WAAW,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAe;IAC3C,OAAO,WAAW,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAe;IAClC,OAAO,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAe;IAC1C,OAAO,WAAW,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,IAAe;IACrC,OAAO,WAAW,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;AAC3C,CAAC;AAED,6EAA6E;AAC7E,gFAAgF;AAChF,6EAA6E;AAC7E,6EAA6E;AAC7E,EAAE;AACF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAA0D;IACrF,OAAO,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,aAAa,EAAE;IAC9D,EAAE,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,aAAa,EAAE;IACzD,KAAK,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAE,aAAa,EAAE;CAC7D,CAAC;AAEF,8EAA8E;AAC9E,+EAA+E;AAC/E,MAAM,UAAU,kBAAkB,CAAC,IAAe;IAChD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC5D,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;AACjC,CAAC;AAED,2EAA2E;AAC3E,6EAA6E;AAC7E,0EAA0E;AAC1E,4CAA4C;AAC5C,EAAE;AACF,+EAA+E;AAC/E,uEAAuE;AACvE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC;IACrC,CAAC,CAAC,MAAM,EAAE;IACV,CAAC,CAAC,MAAM,CAAC;QACP,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;QACpC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;KAC1C,CAAC;CACH,CAAC,CAAC"}
@@ -1,82 +0,0 @@
1
- /*
2
- * WHICH SERVER PACKAGE IS RUNNING — a LEAF module, importing nothing from
3
- * `tools/`.
4
- *
5
- * It lived in `transport.ts`, and `capabilities.ts` imported it from there. The
6
- * moment `status` needs to REPORT capabilities, that becomes
7
- * transport -> capabilities -> transport: a cycle, and the same one Task 9
8
- * produced when the kind registry sat inside `record-events.ts`. That one only
9
- * worked because `tools/index.ts` happened to import in the surviving order —
10
- * a load-ORDER dependency, invisible until something imported a module
11
- * directly, which is what a consumer or a test does.
12
- *
13
- * A cycle that works by luck is not a working cycle, so the shared fact moves
14
- * out rather than the edge being added on top of it.
15
- *
16
- * NOTE WHAT THIS REPORTS AND WHAT IT DOES NOT. `version` is the label in the
17
- * package.json this process loaded from — CONTEXT for a reader, never evidence
18
- * of a capability. A published tarball has already been observed carrying a
19
- * change its version said it could not. Capability questions are answered by
20
- * `capabilities`, which CALLS the code.
21
- */
22
- import { existsSync, readFileSync } from "node:fs";
23
- import { spawnSync } from "node:child_process";
24
- import path from "node:path";
25
- import { fileURLToPath } from "node:url";
26
- import { isGitRepo } from "./tools/scopes.js";
27
- /** Running server package + optional git identity. `fromDir` is a test seam. */
28
- export function resolveServerIdentity(fromDir) {
29
- const start = fromDir ?? path.dirname(fileURLToPath(import.meta.url));
30
- let dir = start;
31
- let pkgFile;
32
- for (let i = 0; i < 8; i++) {
33
- const candidate = path.join(dir, "package.json");
34
- if (existsSync(candidate)) {
35
- pkgFile = candidate;
36
- break;
37
- }
38
- const parent = path.dirname(dir);
39
- if (parent === dir)
40
- break;
41
- dir = parent;
42
- }
43
- const pkgPath = pkgFile ?? path.resolve(start, "..", "..", "package.json");
44
- const pkgDir = path.dirname(pkgPath);
45
- let version = "unknown";
46
- try {
47
- const raw = JSON.parse(readFileSync(pkgPath, "utf8"));
48
- if (typeof raw.version === "string" && raw.version)
49
- version = raw.version;
50
- }
51
- catch {
52
- /* leave unknown — never invent a version */
53
- }
54
- const out = {
55
- path: pkgDir,
56
- version,
57
- };
58
- dir = pkgDir;
59
- let gitRoot;
60
- for (let i = 0; i < 10; i++) {
61
- if (existsSync(path.join(dir, ".git"))) {
62
- gitRoot = dir;
63
- break;
64
- }
65
- const parent = path.dirname(dir);
66
- if (parent === dir)
67
- break;
68
- dir = parent;
69
- }
70
- if (gitRoot && isGitRepo(gitRoot)) {
71
- const branch = spawnSync("git", ["-C", gitRoot, "rev-parse", "--abbrev-ref", "HEAD"], { encoding: "utf8" });
72
- const sha = spawnSync("git", ["-C", gitRoot, "rev-parse", "HEAD"], { encoding: "utf8" });
73
- const b = branch.status === 0 ? String(branch.stdout).trim() : "";
74
- const s = sha.status === 0 ? String(sha.stdout).trim() : "";
75
- if (b)
76
- out.branch = b;
77
- if (s)
78
- out.sha = s;
79
- }
80
- return out;
81
- }
82
- //# sourceMappingURL=server-identity.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server-identity.js","sourceRoot":"","sources":["../src/server-identity.ts"],"names":[],"mappings":"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"}