agent-coord-mcp 0.26.21 → 0.26.22
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.
- package/dist/capabilities.js +250 -2
- package/dist/capabilities.js.map +1 -1
- package/dist/closing-line.js +83 -0
- package/dist/closing-line.js.map +1 -0
- package/dist/commit-cite.js +55 -0
- package/dist/commit-cite.js.map +1 -0
- package/dist/gated-head.js +67 -20
- package/dist/gated-head.js.map +1 -1
- package/dist/server-spread.js +195 -0
- package/dist/server-spread.js.map +1 -0
- package/dist/server.js +2 -2
- package/dist/server.js.map +1 -1
- package/dist/store.js +32 -0
- package/dist/store.js.map +1 -1
- package/dist/tools/away.js +67 -7
- package/dist/tools/away.js.map +1 -1
- package/dist/tools/board-ref.js +44 -4
- package/dist/tools/board-ref.js.map +1 -1
- package/dist/tools/event-kinds.js +5 -1
- package/dist/tools/event-kinds.js.map +1 -1
- package/dist/tools/events.js +31 -2
- package/dist/tools/events.js.map +1 -1
- package/dist/tools/messaging.js +64 -6
- package/dist/tools/messaging.js.map +1 -1
- package/dist/tools/record-events.js +85 -5
- package/dist/tools/record-events.js.map +1 -1
- package/dist/tools/records.js +231 -38
- package/dist/tools/records.js.map +1 -1
- package/dist/tools/registry.js +52 -2
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/seat-build.js +173 -0
- package/dist/tools/seat-build.js.map +1 -0
- package/dist/tools/shared.js.map +1 -1
- package/dist/tools/stall.js +1095 -18
- package/dist/tools/stall.js.map +1 -1
- package/dist/tools/transport.js +21 -2
- package/dist/tools/transport.js.map +1 -1
- package/dist/tools/worktrees.js +14 -0
- package/dist/tools/worktrees.js.map +1 -1
- package/package.json +1 -1
- package/scripts/coord-attention-clock.mjs +2 -0
- package/scripts/coord-stall-clock.mjs +52 -11
- package/src/capabilities.ts +264 -2
- package/src/closing-line.ts +85 -0
- package/src/commit-cite.ts +58 -0
- package/src/gated-head.ts +128 -26
- package/src/server-spread.ts +233 -0
- package/src/server.ts +2 -2
- package/src/store.ts +32 -0
- package/src/tools/away.ts +82 -9
- package/src/tools/board-ref.ts +70 -3
- package/src/tools/event-kinds.ts +17 -1
- package/src/tools/events.ts +33 -2
- package/src/tools/messaging.ts +63 -6
- package/src/tools/record-events.ts +78 -5
- package/src/tools/records.ts +248 -38
- package/src/tools/registry.ts +54 -3
- package/src/tools/seat-build.ts +194 -0
- package/src/tools/shared.ts +22 -0
- package/src/tools/stall.ts +1266 -23
- package/src/tools/transport.ts +21 -2
- package/src/tools/worktrees.ts +13 -0
package/dist/tools/away.js
CHANGED
|
@@ -71,6 +71,34 @@ export const PARKED_CATEGORIES = [
|
|
|
71
71
|
"anything altering scope or authority",
|
|
72
72
|
"destructive machine actions",
|
|
73
73
|
];
|
|
74
|
+
/*
|
|
75
|
+
* ⟨q-5a71fc3b⟩ — THE THRESHOLD, NAMED. `coord_away` armed a fleet that was 3/5
|
|
76
|
+
* blind, silently: the refusal only fired at ZERO measurable lanes, so "2 of
|
|
77
|
+
* 5" — three seats the clock could not see — read as covered enough. A
|
|
78
|
+
* partially blind fleet IS the incident, not a lesser case of it: the seats
|
|
79
|
+
* nobody can see are exactly the ones an absence leaves unattended. So the
|
|
80
|
+
* threshold is every in-flight lane the clock scores, the refusal names the
|
|
81
|
+
* seats short of it, and `acknowledgeBlindFleet` is the only way past.
|
|
82
|
+
*/
|
|
83
|
+
export const COVERAGE_THRESHOLD = "EVERY in-flight lane the clock scores must be measurable";
|
|
84
|
+
/*
|
|
85
|
+
* ⟨q-ce585029⟩ — A QUERY REPORTS THE COVERAGE MEASURED AT ARM TIME, AND SAYS
|
|
86
|
+
* SO. "Coverage 2/5" read on 09-11 was three days old by the time it was
|
|
87
|
+
* quoted as current. The query stays free (no re-measure); the summary
|
|
88
|
+
* carries the reading's age and labels it stale past this many minutes.
|
|
89
|
+
*/
|
|
90
|
+
export const COVERAGE_STALE_MINUTES = 60;
|
|
91
|
+
export const fmtAge = (ms) => (ms < 60_000 ? `${Math.max(0, Math.round(ms / 1000))}s` : ms < 3_600_000 ? `${Math.floor(ms / 60_000)}m` : ms < 86_400_000 ? `${Math.floor(ms / 3_600_000)}h` : `${Math.floor(ms / 86_400_000)}d`);
|
|
92
|
+
export function coverageAgeOf(coverage, now = Date.now()) {
|
|
93
|
+
const at = Date.parse(coverage.at);
|
|
94
|
+
if (!Number.isFinite(at))
|
|
95
|
+
return { ageMs: null, stale: true, label: "measured at an unreadable time — treat as stale" };
|
|
96
|
+
const ageMs = Math.max(0, now - at);
|
|
97
|
+
const stale = ageMs > COVERAGE_STALE_MINUTES * 60_000;
|
|
98
|
+
return { ageMs, stale, label: `measured ${fmtAge(ageMs)} ago${stale ? ` — STALE (older than ${COVERAGE_STALE_MINUTES}m; re-arm or run stall_check for a current reading)` : ""}` };
|
|
99
|
+
}
|
|
100
|
+
/** Met when nothing scored is unseen — an empty board (0 of 0) is idle, not blind, and needs no special case. */
|
|
101
|
+
export const meetsCoverageThreshold = (c) => c.measurable >= c.checked;
|
|
74
102
|
export function readAway() {
|
|
75
103
|
const f = awayFile();
|
|
76
104
|
if (!existsSync(f))
|
|
@@ -153,9 +181,26 @@ async function measureCoverage(repo) {
|
|
|
153
181
|
return null;
|
|
154
182
|
try {
|
|
155
183
|
const r = (await stallCheckTool({ repo }));
|
|
184
|
+
// ⟨q-3d82f1a9⟩ — AN UNREADABLE BOARD IS A NAMED STATE, not "could not measure".
|
|
185
|
+
// The clock refused to answer because the board broke; arming on it would
|
|
186
|
+
// promise a watched fleet over a table nobody can read.
|
|
187
|
+
if (r?.boardParse && !r.boardParse.readable) {
|
|
188
|
+
return {
|
|
189
|
+
checked: 0, measurable: 0, blind: [], roles: 0, deliberate: 0,
|
|
190
|
+
unreadable: { rowsPresent: r.boardParse.rowsPresent, rowsParsed: r.boardParse.rowsParsed, why: r.boardParse.why },
|
|
191
|
+
at: new Date().toISOString(),
|
|
192
|
+
};
|
|
193
|
+
}
|
|
156
194
|
if (!r?.ok)
|
|
157
195
|
return null;
|
|
158
|
-
return {
|
|
196
|
+
return {
|
|
197
|
+
checked: r.checked ?? 0,
|
|
198
|
+
measurable: r.measurable ?? 0,
|
|
199
|
+
blind: r.blind ?? [],
|
|
200
|
+
roles: r.roles?.length ?? 0,
|
|
201
|
+
deliberate: r.deliberate?.length ?? 0,
|
|
202
|
+
at: new Date().toISOString(),
|
|
203
|
+
};
|
|
159
204
|
}
|
|
160
205
|
catch {
|
|
161
206
|
return null;
|
|
@@ -187,9 +232,11 @@ export async function coordAwayTool(args) {
|
|
|
187
232
|
project: args.project,
|
|
188
233
|
armed: true,
|
|
189
234
|
state: prior,
|
|
235
|
+
coverageAge: coverageAgeOf(prior.coverage),
|
|
190
236
|
summary: `'${args.project}' is ARMED — '${prior.leadId}' leads since ${prior.at}` +
|
|
191
237
|
`${prior.until ? ` until ${prior.until}` : ""}. ` +
|
|
192
|
-
`Coverage ${prior.coverage.measurable}/${prior.coverage.checked}` +
|
|
238
|
+
`Coverage ${prior.coverage.measurable}/${prior.coverage.checked} lane(s) ${coverageAgeOf(prior.coverage).label}` +
|
|
239
|
+
`${prior.coverage.roles ? ` · ${prior.coverage.roles} role(s) present, not scored` : ""}` +
|
|
193
240
|
`${prior.blindAcknowledged ? " (ACKNOWLEDGED BLIND)" : ""}. ` +
|
|
194
241
|
`Decisions logged to ${prior.decisionLog}.`,
|
|
195
242
|
};
|
|
@@ -222,16 +269,29 @@ export async function coordAwayTool(args) {
|
|
|
222
269
|
`record that the promise is being made anyway.`,
|
|
223
270
|
};
|
|
224
271
|
}
|
|
272
|
+
// ⟨q-3d82f1a9⟩ — REFUSED OUTRIGHT, and not acknowledgeable: a blind fleet is
|
|
273
|
+
// one the clock can see and cannot measure; an unreadable board is one the
|
|
274
|
+
// clock cannot even see. "0 of 0" here is not idle, and no flag makes it so.
|
|
275
|
+
if (coverage.unreadable) {
|
|
276
|
+
return {
|
|
277
|
+
ok: false,
|
|
278
|
+
error: `REFUSING: docs/WORKSTREAMS.md is UNREADABLE — ${coverage.unreadable.rowsPresent} row(s) present in the Active Streams table, ` +
|
|
279
|
+
`${coverage.unreadable.rowsParsed} parsed. ${coverage.unreadable.why} ` +
|
|
280
|
+
`Away mode promises a watched fleet; a board the clock cannot read is not a quiet fleet, it is an unwatched one. Fix the row and re-arm.`,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
225
283
|
// `checked > 0` MATTERS: an empty board is an IDLE fleet, not a blind one.
|
|
226
284
|
// Without it, arming while nothing is in flight refuses with "the clock
|
|
227
285
|
// covers 0 of 0" — a refusal that reads as a fleet nobody can see when in
|
|
228
286
|
// fact there is nothing to see, and the only way past it would be to
|
|
229
287
|
// acknowledge a blindness that does not exist.
|
|
230
|
-
|
|
288
|
+
// ⟨q-5a71fc3b⟩ — below the threshold, not only at zero: "2 of 5" refuses.
|
|
289
|
+
if (!meetsCoverageThreshold(coverage) && !args.acknowledgeBlindFleet) {
|
|
231
290
|
return {
|
|
232
291
|
ok: false,
|
|
233
|
-
error: `REFUSING: the stall clock covers ${coverage.measurable} of ${coverage.checked} in-flight row(s)
|
|
234
|
-
`
|
|
292
|
+
error: `REFUSING: the stall clock covers ${coverage.measurable} of ${coverage.checked} in-flight row(s); the threshold is that ${COVERAGE_THRESHOLD} ` +
|
|
293
|
+
`(${coverage.checked - coverage.measurable} short)${coverage.blind.length ? ` — blind on: ${coverage.blind.join(", ")}` : ""}. ` +
|
|
294
|
+
`${coverage.measurable === 0 ? "It would RUN and see nothing. " : "The seats it cannot see are exactly the ones an absence leaves unattended. "}` +
|
|
235
295
|
`"The clock ran" and "the fleet is observed" are different facts, and this verb must not treat the first as the second. ` +
|
|
236
296
|
`The usual cause is a board 'Branch · Worktree' cell holding a PATH rather than a branch ref: a path resolves for ` +
|
|
237
297
|
`git and measures the wrong thing, so the check reports it unmeasurable rather than guessing. Fix those cells and ` +
|
|
@@ -247,7 +307,7 @@ export async function coordAwayTool(args) {
|
|
|
247
307
|
at: new Date().toISOString(),
|
|
248
308
|
decisionLog: args.decisionLog,
|
|
249
309
|
coverage,
|
|
250
|
-
...(coverage
|
|
310
|
+
...(!meetsCoverageThreshold(coverage) ? { blindAcknowledged: true } : {}),
|
|
251
311
|
};
|
|
252
312
|
writeAway(state);
|
|
253
313
|
return {
|
|
@@ -263,7 +323,7 @@ export async function coordAwayTool(args) {
|
|
|
263
323
|
`Decides: planning · priority · curation · roadmap · canon · releases under standing authorisation. ` +
|
|
264
324
|
`Never: merges, gates, or takes a code lane. Parks for David: ${PARKED_CATEGORIES.join(" · ")}. ` +
|
|
265
325
|
`Decisions logged to ${args.decisionLog}. ` +
|
|
266
|
-
`Stall coverage ${coverage.measurable}/${coverage.checked}${coverage
|
|
326
|
+
`Stall coverage ${coverage.measurable}/${coverage.checked}${!meetsCoverageThreshold(coverage) ? ` — ACKNOWLEDGED BLIND${coverage.measurable === 0 ? ": the clock runs and sees nothing" : ""}${coverage.blind.length ? ` on: ${coverage.blind.join(", ")}` : ""}` : ""}.`,
|
|
267
327
|
};
|
|
268
328
|
}
|
|
269
329
|
if (!prior?.on)
|
package/dist/tools/away.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"away.js","sourceRoot":"","sources":["../../src/tools/away.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;AAE1D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,YAAY,GAA2B;IAClD,KAAK,EAAE,iKAAiK;IACxK,IAAI,EAAE,0IAA0I;CACjJ,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,SAAS;IACT,SAAS;IACT,mBAAmB;IACnB,aAAa;IACb,sCAAsC;IACtC,6BAA6B;CACrB,CAAC;
|
|
1
|
+
{"version":3,"file":"away.js","sourceRoot":"","sources":["../../src/tools/away.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/board-ref.js
CHANGED
|
@@ -73,9 +73,36 @@ const isSyntacticallyValidRef = (name) => {
|
|
|
73
73
|
return false;
|
|
74
74
|
}
|
|
75
75
|
};
|
|
76
|
-
|
|
76
|
+
export function cellKindOf(cell) {
|
|
77
|
+
const s = String(cell ?? "").trim();
|
|
78
|
+
if (!s || s === "—" || s === "-" || s === "–")
|
|
79
|
+
return "empty";
|
|
80
|
+
return /^`[^`]+`/.test(s) ? "ref" : "prose";
|
|
81
|
+
}
|
|
82
|
+
/** The `\`ref\`` in a `Branch · Worktree` cell's REF POSITION (leading token), or "". */
|
|
77
83
|
export function refInCell(cell) {
|
|
78
|
-
return (String(cell ?? "").match(
|
|
84
|
+
return (String(cell ?? "").trim().match(/^`([^`]+)`/)?.[1] ?? "").trim();
|
|
85
|
+
}
|
|
86
|
+
/** A display elision a human typed into a machine-read field. */
|
|
87
|
+
const ELIDED = /…|\.\.\./;
|
|
88
|
+
/*
|
|
89
|
+
* ⟨q-5d1c8e04⟩ — LANES vs ROLES. A ROLE row is a standing seat (coordinator,
|
|
90
|
+
* aide) with nothing to score: no branch, no slice, no stall. It is written with
|
|
91
|
+
* its own status glyph and a `—` branch cell, in the same table. The glyph is
|
|
92
|
+
* a bus-level ROW KIND, not a work state: the seam's `workStateOf` reads it as
|
|
93
|
+
* `unknown`, which is correct — a role is not work, and the seam is not asked
|
|
94
|
+
* to invent a state for it.
|
|
95
|
+
*
|
|
96
|
+
* ⚠ A 🪑 ROW THAT CARRIES A REF IS A LANE IN DISGUISE and is scored as one —
|
|
97
|
+
* relabelling work as a role must not exempt it from the clock.
|
|
98
|
+
*/
|
|
99
|
+
export const ROLE_GLYPH = "🪑";
|
|
100
|
+
const STATUS_DECORATION = /^[\s*⭐]+/u;
|
|
101
|
+
export const isRoleStatus = (status) => String(status ?? "").replace(STATUS_DECORATION, "").startsWith(ROLE_GLYPH);
|
|
102
|
+
export function rowKindOf(row) {
|
|
103
|
+
if (!isRoleStatus(row.status))
|
|
104
|
+
return "lane";
|
|
105
|
+
return cellKindOf(row.branchWorktree) === "ref" ? "role-with-ref" : "role";
|
|
79
106
|
}
|
|
80
107
|
/** The remote-tracking form a board cell should name for `branch`. */
|
|
81
108
|
export const boardRefFor = (branch) => (branch.startsWith("origin/") ? branch : `origin/${branch}`);
|
|
@@ -88,8 +115,21 @@ export const boardRefFor = (branch) => (branch.startsWith("origin/") ? branch :
|
|
|
88
115
|
*/
|
|
89
116
|
export function classifyBoardRef(repo, agentId, cell, base = "origin/main") {
|
|
90
117
|
const raw = refInCell(cell);
|
|
91
|
-
if (!raw)
|
|
92
|
-
|
|
118
|
+
if (!raw) {
|
|
119
|
+
// Words in the ref position are a DECLARATION, not an absence: the row
|
|
120
|
+
// says it has no per-agent branch. Only a blank or `—` is "nothing said".
|
|
121
|
+
if (cellKindOf(cell) === "prose") {
|
|
122
|
+
return { kind: "none", why: `the Branch · Worktree cell declares in words that this row carries no per-agent branch: "${String(cell).trim().slice(0, 60)}"` };
|
|
123
|
+
}
|
|
124
|
+
return { kind: "empty", why: "no ref in the Branch · Worktree cell, and nothing declared in its place" };
|
|
125
|
+
}
|
|
126
|
+
if (ELIDED.test(raw)) {
|
|
127
|
+
return {
|
|
128
|
+
kind: "elided",
|
|
129
|
+
why: `'${raw}' is a ref a human abbreviated for display — it contains an elision and cannot be looked up as written. ` +
|
|
130
|
+
`Unreadable by construction, not "unpushed": the real ref may well exist. Write the full ref in the cell; the note can carry the shape.`,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
93
133
|
const bare = raw.replace(/^origin\//, "");
|
|
94
134
|
// Task 5.3/22.1: CHECKED FIRST AND UNCONDITIONALLY — the original defect
|
|
95
135
|
// (`docs/*`) was previously only caught in a repo with NO origin remote at
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"board-ref.js","sourceRoot":"","sources":["../../src/tools/board-ref.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"board-ref.js","sourceRoot":"","sources":["../../src/tools/board-ref.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,23 +16,27 @@
|
|
|
16
16
|
export const EVENT_KINDS = {
|
|
17
17
|
item: {
|
|
18
18
|
record: "docs/QUEUE.md + docs/DONE.md",
|
|
19
|
-
what: "a queue item closed —
|
|
19
|
+
what: "a queue item closed — a DONE.md entry beginning with its ⟨q-…⟩ id appeared (land writes it), or it left QUEUE.md against one unambiguous entry",
|
|
20
20
|
targetIs: "the queue item id",
|
|
21
|
+
probe: { diff: "diff --git a/docs/QUEUE.md b/docs/QUEUE.md\n--- a/docs/QUEUE.md\n+++ b/docs/QUEUE.md\n@@ -1,1 +1,1 @@\n-- [ ] (P1) ⟨q-0a0a0a01⟩ Kit: the first thing to do\n-- [ ] (P1) ⟨q-0a0a0a02⟩ Kit: the second thing to do\n\ndiff --git a/docs/DONE.md b/docs/DONE.md\n--- a/docs/DONE.md\n+++ b/docs/DONE.md\n@@ -1,1 +1,1 @@\n+- [x] ⟨q-0a0a0a01⟩ Kit: what was done for the first… — owner/repo#77 · 2026-09-14\n+- [x] ⟨q-0a0a0a02⟩ Kit: what was done for the second… — owner/repo#77 · 2026-09-14\n" },
|
|
21
22
|
},
|
|
22
23
|
pr: {
|
|
23
24
|
record: "docs/DONE.md",
|
|
24
25
|
what: "a PR recorded in the completion log",
|
|
25
26
|
targetIs: "the PR ref, e.g. owner/repo#163",
|
|
27
|
+
probe: { diff: "diff --git a/docs/DONE.md b/docs/DONE.md\n--- a/docs/DONE.md\n+++ b/docs/DONE.md\n@@ -1,1 +1,1 @@\n+- [x] a PR recorded in the completion log — owner/repo#78 · 2026-09-14\n" },
|
|
26
28
|
},
|
|
27
29
|
task: {
|
|
28
30
|
record: "docs/phases/**/PHASE*_TASKS.md",
|
|
29
31
|
what: "a phase task checkbox newly ticked",
|
|
30
32
|
targetIs: "the task key, e.g. 5:12.1",
|
|
33
|
+
probe: { diff: "diff --git a/docs/phases/phase9/PHASE9_TASKS.md b/docs/phases/phase9/PHASE9_TASKS.md\n--- a/docs/phases/phase9/PHASE9_TASKS.md\n+++ b/docs/phases/phase9/PHASE9_TASKS.md\n@@ -1,1 +1,1 @@\n-- [ ] 1.1 first\n+- [x] 1.1 first\n" },
|
|
31
34
|
},
|
|
32
35
|
phase: {
|
|
33
36
|
record: "docs/phases/**/PHASE*_TASKS.md",
|
|
34
37
|
what: "the last open checkbox in a phase document ticked",
|
|
35
38
|
targetIs: "the phase number, e.g. 5",
|
|
39
|
+
probe: { diff: "diff --git a/docs/phases/phase9/PHASE9_TASKS.md b/docs/phases/phase9/PHASE9_TASKS.md\n--- a/docs/phases/phase9/PHASE9_TASKS.md\n+++ b/docs/phases/phase9/PHASE9_TASKS.md\n@@ -1,1 +1,1 @@\n-- [ ] 1.2 second\n+- [x] 1.2 second\n", after: { phases: { "docs/phases/phase9/PHASE9_TASKS.md": "# Phase 9\n\n- [x] 1.1 first\n- [x] 1.2 second\n" } } },
|
|
36
40
|
},
|
|
37
41
|
};
|
|
38
42
|
export const EVENT_KIND_IDS = Object.keys(EVENT_KINDS);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-kinds.js","sourceRoot":"","sources":["../../src/tools/event-kinds.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"event-kinds.js","sourceRoot":"","sources":["../../src/tools/event-kinds.ts"],"names":[],"mappings":"AAiCA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,IAAI,EAAE;QACJ,MAAM,EAAE,8BAA8B;QACtC,IAAI,EAAE,gJAAgJ;QACtJ,QAAQ,EAAE,mBAAmB;QAC7B,KAAK,EAAE,EAAE,IAAI,EAAE,keAAke,EAAe;KACjgB;IACD,EAAE,EAAE;QACF,MAAM,EAAE,cAAc;QACtB,IAAI,EAAE,qCAAqC;QAC3C,QAAQ,EAAE,iCAAiC;QAC3C,KAAK,EAAE,EAAE,IAAI,EAAE,8KAA8K,EAAe;KAC7M;IACD,IAAI,EAAE;QACJ,MAAM,EAAE,gCAAgC;QACxC,IAAI,EAAE,oCAAoC;QAC1C,QAAQ,EAAE,2BAA2B;QACrC,KAAK,EAAE,EAAE,IAAI,EAAE,iOAAiO,EAAe;KAChQ;IACD,KAAK,EAAE;QACL,MAAM,EAAE,gCAAgC;QACxC,IAAI,EAAE,mDAAmD;QACzD,QAAQ,EAAE,0BAA0B;QACpC,KAAK,EAAE,EAAE,IAAI,EAAE,mOAAmO,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,oCAAoC,EAAE,kDAAkD,EAAE,EAAE,EAAe;KACnX;CACO,CAAC;AAEX,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAA4B,CAAC"}
|
package/dist/tools/events.js
CHANGED
|
@@ -44,8 +44,31 @@ function writeSubs(subs) {
|
|
|
44
44
|
* subscription with no last-evaluated mark has produced no evidence of
|
|
45
45
|
* anything, and "no events" is the same output a broken subscription gives.
|
|
46
46
|
*/
|
|
47
|
+
/**
|
|
48
|
+
* ⟨q-2b7d9f04⟩ — CAPABILITY, NOT LIVENESS. The `item` subscription read
|
|
49
|
+
* `health: ok — no events yet` for three days while the scanner's grammar
|
|
50
|
+
* could not produce its kind from any commit: the scan clock was fresh, the
|
|
51
|
+
* emitter list had an entry, and the field answered the easier question. The
|
|
52
|
+
* probe is registered by record-events.ts (which owns the grammar) and asks
|
|
53
|
+
* "can this kind be produced at all?"; a kind that cannot is an ERROR, however
|
|
54
|
+
* recently the scanner ran. Absent probe → no claim either way.
|
|
55
|
+
*/
|
|
56
|
+
let capabilityProbe = null;
|
|
57
|
+
export function setCapabilityProbe(fn) {
|
|
58
|
+
capabilityProbe = fn;
|
|
59
|
+
}
|
|
60
|
+
export const kindCanFire = (kind) => (capabilityProbe ? capabilityProbe(kind) : null);
|
|
47
61
|
export function subscriptionHealth(s) {
|
|
48
62
|
const iso = (n) => new Date(n).toISOString();
|
|
63
|
+
// ⟨q-2b7d9f04⟩ — a kind the grammar cannot produce is not ok, scanned or not.
|
|
64
|
+
if (kindCanFire(s.kind) === false) {
|
|
65
|
+
return {
|
|
66
|
+
level: "error",
|
|
67
|
+
detail: `CANNOT FIRE — the scanner's grammar produces no '${s.kind}' event from the kind's own probe, so this subscription is structurally unable to deliver ` +
|
|
68
|
+
`${s.lastScannedAt ? `(scanned ${iso(s.lastScannedAt)}: the clock is live, the capability is not)` : "(and has never been scanned)"}. ` +
|
|
69
|
+
"Never fired and cannot fire are different facts; this is the second.",
|
|
70
|
+
};
|
|
71
|
+
}
|
|
49
72
|
// THREE STATES, BECAUSE THERE ARE THREE FACTS. They were two, and the
|
|
50
73
|
// collapse cost a week: an `item` subscriber read `error — never evaluated`
|
|
51
74
|
// the whole time, because `evaluate()` only touches subscriptions whose kind
|
|
@@ -209,10 +232,16 @@ export async function listSubscriptionsTool(args) {
|
|
|
209
232
|
const all = readSubs();
|
|
210
233
|
const subs = args.agentId ? all.filter((s) => s.agentId === args.agentId) : all;
|
|
211
234
|
const rows = subs.map((s) => ({ ...s, health: subscriptionHealth(s) }));
|
|
212
|
-
const
|
|
235
|
+
const cannotFire = rows.filter((r) => r.health.level === "error" && /^CANNOT FIRE/.test(r.health.detail));
|
|
236
|
+
const neverEvaluated = rows.filter((r) => r.health.level === "error" && !/^CANNOT FIRE/.test(r.health.detail));
|
|
213
237
|
const undetermined = rows.filter((r) => r.health.level === "unknown");
|
|
214
238
|
return {
|
|
215
|
-
ok: neverEvaluated.length === 0,
|
|
239
|
+
ok: neverEvaluated.length === 0 && cannotFire.length === 0,
|
|
240
|
+
// ⟨q-2b7d9f04⟩ — capability per kind, beside each row's liveness.
|
|
241
|
+
capability: Object.fromEntries(EVENT_KIND_IDS.map((k) => [k, kindCanFire(k)])),
|
|
242
|
+
...(cannotFire.length
|
|
243
|
+
? { cannotFire: `${cannotFire.length} of ${rows.length} subscription(s) are to a kind the scanner CANNOT PRODUCE — they will never fire, however live the scan clock reads: ${[...new Set(cannotFire.map((r) => r.kind))].join(", ")}.` }
|
|
244
|
+
: {}),
|
|
216
245
|
// Population beside the verdict, always: "no subscriptions" and "none
|
|
217
246
|
// listed for you" are different claims.
|
|
218
247
|
population: { listed: rows.length, total: all.length },
|
package/dist/tools/events.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/tools/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAkC,MAAM,kBAAkB,CAAC;AAE/F,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;AAE7D,+EAA+E;AAC/E,8EAA8E;AAC9E,+EAA+E;AAC/E,yDAAyD;AACzD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;AAiCvC,MAAM,UAAU,QAAQ;IACtB,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,IAAI,EAAE,CAAmB,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAAoB;IACrC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,aAAa,CAAC,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACrF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,CAAe;IAChD,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/tools/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAkC,MAAM,kBAAkB,CAAC;AAE/F,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;AAE7D,+EAA+E;AAC/E,8EAA8E;AAC9E,+EAA+E;AAC/E,yDAAyD;AACzD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;AAiCvC,MAAM,UAAU,QAAQ;IACtB,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,IAAI,EAAE,CAAmB,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAAoB;IACrC,SAAS,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,aAAa,CAAC,QAAQ,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACrF,CAAC;AAED;;;;;;;;GAQG;AACH;;;;;;;;GAQG;AACH,IAAI,eAAe,GAAwC,IAAI,CAAC;AAChE,MAAM,UAAU,kBAAkB,CAAC,EAAuC;IACxE,eAAe,GAAG,EAAE,CAAC;AACvB,CAAC;AACD,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAa,EAAkB,EAAE,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAE/G,MAAM,UAAU,kBAAkB,CAAC,CAAe;IAChD,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACrD,8EAA8E;IAC9E,IAAI,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC;QAClC,OAAO;YACL,KAAK,EAAE,OAAO;YACd,MAAM,EACJ,oDAAoD,CAAC,CAAC,IAAI,4FAA4F;gBACtJ,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,6CAA6C,CAAC,CAAC,CAAC,8BAA8B,IAAI;gBACvI,sEAAsE;SACzE,CAAC;IACJ,CAAC;IAED,sEAAsE;IACtE,4EAA4E;IAC5E,6EAA6E;IAC7E,4EAA4E;IAC5E,8EAA8E;IAC9E,EAAE;IACF,4DAA4D;IAC5D,yEAAyE;IACzE,yDAAyD;IACzD,IAAI,CAAC,CAAC,aAAa,KAAK,SAAS,IAAI,CAAC,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;QAChE,4EAA4E;QAC5E,0EAA0E;QAC1E,0EAA0E;QAC1E,yBAAyB;QACzB,OAAO;YACL,KAAK,EAAE,SAAS;YAChB,MAAM,EACJ,oIAAoI;gBACpI,sHAAsH;SACzH,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACrB,OAAO;YACL,KAAK,EAAE,OAAO;YACd,MAAM,EACJ,gIAAgI;gBAChI,sCAAsC;SACzC,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;QAC/B,0EAA0E;QAC1E,qDAAqD;QACrD,OAAO;YACL,KAAK,EAAE,IAAI;YACX,MAAM,EACJ,WAAW,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,iDAAiD,CAAC,CAAC,IAAI,4BAA4B;gBAClH,oGAAoG;SACvG,CAAC;IACJ,CAAC;IACD,OAAO;QACL,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,CAAC,CAAC,WAAW;YACnB,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,oBAAoB,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE;YAC/G,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,oBAAoB,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,iBAAiB;KAC/F,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAa,EAAE,MAAc,EAAE,GAAW,EAAU,EAAE,CAC7E,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAErF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc,CAAC,UAAkB,EAAE,EAAe;IAChE,IAAI,CAAC,EAAE,CAAC,GAAG;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,MAAM,qDAAqD,EAAE,CAAC;IACjI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC;QACtC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EACH,oBAAoB,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,MAAM,aAAa,EAAE,CAAC,GAAG,yBAAyB;gBACpF,8FAA8F;gBAC9F,uEAAuE;SAC1E,CAAC;IACJ,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAoB,EAAE,EAAe,EAAkB,EAAE,CAChF,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC;AAInE;;;;;;GAMG;AACH;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,IAAoB,EAAE,GAAW;IAC3D,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAoB,EAAE,EAAe,EAAE,GAAW;IACzE,MAAM,GAAG,GAAG,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,UAAU,GAAe,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC1B,4DAA4D;QAC5D,MAAM,OAAO,GAAG,EAAE,GAAG,CAAC,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC;QAC7C,IAAI,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC,IAAI;YAAE,OAAO,OAAO,CAAC;QACvC,MAAM,SAAS,GAAG,EAAE,GAAG,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC;QACvD,IAAI,CAAC,CAAC,MAAM,KAAK,EAAE,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QAC7C,IAAI,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9B,UAAU,CAAC,IAAI,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC,CAAC;YACnG,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;QACxF,OAAO,EAAE,GAAG,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IAC1F,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;AACpC,CAAC;AAED,kFAAkF;AAElF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC1B,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAwD;IAC1F,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9G,IAAI,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,IAAa,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,mFAAmF,EAAE,CAAC;IACtJ,MAAM,GAAG,GAAiB;QACxB,EAAE,EAAE,UAAU,EAAE;QAChB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,0EAA0E;QAC1E,sEAAsE;QACtE,4EAA4E;QAC5E,2EAA2E;QAC3E,cAAc;QACd,aAAa,EAAE,IAAI;QACnB,eAAe,EAAE,IAAI;QACrB,WAAW,EAAE,IAAI;QACjB,SAAS,EAAE,EAAE;KACd,CAAC;IACF,SAAS,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;IAC1B,OAAO,EAAE,EAAE,EAAE,IAAa,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;AACnF,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;AAEvF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAqC;IACzE,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;IACxB,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/C,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,EAAE,EAAE,KAAc,EAAE,KAAK,EAAE,oBAAoB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IAC/E,yEAAyE;IACzE,6DAA6D;IAC7D,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,EAAE,EAAE,KAAc,EAAE,KAAK,EAAE,iBAAiB,IAAI,CAAC,EAAE,iBAAiB,GAAG,CAAC,OAAO,WAAW,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACvJ,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAChD,OAAO,EAAE,EAAE,EAAE,IAAa,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;AAE1E,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAA0B;IACpE,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAChF,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACxE,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1G,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,OAAO,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/G,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IACtE,OAAO;QACL,EAAE,EAAE,cAAc,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;QAC1D,kEAAkE;QAClE,UAAU,EAAE,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9E,GAAG,CAAC,UAAU,CAAC,MAAM;YACnB,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,UAAU,CAAC,MAAM,OAAO,IAAI,CAAC,MAAM,wHAAwH,CAAC,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;YACzO,CAAC,CAAC,EAAE,CAAC;QACP,sEAAsE;QACtE,wCAAwC;QACxC,UAAU,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;QACtD,aAAa,EAAE,IAAI;QACnB,GAAG,CAAC,cAAc,CAAC,MAAM;YACvB,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,cAAc,CAAC,MAAM,OAAO,IAAI,CAAC,MAAM,gJAAgJ,EAAE;YACvM,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,YAAY,CAAC,MAAM;YACrB,CAAC,CAAC;gBACE,YAAY,EAAE,GAAG,YAAY,CAAC,MAAM,OAAO,IAAI,CAAC,MAAM,4JAA4J;aACnN;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,gBAAgB,CAAC,IAAoB;IACnD,SAAS,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC"}
|
package/dist/tools/messaging.js
CHANGED
|
@@ -6,6 +6,7 @@ import { randomUUID } from "node:crypto";
|
|
|
6
6
|
import { existsSync, watch } from "node:fs";
|
|
7
7
|
import { promises as fsp } from "node:fs";
|
|
8
8
|
import { z } from "zod";
|
|
9
|
+
import { checkClosingLine } from "../closing-line.js";
|
|
9
10
|
import { readLog } from "./logwatch.js";
|
|
10
11
|
// The replay grammar is single-sourced in hooks/replay.mjs and shared with both
|
|
11
12
|
// pushers — see the note at the annotation site below. `hooks/` ships beside
|
|
@@ -16,6 +17,8 @@ import { renderRecord } from "./render.js";
|
|
|
16
17
|
import path from "node:path";
|
|
17
18
|
import { AGENTS_FILE, DEFAULT_ROOM, INBOX_DIR, ROOM_FILE, ROOMS_DIR, STATUS_FILE, appendJsonl, cursorFile, ensureRoom, fileSize, getRooms, inboxFile, listInboxFiles, memberRooms, normalizeRoom, readJson, readJsonl, receiptFile, roomFile, stashHistory, retrieveHistory, updateJson, } from "../store.js";
|
|
18
19
|
import { sourceFile, getOffset, setOffset, MAX_WAIT_MS, isDecision, } from "./shared.js";
|
|
20
|
+
import { isKnownHuman } from "../store.js";
|
|
21
|
+
import { verifyCommitCite } from "../commit-cite.js";
|
|
19
22
|
// ---------- send_message ----------
|
|
20
23
|
// Typed protocol record (Phase 8). Additive: omitting it reproduces v1
|
|
21
24
|
// behavior exactly.
|
|
@@ -39,10 +42,18 @@ const decisionPayload = z.looseObject({
|
|
|
39
42
|
recommendation: z.string().min(1),
|
|
40
43
|
ifNoAction: z.string().min(1),
|
|
41
44
|
});
|
|
45
|
+
// ⟨q-dcbaf544⟩ — `gatedBy` is the seat that JUDGED when it is not the sender;
|
|
46
|
+
// `scribe` is the sender that TRANSCRIBED it. Fields, not prose: a name in
|
|
47
|
+
// prose is a mention, a name in a field is a position, and only the position
|
|
48
|
+
// survives a scanner. Authority does not move (David's ruling 2026-09-14):
|
|
49
|
+
// the roles that may emit `verdict` are unchanged; this is how a gate routed
|
|
50
|
+
// to any other seat reaches the record without lying about who gated.
|
|
42
51
|
const verdictPayload = z.looseObject({
|
|
43
52
|
result: z.enum(["pass", "fail"]),
|
|
44
53
|
headRefOid: z.string().min(1),
|
|
45
54
|
notes: z.string().optional(),
|
|
55
|
+
gatedBy: z.string().min(1).optional(),
|
|
56
|
+
scribe: z.string().min(1).optional(),
|
|
46
57
|
});
|
|
47
58
|
// Discriminated on `type`, so an unknown type is rejected outright while a
|
|
48
59
|
// known type is checked only against its own shape. `payload` is optional on
|
|
@@ -92,6 +103,20 @@ export async function checkRecordAuthority(from, record) {
|
|
|
92
103
|
`Send it as text, or register with the role that owns this record type.`,
|
|
93
104
|
};
|
|
94
105
|
}
|
|
106
|
+
/** ⟨q-dcbaf544⟩ — `scribe`, when present, must be the sender; `gatedBy` may name anyone (that is its point). */
|
|
107
|
+
export function checkVerdictScribe(from, record) {
|
|
108
|
+
if (!record || record.type !== "verdict")
|
|
109
|
+
return { ok: true };
|
|
110
|
+
const p = record.payload;
|
|
111
|
+
if (p?.scribe && p.scribe !== from) {
|
|
112
|
+
return {
|
|
113
|
+
ok: false,
|
|
114
|
+
error: `verdict payload.scribe is '${p.scribe}' but the sender is '${from}' — the scribe is the seat that SENDS the record. ` +
|
|
115
|
+
`Put the seat that judged in payload.gatedBy and either omit scribe or set it to '${from}'.`,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return { ok: true };
|
|
119
|
+
}
|
|
95
120
|
// ---------- typed records obligatory (Phase 5.1 Task 12) ----------
|
|
96
121
|
// An untyped agent→agent message must not be able to EXIST. Enforced HERE, at
|
|
97
122
|
// the send, and not at the render: a rule applied where the message is read
|
|
@@ -117,7 +142,10 @@ async function typedRecordCheck(args) {
|
|
|
117
142
|
// David-facing prose stays prose. An UNREGISTERED recipient is treated as an
|
|
118
143
|
// agent, not as a human: the safe reading of "I cannot tell" is the rule, and
|
|
119
144
|
// a human on this bus has a registry entry (that is how the pane is found).
|
|
120
|
-
|
|
145
|
+
// ⟨q-178878aa⟩ — and the human need not be a REGISTERED agent: a registry entry for a
|
|
146
|
+
// human is evicted after EVICT_MS (no heartbeat), so the exemption keys on the durable
|
|
147
|
+
// human set the server knows (humans.json + AGENT_COORD_HUMANS), read here, at send time.
|
|
148
|
+
if (args.to && (isHuman(reg[args.to]) || (await isKnownHuman(args.to))))
|
|
121
149
|
return { ok: true };
|
|
122
150
|
const sender = reg[args.from];
|
|
123
151
|
if (sender?.proseOnly)
|
|
@@ -139,7 +167,8 @@ async function typedRecordCheck(args) {
|
|
|
139
167
|
`${guidance} ` +
|
|
140
168
|
`Types: decision · verdict · done · blocker · risk · fyi · action · go · scope; 'fyi' is the honest ` +
|
|
141
169
|
`catch-all — do not force a false 'decision'/'risk' to get past this. ` +
|
|
142
|
-
`Messages TO a human are exempt,
|
|
170
|
+
`Messages TO a human are exempt (a recipient registered with a human role, or an id the server knows as human: ` +
|
|
171
|
+
`humans.json / AGENT_COORD_HUMANS — see list_agents.humans), and an agent that cannot pick a type declares proseOnly:true at join.`,
|
|
143
172
|
};
|
|
144
173
|
}
|
|
145
174
|
export const sendMessageSchema = {
|
|
@@ -156,6 +185,9 @@ export const sendMessageSchema = {
|
|
|
156
185
|
// unknown → store + warn) so the rejection shape matches identity-binding
|
|
157
186
|
// / unknown-recipient, not a schema throw. Existing records unchanged.
|
|
158
187
|
inReplyTo: z.string().optional(),
|
|
188
|
+
// ⟨q-cc0819dc⟩ — needed only for a `done` cited by COMMIT: the repository whose
|
|
189
|
+
// origin/main must carry the sha (one local git call, no network).
|
|
190
|
+
repo: z.string().optional(),
|
|
159
191
|
};
|
|
160
192
|
const MESSAGE_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
161
193
|
async function messageIdExists(id) {
|
|
@@ -208,18 +240,42 @@ export async function sendMessageTool(args) {
|
|
|
208
240
|
const authority = await checkRecordAuthority(args.from, args.record);
|
|
209
241
|
if (!authority.ok)
|
|
210
242
|
return { ok: false, error: authority.error };
|
|
243
|
+
// ⟨q-dcbaf544⟩ — a scribe is the sender by definition; a verdict whose
|
|
244
|
+
// `scribe` names someone else has its two positions crossed and would be
|
|
245
|
+
// attributed wrongly by every reader. Refused as a value, nothing written.
|
|
246
|
+
const scribeCheck = checkVerdictScribe(args.from, args.record);
|
|
247
|
+
if (!scribeCheck.ok)
|
|
248
|
+
return { ok: false, error: scribeCheck.error };
|
|
211
249
|
// A `done` must cite the work it claims. Presence and shape only — resolving
|
|
212
250
|
// the ref against gh/git is a consumer's job, and the send path makes no
|
|
213
251
|
// network calls. Rejected as a value, not a throw, mirroring the
|
|
214
252
|
// identity-binding rejection in src/server.ts.
|
|
215
253
|
if (args.record?.type === "done") {
|
|
216
|
-
|
|
217
|
-
|
|
254
|
+
// ⟨q-fee7239f⟩ — the same check that reads the closing citation reads the
|
|
255
|
+
// closing GRAMMAR: a merge closing may not assert a deletion it has not
|
|
256
|
+
// read. Refused as a value, naming the two accepted forms; nothing written.
|
|
257
|
+
const closing = checkClosingLine(String(args.text ?? ""));
|
|
258
|
+
if (!closing.ok)
|
|
259
|
+
return { ok: false, error: closing.error };
|
|
260
|
+
const cites = args.record.cites ?? [];
|
|
261
|
+
const hasPr = cites.some((c) => c.kind === "pr" && c.ref.trim().length > 0);
|
|
262
|
+
const commitCites = cites.filter((c) => c.kind === "commit");
|
|
263
|
+
if (!hasPr && commitCites.length === 0) {
|
|
218
264
|
return {
|
|
219
265
|
ok: false,
|
|
220
|
-
error: "a 'done' record must carry at least one {kind:'pr'} citation — an uncited DONE is an unverifiable claim"
|
|
266
|
+
error: "a 'done' record must carry at least one {kind:'pr'} citation — an uncited DONE is an unverifiable claim. " +
|
|
267
|
+
"Work that has no PR by rule (docs pushed straight to the shared branch) cites {kind:'commit', ref:<full 40-hex sha>} " +
|
|
268
|
+
"and passes `repo`, the repository whose origin/main carries it.",
|
|
221
269
|
};
|
|
222
270
|
}
|
|
271
|
+
// ⟨q-cc0819dc⟩ — a COMMIT cite satisfies a `done` only when the commit is real and on the
|
|
272
|
+
// shared branch: every commit cite is verified, so a fabricated or short sha is refused
|
|
273
|
+
// by name and nothing is written. A PR cite beside it does not excuse a bad commit cite.
|
|
274
|
+
for (const c of commitCites) {
|
|
275
|
+
const v = verifyCommitCite(c.ref, args.repo);
|
|
276
|
+
if (!v.ok)
|
|
277
|
+
return { ok: false, error: `a 'done' record cited by commit was refused — ${v.why}` };
|
|
278
|
+
}
|
|
223
279
|
}
|
|
224
280
|
// `text` is what every consumer reads, so it must exist. The author's
|
|
225
281
|
// wording ALWAYS wins: a record renders only to fill an absent text, never
|
|
@@ -303,7 +359,9 @@ export async function sendMessageTool(args) {
|
|
|
303
359
|
const reg = await readJson(AGENTS_FILE, {});
|
|
304
360
|
const recipientWarning = reg[args.to]
|
|
305
361
|
? undefined
|
|
306
|
-
:
|
|
362
|
+
: (await isKnownHuman(args.to))
|
|
363
|
+
? undefined // a human is not an agent and is not expected to be registered; the inbox is theirs to read
|
|
364
|
+
: `recipient '${args.to}' is not a registered agent — message stored in their inbox but no one may be listening`;
|
|
307
365
|
const warning = [typedWarning, recipientWarning, replyWarning, slashWarning].filter(Boolean).join("; ") || undefined;
|
|
308
366
|
return { ok: true, id: msg.id, target, room: undefined, warning };
|
|
309
367
|
}
|