monomind 2.1.0 → 2.1.4

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 (57) hide show
  1. package/README.md +77 -94
  2. package/package.json +3 -3
  3. package/packages/@monomind/cli/.claude/commands/mastermind/createorg.md +8 -9
  4. package/packages/@monomind/cli/.claude/helpers/handlers/capture-handler.cjs +24 -10
  5. package/packages/@monomind/cli/.claude/helpers/handlers/gates-handler.cjs +2 -2
  6. package/packages/@monomind/cli/.claude/helpers/handlers/route-handler.cjs +29 -0
  7. package/packages/@monomind/cli/.claude/helpers/handlers/session-handler.cjs +35 -23
  8. package/packages/@monomind/cli/.claude/helpers/hook-handler.cjs +21 -0
  9. package/packages/@monomind/cli/.claude/helpers/utils/monograph.cjs +73 -2
  10. package/packages/@monomind/cli/.claude/skills/mastermind-skills/createorg.md +91 -701
  11. package/packages/@monomind/cli/.claude/skills/mastermind-skills/org-settings.md +46 -47
  12. package/packages/@monomind/cli/.claude/skills/mastermind-skills/runorg.md +12 -1
  13. package/packages/@monomind/cli/README.md +77 -94
  14. package/packages/@monomind/cli/dist/src/browser/workflow/store.d.ts +2 -2
  15. package/packages/@monomind/cli/dist/src/commands/browse.d.ts +1 -1
  16. package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.js +5 -0
  17. package/packages/@monomind/cli/dist/src/commands/org.js +46 -29
  18. package/packages/@monomind/cli/dist/src/commands/platforms.d.ts +1 -1
  19. package/packages/@monomind/cli/dist/src/init/executor.js +30 -6
  20. package/packages/@monomind/cli/dist/src/mcp-tools/auto-install.d.ts +8 -8
  21. package/packages/@monomind/cli/dist/src/mcp-tools/coherence/types.d.ts +31 -31
  22. package/packages/@monomind/cli/dist/src/mcp-tools/hive-mind-tools.js +5 -1
  23. package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +28 -3
  24. package/packages/@monomind/cli/dist/src/mcp-tools/quality/coverage-analysis/prioritize-gaps.d.ts +36 -36
  25. package/packages/@monomind/cli/dist/src/mcp-tools/quality/security-compliance/detect-secrets.d.ts +4 -4
  26. package/packages/@monomind/cli/dist/src/memory/ewc-consolidation.d.ts +12 -0
  27. package/packages/@monomind/cli/dist/src/memory/sona-optimizer.d.ts +12 -0
  28. package/packages/@monomind/cli/dist/src/orgrt/broker.d.ts +3 -1
  29. package/packages/@monomind/cli/dist/src/orgrt/broker.js +8 -3
  30. package/packages/@monomind/cli/dist/src/orgrt/bus.d.ts +5 -1
  31. package/packages/@monomind/cli/dist/src/orgrt/bus.js +5 -1
  32. package/packages/@monomind/cli/dist/src/orgrt/daemon.d.ts +35 -1
  33. package/packages/@monomind/cli/dist/src/orgrt/daemon.js +190 -21
  34. package/packages/@monomind/cli/dist/src/orgrt/forwarder.js +47 -10
  35. package/packages/@monomind/cli/dist/src/orgrt/inbox.d.ts +11 -0
  36. package/packages/@monomind/cli/dist/src/orgrt/inbox.js +56 -0
  37. package/packages/@monomind/cli/dist/src/orgrt/policy.d.ts +5 -1
  38. package/packages/@monomind/cli/dist/src/orgrt/policy.js +58 -5
  39. package/packages/@monomind/cli/dist/src/orgrt/server.d.ts +3 -2
  40. package/packages/@monomind/cli/dist/src/orgrt/server.js +31 -40
  41. package/packages/@monomind/cli/dist/src/orgrt/session.d.ts +11 -1
  42. package/packages/@monomind/cli/dist/src/orgrt/session.js +32 -1
  43. package/packages/@monomind/cli/dist/src/orgrt/test-loop.js +8 -8
  44. package/packages/@monomind/cli/dist/src/orgrt/types.d.ts +53 -53
  45. package/packages/@monomind/cli/dist/src/output.d.ts +29 -29
  46. package/packages/@monomind/cli/dist/src/output.js +10 -2
  47. package/packages/@monomind/cli/dist/src/pricing/model-pricing.d.ts +1 -1
  48. package/packages/@monomind/cli/dist/src/types.d.ts +2 -2
  49. package/packages/@monomind/cli/dist/src/ui/collector.mjs +20 -5
  50. package/packages/@monomind/cli/dist/src/ui/dashboard.html +465 -500
  51. package/packages/@monomind/cli/dist/src/ui/orgs-files.js +192 -0
  52. package/packages/@monomind/cli/dist/src/ui/orgs.html +21 -52
  53. package/packages/@monomind/cli/dist/src/ui/server.mjs +174 -164
  54. package/packages/@monomind/cli/package.json +12 -16
  55. package/packages/@monomind/cli/scripts/publish.sh +6 -0
  56. package/scripts/generate-agent-avatars.mjs +3 -3
  57. package/packages/@monomind/cli/dist/src/orgrt/live.html +0 -56
