agent-coord-mcp 0.18.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.
- package/README.md +13 -1
- package/dist/server.js +127 -9
- package/dist/server.js.map +1 -1
- package/dist/store.js +33 -1
- package/dist/store.js.map +1 -1
- package/dist/tools/admin.js +24 -5
- package/dist/tools/admin.js.map +1 -1
- package/dist/tools/registry.js +69 -1
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/transport.js +134 -25
- package/dist/tools/transport.js.map +1 -1
- package/dist/tools/work.js +28 -8
- package/dist/tools/work.js.map +1 -1
- package/dist/work.js +36 -4
- package/dist/work.js.map +1 -1
- package/hooks/submit.mjs +136 -14
- package/hooks/tmux-pusher.mjs +6 -0
- package/package.json +1 -1
- package/scripts/check-self-dependency.mjs +22 -10
- package/scripts/check-test-count.mjs +1 -1
- package/scripts/coord-pusher.mjs +39 -9
- package/src/server.ts +131 -9
- package/src/store.ts +45 -1
- package/src/tools/admin.ts +22 -5
- package/src/tools/registry.ts +96 -0
- package/src/tools/transport.ts +154 -23
- package/src/tools/work.ts +28 -7
- package/src/work.ts +64 -7
package/src/work.ts
CHANGED
|
@@ -63,6 +63,33 @@ export type BoardRow = {
|
|
|
63
63
|
raw?: string;
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
+
// The one arity BoardRow can hold. boardCells() and the parser's arity guard
|
|
67
|
+
// both reference this constant so the two sides cannot drift; a test pins
|
|
68
|
+
// boardCells().length === BOARD_ARITY.
|
|
69
|
+
export const BOARD_ARITY = 5;
|
|
70
|
+
|
|
71
|
+
// A table row whose column count does not match BoardRow. It is REFUSED a
|
|
72
|
+
// record (boardRowsOf never returns it) but PRESERVED byte-exactly — the
|
|
73
|
+
// alternative, destructuring whatever arity into a fixed 5-tuple, silently
|
|
74
|
+
// narrowed 6-column rows and widened 4-column ones on export (hit live
|
|
75
|
+
// 2026-07-29: #38's extra `Pane` column was dropped on write-back). Refusing
|
|
76
|
+
// the row rather than throwing keeps one bad row from taking down the whole
|
|
77
|
+
// document's import. The schema decision stays with the board owner: widening
|
|
78
|
+
// BoardRow is a deliberate act (change BOARD_ARITY, boardCells, and this
|
|
79
|
+
// guard together), never something a docs commit does by accident.
|
|
80
|
+
export type MalformedRow = {
|
|
81
|
+
malformed: true;
|
|
82
|
+
// Replayed byte-exactly on render — never narrowed, never widened.
|
|
83
|
+
verbatim: string;
|
|
84
|
+
// Names the line, quotes the row, states expected/actual — loud enough to
|
|
85
|
+
// fix from the message alone.
|
|
86
|
+
issue: string;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export function isMalformedRow(r: BoardRow | MalformedRow): r is MalformedRow {
|
|
90
|
+
return (r as MalformedRow).malformed === true;
|
|
91
|
+
}
|
|
92
|
+
|
|
66
93
|
// A parsed document: an ordered block list. `text` blocks are verbatim lines
|
|
67
94
|
// (never interpreted); the others carry records rendered back in place.
|
|
68
95
|
export type Block =
|
|
@@ -71,7 +98,7 @@ export type Block =
|
|
|
71
98
|
| { kind: "done"; entries: DoneEntry[] }
|
|
72
99
|
// `header` and `align` are kept as raw lines for the same reason as
|
|
73
100
|
// BoardRow.raw — the alignment row (`|---|---|`) has no canonical form.
|
|
74
|
-
| { kind: "board"; header: string; align: string; rows: BoardRow[] };
|
|
101
|
+
| { kind: "board"; header: string; align: string; rows: (BoardRow | MalformedRow)[] };
|
|
75
102
|
|
|
76
103
|
export type WorkDoc = {
|
|
77
104
|
// Kept so an export can be written back with the exact byte tail it had.
|
|
@@ -182,11 +209,13 @@ function boardCells(r: BoardRow): string[] {
|
|
|
182
209
|
}
|
|
183
210
|
|
|
184
211
|
// Replay the original line when the fields still say what it said; re-render
|
|
185
|
-
// once anything actually changed.
|
|
186
|
-
|
|
212
|
+
// once anything actually changed. A malformed row has no fields to have
|
|
213
|
+
// changed — it replays its bytes, always.
|
|
214
|
+
export function renderBoardRow(r: BoardRow | MalformedRow): string {
|
|
215
|
+
if (isMalformedRow(r)) return r.verbatim;
|
|
187
216
|
if (r.raw !== undefined) {
|
|
188
217
|
const cells = splitRow(r.raw);
|
|
189
|
-
if (cells.length ===
|
|
218
|
+
if (cells.length === BOARD_ARITY && cells.every((c, i) => c === boardCells(r)[i])) return r.raw;
|
|
190
219
|
}
|
|
191
220
|
return renderRow(boardCells(r));
|
|
192
221
|
}
|
|
@@ -280,11 +309,28 @@ export function parseWorkDoc(source: string): WorkDoc {
|
|
|
280
309
|
|
|
281
310
|
// Lanes table: a header row followed by an alignment row.
|
|
282
311
|
if (TABLE_ROW.test(line) && TABLE_ALIGN.test(lines[i + 1] ?? "")) {
|
|
283
|
-
const rows: BoardRow[] = [];
|
|
312
|
+
const rows: (BoardRow | MalformedRow)[] = [];
|
|
284
313
|
let j = i + 2;
|
|
285
314
|
for (; j < lines.length && TABLE_ROW.test(lines[j] ?? ""); j++) {
|
|
286
315
|
const raw = lines[j] ?? "";
|
|
287
|
-
const
|
|
316
|
+
const cells = splitRow(raw);
|
|
317
|
+
// Arity guard: a row BoardRow cannot hold is refused a record, kept
|
|
318
|
+
// verbatim, and named loudly — destructuring it into the 5-tuple is
|
|
319
|
+
// exactly the silent narrow/widen this exists to prevent. An empty
|
|
320
|
+
// trailing cell (`| a | b | c | d | |`) is still five columns and
|
|
321
|
+
// still a legitimate row.
|
|
322
|
+
if (cells.length !== BOARD_ARITY) {
|
|
323
|
+
rows.push({
|
|
324
|
+
malformed: true,
|
|
325
|
+
verbatim: raw,
|
|
326
|
+
issue:
|
|
327
|
+
`board row at line ${j + 1} has ${cells.length} column(s), expected ${BOARD_ARITY} — ` +
|
|
328
|
+
`refused (kept verbatim, excluded from board records). Fix the row, or widen BoardRow ` +
|
|
329
|
+
`deliberately (BOARD_ARITY + boardCells + this guard together). Row: ${raw}`,
|
|
330
|
+
});
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
const [lane = "", owner = "", state = "", currentSlice = "", nextGo = ""] = cells;
|
|
288
334
|
rows.push({ id: idFor("b", lane), lane, owner, state, currentSlice, nextGo, raw });
|
|
289
335
|
}
|
|
290
336
|
flushText();
|
|
@@ -325,5 +371,16 @@ export function doneEntriesOf(doc: WorkDoc): DoneEntry[] {
|
|
|
325
371
|
}
|
|
326
372
|
|
|
327
373
|
export function boardRowsOf(doc: WorkDoc): BoardRow[] {
|
|
328
|
-
return doc.blocks.flatMap((b) =>
|
|
374
|
+
return doc.blocks.flatMap((b) =>
|
|
375
|
+
b.kind === "board" ? b.rows.filter((r): r is BoardRow => !isMalformedRow(r)) : [],
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Every refused row's issue, in document order — what makes the parse-time
|
|
380
|
+
// rejection LOUD at the tool layer (import_work/list_work/export_work all
|
|
381
|
+
// surface it) instead of a filtered-out record nobody notices.
|
|
382
|
+
export function workDocIssues(doc: WorkDoc): string[] {
|
|
383
|
+
return doc.blocks.flatMap((b) =>
|
|
384
|
+
b.kind === "board" ? b.rows.filter(isMalformedRow).map((r) => r.issue) : [],
|
|
385
|
+
);
|
|
329
386
|
}
|