@davidbalzan/groundwork-console 0.1.14 → 0.1.15
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/bus.js +40 -0
- package/dist/kitresolve.js +11 -3
- package/dist/server.js +16 -6
- package/dist/skills.js +45 -1
- package/package.json +6 -3
- package/public/assets/{abnfDiagram-N423BO3Z-BSvB33qO.js → abnfDiagram-N423BO3Z-BazEjqqO.js} +1 -1
- package/public/assets/{arc-zFmco7vQ.js → arc-B7L9Wm_N.js} +1 -1
- package/public/assets/architecture-TIHT7OUA-CssFxMhM.js +1 -0
- package/public/assets/{architectureDiagram-T3A2C74G-Dq8B7QSd.js → architectureDiagram-T3A2C74G-MLhuSxpt.js} +1 -1
- package/public/assets/{blockDiagram-VBNYF7ZC-Dyx-2MxL.js → blockDiagram-VBNYF7ZC-BQPonMeH.js} +1 -1
- package/public/assets/{c4Diagram-5PPSVZJV-BcQgTpcV.js → c4Diagram-5PPSVZJV-Cz9rjAfz.js} +1 -1
- package/public/assets/channel-CEZ4Oy1C.js +1 -0
- package/public/assets/{chunk-2GRJ4B5K-0LJiHhVt.js → chunk-2GRJ4B5K-DX-wb55s.js} +1 -1
- package/public/assets/{chunk-4I5QYGJK-DU9jcgy8.js → chunk-4I5QYGJK-GtAn9Uuq.js} +1 -1
- package/public/assets/{chunk-5RXB4S5H-Dbb9fQEh.js → chunk-5RXB4S5H-CdlTe7Kd.js} +1 -1
- package/public/assets/{chunk-6Q2QTUOP-BEP7PF5q.js → chunk-6Q2QTUOP-DpEP78Fx.js} +1 -1
- package/public/assets/{chunk-7Z6QIM7H-BDULl8ao.js → chunk-7Z6QIM7H-D70dHZIb.js} +1 -1
- package/public/assets/{chunk-GF5L2VYU-CKmEMSg9.js → chunk-GF5L2VYU-Bj5gzsOF.js} +1 -1
- package/public/assets/{chunk-I66GZJ75-C8VZHfLH.js → chunk-I66GZJ75-DYvsApTB.js} +1 -1
- package/public/assets/{chunk-JQJVKLGR-DM2yoV15.js → chunk-JQJVKLGR-sPaAWMcl.js} +1 -1
- package/public/assets/{chunk-KBJHAD2P-BRAKI2QY.js → chunk-KBJHAD2P-sIJR9nWn.js} +1 -1
- package/public/assets/{chunk-NSK5VX7P-DV7uo6bZ.js → chunk-NSK5VX7P-BBXDYhCk.js} +1 -1
- package/public/assets/{chunk-QR6OTTB3-CIKpM1Nr.js → chunk-QR6OTTB3-0D3J_ldz.js} +1 -1
- package/public/assets/{chunk-RYQCIY6F-DrSpjyPL.js → chunk-RYQCIY6F-ByFYkZW5.js} +1 -1
- package/public/assets/{chunk-UBXNYLIW-CKJQ1y-l.js → chunk-UBXNYLIW-vH5z2CFq.js} +1 -1
- package/public/assets/{chunk-W5SLKNZC-BrvtgZ7x.js → chunk-W5SLKNZC-DXOAlDYx.js} +1 -1
- package/public/assets/{chunk-WRU74C26-D5OxzQZ_.js → chunk-WRU74C26-BDeea6GT.js} +1 -1
- package/public/assets/{chunk-XXDRQBXY-B7N0mEcW.js → chunk-XXDRQBXY-CyNmLpLK.js} +1 -1
- package/public/assets/classDiagram-JCYQIIEL-BTuFAVSb.js +1 -0
- package/public/assets/classDiagram-v2-OCEON4UE-BTuFAVSb.js +1 -0
- package/public/assets/{cose-bilkent-JH36ORCC-B4AeOPAc.js → cose-bilkent-JH36ORCC-DyR57pP4.js} +1 -1
- package/public/assets/{cynefin-VYW2F7L2-DzOwlGVY.js → cynefin-VYW2F7L2-BfcydoVY.js} +1 -1
- package/public/assets/{cynefinDiagram-MW4NZA55-SA4aXkpc.js → cynefinDiagram-MW4NZA55-D4C7d9xF.js} +1 -1
- package/public/assets/{dagre-VZM6K2ZE-C5ltS5m2.js → dagre-VZM6K2ZE-Bb3QdyiU.js} +1 -1
- package/public/assets/{diagram-7IWD3JNH-TU7uqjDX.js → diagram-7IWD3JNH-75Re1gEQ.js} +1 -1
- package/public/assets/{diagram-B4RE2ZJO-HCe8Z_RD.js → diagram-B4RE2ZJO-DBZrEAjD.js} +1 -1
- package/public/assets/{diagram-LBJQPF4R-9kRxXqkG.js → diagram-LBJQPF4R-DP03ppoa.js} +1 -1
- package/public/assets/{diagram-Q27KOJAE-DfLFPFvB.js → diagram-Q27KOJAE-Baaak7ET.js} +1 -1
- package/public/assets/{diagram-UB23O5K3-BUpWSI8L.js → diagram-UB23O5K3-DRtw-cVM.js} +1 -1
- package/public/assets/{dist-By9Jxne0.js → dist-oRJzdzK9.js} +1 -1
- package/public/assets/{ebnfDiagram-BXEA7PRR-Dz83w-0Y.js → ebnfDiagram-BXEA7PRR-DSIhRAUP.js} +1 -1
- package/public/assets/{erDiagram-JOGREHBK-DHZjXCza.js → erDiagram-JOGREHBK-tfCb8QEk.js} +1 -1
- package/public/assets/eventmodeling-45OFAUF4-Br197Gcb.js +1 -0
- package/public/assets/flowDiagram-UKHOOZJN-BDKCF_Nj.js +1 -0
- package/public/assets/{ganttDiagram-PKOTCBZU-B3tcBB-9.js → ganttDiagram-PKOTCBZU-BYZrkk6r.js} +1 -1
- package/public/assets/{gitGraph-TEB2WS4Q-BQKfiZNh.js → gitGraph-TEB2WS4Q-BtIPzVXt.js} +1 -1
- package/public/assets/{gitGraphDiagram-DS77QQ5N-BM480xTb.js → gitGraphDiagram-DS77QQ5N-B319uA7z.js} +1 -1
- package/public/assets/index-BmpLrTQR.css +2 -0
- package/public/assets/{index-Crr1PM3T.js → index-Dl33_YDJ.js} +8 -8
- package/public/assets/{info-DKCQHKI2-DW33_uuk.js → info-DKCQHKI2-CTIPSIKZ.js} +1 -1
- package/public/assets/{infoDiagram-6WML65LV-BeewbX8V.js → infoDiagram-6WML65LV-D-foqSEg.js} +1 -1
- package/public/assets/{ishikawaDiagram-WSZJBQD7-DcWSwP2B.js → ishikawaDiagram-WSZJBQD7-CsSDhWgz.js} +1 -1
- package/public/assets/{journeyDiagram-NVQOT4AX-BxT4Ea_S.js → journeyDiagram-NVQOT4AX-D4kgOJAw.js} +1 -1
- package/public/assets/{kanban-definition-27J2QSJJ-CEvqnKgz.js → kanban-definition-27J2QSJJ-B3kNYdeo.js} +1 -1
- package/public/assets/{line-DrJMZj-O.js → line-DI4sM6NI.js} +1 -1
- package/public/assets/{linear-cUeO7N7d.js → linear-CR-Nr7tu.js} +1 -1
- package/public/assets/{mermaid-parser.core-CIHTTkEa.js → mermaid-parser.core-Jx7mG9S9.js} +3 -3
- package/public/assets/{mermaid.core-Cc5OhPpa.js → mermaid.core-Dad-8IqK.js} +4 -4
- package/public/assets/{mindmap-definition-FAOFIHXS-DsHkrrK_.js → mindmap-definition-FAOFIHXS-DNeiGiTc.js} +1 -1
- package/public/assets/{packet-7NZHBO7P-C_T3uLvX.js → packet-7NZHBO7P-DDW1h-3U.js} +1 -1
- package/public/assets/{pegDiagram-VL7TDLO6-CBdlvXSc.js → pegDiagram-VL7TDLO6-BhFSf_Qi.js} +1 -1
- package/public/assets/{pie-RZYD4A2V-CpetmYJU.js → pie-RZYD4A2V-DlcS3vnT.js} +1 -1
- package/public/assets/{pieDiagram-7S7Q4E2Y-CT3wi9zO.js → pieDiagram-7S7Q4E2Y-bIpfrRof.js} +1 -1
- package/public/assets/{quadrantDiagram-CIZ2JOQS-Vuywai3l.js → quadrantDiagram-CIZ2JOQS-BOsxmZiJ.js} +1 -1
- package/public/assets/{radar-I7S5WNFK-rNDTWylh.js → radar-I7S5WNFK-y6e8oiKJ.js} +1 -1
- package/public/assets/{railroad-3IZDKUUU-B09wa8N5.js → railroad-3IZDKUUU-DSMAGu-t.js} +1 -1
- package/public/assets/railroad-abnf-AHOZXSZD-cMf5ZHgo.js +1 -0
- package/public/assets/railroad-ebnf-EBAXGLYW-C4ZEbGk2.js +1 -0
- package/public/assets/railroad-peg-LSFZ7HO6-KGZPMRIB.js +1 -0
- package/public/assets/{railroadDiagram-AXF67PYL-DxwqeTls.js → railroadDiagram-AXF67PYL-BRtEa2OT.js} +1 -1
- package/public/assets/{requirementDiagram-LRYGKXZP-UGxNbVIj.js → requirementDiagram-LRYGKXZP-Dikys7Ub.js} +1 -1
- package/public/assets/{sankeyDiagram-W5VNT64P-DpR73q2C.js → sankeyDiagram-W5VNT64P-BiYgVWtA.js} +1 -1
- package/public/assets/{sequenceDiagram-SI44F4Z6-xvxxzFmu.js → sequenceDiagram-SI44F4Z6-BUtXadia.js} +1 -1
- package/public/assets/{src-eh414mKr.js → src-BtDe6ofe.js} +1 -1
- package/public/assets/{stateDiagram-OKZ733FA-Cqt3c052.js → stateDiagram-OKZ733FA-5fho-t3_.js} +1 -1
- package/public/assets/stateDiagram-v2-UEYNNEHI-DFmJr5_x.js +1 -0
- package/public/assets/{swimlanes-SLNWSIFB-BJknsAAA.js → swimlanes-SLNWSIFB-BpmWJ8es.js} +1 -1
- package/public/assets/swimlanesDiagram-ULZ7WXOC-0uIZxCfL.js +8 -0
- package/public/assets/{timeline-definition-Z64GVDOM-Dkcqv4tL.js → timeline-definition-Z64GVDOM-_w3lytrY.js} +1 -1
- package/public/assets/{treeView-QDETBFTQ-C1uzwCFh.js → treeView-QDETBFTQ-D_l_9pyQ.js} +1 -1
- package/public/assets/{treemap-6X3UGDF4-C59GIx2E.js → treemap-6X3UGDF4-DvWVuWhL.js} +1 -1
- package/public/assets/{vennDiagram-T6HMQDX7-Cd3Zvctp.js → vennDiagram-T6HMQDX7-ClZPTfxU.js} +1 -1
- package/public/assets/{wardley-OPB4EBWU-D3P85e8V.js → wardley-OPB4EBWU-CgyA0GRV.js} +1 -1
- package/public/assets/{wardleyDiagram-T6FBY63Y-BLX8xtsj.js → wardleyDiagram-T6FBY63Y-DNhv1Bla.js} +1 -1
- package/public/assets/{xychartDiagram-ELKLHX3M-CUfF0x4C.js → xychartDiagram-ELKLHX3M-CNeebJO2.js} +1 -1
- package/public/index.html +2 -2
- package/public/assets/architecture-TIHT7OUA-BQFAhsKM.js +0 -1
- package/public/assets/channel-BBOBumsc.js +0 -1
- package/public/assets/classDiagram-JCYQIIEL-g9vVH4Bz.js +0 -1
- package/public/assets/classDiagram-v2-OCEON4UE-g9vVH4Bz.js +0 -1
- package/public/assets/eventmodeling-45OFAUF4-UQEvaa-G.js +0 -1
- package/public/assets/flowDiagram-UKHOOZJN-D3oCUrRO.js +0 -1
- package/public/assets/index-C40rGsvd.css +0 -2
- package/public/assets/railroad-abnf-AHOZXSZD-DPdRoDGL.js +0 -1
- package/public/assets/railroad-ebnf-EBAXGLYW-BWVVmeh0.js +0 -1
- package/public/assets/railroad-peg-LSFZ7HO6-CFlw0fDo.js +0 -1
- package/public/assets/stateDiagram-v2-UEYNNEHI-toMIf4-z.js +0 -1
- package/public/assets/swimlanesDiagram-ULZ7WXOC-BF4o5mrv.js +0 -8
package/dist/bus.js
CHANGED
|
@@ -102,6 +102,23 @@ export function agentsSync(root, scanLines = SCAN_LINES) {
|
|
|
102
102
|
return { ...a, transport: t?.transport ?? t?.kind ?? (t ? "tmux-push" : null), pane: t?.tmuxTarget ?? null, reachability: reachOf(age), heartbeatAgeMs: Number.isFinite(age) ? age : null, lastSeen: lastSeen || null, progress: progressOf(output.get(a.agentId), now, scanLines) };
|
|
103
103
|
}).sort((a, b) => (b.lastSeen ?? 0) - (a.lastSeen ?? 0));
|
|
104
104
|
}
|
|
105
|
+
export function busConditions(root) {
|
|
106
|
+
const halt = readJson(path.join(root, "halt.json"), null);
|
|
107
|
+
const away = readJson(path.join(root, "coord-away.json"), null);
|
|
108
|
+
const subs = readJson(path.join(root, "subscriptions.json"), {});
|
|
109
|
+
const stallFile = path.join(root, "stall-check.json");
|
|
110
|
+
const stallRaw = existsSync(stallFile) ? readJson(stallFile, {}) : null;
|
|
111
|
+
const runs = (stallRaw?.history ?? []).filter((r) => typeof r?.at === "number").sort((a, b) => a.at - b.at);
|
|
112
|
+
const last = runs.length ? runs[runs.length - 1] : null;
|
|
113
|
+
const list = subs.subscriptions ?? [];
|
|
114
|
+
const never = list.filter((x) => x.lastEvaluatedAt === null || x.lastEvaluatedAt === undefined);
|
|
115
|
+
return {
|
|
116
|
+
halt: halt ? { active: true, ...halt } : { active: false },
|
|
117
|
+
away: away ? { active: true, ...away } : { active: false },
|
|
118
|
+
subscriptions: { total: list.length, neverEvaluated: never.length, agents: [...new Set(never.map((x) => x.agentId).filter((a) => !!a))] },
|
|
119
|
+
stallClock: { inUse: stallRaw !== null, runs: runs.slice(-12), last, ageMs: last ? Date.now() - last.at : null },
|
|
120
|
+
};
|
|
121
|
+
}
|
|
105
122
|
export function rooms(root) {
|
|
106
123
|
const meta = readJson(path.join(root, "rooms.json"), {});
|
|
107
124
|
const dir = path.join(root, "rooms");
|
|
@@ -135,3 +152,26 @@ export function scopes(root) { return readJson(path.join(root, "scopes.json"), {
|
|
|
135
152
|
/* prefix classification — same table as seam/protocol/prefixes.ts (byte-0, case-sensitive) */
|
|
136
153
|
export const PREFIXES = ["DAVID_DECISION", "SCOPE CHANGE", "AGENT_ACTION", "BLOCKER", "VERDICT", "RISK", "DONE", "FYI", "GO"];
|
|
137
154
|
export function prefixOf(text) { return PREFIXES.find((p) => text.startsWith(p + ":") || text.startsWith(p + " ")) ?? null; }
|
|
155
|
+
/* A message's prefix from its TYPED RECORD where it has one, falling back to the text scan.
|
|
156
|
+
*
|
|
157
|
+
* The bus carries the same fact twice: `record.type` is structured, and the prose repeats it as a
|
|
158
|
+
* leading token. Reading only the prose meant a correctly-typed message whose author varied the
|
|
159
|
+
* wording was classified by a regex over free text — two sources for one fact, with the weaker one
|
|
160
|
+
* winning by default.
|
|
161
|
+
*
|
|
162
|
+
* The record wins where present because the SENDER declared it, and the bus enforces authority on
|
|
163
|
+
* the restricted types; the text scan stays for the messages that carry no record (175 of 214 in
|
|
164
|
+
* this store at time of writing), which is a fallback rather than a second opinion.
|
|
165
|
+
*
|
|
166
|
+
* One function, used at every call site. Three copies of this mapping is how the next divergence
|
|
167
|
+
* gets written. */
|
|
168
|
+
const RECORD_PREFIX = {
|
|
169
|
+
decision: "DAVID_DECISION", verdict: "VERDICT", done: "DONE", blocker: "BLOCKER",
|
|
170
|
+
risk: "RISK", fyi: "FYI", action: "AGENT_ACTION", go: "GO", scope: "SCOPE CHANGE",
|
|
171
|
+
};
|
|
172
|
+
export function prefixOfMessage(m) {
|
|
173
|
+
const t = m.record?.type;
|
|
174
|
+
if (typeof t === "string" && RECORD_PREFIX[t])
|
|
175
|
+
return RECORD_PREFIX[t];
|
|
176
|
+
return typeof m.text === "string" ? prefixOf(m.text) : null;
|
|
177
|
+
}
|
package/dist/kitresolve.js
CHANGED
|
@@ -48,7 +48,6 @@ const pkgVersionNear = (file) => { if (!file)
|
|
|
48
48
|
}
|
|
49
49
|
d = path.dirname(d);
|
|
50
50
|
} return null; };
|
|
51
|
-
/** Installed versions the console actually resolves to (seam from node_modules; the rest from wherever the CLIs came from). */
|
|
52
51
|
export function installedVersions(kitPath) {
|
|
53
52
|
let seam = null;
|
|
54
53
|
try {
|
|
@@ -56,7 +55,13 @@ export function installedVersions(kitPath) {
|
|
|
56
55
|
}
|
|
57
56
|
catch { /* not installed */ }
|
|
58
57
|
const gw = groundworkCli(kitPath), pb = playbookCli(kitPath), mcp = mcpServer(kitPath);
|
|
59
|
-
|
|
58
|
+
const root = hasKitCheckout(kitPath) ? path.resolve(kitPath) : null;
|
|
59
|
+
const from = (file) => (!file ? null : root && path.resolve(file).startsWith(root + path.sep) ? "kit checkout" : "global install");
|
|
60
|
+
return {
|
|
61
|
+
seam, groundwork: pkgVersionNear(gw), playbook: pkgVersionNear(pb), mcp: pkgVersionNear(mcp),
|
|
62
|
+
sources: { seam: (seam ? "console dependency" : null), groundwork: from(gw), playbook: from(pb), mcp: from(mcp) },
|
|
63
|
+
paths: { groundwork: gw, playbook: pb, mcp, kitCheckout: root },
|
|
64
|
+
};
|
|
60
65
|
}
|
|
61
66
|
/** Floor check: the console's requirement is a MINIMUM within the same major (kit packages bump minors often; 0.25.1 must satisfy "^0.24.0").
|
|
62
67
|
Written as ^a.b.c for familiarity, evaluated as >= a.b.c and < (a+1).0.0 — NOT strict caret semantics for 0.x. */
|
|
@@ -76,7 +81,10 @@ export function satisfies(v, range) {
|
|
|
76
81
|
}
|
|
77
82
|
export function requiresReport(kitPath, caps) {
|
|
78
83
|
const inst = installedVersions(kitPath);
|
|
79
|
-
|
|
84
|
+
/* `source` rides along so a reader of /api/kit can tell WHICH question each number answers.
|
|
85
|
+
`requires.seam` is the console's own dependency; `packages.seam` (when a kit checkout exists)
|
|
86
|
+
is the kit's manifest. They differ legitimately and used to differ silently. */
|
|
87
|
+
const check = (k) => ({ required: REQUIRES[k], installed: inst[k], ok: satisfies(inst[k], REQUIRES[k]), source: inst.sources[k] });
|
|
80
88
|
const r = { seam: check("seam"), mcp: { ...check("mcp"), capabilities: caps ?? { inReplyTo: null, sendCommand: null }, warnings: caps?.inReplyTo === false ? ["inReplyTo missing — decision replies will not be linked/cleared; upgrade agent-coord-mcp"] : [] }, groundwork: check("groundwork"), playbook: check("playbook") };
|
|
81
89
|
return { ...r, paths: inst.paths, ok: Object.values(r).every((x) => x.ok !== false) };
|
|
82
90
|
}
|
package/dist/server.js
CHANGED
|
@@ -12,11 +12,11 @@ import { hostname as osHostname } from "node:os";
|
|
|
12
12
|
import { loadConfig, saveProjects, validateProjectPath, CONFIG_FILE } from "./config.js";
|
|
13
13
|
import { boardOf, docOf, docsIndex, phaseTasksOf } from "./seam.js";
|
|
14
14
|
import { DocWriteError, sha256, writeDoc } from "./docwrite.js";
|
|
15
|
-
import { agents, agentsAsync, rooms, roomMessages, roomMessageCount, statusStream, scopes,
|
|
15
|
+
import { agents, agentsAsync, rooms, roomMessages, roomMessageCount, statusStream, scopes, prefixOfMessage, busConditions } from "./bus.js";
|
|
16
16
|
import { capturePane } from "./tmux.js";
|
|
17
17
|
import { spawnAgent, suggestId, fleetStatus, FLEET_TEMPLATES, HARNESS_CMD, ROLE_SKILL } from "./provision.js";
|
|
18
18
|
import { doctor, status, list, playbookList } from "./groundwork.js";
|
|
19
|
-
import { detectedHarnesses, groundworkSkills, playbookCards } from "./skills.js";
|
|
19
|
+
import { detectedHarnesses, groundworkSkills, playbookCards, cardLoads } from "./skills.js";
|
|
20
20
|
import { extensionsOf } from "./extensions.js";
|
|
21
21
|
import { parseWorkDoc, workstreamsExtensionsOf } from "@davidbalzan/groundwork-seam";
|
|
22
22
|
import { EventEngine } from "./events.js";
|
|
@@ -604,7 +604,7 @@ app.get("/bus/inbox", async (c) => {
|
|
|
604
604
|
return null;
|
|
605
605
|
} }).filter(Boolean) : [];
|
|
606
606
|
const unreadIds = new Set(out.messages.map((m) => m.id));
|
|
607
|
-
const messages = all.map((m) => ({ ...m, unread: unreadIds.has(m.id) && !isAnswered(m.id), answered: isAnswered(m.id), prefix:
|
|
607
|
+
const messages = all.map((m) => ({ ...m, unread: unreadIds.has(m.id) && !isAnswered(m.id), answered: isAnswered(m.id), prefix: prefixOfMessage(m) }));
|
|
608
608
|
// Pending decisions per sender: unread, unanswered DAVID_DECISION DMs — the avatar cue.
|
|
609
609
|
const decisions = {};
|
|
610
610
|
for (const m of messages)
|
|
@@ -629,7 +629,7 @@ app.get("/bus/dm/:agent", (c) => {
|
|
|
629
629
|
} }).filter(Boolean) : [];
|
|
630
630
|
const mine = readJsonl(path.join(cfg.coordDir, "inbox", "david.jsonl")).filter((m) => m.from === agent);
|
|
631
631
|
const theirs = readJsonl(path.join(cfg.coordDir, "inbox", `${agent}.jsonl`)).filter((m) => m.from === "david");
|
|
632
|
-
const messages = [...mine, ...theirs].sort((a, b) => Number(a.ts ?? 0) - Number(b.ts ?? 0)).slice(-limit).map((m) => ({ ...m, prefix:
|
|
632
|
+
const messages = [...mine, ...theirs].sort((a, b) => Number(a.ts ?? 0) - Number(b.ts ?? 0)).slice(-limit).map((m) => ({ ...m, prefix: prefixOfMessage(m) }));
|
|
633
633
|
return c.json({ agent, messages, lastFromAgent: mine.length ? Number(mine[mine.length - 1].ts ?? 0) : 0 });
|
|
634
634
|
});
|
|
635
635
|
app.post("/bus/inbox/read", async (c) => {
|
|
@@ -1058,11 +1058,13 @@ app.get("/bus/rooms/:room/messages", (c) => {
|
|
|
1058
1058
|
const limit = Number(c.req.query("limit") ?? 100);
|
|
1059
1059
|
const before = c.req.query("before") ? Number(c.req.query("before")) : undefined;
|
|
1060
1060
|
const room = c.req.param("room");
|
|
1061
|
-
const msgs = roomMessages(cfg.coordDir, room, limit, before).map((m) => ({ ...m, prefix:
|
|
1061
|
+
const msgs = roomMessages(cfg.coordDir, room, limit, before).map((m) => ({ ...m, prefix: prefixOfMessage(m), answered: isAnswered(m.id) }));
|
|
1062
1062
|
return c.json({ room, total: roomMessageCount(cfg.coordDir, room), messages: msgs, oldestTs: msgs[0]?.ts ?? null });
|
|
1063
1063
|
});
|
|
1064
1064
|
app.get("/bus/status", (c) => c.json(statusStream(cfg.coordDir, Number(c.req.query("limit") ?? 50))));
|
|
1065
1065
|
app.get("/bus/scopes", (c) => c.json(scopes(cfg.coordDir)));
|
|
1066
|
+
app.get("/bus/conditions", (c) => c.json(busConditions(cfg.coordDir)));
|
|
1067
|
+
app.get("/bus/card-loads", (c) => c.json(cardLoads()));
|
|
1066
1068
|
events.start(15_000);
|
|
1067
1069
|
notifier.start(15_000);
|
|
1068
1070
|
/* Uploads TTL purge: at boot + every 30 min (unref'd so it never holds the process). A Run is logged only when something was deleted. */
|
|
@@ -1094,4 +1096,12 @@ if (existsSync(PUBLIC_DIR)) {
|
|
|
1094
1096
|
}
|
|
1095
1097
|
// Bind loopback only: the console can write to the bus and to docs/ and has no auth yet. Set GROUNDWORK_CONSOLE_HOST=0.0.0.0 to expose (put auth in front first).
|
|
1096
1098
|
const hostname = process.env.GROUNDWORK_CONSOLE_HOST ?? "127.0.0.1";
|
|
1097
|
-
serve({ fetch: root.fetch, port, hostname }, () => {
|
|
1099
|
+
serve({ fetch: root.fetch, port, hostname }, () => {
|
|
1100
|
+
const rq = requiresReport(cfg.kitPath); /* Grouped BY SOURCE. Printing four numbers after one "checkout <path>" label said they all came
|
|
1101
|
+
from there; three do and `seam` is this console's own dependency, so our pin read as a stale
|
|
1102
|
+
kit. Same numbers, each now attributable. */
|
|
1103
|
+
const kitTrio = `mcp ${rq.mcp.installed ?? "?"} groundwork ${rq.groundwork.installed ?? "?"} playbook ${rq.playbook.installed ?? "?"}`;
|
|
1104
|
+
const kitFrom = rq.paths.kitCheckout ? `checkout ${rq.paths.kitCheckout}` : "global install (no kit checkout)";
|
|
1105
|
+
console.log(`kit resolve: ${kitFrom} · ${kitTrio} · seam ${rq.seam.installed ?? "?"} (this console's dependency, not the kit's) · requires ${rq.ok ? "OK" : "MISMATCH " + JSON.stringify(REQUIRES)}`);
|
|
1106
|
+
console.log(`groundwork-console api → http://${hostname}:${port}/api store=${cfg.coordDir} auth=${authEnabled ? `token (${tokenFile})` : "OFF"}`);
|
|
1107
|
+
});
|
package/dist/skills.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* Supplement to the CLIs' `list --json`: compare installed SKILL.md with what the installer would write (in-sync signal the CLIs do not report).
|
|
2
2
|
groundwork: byte-copy → raw hash. playbook: per-harness placeholder rewrite → hash the rewritten source (see loadRewrite). */
|
|
3
|
-
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
3
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import path from "node:path";
|
|
@@ -98,3 +98,47 @@ export async function playbookCards(kitPath) {
|
|
|
98
98
|
legacyDirs: homes.flatMap(([h, d]) => ["coord-curator", "coord-liaison"].filter((n) => existsSync(path.join(d, n))).map((n) => `${h}:${n}`)),
|
|
99
99
|
};
|
|
100
100
|
}
|
|
101
|
+
export function cardLoads(root = homedir()) {
|
|
102
|
+
const home = path.join(root, ".claude/skills");
|
|
103
|
+
const cards = existsSync(home) ? readdirSync(home).map((d) => path.join(home, d, "SKILL.md")).filter((f) => existsSync(f)) : [];
|
|
104
|
+
/* NEWEST card write is the bar: any card changing means a session that predates it may be holding
|
|
105
|
+
a superseded copy of THAT one, and a per-card bar would claim precision this cannot support. */
|
|
106
|
+
const cardsWrittenAt = cards.length ? Math.max(...cards.map((f) => statSync(f).mtimeMs)) : null;
|
|
107
|
+
const dir = path.join(root, "agent-coord/sessions");
|
|
108
|
+
const files = existsSync(dir) ? readdirSync(dir).filter((f) => f.endsWith(".json")) : [];
|
|
109
|
+
const live = new Map();
|
|
110
|
+
let stale = 0;
|
|
111
|
+
for (const f of files) {
|
|
112
|
+
let s = {};
|
|
113
|
+
try {
|
|
114
|
+
s = JSON.parse(readFileSync(path.join(dir, f), "utf8"));
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (!s.agentId || typeof s.pid !== "number" || typeof s.boundAt !== "number")
|
|
120
|
+
continue;
|
|
121
|
+
if (!alive(s.pid)) {
|
|
122
|
+
stale++;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const prev = live.get(s.agentId);
|
|
126
|
+
if (!prev || s.boundAt > prev.boundAt) {
|
|
127
|
+
live.set(s.agentId, { agentId: s.agentId, boundAt: s.boundAt, pid: s.pid, pane: s.tmuxPane ?? null, state: cardsWrittenAt !== null && s.boundAt > cardsWrittenAt ? "current" : "unknown" });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return { cardsWrittenAt, skillsHome: home, agents: [...live.values()].sort((a, b) => a.agentId.localeCompare(b.agentId)), staleSessionFiles: stale };
|
|
131
|
+
}
|
|
132
|
+
/* Is this pid running? `kill(pid, 0)` signals nothing; it only asks.
|
|
133
|
+
ESRCH means no such process. EPERM means THE PROCESS EXISTS and is not ours — treating that as
|
|
134
|
+
dead would silently drop a live agent from the table, which is the failure direction that matters
|
|
135
|
+
here: a missing row reads as "no such agent" rather than as "could not tell". */
|
|
136
|
+
function alive(pid) {
|
|
137
|
+
try {
|
|
138
|
+
process.kill(pid, 0);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
return e?.code === "EPERM";
|
|
143
|
+
}
|
|
144
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@davidbalzan/groundwork-console",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.15",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@davidbalzan/groundwork-seam": "0.1.8",
|
|
@@ -48,12 +48,15 @@
|
|
|
48
48
|
"publish-check": "node scripts/publish-check.mjs",
|
|
49
49
|
"test:inject": "tsx test/inject.test.mts",
|
|
50
50
|
"test:skills": "tsx test/skills.test.mts",
|
|
51
|
-
"test": "pnpm run test:inject && pnpm run test:skills && pnpm run test:board && pnpm run test:panes && pnpm run test:seam-contract && pnpm run test:prref && pnpm run test:progress && pnpm run test:publish-check",
|
|
51
|
+
"test": "pnpm run test:inject && pnpm run test:skills && pnpm run test:board && pnpm run test:panes && pnpm run test:seam-contract && pnpm run test:prref && pnpm run test:progress && pnpm run test:publish-check && pnpm run test:record && pnpm run test:kitresolve && pnpm run test:cardloads",
|
|
52
52
|
"test:board": "tsx test/board.test.mts",
|
|
53
53
|
"test:panes": "tsx test/panes.test.mts",
|
|
54
54
|
"test:seam-contract": "tsx test/seam-contract.test.mts",
|
|
55
55
|
"test:prref": "tsx test/prref.test.mts",
|
|
56
56
|
"test:progress": "tsx test/progress.test.mts",
|
|
57
|
-
"test:publish-check": "tsx test/publish-check.test.mts"
|
|
57
|
+
"test:publish-check": "tsx test/publish-check.test.mts",
|
|
58
|
+
"test:record": "tsx test/record.test.mts",
|
|
59
|
+
"test:kitresolve": "tsx test/kitresolve.test.mts",
|
|
60
|
+
"test:cardloads": "tsx test/cardloads.test.mts"
|
|
58
61
|
}
|
|
59
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{m as e,t}from"./mermaid-parser.core-
|
|
1
|
+
import{m as e,t}from"./mermaid-parser.core-Jx7mG9S9.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-BtDe6ofe.js";import"./chunk-I66GZJ75-DYvsApTB.js";import{n as i,r as a,t as o}from"./chunk-6Q2QTUOP-DpEP78Fx.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-Dad-8IqK.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-
|
|
1
|
+
import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-oRJzdzK9.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i){if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./chunk-KEIR6QF5-BICK3FdT.js";import{M as e}from"./mermaid-parser.core-Jx7mG9S9.js";export{e as createArchitectureServices};
|