@@ -19,12 +19,20 @@ function validateOrgName(name) {
19
19
  }
20
20
  return { ok: true, name };
21
21
  }
22
- /** Config filenames for real orgs under orgsDir — excludes org-internal
23
- * artifact files (state/goals/threads/etc) that share the .json extension. */
24
- const ORG_ARTIFACT_SUFFIXES = ['-state', '-goals', '-threads', '-activity', '-approvals', '-members', '-secrets', '-budgets'];
22
+ /** Suffixes of org-internal artifact files (state/goals/threads/etc) that
23
+ * share the `<org>.json`/`.jsonl` naming pattern with the org's own config
24
+ * file. Single source of truth for both listOrgConfigFiles() (which must
25
+ * exclude them when discovering real org configs) and deleteAction (which
26
+ * must remove all of them when deleting an org). */
27
+ const ORG_ARTIFACT_SUFFIXES = [
28
+ '-state', '-goals', '-threads', '-activity', '-approvals', '-members', '-secrets', '-budgets',
29
+ '-routines', '-issues', '-projects', '-workspaces', '-worktrees', '-environments',
30
+ '-plugins', '-adapters', '-join-requests', '-bootstrap', '-project-workspaces',
31
+ '-approval-comments', '-skills',
32
+ ];
25
33
  function listOrgConfigFiles(orgsDir) {
26
34
  return readdirSync(orgsDir)
27
- .filter(f => f.endsWith('.json') && !ORG_ARTIFACT_SUFFIXES.some(suf => f.includes(suf)));
35
+ .filter(f => f.endsWith('.json') && !f.startsWith('._') && !ORG_ARTIFACT_SUFFIXES.some(suf => f.includes(suf)));
28
36
  }
29
37
  /** Remove a lingering stopfile so a fresh `org run` doesn't self-terminate. */
