monomind 2.1.9 → 2.3.0
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/package.json +2 -2
- package/packages/@monomind/cli/.claude/commands/mastermind/createorg.md +24 -16
- package/packages/@monomind/cli/.claude/commands/mastermind/master.md +23 -7
- package/packages/@monomind/cli/.claude/commands/mastermind/runorg.md +3 -1
- package/packages/@monomind/cli/.claude/commands/mastermind/stoporg.md +6 -3
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/code-quality-reviewer-prompt.md +3 -3
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/createorg.md +19 -24
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/debug.md +49 -4
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/design.md +11 -10
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/final-reviewer-prompt.md +144 -0
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/implementer-prompt.md +9 -4
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/org-settings.md +20 -2
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/orgs.md +40 -19
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/orgstatus.md +90 -41
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/plan.md +19 -0
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/skill-builder.md +171 -0
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/spec-reviewer-prompt.md +19 -2
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/stoporg.md +7 -5
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/taskdev.md +83 -15
- package/packages/@monomind/cli/.claude/skills/mastermind-skills/tdd.md +30 -0
- package/packages/@monomind/cli/dist/src/autopilot-state.js +6 -4
- package/packages/@monomind/cli/dist/src/browser/dashboard/server.js +4 -1
- package/packages/@monomind/cli/dist/src/capabilities/manager.js +3 -1
- package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.js +26 -0
- package/packages/@monomind/cli/dist/src/commands/agent-ops.js +28 -46
- package/packages/@monomind/cli/dist/src/commands/cleanup.d.ts +18 -0
- package/packages/@monomind/cli/dist/src/commands/cleanup.js +120 -0
- package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.js +13 -4
- package/packages/@monomind/cli/dist/src/commands/hooks-routing-commands.js +34 -18
- package/packages/@monomind/cli/dist/src/commands/hooks-workers.js +8 -2
- package/packages/@monomind/cli/dist/src/commands/hooks.js +1 -1
- package/packages/@monomind/cli/dist/src/commands/init-wizard.js +2 -2
- package/packages/@monomind/cli/dist/src/commands/init.js +54 -10
- package/packages/@monomind/cli/dist/src/commands/mcp.js +4 -1
- package/packages/@monomind/cli/dist/src/commands/memory-admin.js +7 -1
- package/packages/@monomind/cli/dist/src/commands/org-observe.d.ts +18 -0
- package/packages/@monomind/cli/dist/src/commands/org-observe.js +295 -0
- package/packages/@monomind/cli/dist/src/commands/org.d.ts +9 -1
- package/packages/@monomind/cli/dist/src/commands/org.js +191 -9
- package/packages/@monomind/cli/dist/src/commands/performance.js +4 -1
- package/packages/@monomind/cli/dist/src/commands/platforms.js +4 -1
- package/packages/@monomind/cli/dist/src/commands/security-scan.js +8 -2
- package/packages/@monomind/cli/dist/src/commands/start.js +4 -1
- package/packages/@monomind/cli/dist/src/commands/swarm.js +5 -4
- package/packages/@monomind/cli/dist/src/index.js +13 -3
- package/packages/@monomind/cli/dist/src/init/executor.js +19 -5
- package/packages/@monomind/cli/dist/src/init/settings-generator.js +8 -1
- package/packages/@monomind/cli/dist/src/knowledge/document-pipeline.js +3 -2
- package/packages/@monomind/cli/dist/src/mcp-tools/agent-tools.d.ts +1 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/agent-tools.js +63 -20
- package/packages/@monomind/cli/dist/src/mcp-tools/claims-tools.js +3 -1
- package/packages/@monomind/cli/dist/src/mcp-tools/config-tools.js +3 -2
- package/packages/@monomind/cli/dist/src/mcp-tools/daa-tools.js +3 -2
- package/packages/@monomind/cli/dist/src/mcp-tools/embeddings-tools.js +6 -2
- package/packages/@monomind/cli/dist/src/mcp-tools/github-tools.js +35 -10
- package/packages/@monomind/cli/dist/src/mcp-tools/hive-mind-tools.js +24 -7
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-embedding.js +13 -3
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-intelligence.js +9 -3
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-routing.d.ts +1 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-routing.js +112 -10
- package/packages/@monomind/cli/dist/src/mcp-tools/hooks-tools.js +2 -1
- package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +8 -2
- package/packages/@monomind/cli/dist/src/mcp-tools/performance-tools.js +3 -2
- package/packages/@monomind/cli/dist/src/mcp-tools/session-tools.js +15 -5
- package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +4 -1
- package/packages/@monomind/cli/dist/src/mcp-tools/system-tools.js +6 -4
- package/packages/@monomind/cli/dist/src/mcp-tools/task-tools.d.ts +20 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/task-tools.js +38 -16
- package/packages/@monomind/cli/dist/src/mcp-tools/terminal-tools.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/mcp-tools/terminal-tools.js +68 -24
- package/packages/@monomind/cli/dist/src/memory/ewc-consolidation.js +6 -2
- package/packages/@monomind/cli/dist/src/memory/intelligence.js +32 -10
- package/packages/@monomind/cli/dist/src/memory/memory-bridge.js +16 -4
- package/packages/@monomind/cli/dist/src/memory/memory-crud.js +26 -2
- package/packages/@monomind/cli/dist/src/memory/memory-initializer.js +3 -2
- package/packages/@monomind/cli/dist/src/memory/memory-migrations.js +2 -0
- package/packages/@monomind/cli/dist/src/monovector/command-outcomes.js +4 -1
- package/packages/@monomind/cli/dist/src/orgrt/bus.js +4 -1
- package/packages/@monomind/cli/dist/src/orgrt/daemon.js +74 -19
- package/packages/@monomind/cli/dist/src/orgrt/inbox.js +3 -1
- package/packages/@monomind/cli/dist/src/orgrt/reporting.d.ts +40 -0
- package/packages/@monomind/cli/dist/src/orgrt/reporting.js +127 -0
- package/packages/@monomind/cli/dist/src/orgrt/session.d.ts +2 -0
- package/packages/@monomind/cli/dist/src/orgrt/session.js +10 -2
- package/packages/@monomind/cli/dist/src/orgrt/templates.d.ts +16 -0
- package/packages/@monomind/cli/dist/src/orgrt/templates.js +57 -0
- package/packages/@monomind/cli/dist/src/services/config-file-manager.js +10 -1
- package/packages/@monomind/cli/dist/src/transfer/storage/gcs.js +6 -2
- package/packages/@monomind/cli/dist/src/ui/orgs.html +32 -0
- package/packages/@monomind/cli/dist/src/ui/server.mjs +25 -0
- package/packages/@monomind/cli/dist/src/update/executor.js +3 -1
- package/packages/@monomind/cli/dist/src/update/rate-limiter.js +3 -1
- package/packages/@monomind/cli/package.json +2 -2
|
@@ -4,13 +4,13 @@ import { join, resolve } from 'node:path';
|
|
|
4
4
|
import { output } from '../output.js';
|
|
5
5
|
import { OrgDaemon } from '../orgrt/daemon.js';
|
|
6
6
|
import { startOrgServer } from '../orgrt/server.js';
|
|
7
|
-
import { ORG_DIR } from '../orgrt/types.js';
|
|
7
|
+
import { ORG_DIR, OrgDefSchema } from '../orgrt/types.js';
|
|
8
8
|
const log = (text) => { console.log(text); };
|
|
9
9
|
/** Org names are used to build filesystem paths under .monomind/orgs — reject
|
|
10
10
|
* anything that isn't a plain identifier to prevent path traversal (e.g.
|
|
11
11
|
* `monomind org stop '../../../../tmp/x'`). */
|
|
12
12
|
const ORG_NAME_RE = /^[a-z0-9][a-z0-9_-]*$/i;
|
|
13
|
-
function validateOrgName(name) {
|
|
13
|
+
export function validateOrgName(name) {
|
|
14
14
|
if (!name)
|
|
15
15
|
return { ok: false, result: { success: false, message: 'org name required' } };
|
|
16
16
|
if (!ORG_NAME_RE.test(name)) {
|
|
@@ -30,7 +30,7 @@ const ORG_ARTIFACT_SUFFIXES = [
|
|
|
30
30
|
'-plugins', '-adapters', '-join-requests', '-bootstrap', '-project-workspaces',
|
|
31
31
|
'-approval-comments', '-skills',
|
|
32
32
|
];
|
|
33
|
-
function listOrgConfigFiles(orgsDir) {
|
|
33
|
+
export function listOrgConfigFiles(orgsDir) {
|
|
34
34
|
return readdirSync(orgsDir)
|
|
35
35
|
.filter(f => f.endsWith('.json') && !f.startsWith('._') && !ORG_ARTIFACT_SUFFIXES.some(suf => f.includes(suf)));
|
|
36
36
|
}
|
|
@@ -53,6 +53,32 @@ const runAction = async (ctx) => {
|
|
|
53
53
|
const taskFlag = ctx.flags['task'];
|
|
54
54
|
if (Array.isArray(taskFlag))
|
|
55
55
|
return { success: false, message: '--task was passed more than once — pass it exactly once' };
|
|
56
|
+
// Fail before any side effects (inbox server) when the org doesn't exist.
|
|
57
|
+
const orgsDir = join(ctx.cwd, ORG_DIR);
|
|
58
|
+
if (!existsSync(join(orgsDir, `${name}.json`))) {
|
|
59
|
+
const known = existsSync(orgsDir) ? listOrgConfigFiles(orgsDir).map(f => f.replace(/\.json$/, '')) : [];
|
|
60
|
+
log(output.error(`Org not found: ${name}${known.length ? ` — available: ${known.join(', ')}` : ' — create one with /mastermind:createorg'}`));
|
|
61
|
+
return { success: false, message: 'org not found' };
|
|
62
|
+
}
|
|
63
|
+
if (ctx.flags['dryRun'] === true) {
|
|
64
|
+
// Validate + preview each role's actual briefing without spawning sessions.
|
|
65
|
+
try {
|
|
66
|
+
const def = OrgDefSchema.parse(JSON.parse(readFileSync(join(orgsDir, `${name}.json`), 'utf8')));
|
|
67
|
+
const { buildRolePrompt } = await import('../orgrt/session.js');
|
|
68
|
+
const roster = def.roles.map(r => r.id);
|
|
69
|
+
const perRole = Math.floor((def.run_config.budget_tokens ?? 1_000_000) / def.roles.length);
|
|
70
|
+
log(output.info(`DRY RUN — org ${name}: ${def.roles.length} roles, ${perRole} tokens each, goal: ${taskFlag ?? def.goal}`));
|
|
71
|
+
for (const role of def.roles) {
|
|
72
|
+
log(output.info(`\n─── ${role.id} (${role.title || role.type})${role.adapter_config?.model ? ` [${role.adapter_config.model}]` : ''} ───`));
|
|
73
|
+
log(buildRolePrompt(role, { name: def.name, goal: taskFlag ?? def.goal }, roster));
|
|
74
|
+
}
|
|
75
|
+
return { success: true, message: 'dry run complete — no sessions started' };
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
log(output.error(`Config invalid: ${err instanceof Error ? err.message : String(err)}`));
|
|
79
|
+
return { success: false, message: 'invalid org config' };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
56
82
|
const crossProcess = ctx.flags['crossProcess'] !== false;
|
|
57
83
|
const daemon = new OrgDaemon(ctx.cwd, { crossProcess });
|
|
58
84
|
let srv;
|
|
@@ -60,7 +86,20 @@ const runAction = async (ctx) => {
|
|
|
60
86
|
srv = await startOrgServer(daemon, 0);
|
|
61
87
|
daemon.setInboxUrl(`http://127.0.0.1:${srv.port}`);
|
|
62
88
|
}
|
|
63
|
-
|
|
89
|
+
let running;
|
|
90
|
+
try {
|
|
91
|
+
running = await daemon.startOrg(name, taskFlag);
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
// Don't leave the inbox server holding the event loop open on a failed start.
|
|
95
|
+
srv?.close();
|
|
96
|
+
await daemon.stopAll().catch(() => { });
|
|
97
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
98
|
+
const hint = err instanceof Error && err.name === 'ZodError'
|
|
99
|
+
? ` — run "monomind org validate ${name}" for details` : '';
|
|
100
|
+
log(output.error(`Could not start org ${name}: ${detail}${hint}`));
|
|
101
|
+
return { success: false, message: 'org start failed' };
|
|
102
|
+
}
|
|
64
103
|
log(output.info(`org ${name} running (${running.def.roles.length} agents, run ${running.run}) — Ctrl-C or "monomind org stop ${name}" to stop`));
|
|
65
104
|
// stopfile poll lets `org stop` work from another terminal;
|
|
66
105
|
// clear any stale stopfile from a previous run before polling
|
|
@@ -79,18 +118,41 @@ const runAction = async (ctx) => {
|
|
|
79
118
|
srv?.close();
|
|
80
119
|
return { success: true, message: `org ${name} stopped` };
|
|
81
120
|
};
|
|
121
|
+
/** True when runtime.json records a running org whose recorded pid is still alive. */
|
|
122
|
+
const isOrgRunning = (cwd, name) => {
|
|
123
|
+
try {
|
|
124
|
+
const rt = JSON.parse(readFileSync(join(cwd, ORG_DIR, name, 'runtime.json'), 'utf8'));
|
|
125
|
+
if (rt.status !== 'running' || !rt.pid)
|
|
126
|
+
return false;
|
|
127
|
+
process.kill(rt.pid, 0); // throws if the pid is gone (crashed daemon left a stale file)
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
82
134
|
const stopAction = async (ctx) => {
|
|
83
135
|
const validated = validateOrgName(ctx.args[0]);
|
|
84
136
|
if (!validated.ok)
|
|
85
137
|
return validated.result;
|
|
86
138
|
const name = validated.name;
|
|
139
|
+
if (!existsSync(join(ctx.cwd, ORG_DIR, `${name}.json`))) {
|
|
140
|
+
log(output.error(`Org not found: ${name}`));
|
|
141
|
+
return { success: false, message: 'org not found' };
|
|
142
|
+
}
|
|
87
143
|
const { writeFileSync, mkdirSync } = await import('node:fs');
|
|
88
144
|
mkdirSync(join(ctx.cwd, ORG_DIR, name), { recursive: true });
|
|
89
145
|
writeFileSync(join(ctx.cwd, ORG_DIR, name, 'stop'), new Date().toISOString());
|
|
90
146
|
return { success: true, message: `stop requested for ${name} (daemon exits within 2s)` };
|
|
91
147
|
};
|
|
92
148
|
const statusAction = async (ctx) => {
|
|
93
|
-
|
|
149
|
+
let name;
|
|
150
|
+
if (ctx.args[0]) {
|
|
151
|
+
const validated = validateOrgName(ctx.args[0]);
|
|
152
|
+
if (!validated.ok)
|
|
153
|
+
return validated.result;
|
|
154
|
+
name = validated.name;
|
|
155
|
+
}
|
|
94
156
|
const orgDir = join(ctx.cwd, ORG_DIR);
|
|
95
157
|
const targets = name ? [name] : (existsSync(orgDir)
|
|
96
158
|
? listOrgConfigFiles(orgDir).map(f => f.replace(/\.json$/, ''))
|
|
@@ -107,6 +169,17 @@ const statusAction = async (ctx) => {
|
|
|
107
169
|
continue;
|
|
108
170
|
}
|
|
109
171
|
}
|
|
172
|
+
// A "running" record whose pid is gone means the daemon died without its
|
|
173
|
+
// stopOrg cleanup — surface that instead of reporting it as still running.
|
|
174
|
+
if (state.status === 'running' && state.pid) {
|
|
175
|
+
try {
|
|
176
|
+
process.kill(state.pid, 0);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
log(output.warning(`${t}: crashed (runtime.json says running but pid ${state.pid} is gone)${state.run ? ` — run ${state.run}` : ''} — close it out with "monomind org mark-complete ${t}"`));
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
110
183
|
log(output.info(`${t}: ${state.status}${state.run ? ` (run ${state.run}, pid ${state.pid})` : ''}`));
|
|
111
184
|
}
|
|
112
185
|
return { success: true };
|
|
@@ -198,8 +271,27 @@ const listAction = async (ctx) => {
|
|
|
198
271
|
return { success: true };
|
|
199
272
|
}
|
|
200
273
|
log(output.info(`Found ${configs.length} org(s):`));
|
|
201
|
-
for (const f of configs)
|
|
202
|
-
|
|
274
|
+
for (const f of configs) {
|
|
275
|
+
const stem = f.replace(/\.json$/, '');
|
|
276
|
+
let detail = '';
|
|
277
|
+
try {
|
|
278
|
+
const def = JSON.parse(readFileSync(join(orgsDir, f), 'utf8'));
|
|
279
|
+
const roles = Array.isArray(def.roles) ? def.roles.length : 0;
|
|
280
|
+
const sched = def.schedule ? `every ${def.schedule}` : 'manual';
|
|
281
|
+
let status = 'never run';
|
|
282
|
+
try {
|
|
283
|
+
status = JSON.parse(readFileSync(join(orgsDir, stem, 'runtime.json'), 'utf8')).status ?? status;
|
|
284
|
+
}
|
|
285
|
+
catch { /* no runtime state yet */ }
|
|
286
|
+
const goal = typeof def.goal === 'string' && def.goal
|
|
287
|
+
? ` — ${def.goal.length > 60 ? `${def.goal.slice(0, 57)}...` : def.goal}` : '';
|
|
288
|
+
detail = ` (${roles} role${roles === 1 ? '' : 's'}, ${sched}, ${status})${goal}`;
|
|
289
|
+
}
|
|
290
|
+
catch {
|
|
291
|
+
detail = ' (unreadable config — run `monomind org validate`)';
|
|
292
|
+
}
|
|
293
|
+
log(output.info(` • ${stem}${detail}`));
|
|
294
|
+
}
|
|
203
295
|
return { success: true };
|
|
204
296
|
};
|
|
205
297
|
const deleteAction = async (ctx) => {
|
|
@@ -225,6 +317,10 @@ const deleteAction = async (ctx) => {
|
|
|
225
317
|
log(output.error(`Org not found: ${orgName}`));
|
|
226
318
|
return { success: false, message: 'org not found' };
|
|
227
319
|
}
|
|
320
|
+
if (isOrgRunning(cwd, orgName) && ctx.flags['force'] !== true) {
|
|
321
|
+
log(output.error(`Org "${orgName}" is currently running — stop it first (monomind org stop ${orgName}) or pass --force.`));
|
|
322
|
+
return { success: false, message: 'org is running' };
|
|
323
|
+
}
|
|
228
324
|
let removed = 0;
|
|
229
325
|
for (const suf of ['', ...ORG_ARTIFACT_SUFFIXES]) {
|
|
230
326
|
for (const ext of ['.json', '.jsonl']) {
|
|
@@ -298,6 +394,7 @@ export const orgCommand = {
|
|
|
298
394
|
options: [
|
|
299
395
|
{ name: 'task', description: 'Override the org goal for this run', type: 'string' },
|
|
300
396
|
{ name: 'cross-process', description: 'Discover and message orgs hosted by other monomind processes on this machine (default true)', type: 'boolean', default: true },
|
|
397
|
+
{ name: 'dry-run', description: 'Validate and print each role\'s briefing without starting any agent sessions', type: 'boolean' },
|
|
301
398
|
],
|
|
302
399
|
examples: [{ command: 'monomind org run growth --task "weekly report"', description: 'Run the growth org once with a task' }],
|
|
303
400
|
action: runAction,
|
|
@@ -316,10 +413,95 @@ export const orgCommand = {
|
|
|
316
413
|
options: [{ name: 'times', short: 'n', description: 'Iterations', type: 'number', default: 5 }],
|
|
317
414
|
action: testLoopAction,
|
|
318
415
|
},
|
|
416
|
+
{
|
|
417
|
+
name: 'logs', description: 'Show (or follow) the formatted event log of an org run',
|
|
418
|
+
options: [
|
|
419
|
+
{ name: 'run', description: 'Run id (default: latest)', type: 'string' },
|
|
420
|
+
{ name: 'role', description: 'Only events from/to this role', type: 'string' },
|
|
421
|
+
{ name: 'follow', short: 'f', description: 'Keep tailing until Ctrl-C', type: 'boolean' },
|
|
422
|
+
],
|
|
423
|
+
examples: [{ command: 'monomind org logs growth --follow', description: 'Live-tail the latest run' }],
|
|
424
|
+
action: async (ctx) => {
|
|
425
|
+
const v = validateOrgName(ctx.args[0]);
|
|
426
|
+
if (!v.ok)
|
|
427
|
+
return v.result;
|
|
428
|
+
const { logsAction } = await import('./org-observe.js');
|
|
429
|
+
return logsAction(ctx, v.name);
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
name: 'report', description: 'Summarize an org run: outcome, per-role activity, tokens, assets, crashes',
|
|
434
|
+
options: [
|
|
435
|
+
{ name: 'run', description: 'Run id (default: latest)', type: 'string' },
|
|
436
|
+
{ name: 'all', description: 'List all recorded runs from history', type: 'boolean' },
|
|
437
|
+
],
|
|
438
|
+
examples: [{ command: 'monomind org report growth', description: 'Report on the latest run' }],
|
|
439
|
+
action: async (ctx) => {
|
|
440
|
+
const v = validateOrgName(ctx.args[0]);
|
|
441
|
+
if (!v.ok)
|
|
442
|
+
return v.result;
|
|
443
|
+
const { reportAction } = await import('./org-observe.js');
|
|
444
|
+
return reportAction(ctx, v.name);
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
name: 'questions', description: 'List pending ask_human questions from an org\'s agents',
|
|
449
|
+
options: [{ name: 'all', description: 'Include answered questions', type: 'boolean' }],
|
|
450
|
+
examples: [{ command: 'monomind org questions growth', description: 'Show unanswered questions' }],
|
|
451
|
+
action: async (ctx) => {
|
|
452
|
+
const v = validateOrgName(ctx.args[0]);
|
|
453
|
+
if (!v.ok)
|
|
454
|
+
return v.result;
|
|
455
|
+
const { questionsAction } = await import('./org-observe.js');
|
|
456
|
+
return questionsAction(ctx, v.name);
|
|
457
|
+
},
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
name: 'answer', description: 'Answer a pending ask_human question (live if the org is running, queued otherwise)',
|
|
461
|
+
examples: [{ command: 'monomind org answer growth q-123-ab "yes, ship it"', description: 'Answer question q-123-ab' }],
|
|
462
|
+
action: async (ctx) => {
|
|
463
|
+
const v = validateOrgName(ctx.args[0]);
|
|
464
|
+
if (!v.ok)
|
|
465
|
+
return v.result;
|
|
466
|
+
const { answerAction } = await import('./org-observe.js');
|
|
467
|
+
return answerAction(ctx, v.name);
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
name: 'create', description: 'Scaffold an org config from a starter template',
|
|
472
|
+
options: [
|
|
473
|
+
{ name: 'template', description: 'content-team | dev-team | research-pod', type: 'string' },
|
|
474
|
+
{ name: 'goal', description: 'Org goal (defaults to the template\'s placeholder)', type: 'string' },
|
|
475
|
+
{ name: 'schedule', description: 'Daemon schedule, e.g. 30m or 2h', type: 'string' },
|
|
476
|
+
{ name: 'force', description: 'Overwrite an existing org config', type: 'boolean' },
|
|
477
|
+
],
|
|
478
|
+
examples: [{ command: 'monomind org create blog --template content-team --goal "3 posts/week"', description: 'Create a content org' }],
|
|
479
|
+
action: async (ctx) => {
|
|
480
|
+
const v = validateOrgName(ctx.args[0]);
|
|
481
|
+
if (!v.ok)
|
|
482
|
+
return v.result;
|
|
483
|
+
const { createAction } = await import('./org-observe.js');
|
|
484
|
+
return createAction(ctx, v.name);
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
name: 'validate', description: 'Validate org config(s) against the runtime schema and structural invariants',
|
|
489
|
+
examples: [
|
|
490
|
+
{ command: 'monomind org validate growth', description: 'Validate one org config' },
|
|
491
|
+
{ command: 'monomind org validate', description: 'Validate every org config in the project' },
|
|
492
|
+
],
|
|
493
|
+
action: async (ctx) => {
|
|
494
|
+
const { validateAction } = await import('./org-observe.js');
|
|
495
|
+
return validateAction(ctx);
|
|
496
|
+
},
|
|
497
|
+
},
|
|
319
498
|
{ name: 'list', description: 'List all orgs in the current project', action: listAction },
|
|
320
499
|
{
|
|
321
500
|
name: 'delete', description: 'Delete an org and all its data',
|
|
322
|
-
options: [
|
|
501
|
+
options: [
|
|
502
|
+
{ name: 'yes', short: 'y', description: 'Skip confirmation', type: 'boolean' },
|
|
503
|
+
{ name: 'force', description: 'Delete even if the org appears to be running', type: 'boolean' },
|
|
504
|
+
],
|
|
323
505
|
action: deleteAction,
|
|
324
506
|
},
|
|
325
507
|
{ name: 'mark-complete', description: 'Manually close a stale/crashed run', action: markCompleteAction },
|
|
@@ -329,7 +511,7 @@ export const orgCommand = {
|
|
|
329
511
|
// index.ts's dispatcher never prints result.message on a failed action —
|
|
330
512
|
// it only exits with result.exitCode — so this must log itself or bare
|
|
331
513
|
// `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>';
|
|
514
|
+
const message = 'usage: monomind org <run|stop|status|serve|test-loop|logs|report|questions|answer|create|validate|list|delete|mark-complete>';
|
|
333
515
|
log(output.error(message));
|
|
334
516
|
return { success: false, message };
|
|
335
517
|
},
|
|
@@ -535,7 +535,10 @@ const bottleneckCommand = {
|
|
|
535
535
|
try {
|
|
536
536
|
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
537
537
|
}
|
|
538
|
-
catch {
|
|
538
|
+
catch (e) {
|
|
539
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
540
|
+
console.error('[performance-bottleneck] failed to parse monomind.config.json:', e);
|
|
541
|
+
}
|
|
539
542
|
const perf = (config.performance ?? {});
|
|
540
543
|
const hnsw = (perf.hnsw ?? {});
|
|
541
544
|
if (!hnsw.quantization) {
|
|
@@ -224,7 +224,10 @@ function setupCursor(activateScriptPath, repoPath) {
|
|
|
224
224
|
try {
|
|
225
225
|
settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
226
226
|
}
|
|
227
|
-
catch {
|
|
227
|
+
catch (e) {
|
|
228
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
229
|
+
console.error('[setupCursor] failed to parse existing .cursor/settings.json, overwriting with empty:', e);
|
|
230
|
+
}
|
|
228
231
|
}
|
|
229
232
|
const hooks = settings['hooks'] ?? {};
|
|
230
233
|
const sessionStart = hooks['SessionStart'] ?? [];
|
|
@@ -141,10 +141,16 @@ export const scanCommand = {
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
-
catch { /* JSON parse failed */
|
|
144
|
+
catch (e) { /* JSON parse failed */
|
|
145
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
146
|
+
console.error('[security-scan] failed to parse npm audit output:', e);
|
|
147
|
+
}
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
|
-
catch { /* npm audit failed */
|
|
150
|
+
catch (e) { /* npm audit failed */
|
|
151
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
152
|
+
console.error('[security-scan] dependency check failed:', e);
|
|
153
|
+
}
|
|
148
154
|
}
|
|
149
155
|
if (scanType === 'all' || scanType === 'code') {
|
|
150
156
|
spinner.setText('Scanning for hardcoded secrets...');
|
|
@@ -90,7 +90,10 @@ function loadConfig(cwd) {
|
|
|
90
90
|
const content = fs.readFileSync(configPath, 'utf-8');
|
|
91
91
|
return parseSimpleYaml(content);
|
|
92
92
|
}
|
|
93
|
-
catch {
|
|
93
|
+
catch (e) {
|
|
94
|
+
// Caller falls back to hardcoded defaults (topology/maxAgents) as if no config existed
|
|
95
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
96
|
+
console.error('[loadConfig] failed to read/parse .monomind/config.yaml, falling back to defaults:', e);
|
|
94
97
|
return null;
|
|
95
98
|
}
|
|
96
99
|
}
|
|
@@ -339,8 +339,9 @@ const initCommand = {
|
|
|
339
339
|
};
|
|
340
340
|
writeJsonFileAtomic(stateFile, store);
|
|
341
341
|
}
|
|
342
|
-
catch {
|
|
343
|
-
|
|
342
|
+
catch (e) {
|
|
343
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
344
|
+
console.error('[swarm-init] failed to persist swarm state file:', e);
|
|
344
345
|
}
|
|
345
346
|
if (ctx.flags.format === 'json') {
|
|
346
347
|
output.printJson(result);
|
|
@@ -517,8 +518,8 @@ const statusCommand = {
|
|
|
517
518
|
output.writeln(output.warning('No active swarm'));
|
|
518
519
|
output.writeln();
|
|
519
520
|
output.writeln(output.dim('Start a swarm with:'));
|
|
520
|
-
output.writeln(output.dim(' npx
|
|
521
|
-
output.writeln(output.dim(' npx
|
|
521
|
+
output.writeln(output.dim(' npx monomind@latest swarm init'));
|
|
522
|
+
output.writeln(output.dim(' npx monomind@latest swarm start'));
|
|
522
523
|
output.writeln();
|
|
523
524
|
return { success: true, data: status };
|
|
524
525
|
}
|
|
@@ -25,7 +25,9 @@ function getPackageVersion() {
|
|
|
25
25
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
26
26
|
return pkg.version || '3.0.0';
|
|
27
27
|
}
|
|
28
|
-
catch {
|
|
28
|
+
catch (e) {
|
|
29
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
30
|
+
console.error('[index] getPackageVersion failed, using fallback:', e);
|
|
29
31
|
return '3.0.0';
|
|
30
32
|
}
|
|
31
33
|
}
|
|
@@ -472,7 +474,11 @@ export class CLI {
|
|
|
472
474
|
});
|
|
473
475
|
void _swarmCheckpointer;
|
|
474
476
|
}
|
|
475
|
-
catch {
|
|
477
|
+
catch (e) {
|
|
478
|
+
// optional — monomind/memory may not be installed
|
|
479
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
480
|
+
console.error('[index] SwarmCheckpointer init failed:', e);
|
|
481
|
+
}
|
|
476
482
|
// Task 30: Build unified agent registry — extras (canonical) first, dev copies second.
|
|
477
483
|
// Deduplication is slug-based; agency-agents wins on conflict.
|
|
478
484
|
// Extra paths are read from MONOMIND_EXTRA_AGENT_PATHS env var (colon-separated)
|
|
@@ -486,7 +492,11 @@ export class CLI {
|
|
|
486
492
|
mkdirSync(outDir, { recursive: true });
|
|
487
493
|
buildUnifiedRegistry(roots, join(outDir, 'registry.json'));
|
|
488
494
|
}
|
|
489
|
-
catch {
|
|
495
|
+
catch (e) {
|
|
496
|
+
// optional — registry build failures must never block startup
|
|
497
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
498
|
+
console.error('[index] agent registry build failed:', e);
|
|
499
|
+
}
|
|
490
500
|
// Task 04: CapabilityMetadata validation moved to `monomind doctor -c registry`
|
|
491
501
|
// (see doctor-project-checks.ts:checkAgentRegistry). Printing this from a
|
|
492
502
|
// fire-and-forget startup task raced process exit — short-lived commands
|
|
@@ -926,8 +926,10 @@ async function writeSettings(targetDir, options, result) {
|
|
|
926
926
|
result.skipped.push('.claude/settings.json');
|
|
927
927
|
}
|
|
928
928
|
}
|
|
929
|
-
catch {
|
|
929
|
+
catch (e) {
|
|
930
930
|
// Existing file is corrupt — overwrite
|
|
931
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
932
|
+
console.error('[writeSettings] existing settings.json unparseable, overwriting with generated defaults:', e);
|
|
931
933
|
atomicWriteFile(settingsPath, JSON.stringify(generated, null, 2));
|
|
932
934
|
result.created.files.push('.claude/settings.json');
|
|
933
935
|
}
|
|
@@ -2000,8 +2002,10 @@ async function writeClaudeMd(targetDir, options, result) {
|
|
|
2000
2002
|
result.created.files.push('~/.claude/CLAUDE.md');
|
|
2001
2003
|
}
|
|
2002
2004
|
}
|
|
2003
|
-
catch {
|
|
2005
|
+
catch (e) {
|
|
2004
2006
|
// Non-critical — global CLAUDE.md is best-effort
|
|
2007
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
2008
|
+
console.error('[writeClaudeMd] failed to write/append ~/.claude/CLAUDE.md:', e);
|
|
2005
2009
|
}
|
|
2006
2010
|
// Also inject the token-display hook into ~/.claude/settings.json
|
|
2007
2011
|
const globalSettingsPath = path.join(globalClaudeDir, 'settings.json');
|
|
@@ -2014,7 +2018,11 @@ async function writeClaudeMd(targetDir, options, result) {
|
|
|
2014
2018
|
try {
|
|
2015
2019
|
globalSettings = JSON.parse(fs.readFileSync(globalSettingsPath, 'utf-8'));
|
|
2016
2020
|
}
|
|
2017
|
-
catch {
|
|
2021
|
+
catch (e) {
|
|
2022
|
+
// malformed JSON — start fresh
|
|
2023
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
2024
|
+
console.error('[writeClaudeMd] ~/.claude/settings.json unparseable, starting fresh:', e);
|
|
2025
|
+
}
|
|
2018
2026
|
}
|
|
2019
2027
|
// Inject SessionStart token hook if not already present
|
|
2020
2028
|
const hooks = globalSettings.hooks ?? {};
|
|
@@ -2031,8 +2039,10 @@ async function writeClaudeMd(targetDir, options, result) {
|
|
|
2031
2039
|
result.created.files.push('~/.claude/settings.json (added token hook)');
|
|
2032
2040
|
}
|
|
2033
2041
|
}
|
|
2034
|
-
catch {
|
|
2042
|
+
catch (e) {
|
|
2035
2043
|
// Non-critical — global settings hook is best-effort
|
|
2044
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
2045
|
+
console.error('[writeClaudeMd] failed to inject token hook into ~/.claude/settings.json:', e);
|
|
2036
2046
|
}
|
|
2037
2047
|
}
|
|
2038
2048
|
}
|
|
@@ -2163,7 +2173,11 @@ function _registerMonomindProject(dir) {
|
|
|
2163
2173
|
reg = JSON.parse(fs.readFileSync(registryPath, 'utf-8'));
|
|
2164
2174
|
}
|
|
2165
2175
|
}
|
|
2166
|
-
catch {
|
|
2176
|
+
catch (e) {
|
|
2177
|
+
// Unparseable registry — proceeding with an empty list will overwrite it below, losing previously registered projects
|
|
2178
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
2179
|
+
console.error('[_registerMonomindProject] ~/.monomind-projects.json unparseable, resetting:', e);
|
|
2180
|
+
}
|
|
2167
2181
|
if (!Array.isArray(reg.projects))
|
|
2168
2182
|
reg.projects = [];
|
|
2169
2183
|
const abs = path.resolve(dir);
|
|
@@ -229,8 +229,15 @@ function generateHooksConfig(config, graphify = true) {
|
|
|
229
229
|
matcher: 'Write|Edit|MultiEdit',
|
|
230
230
|
hooks: [
|
|
231
231
|
{
|
|
232
|
+
// Was 'pre-edit' — not a registered hook-handler.cjs dispatch
|
|
233
|
+
// command (only 'pre-write' is), so this silently no-op'd on
|
|
234
|
+
// every default init: hook-handler.cjs's dispatcher falls through
|
|
235
|
+
// to `else if (command) { console.log('[OK] Hook: ' + command); }`
|
|
236
|
+
// for any unrecognized subcommand, meaning the secrets-detection
|
|
237
|
+
// gate (gates-handler.cjs's handlePreWrite) never actually ran
|
|
238
|
+
// for any project set up via a default `monomind init`.
|
|
232
239
|
type: 'command',
|
|
233
|
-
command: hookHandlerCmd('pre-
|
|
240
|
+
command: hookHandlerCmd('pre-write'),
|
|
234
241
|
timeout: config.timeout,
|
|
235
242
|
},
|
|
236
243
|
],
|
|
@@ -159,8 +159,9 @@ export async function ingestDocument(filePath, scope = 'shared', rootDir = proce
|
|
|
159
159
|
if (storeResult?.success)
|
|
160
160
|
indexed++;
|
|
161
161
|
}
|
|
162
|
-
catch {
|
|
163
|
-
|
|
162
|
+
catch (e) {
|
|
163
|
+
if (process.env.DEBUG || process.env.MONOMIND_DEBUG)
|
|
164
|
+
console.error(`[ingestDocument] failed to store chunk ${chunk.chunkIndex} of ${resolved}:`, e);
|
|
164
165
|
}
|
|
165
166
|
}
|
|
166
167
|
}
|
|
@@ -24,6 +24,7 @@ interface AgentStore {
|
|
|
24
24
|
version: string;
|
|
25
25
|
}
|
|
26
26
|
export declare function loadAgentStore(): AgentStore;
|
|
27
|
+
export declare function loadAgentStoreOrNull(): AgentStore | null;
|
|
27
28
|
export declare const agentTools: MCPTool[];
|
|
28
29
|
export {};
|
|
29
30
|
//# sourceMappingURL=agent-tools.d.ts.map
|