30
38
  export const clearStopfile = (cwd, name) => {
@@ -32,22 +40,27 @@ export const clearStopfile = (cwd, name) => {
32
40
  };
33
41
  const runAction = async (ctx) => {
34
42
  if (!ctx.args[0])
35
- return { success: false, message: 'org name required: monomind org run <name> [--task "..."] [--serve] [--port N]' };
43
+ return { success: false, message: 'org name required: monomind org run <name> [--task "..."]' };
36
44
  const validated = validateOrgName(ctx.args[0]);
37
45
  if (!validated.ok)
38
46
  return validated.result;
39
47
  const name = validated.name;
48
+ // A repeated --task flag is promoted to an array by the parser (deliberate,
49
+ // documented behavior elsewhere — repeats never silently drop a value); a
50
+ // plain `as string` cast would let that array flow straight into the org's
51
+ // goal and get stringified as "a,b" with no warning. Checked before any
52
+ // side effects (starting the xdeliver listener) run.
53
+ const taskFlag = ctx.flags['task'];
54
+ if (Array.isArray(taskFlag))
55
+ return { success: false, message: '--task was passed more than once — pass it exactly once' };
40
56
  const crossProcess = ctx.flags['crossProcess'] !== false;
41
57
  const daemon = new OrgDaemon(ctx.cwd, { crossProcess });
42
58
  let srv;
43
- if (ctx.flags['serve'] !== false) {
44
- const port = Number(ctx.flags['port'] ?? 4243);
45
- srv = await startOrgServer(daemon, port);
46
- log(output.info(`org live view: http://localhost:${srv.port}`));
47
- if (crossProcess)
48
- daemon.setInboxUrl(`http://127.0.0.1:${srv.port}`);
59
+ if (crossProcess) {
60
+ srv = await startOrgServer(daemon, 0);
61
+ daemon.setInboxUrl(`http://127.0.0.1:${srv.port}`);
49
62
  }
50
- const running = await daemon.startOrg(name, ctx.flags['task']);
63
+ const running = await daemon.startOrg(name, taskFlag);
51
64
  log(output.info(`org ${name} running (${running.def.roles.length} agents, run ${running.run}) — Ctrl-C or "monomind org stop ${name}" to stop`));
52
65
  // stopfile poll lets `org stop` work from another terminal;
53
66
  // clear any stale stopfile from a previous run before polling
@@ -101,10 +114,12 @@ const statusAction = async (ctx) => {
101
114
  const serveAction = async (ctx) => {
102
115
  const crossProcess = ctx.flags['crossProcess'] !== false;
103
116
  const daemon = new OrgDaemon(ctx.cwd, { crossProcess });
104
- const srv = await startOrgServer(daemon, Number(ctx.flags['port'] ?? 4243));
105
- log(output.info(`org daemon serving on http://localhost:${srv.port} — Ctrl-C to stop`));
106
- if (crossProcess)
117
+ let srv;
118
+ if (crossProcess) {
119
+ srv = await startOrgServer(daemon, 0);
107
120
  daemon.setInboxUrl(`http://127.0.0.1:${srv.port}`);
121
+ }
122
+ log(output.info('org daemon serving — Ctrl-C to stop'));
108
123
  // schedule orgs whose definition declares an interval (e.g. "15m", "2h")
109
124
  const { OrgScheduler, parseSchedule } = await import('../orgrt/scheduler.js');
110
125
  const sched = new OrgScheduler(async (name, intervalMs) => {
@@ -137,7 +152,7 @@ const serveAction = async (ctx) => {
137
152
  });
138
153
  const orgDir = join(ctx.cwd, ORG_DIR);
139
154
  if (existsSync(orgDir)) {
140
- for (const f of readdirSync(orgDir).filter(f => f.endsWith('.json'))) {
155
+ for (const f of listOrgConfigFiles(orgDir)) {
141
156
  try {
142
157
  const def = JSON.parse(readFileSync(join(orgDir, f), 'utf8'));
143
158
  const ms = parseSchedule(def.schedule);
@@ -150,13 +165,15 @@ const serveAction = async (ctx) => {
150
165
  log(output.info(`scheduled org ${stem} every ${Math.round(ms / 60_000)}m`));
151
166
  }
152
167
  }
153
- catch { /* skip unparseable org file */ }
168
+ catch (err) {
169
+ log(output.warning(`org file ${f}: could not parse — skipping (${err instanceof Error ? err.message : 'invalid JSON'})`));
170
+ }
154
171
  }
155
172
  }
156
173
  await new Promise(r => { process.once('SIGINT', () => r()); process.once('SIGTERM', () => r()); });
157
174
  sched.stop();
158
175
  await daemon.stopAll();
159
- srv.close();
176
+ srv?.close();
160
177
  return { success: true };
161
178
  };
162
179
  const testLoopAction = async (ctx) => {
@@ -191,7 +208,7 @@ const deleteAction = async (ctx) => {
191
208
  log(output.error('Usage: monomind org delete <name>'));
192
209
  return { success: false, message: 'org name required' };
193
210
  }
194
- if (!/^[a-z0-9][a-z0-9_-]*$/i.test(orgName)) {
211
+ if (!ORG_NAME_RE.test(orgName)) {
195
212
  log(output.error(`Invalid org name: ${orgName}`));
196
213
  return { success: false, message: 'invalid org name' };
197
214
  }
@@ -208,12 +225,8 @@ const deleteAction = async (ctx) => {
208
225
  log(output.error(`Org not found: ${orgName}`));
209
226
  return { success: false, message: 'org not found' };
210
227
  }
211
- const suffixes = ['', '-state', '-goals', '-routines', '-approvals', '-activity',
212
- '-issues', '-members', '-projects', '-workspaces', '-worktrees', '-environments',
213
- '-plugins', '-adapters', '-budgets', '-threads', '-secrets', '-join-requests',
214
- '-bootstrap', '-project-workspaces', '-approval-comments', '-skills'];
215
228
  let removed = 0;
216
- for (const suf of suffixes) {
229
+ for (const suf of ['', ...ORG_ARTIFACT_SUFFIXES]) {
217
230
  for (const ext of ['.json', '.jsonl']) {
218
231
  const f = join(orgsDir, `${orgName}${suf}${ext}`);
219
232
  try {
@@ -248,7 +261,7 @@ const deleteAction = async (ctx) => {
248
261
  };
249
262
  const markCompleteAction = async (ctx) => {
250
263
  const orgName = ctx.args[0];
251
- if (!orgName || !/^[a-z0-9][a-z0-9_-]*$/i.test(orgName)) {
264
+ if (!orgName || !ORG_NAME_RE.test(orgName)) {
252
265
  log(output.error('Usage: monomind org mark-complete <name>'));
253
266
  return { success: false, message: 'valid org name required' };
254
267
  }
@@ -284,8 +297,6 @@ export const orgCommand = {
284
297
  name: 'run', description: 'Start an org (foreground daemon)',
285
298
  options: [
286
299
  { name: 'task', description: 'Override the org goal for this run', type: 'string' },
287
- { name: 'serve', description: 'Serve the live dashboard (default true)', type: 'boolean', default: true },
288
- { name: 'port', description: 'Live dashboard port', type: 'number', default: 4243 },
289
300
  { name: 'cross-process', description: 'Discover and message orgs hosted by other monomind processes on this machine (default true)', type: 'boolean', default: true },
290
301
  ],
291
302
  examples: [{ command: 'monomind org run growth --task "weekly report"', description: 'Run the growth org once with a task' }],
@@ -296,7 +307,6 @@ export const orgCommand = {
296
307
  {
297
308
  name: 'serve', description: 'Start the daemon server only (hosts scheduled orgs)',
298
309
  options: [
299
- { name: 'port', description: 'Port', type: 'number', default: 4243 },
300
310
  { name: 'cross-process', description: 'Discover and message orgs hosted by other monomind processes on this machine (default true)', type: 'boolean', default: true },
301
311
  ],
302
312
  action: serveAction,
@@ -315,7 +325,14 @@ export const orgCommand = {
315
325
  { name: 'mark-complete', description: 'Manually close a stale/crashed run', action: markCompleteAction },
316
326
  ],
317
327
  examples: [{ command: 'monomind org run my-org', description: 'Run an org under full daemon control' }],
318
- action: async () => ({ success: false, message: 'usage: monomind org <run|stop|status|serve|test-loop|list|delete|mark-complete>' }),
328
+ action: async () => {
329
+ // index.ts's dispatcher never prints result.message on a failed action —
330
+ // it only exits with result.exitCode — so this must log itself or bare
331
+ // `monomind org` exits silently with code 1 and zero output.
332
+ const message = 'usage: monomind org <run|stop|status|serve|test-loop|list|delete|mark-complete>';
333
+ log(output.error(message));
334
+ return { success: false, message };
335
+ },
319
336
  };
320
337
  export default orgCommand;
321
338
  //# sourceMappingURL=org.js.map
@@ -5,7 +5,7 @@
5
5
  * github.com/monoes/monomind
6
6
  */
7
7
  import type { Command } from '../types.js';
8
- export declare const SUPPORTED_PLATFORMS: readonly ["claude", "gemini", "cursor", "vscode", "copilot", "opencode", "aider", "kiro", "trae", "claw", "droid", "antigravity", "hermes", "codex"];
8
+ export declare const SUPPORTED_PLATFORMS: readonly ['claude', 'gemini', 'cursor', 'vscode', 'copilot', 'opencode', 'aider', 'kiro', 'trae', 'claw', 'droid', 'antigravity', 'hermes', 'codex'];
9
9
  export type Platform = typeof SUPPORTED_PLATFORMS[number];
10
10
  export declare const platformsCommand: Command;
11
11
  //# sourceMappingURL=platforms.d.ts.map
@@ -575,6 +575,13 @@ export async function executeUpgrade(targetDir, upgradeSettings = false) {
575
575
  const destHelpersDir = path.join(targetDir, '.claude', 'helpers');
576
576
  // Copy top-level critical files atomically
577
577
  const criticalHelpers = ['auto-memory-hook.mjs', 'hook-handler.cjs', 'intelligence.cjs', 'statusline.cjs', 'graphify-freshen.cjs'];
578
+ // Generated fallback for any critical helper missing from the source dir itself
579
+ // (e.g. the published npm template lacking auto-memory-hook.mjs).
580
+ const criticalGenerators = {
581
+ 'hook-handler.cjs': generateHookHandler,
582
+ 'intelligence.cjs': generateIntelligenceStub,
583
+ 'auto-memory-hook.mjs': generateAutoMemoryHook,
584
+ };
578
585
  for (const helperName of criticalHelpers) {
579
586
  const targetPath = path.join(destHelpersDir, helperName);
580
587
  const sourcePath = path.join(sourceHelpersForUpgrade, helperName);
@@ -594,6 +601,17 @@ export async function executeUpgrade(targetDir, upgradeSettings = false) {
594
601
  catch { }
595
602
  fs.renameSync(tmp, targetPath);
596
603
  }
604
+ else if (!fs.existsSync(targetPath) && criticalGenerators[helperName]) {
605
+ const content = criticalGenerators[helperName]();
606
+ const tmp = `${targetPath}.${process.pid}.tmp`;
607
+ fs.writeFileSync(tmp, content, 'utf-8');
608
+ try {
609
+ fs.chmodSync(tmp, 0o755);
610
+ }
611
+ catch { }
612
+ fs.renameSync(tmp, targetPath);
613
+ result.created.push(`.claude/helpers/${helperName}`);
614
+ }
597
615
  }
598
616
  // Always recursively sync subdirectories (utils/, handlers/) — required by hook-handler.cjs.
599
617
  // Uses recursive copy so any future nested subdirs are also covered.
@@ -1222,7 +1240,6 @@ async function writeHelpers(targetDir, options, result) {
1222
1240
  const sourceHelpersDir = findSourceHelpersDir(options.sourceBaseDir);
1223
1241
  // Try to copy existing helpers from source first (recursive — includes utils/ and handlers/)
1224
1242
  if (sourceHelpersDir && fs.existsSync(sourceHelpersDir)) {
1225
- let copiedCount = 0;
1226
1243
  const copyRecursive = (srcDir, destDir, relBase) => {
1227
1244
  fs.mkdirSync(destDir, { recursive: true });
1228
1245
  for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
@@ -1242,7 +1259,6 @@ async function writeHelpers(targetDir, options, result) {
1242
1259
  fs.chmodSync(destPath, '755');
1243
1260
  }
1244
1261
  result.created.files.push(`.claude/helpers/${relPath}`);
1245
- copiedCount++;
1246
1262
  }
1247
1263
  else {
1248
1264
  result.skipped.push(`.claude/helpers/${relPath}`);
@@ -1251,11 +1267,12 @@ async function writeHelpers(targetDir, options, result) {
1251
1267
  }
1252
1268
  };
1253
1269
  copyRecursive(sourceHelpersDir, helpersDir, '');
1254
- if (copiedCount > 0) {
1255
- return; // Skip generating if we copied from source
1256
- }
1257
1270
  }
1258
- // Fall back to generating helpers if source not available
1271
+ // Always run the fallback generator too it only fills in files still missing
1272
+ // after the source copy above (it no-ops on anything the copy already wrote).
1273
+ // Without this, a source dir that's present but incomplete (e.g. missing
1274
+ // auto-memory-hook.mjs) silently ships a project wired to hooks that reference
1275
+ // a file that was never installed.
1259
1276
  const helpers = {
1260
1277
  'pre-commit': generatePreCommitHook(),
1261
1278
  'post-commit': generatePostCommitHook(),
@@ -1268,6 +1285,13 @@ async function writeHelpers(targetDir, options, result) {
1268
1285
  };
1269
1286
  for (const [name, content] of Object.entries(helpers)) {
1270
1287
  const filePath = path.join(helpersDir, name);
1288
+ // If the source dir has this file, copyRecursive above already applied
1289
+ // the correct (force-aware) copy — never let this generated fallback
1290
+ // clobber it with a bare-bones stub. Only step in when source truly
1291
+ // doesn't have the file, regardless of `force`.
1292
+ const inSource = !!(sourceHelpersDir && fs.existsSync(path.join(sourceHelpersDir, name)));
1293
+ if (inSource)
1294
+ continue;
1271
1295
  if (!fs.existsSync(filePath) || options.force) {
1272
1296
  atomicWriteFile(filePath, content);
1273
1297
  // Make shell scripts executable
@@ -47,12 +47,12 @@ export declare function resetInstallAttempts(): void;
47
47
  */
48
48
  export declare const OPTIONAL_PACKAGES: {
49
49
  readonly 'monofence-ai': {
50
- readonly description: "AI manipulation defense (prompt injection, PII detection)";
51
- readonly tools: readonly ["aidefence_scan", "aidefence_analyze", "aidefence_stats", "aidefence_learn"];
50
+ readonly description: 'AI manipulation defense (prompt injection, PII detection)';
51
+ readonly tools: readonly ['aidefence_scan', 'aidefence_analyze', 'aidefence_stats', 'aidefence_learn'];
52
52
  };
53
53
  readonly 'onnxruntime-node': {
54
- readonly description: "ONNX runtime for neural network inference";
55
- readonly tools: readonly ["neural_*"];
54
+ readonly description: 'ONNX runtime for neural network inference';
55
+ readonly tools: readonly ['neural_*'];
56
56
  };
57
57
  };
58
58
  declare const _default: {
@@ -62,12 +62,12 @@ declare const _default: {
62
62
  resetInstallAttempts: typeof resetInstallAttempts;
63
63
  OPTIONAL_PACKAGES: {
64
64
  readonly 'monofence-ai': {
65
- readonly description: "AI manipulation defense (prompt injection, PII detection)";
66
- readonly tools: readonly ["aidefence_scan", "aidefence_analyze", "aidefence_stats", "aidefence_learn"];
65
+ readonly description: 'AI manipulation defense (prompt injection, PII detection)';
66
+ readonly tools: readonly ['aidefence_scan', 'aidefence_analyze', 'aidefence_stats', 'aidefence_learn'];
67
67
  };
68
68
  readonly 'onnxruntime-node': {
69
- readonly description: "ONNX runtime for neural network inference";
70
- readonly tools: readonly ["neural_*"];
69
+ readonly description: 'ONNX runtime for neural network inference';
70
+ readonly tools: readonly ['neural_*'];
71
71
  };
72
72
  };
73
73
  };
@@ -69,8 +69,8 @@ export declare const CoherenceInputSchema: z.ZodObject<{
69
69
  vectors: z.ZodArray<z.ZodArray<z.ZodNumber, "many">, "many">;
70
70
  threshold: z.ZodDefault<z.ZodNumber>;
71
71
  }, "strip", z.ZodTypeAny, {
72
- threshold: number;
73
72
  vectors: number[][];
73
+ threshold: number;
74
74
  }, {
75
75
  vectors: number[][];
76
76
  threshold?: number | undefined;
@@ -98,10 +98,10 @@ export declare const SpectralInputSchema: z.ZodObject<{
98
98
  analyzeType: z.ZodDefault<z.ZodEnum<["stability", "clustering", "connectivity"]>>;
99
99
  }, "strip", z.ZodTypeAny, {
100
100
  matrix: number[][];
101
- analyzeType: "stability" | "clustering" | "connectivity";
101
+ analyzeType: "clustering" | "connectivity" | "stability";
102
102
  }, {
103
103
  matrix: number[][];
104
- analyzeType?: "stability" | "clustering" | "connectivity" | undefined;
104
+ analyzeType?: "clustering" | "connectivity" | "stability" | undefined;
105
105
  }>;
106
106
  export type SpectralInput = z.infer<typeof SpectralInputSchema>;
107
107
  export interface SpectralResult {
@@ -150,15 +150,15 @@ export declare const CausalInputSchema: z.ZodObject<{
150
150
  nodes: string[];
151
151
  edges: [string, string][];
152
152
  };
153
- outcome: string;
154
153
  intervention: string;
154
+ outcome: string;
155
155
  }, {
156
156
  graph: {
157
157
  nodes: string[];
158
158
  edges: [string, string][];
159
159
  };
160
- outcome: string;
161
160
  intervention: string;
161
+ outcome: string;
162
162
  }>;
163
163
  export type CausalInput = z.infer<typeof CausalInputSchema>;
164
164
  export interface CausalResult {
@@ -185,13 +185,13 @@ export declare const AgentStateSchema: z.ZodObject<{
185
185
  }, "strip", z.ZodTypeAny, {
186
186
  agentId: string;
187
187
  embedding: number[];
188
- metadata?: Record<string, unknown> | undefined;
189
188
  vote?: string | undefined;
189
+ metadata?: Record<string, unknown> | undefined;
190
190
  }, {
191
191
  agentId: string;
192
192
  embedding: number[];
193
- metadata?: Record<string, unknown> | undefined;
194
193
  vote?: string | undefined;
194
+ metadata?: Record<string, unknown> | undefined;
195
195
  }>;
196
196
  export type AgentState = z.infer<typeof AgentStateSchema>;
197
197
  export declare const ConsensusInputSchema: z.ZodObject<{
@@ -203,29 +203,29 @@ export declare const ConsensusInputSchema: z.ZodObject<{
203
203
  }, "strip", z.ZodTypeAny, {
204
204
  agentId: string;
205
205
  embedding: number[];
206
- metadata?: Record<string, unknown> | undefined;
207
206
  vote?: string | undefined;
207
+ metadata?: Record<string, unknown> | undefined;
208
208
  }, {
209
209
  agentId: string;
210
210
  embedding: number[];
211
- metadata?: Record<string, unknown> | undefined;
212
211
  vote?: string | undefined;
212
+ metadata?: Record<string, unknown> | undefined;
213
213
  }>, "many">;
214
214
  threshold: z.ZodDefault<z.ZodNumber>;
215
215
  }, "strip", z.ZodTypeAny, {
216
- threshold: number;
217
216
  agentStates: {
218
217
  agentId: string;
219
218
  embedding: number[];
220
- metadata?: Record<string, unknown> | undefined;
221
219
  vote?: string | undefined;
220
+ metadata?: Record<string, unknown> | undefined;
222
221
  }[];
222
+ threshold: number;
223
223
  }, {
224
224
  agentStates: {
225
225
  agentId: string;
226
226
  embedding: number[];
227
- metadata?: Record<string, unknown> | undefined;
228
227
  vote?: string | undefined;
228
+ metadata?: Record<string, unknown> | undefined;
229
229
  }[];
230
230
  threshold?: number | undefined;
231
231
  }>;
@@ -247,11 +247,11 @@ export declare const SimplexSchema: z.ZodObject<{
247
247
  vertices: z.ZodArray<z.ZodNumber, "many">;
248
248
  dimension: z.ZodNumber;
249
249
  }, "strip", z.ZodTypeAny, {
250
- dimension: number;
251
250
  vertices: number[];
252
- }, {
253
251
  dimension: number;
252
+ }, {
254
253
  vertices: number[];
254
+ dimension: number;
255
255
  }>;
256
256
  export type Simplex = z.infer<typeof SimplexSchema>;
257
257
  export declare const SimplicialComplexSchema: z.ZodObject<{
@@ -260,25 +260,25 @@ export declare const SimplicialComplexSchema: z.ZodObject<{
260
260
  vertices: z.ZodArray<z.ZodNumber, "many">;
261
261
  dimension: z.ZodNumber;
262
262
  }, "strip", z.ZodTypeAny, {
263
- dimension: number;
264
263
  vertices: number[];
265
- }, {
266
264
  dimension: number;
265
+ }, {
267
266
  vertices: number[];
267
+ dimension: number;
268
268
  }>, "many">>;
269
269
  maxDimension: z.ZodDefault<z.ZodNumber>;
270
270
  }, "strip", z.ZodTypeAny, {
271
271
  vertices: number[][];
272
- maxDimension: number;
273
272
  simplices?: {
274
- dimension: number;
275
273
  vertices: number[];
274
+ dimension: number;
276
275
  }[] | undefined;
276
+ maxDimension: number;
277
277
  }, {
278
278
  vertices: number[][];
279
279
  simplices?: {
280
- dimension: number;
281
280
  vertices: number[];
281
+ dimension: number;
282
282
  }[] | undefined;
283
283
  maxDimension?: number | undefined;
284
284
  }>;
@@ -290,43 +290,43 @@ export declare const TopologyInputSchema: z.ZodObject<{
290
290
  vertices: z.ZodArray<z.ZodNumber, "many">;
291
291
  dimension: z.ZodNumber;
292
292
  }, "strip", z.ZodTypeAny, {
293
- dimension: number;
294
293
  vertices: number[];
295
- }, {
296
294
  dimension: number;
295
+ }, {
297
296
  vertices: number[];
297
+ dimension: number;
298
298
  }>, "many">>;
299
299
  maxDimension: z.ZodDefault<z.ZodNumber>;
300
300
  }, "strip", z.ZodTypeAny, {
301
301
  vertices: number[][];
302
- maxDimension: number;
303
302
  simplices?: {
304
- dimension: number;
305
303
  vertices: number[];
304
+ dimension: number;
306
305
  }[] | undefined;
306
+ maxDimension: number;
307
307
  }, {
308
308
  vertices: number[][];
309
309
  simplices?: {
310
- dimension: number;
311
310
  vertices: number[];
311
+ dimension: number;
312
312
  }[] | undefined;
313
313
  maxDimension?: number | undefined;
314
314
  }>;
315
315
  }, "strip", z.ZodTypeAny, {
316
316
  complex: {
317
317
  vertices: number[][];
318
- maxDimension: number;
319
318
  simplices?: {
320
- dimension: number;
321
319
  vertices: number[];
320
+ dimension: number;
322
321
  }[] | undefined;
322
+ maxDimension: number;
323
323
  };
324
324
  }, {
325
325
  complex: {
326
326
  vertices: number[][];
327
327
  simplices?: {
328
- dimension: number;
329
328
  vertices: number[];
329
+ dimension: number;
330
330
  }[] | undefined;
331
331
  maxDimension?: number | undefined;
332
332
  };
@@ -362,27 +362,27 @@ export declare const MemoryGateInputSchema: z.ZodObject<{
362
362
  reject: z.ZodDefault<z.ZodNumber>;
363
363
  warn: z.ZodDefault<z.ZodNumber>;
364
364
  }, "strip", z.ZodTypeAny, {
365
- warn: number;
366
365
  reject: number;
366
+ warn: number;
367
367
  }, {
368
- warn?: number | undefined;
369
368
  reject?: number | undefined;
369
+ warn?: number | undefined;
370
370
  }>>;
371
371
  }, "strip", z.ZodTypeAny, {
372
372
  key: string;
373
373
  value?: unknown;
374
374
  existingVectors?: number[][] | undefined;
375
375
  thresholds?: {
376
- warn: number;
377
376
  reject: number;
377
+ warn: number;
378
378
  } | undefined;
379
379
  }, {
380
380
  key: string;
381
381
  value?: unknown;
382
382
  existingVectors?: number[][] | undefined;
383
383
  thresholds?: {
384
- warn?: number | undefined;
385
384
  reject?: number | undefined;
385
+ warn?: number | undefined;
386
386
  } | undefined;
387
387
  }>;
388
388
  export type MemoryGateInput = z.infer<typeof MemoryGateInputSchema>;
@@ -406,7 +406,11 @@ export const hiveMindTools = [
406
406
  id: w,
407
407
  type: agent?.agentType || 'worker',
408
408
  status: agent?.status || 'unknown',
409
- currentTask: agent?.currentTask || null,
409
+ // AgentRecord has no currentTask field — always null. Kept in the
410
+ // response shape for API stability; was already dead before this
411
+ // (the previous `as unknown as Record<string, unknown>` cast hid
412
+ // that `agent?.currentTask` never matched a real field).
413
+ currentTask: null,
410
414
  tasksCompleted: agent?.taskCount || 0,
411
415
  };
412
416
  }),
@@ -744,7 +744,10 @@ async function computeCommitsBehind(repoPath) {
744
744
  const dbPath = getDbPath(repoPath);
745
745
  if (!_isValidDb(dbPath))
746
746
  return null;
747
- const db = openDb(dbPath, { fileMustExist: true });
747
+ // openDb's fileMustExist option isn't in the currently-published
748
+ // @monoes/monograph release this CLI depends on — _isValidDb above is the
749
+ // real guard against openDb silently creating an empty DB at a missing path.
750
+ const db = openDb(dbPath);
748
751
  try {
749
752
  const meta = db.prepare("SELECT value FROM index_meta WHERE key = 'last_commit_hash'").get() ?? db.prepare("SELECT value FROM index_meta WHERE key = 'lastCommit'").get();
750
753
  const lastCommit = meta?.value ?? null;
@@ -1761,9 +1764,15 @@ const monographInstallSkillsTool = {
1761
1764
  }
1762
1765
  // Load community data from graph
1763
1766
  const dbPath = getDbPath(repoPath);
1767
+ // openDb's fileMustExist option isn't in the currently-published
1768
+ // @monoes/monograph release this CLI depends on — check validity
1769
+ // ourselves so a missing DB doesn't get silently auto-created empty.
1770
+ if (!_isValidDb(dbPath)) {
1771
+ return text('Graph not built yet. Run monograph_build first.');
1772
+ }
1764
1773
  let db;
1765
1774
  try {
1766
- db = openDb(dbPath, { fileMustExist: true });
1775
+ db = openDb(dbPath);
1767
1776
  }
1768
1777
  catch {
1769
1778
  return text('Graph not built yet. Run monograph_build first.');
@@ -1974,9 +1983,25 @@ const monographDeadCodeTool = {
1974
1983
  const cats = input.categories ?? ['dead-functions', 'orphan-files', 'stale-dist'];
1975
1984
  const result = {};
1976
1985
  const dbPath = getDbPath(repoPath);
1986
+ // openDb's fileMustExist option isn't in the currently-published
1987
+ // @monoes/monograph release this CLI depends on — check validity
1988
+ // ourselves so a missing DB doesn't get silently auto-created empty.
1989
+ if (!_isValidDb(dbPath)) {
1990
+ return text(JSON.stringify({ error: 'No monograph index found. Run monograph_build first.' }));
1991
+ }
1977
1992
  let db = null;
1978
1993
  try {
1979
- db = openDb(dbPath, { fileMustExist: true });
1994
+ db = openDb(dbPath);
1995
+ // _isValidDb's size check can't distinguish a real index from an
1996
+ // empty-but-schema-migrated DB (better-sqlite3 auto-creates + migrates
1997
+ // on open, and other unguarded openDb() call sites in this file can
1998
+ // create exactly that as a side effect of an unrelated tool call before
1999
+ // monograph_build ever runs). Verify actual content post-open so this
2000
+ // reports "never built" instead of a misleading "0 dead functions found".
2001
+ const { count } = db.prepare('SELECT COUNT(*) as count FROM nodes').get();
2002
+ if (count === 0) {
2003
+ return text(JSON.stringify({ error: 'No monograph index found. Run monograph_build first.' }));
2004
+ }
1980
2005
  }
1981
2006
  catch {
1982
2007
  return text(JSON.stringify({ error: 'No monograph index found. Run monograph_build first.' }));