@monoes/monomindcli 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/.claude/commands/mastermind/createorg.md +24 -16
- package/.claude/commands/mastermind/master.md +23 -7
- package/.claude/commands/mastermind/runorg.md +3 -1
- package/.claude/commands/mastermind/stoporg.md +6 -3
- package/.claude/skills/mastermind-skills/code-quality-reviewer-prompt.md +3 -3
- package/.claude/skills/mastermind-skills/createorg.md +19 -24
- package/.claude/skills/mastermind-skills/debug.md +49 -4
- package/.claude/skills/mastermind-skills/design.md +11 -10
- package/.claude/skills/mastermind-skills/final-reviewer-prompt.md +144 -0
- package/.claude/skills/mastermind-skills/implementer-prompt.md +9 -4
- package/.claude/skills/mastermind-skills/org-settings.md +20 -2
- package/.claude/skills/mastermind-skills/orgs.md +40 -19
- package/.claude/skills/mastermind-skills/orgstatus.md +90 -41
- package/.claude/skills/mastermind-skills/plan.md +19 -0
- package/.claude/skills/mastermind-skills/skill-builder.md +171 -0
- package/.claude/skills/mastermind-skills/spec-reviewer-prompt.md +19 -2
- package/.claude/skills/mastermind-skills/stoporg.md +7 -5
- package/.claude/skills/mastermind-skills/taskdev.md +83 -15
- package/.claude/skills/mastermind-skills/tdd.md +30 -0
- package/dist/src/autopilot-state.js +6 -4
- package/dist/src/autopilot-state.js.map +1 -1
- package/dist/src/browser/dashboard/server.d.ts.map +1 -1
- package/dist/src/browser/dashboard/server.js +4 -1
- package/dist/src/browser/dashboard/server.js.map +1 -1
- package/dist/src/capabilities/manager.d.ts.map +1 -1
- package/dist/src/capabilities/manager.js +3 -1
- package/dist/src/capabilities/manager.js.map +1 -1
- package/dist/src/commands/agent-lifecycle.d.ts.map +1 -1
- package/dist/src/commands/agent-lifecycle.js +26 -0
- package/dist/src/commands/agent-lifecycle.js.map +1 -1
- package/dist/src/commands/agent-ops.d.ts.map +1 -1
- package/dist/src/commands/agent-ops.js +28 -46
- package/dist/src/commands/agent-ops.js.map +1 -1
- package/dist/src/commands/cleanup.d.ts +18 -0
- package/dist/src/commands/cleanup.d.ts.map +1 -1
- package/dist/src/commands/cleanup.js +120 -0
- package/dist/src/commands/cleanup.js.map +1 -1
- package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
- package/dist/src/commands/doctor-project-checks.js +13 -4
- package/dist/src/commands/doctor-project-checks.js.map +1 -1
- package/dist/src/commands/hooks-routing-commands.d.ts.map +1 -1
- package/dist/src/commands/hooks-routing-commands.js +34 -18
- package/dist/src/commands/hooks-routing-commands.js.map +1 -1
- package/dist/src/commands/hooks-workers.d.ts.map +1 -1
- package/dist/src/commands/hooks-workers.js +8 -2
- package/dist/src/commands/hooks-workers.js.map +1 -1
- package/dist/src/commands/hooks.js +1 -1
- package/dist/src/commands/hooks.js.map +1 -1
- package/dist/src/commands/init-wizard.js +2 -2
- package/dist/src/commands/init-wizard.js.map +1 -1
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +54 -10
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/mcp.js +4 -1
- package/dist/src/commands/mcp.js.map +1 -1
- package/dist/src/commands/memory-admin.d.ts.map +1 -1
- package/dist/src/commands/memory-admin.js +7 -1
- package/dist/src/commands/memory-admin.js.map +1 -1
- package/dist/src/commands/org-observe.d.ts +18 -0
- package/dist/src/commands/org-observe.d.ts.map +1 -0
- package/dist/src/commands/org-observe.js +295 -0
- package/dist/src/commands/org-observe.js.map +1 -0
- package/dist/src/commands/org.d.ts +9 -1
- package/dist/src/commands/org.d.ts.map +1 -1
- package/dist/src/commands/org.js +191 -9
- package/dist/src/commands/org.js.map +1 -1
- package/dist/src/commands/performance.js +4 -1
- package/dist/src/commands/performance.js.map +1 -1
- package/dist/src/commands/platforms.js +4 -1
- package/dist/src/commands/platforms.js.map +1 -1
- package/dist/src/commands/security-scan.js +8 -2
- package/dist/src/commands/security-scan.js.map +1 -1
- package/dist/src/commands/start.d.ts.map +1 -1
- package/dist/src/commands/start.js +4 -1
- package/dist/src/commands/start.js.map +1 -1
- package/dist/src/commands/swarm.js +5 -4
- package/dist/src/commands/swarm.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +13 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +19 -5
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/settings-generator.d.ts.map +1 -1
- package/dist/src/init/settings-generator.js +8 -1
- package/dist/src/init/settings-generator.js.map +1 -1
- package/dist/src/knowledge/document-pipeline.js +3 -2
- package/dist/src/knowledge/document-pipeline.js.map +1 -1
- package/dist/src/mcp-tools/agent-tools.d.ts +1 -0
- package/dist/src/mcp-tools/agent-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/agent-tools.js +63 -20
- package/dist/src/mcp-tools/agent-tools.js.map +1 -1
- package/dist/src/mcp-tools/claims-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/claims-tools.js +3 -1
- package/dist/src/mcp-tools/claims-tools.js.map +1 -1
- package/dist/src/mcp-tools/config-tools.js +3 -2
- package/dist/src/mcp-tools/config-tools.js.map +1 -1
- package/dist/src/mcp-tools/daa-tools.js +3 -2
- package/dist/src/mcp-tools/daa-tools.js.map +1 -1
- package/dist/src/mcp-tools/embeddings-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/embeddings-tools.js +6 -2
- package/dist/src/mcp-tools/embeddings-tools.js.map +1 -1
- package/dist/src/mcp-tools/github-tools.js +35 -10
- package/dist/src/mcp-tools/github-tools.js.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.js +24 -7
- package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -1
- package/dist/src/mcp-tools/hooks-embedding.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-embedding.js +13 -3
- package/dist/src/mcp-tools/hooks-embedding.js.map +1 -1
- package/dist/src/mcp-tools/hooks-intelligence.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-intelligence.js +9 -3
- package/dist/src/mcp-tools/hooks-intelligence.js.map +1 -1
- package/dist/src/mcp-tools/hooks-routing.d.ts +1 -0
- package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-routing.js +112 -10
- package/dist/src/mcp-tools/hooks-routing.js.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.js +2 -1
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
- package/dist/src/mcp-tools/monograph-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph-tools.js +8 -2
- package/dist/src/mcp-tools/monograph-tools.js.map +1 -1
- package/dist/src/mcp-tools/performance-tools.js +3 -2
- package/dist/src/mcp-tools/performance-tools.js.map +1 -1
- package/dist/src/mcp-tools/session-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/session-tools.js +15 -5
- package/dist/src/mcp-tools/session-tools.js.map +1 -1
- package/dist/src/mcp-tools/swarm-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/swarm-tools.js +4 -1
- package/dist/src/mcp-tools/swarm-tools.js.map +1 -1
- package/dist/src/mcp-tools/system-tools.js +6 -4
- package/dist/src/mcp-tools/system-tools.js.map +1 -1
- package/dist/src/mcp-tools/task-tools.d.ts +20 -0
- package/dist/src/mcp-tools/task-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/task-tools.js +38 -16
- package/dist/src/mcp-tools/task-tools.js.map +1 -1
- package/dist/src/mcp-tools/terminal-tools.d.ts +2 -0
- package/dist/src/mcp-tools/terminal-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/terminal-tools.js +68 -24
- package/dist/src/mcp-tools/terminal-tools.js.map +1 -1
- package/dist/src/memory/ewc-consolidation.d.ts.map +1 -1
- package/dist/src/memory/ewc-consolidation.js +6 -2
- package/dist/src/memory/ewc-consolidation.js.map +1 -1
- package/dist/src/memory/intelligence.d.ts.map +1 -1
- package/dist/src/memory/intelligence.js +32 -10
- package/dist/src/memory/intelligence.js.map +1 -1
- package/dist/src/memory/memory-bridge.d.ts.map +1 -1
- package/dist/src/memory/memory-bridge.js +16 -4
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/src/memory/memory-crud.d.ts.map +1 -1
- package/dist/src/memory/memory-crud.js +26 -2
- package/dist/src/memory/memory-crud.js.map +1 -1
- package/dist/src/memory/memory-initializer.js +3 -2
- package/dist/src/memory/memory-initializer.js.map +1 -1
- package/dist/src/memory/memory-migrations.d.ts.map +1 -1
- package/dist/src/memory/memory-migrations.js +2 -0
- package/dist/src/memory/memory-migrations.js.map +1 -1
- package/dist/src/monovector/command-outcomes.d.ts.map +1 -1
- package/dist/src/monovector/command-outcomes.js +4 -1
- package/dist/src/monovector/command-outcomes.js.map +1 -1
- package/dist/src/orgrt/bus.d.ts.map +1 -1
- package/dist/src/orgrt/bus.js +4 -1
- package/dist/src/orgrt/bus.js.map +1 -1
- package/dist/src/orgrt/daemon.d.ts.map +1 -1
- package/dist/src/orgrt/daemon.js +74 -19
- package/dist/src/orgrt/daemon.js.map +1 -1
- package/dist/src/orgrt/inbox.d.ts.map +1 -1
- package/dist/src/orgrt/inbox.js +3 -1
- package/dist/src/orgrt/inbox.js.map +1 -1
- package/dist/src/orgrt/reporting.d.ts +40 -0
- package/dist/src/orgrt/reporting.d.ts.map +1 -0
- package/dist/src/orgrt/reporting.js +127 -0
- package/dist/src/orgrt/reporting.js.map +1 -0
- package/dist/src/orgrt/session.d.ts +2 -0
- package/dist/src/orgrt/session.d.ts.map +1 -1
- package/dist/src/orgrt/session.js +10 -2
- package/dist/src/orgrt/session.js.map +1 -1
- package/dist/src/orgrt/templates.d.ts +16 -0
- package/dist/src/orgrt/templates.d.ts.map +1 -0
- package/dist/src/orgrt/templates.js +57 -0
- package/dist/src/orgrt/templates.js.map +1 -0
- package/dist/src/services/config-file-manager.d.ts.map +1 -1
- package/dist/src/services/config-file-manager.js +10 -1
- package/dist/src/services/config-file-manager.js.map +1 -1
- package/dist/src/transfer/storage/gcs.d.ts.map +1 -1
- package/dist/src/transfer/storage/gcs.js +6 -2
- package/dist/src/transfer/storage/gcs.js.map +1 -1
- package/dist/src/ui/orgs.html +32 -0
- package/dist/src/ui/server.mjs +25 -0
- package/dist/src/update/executor.d.ts.map +1 -1
- package/dist/src/update/executor.js +3 -1
- package/dist/src/update/executor.js.map +1 -1
- package/dist/src/update/rate-limiter.d.ts.map +1 -1
- package/dist/src/update/rate-limiter.js +3 -1
- package/dist/src/update/rate-limiter.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
// packages/@monomind/cli/src/commands/org-observe.ts
|
|
2
|
+
// Read-side org subcommands (logs / report) + template scaffolding (create).
|
|
3
|
+
// Kept out of org.ts to respect the 500-line file ceiling.
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { output } from '../output.js';
|
|
7
|
+
import { ORG_DIR, OrgDefSchema } from '../orgrt/types.js';
|
|
8
|
+
import { formatEvent, listRunDirs, readHistory, readRunEvents, summarizeRun } from '../orgrt/reporting.js';
|
|
9
|
+
import { ORG_TEMPLATES, buildFromTemplate } from '../orgrt/templates.js';
|
|
10
|
+
import { parseSchedule } from '../orgrt/scheduler.js';
|
|
11
|
+
import { listOrgConfigFiles, validateOrgName } from './org.js';
|
|
12
|
+
const log = (text) => { console.log(text); };
|
|
13
|
+
/** Validate org config(s) against OrgDefSchema — the exact parse `org run`/`org serve`
|
|
14
|
+
* perform — plus the structural invariants the runtime assumes but the schema can't
|
|
15
|
+
* express (single root role, resolvable reports_to, unique ids, parseable schedule). */
|
|
16
|
+
export const validateAction = async (ctx) => {
|
|
17
|
+
const orgsDir = join(ctx.cwd || process.cwd(), ORG_DIR);
|
|
18
|
+
let files;
|
|
19
|
+
if (ctx.args[0]) {
|
|
20
|
+
const validated = validateOrgName(ctx.args[0]);
|
|
21
|
+
if (!validated.ok)
|
|
22
|
+
return validated.result;
|
|
23
|
+
files = [`${validated.name}.json`];
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
if (!existsSync(orgsDir))
|
|
27
|
+
return { success: false, message: 'no orgs directory — create an org first with /mastermind:createorg' };
|
|
28
|
+
files = listOrgConfigFiles(orgsDir);
|
|
29
|
+
if (!files.length)
|
|
30
|
+
return { success: false, message: 'no org configs found' };
|
|
31
|
+
}
|
|
32
|
+
let failed = 0;
|
|
33
|
+
for (const f of files) {
|
|
34
|
+
const stem = f.replace(/\.json$/, '');
|
|
35
|
+
const path = join(orgsDir, f);
|
|
36
|
+
const errors = [];
|
|
37
|
+
const warnings = [];
|
|
38
|
+
if (!existsSync(path)) {
|
|
39
|
+
log(output.error(`${stem}: not found (${path})`));
|
|
40
|
+
failed++;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const def = OrgDefSchema.parse(JSON.parse(readFileSync(path, 'utf8')));
|
|
45
|
+
const ids = def.roles.map(r => r.id);
|
|
46
|
+
const dupes = ids.filter((id, i) => ids.indexOf(id) !== i);
|
|
47
|
+
if (dupes.length)
|
|
48
|
+
errors.push(`duplicate role id(s): ${[...new Set(dupes)].join(', ')}`);
|
|
49
|
+
const roots = def.roles.filter(r => r.reports_to === null);
|
|
50
|
+
if (roots.length === 0)
|
|
51
|
+
errors.push('no root role — exactly one role must have reports_to: null');
|
|
52
|
+
if (roots.length > 1)
|
|
53
|
+
errors.push(`multiple root roles (${roots.map(r => r.id).join(', ')}) — exactly one may have reports_to: null`);
|
|
54
|
+
for (const r of def.roles) {
|
|
55
|
+
if (r.reports_to !== null && !ids.includes(r.reports_to))
|
|
56
|
+
errors.push(`role "${r.id}": reports_to "${r.reports_to}" matches no role id`);
|
|
57
|
+
if (r.reports_to === r.id)
|
|
58
|
+
errors.push(`role "${r.id}" reports to itself`);
|
|
59
|
+
}
|
|
60
|
+
if (def.schedule != null && parseSchedule(def.schedule) === null)
|
|
61
|
+
errors.push(`schedule "${def.schedule}" is not parseable — use "<N>s", "<N>m", or "<N>h"`);
|
|
62
|
+
if (def.name !== stem)
|
|
63
|
+
warnings.push(`def.name "${def.name}" differs from filename — the runtime addresses this org as "${stem}"`);
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
errors.push(err instanceof Error ? err.message : String(err));
|
|
67
|
+
}
|
|
68
|
+
for (const w of warnings)
|
|
69
|
+
log(output.warning(`${stem}: ${w}`));
|
|
70
|
+
if (errors.length) {
|
|
71
|
+
failed++;
|
|
72
|
+
for (const e of errors)
|
|
73
|
+
log(output.error(`${stem}: ${e}`));
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
log(output.success(`${stem}: valid${warnings.length ? ` (${warnings.length} warning(s))` : ''}`));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return failed
|
|
80
|
+
? { success: false, message: `${failed} of ${files.length} org config(s) failed validation` }
|
|
81
|
+
: { success: true, message: `${files.length} org config(s) valid` };
|
|
82
|
+
};
|
|
83
|
+
const resolveRun = (cwd, name, runFlag) => {
|
|
84
|
+
if (typeof runFlag === 'string' && runFlag)
|
|
85
|
+
return runFlag;
|
|
86
|
+
return listRunDirs(cwd, name)[0] ?? null;
|
|
87
|
+
};
|
|
88
|
+
/** `org logs <name> [--run id] [--role r] [--follow]` — formatted bus.jsonl tail. */
|
|
89
|
+
export const logsAction = async (ctx, name) => {
|
|
90
|
+
const run = resolveRun(ctx.cwd, name, ctx.flags['run']);
|
|
91
|
+
if (!run)
|
|
92
|
+
return { success: false, message: `no runs found for org ${name} — start one with: monomind org run ${name}` };
|
|
93
|
+
const file = join(ctx.cwd, ORG_DIR, name, run, 'bus.jsonl');
|
|
94
|
+
const roleFilter = typeof ctx.flags['role'] === 'string' ? ctx.flags['role'] : null;
|
|
95
|
+
const show = (e) => {
|
|
96
|
+
if (roleFilter && e.from !== roleFilter && e.to !== roleFilter)
|
|
97
|
+
return;
|
|
98
|
+
log(formatEvent(e));
|
|
99
|
+
};
|
|
100
|
+
log(output.info(`org ${name} — ${run}${roleFilter ? ` (role: ${roleFilter})` : ''}`));
|
|
101
|
+
let seenLines = 0;
|
|
102
|
+
const drain = () => {
|
|
103
|
+
if (!existsSync(file))
|
|
104
|
+
return;
|
|
105
|
+
const lines = readFileSync(file, 'utf8').split('\n').filter(Boolean);
|
|
106
|
+
for (const l of lines.slice(seenLines)) {
|
|
107
|
+
try {
|
|
108
|
+
show(JSON.parse(l));
|
|
109
|
+
seenLines++;
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
break;
|
|
113
|
+
} // partial line mid-append — retry it next tick
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
drain();
|
|
117
|
+
if (ctx.flags['follow'] !== true)
|
|
118
|
+
return { success: true };
|
|
119
|
+
log(output.info('following — Ctrl-C to stop'));
|
|
120
|
+
await new Promise(resolve => {
|
|
121
|
+
const iv = setInterval(drain, 500);
|
|
122
|
+
process.once('SIGINT', () => { clearInterval(iv); resolve(); });
|
|
123
|
+
process.once('SIGTERM', () => { clearInterval(iv); resolve(); });
|
|
124
|
+
});
|
|
125
|
+
return { success: true };
|
|
126
|
+
};
|
|
127
|
+
/** `org report <name> [--run id] [--all]` — summarize a run (or list run history). */
|
|
128
|
+
export const reportAction = async (ctx, name) => {
|
|
129
|
+
if (ctx.flags['all'] === true) {
|
|
130
|
+
const history = readHistory(ctx.cwd, name);
|
|
131
|
+
if (!history.length)
|
|
132
|
+
return { success: false, message: `no run history for org ${name}` };
|
|
133
|
+
log(output.info(`org ${name} — ${history.length} recorded run(s):`));
|
|
134
|
+
for (const h of history) {
|
|
135
|
+
const dur = h.durationMs != null ? `${Math.round(h.durationMs / 1000)}s` : '?';
|
|
136
|
+
const outcome = h.outcome ? `${h.outcome.status}: ${h.outcome.summary.slice(0, 60)}` : 'no outcome recorded';
|
|
137
|
+
log(output.info(` • ${h.run} ${dur} ${h.totalTokens} tokens ${h.messages} msgs — ${outcome}`));
|
|
138
|
+
}
|
|
139
|
+
return { success: true };
|
|
140
|
+
}
|
|
141
|
+
const run = resolveRun(ctx.cwd, name, ctx.flags['run']);
|
|
142
|
+
if (!run)
|
|
143
|
+
return { success: false, message: `no runs found for org ${name}` };
|
|
144
|
+
const events = readRunEvents(ctx.cwd, name, run);
|
|
145
|
+
if (!events.length)
|
|
146
|
+
return { success: false, message: `run ${run} has no recorded events` };
|
|
147
|
+
const s = summarizeRun(events);
|
|
148
|
+
// Per-role budget ceiling: same split the daemon applies (budget ÷ role count),
|
|
149
|
+
// with any explicit policy.maxTokens override. Missing/unreadable config → no ceilings.
|
|
150
|
+
let perRoleBudget = null;
|
|
151
|
+
const roleCeiling = new Map();
|
|
152
|
+
try {
|
|
153
|
+
const def = OrgDefSchema.parse(JSON.parse(readFileSync(join(ctx.cwd, ORG_DIR, `${name}.json`), 'utf8')));
|
|
154
|
+
perRoleBudget = Math.floor((def.run_config.budget_tokens ?? 1_000_000) / def.roles.length);
|
|
155
|
+
for (const r of def.roles) {
|
|
156
|
+
const max = r.policy?.maxTokens;
|
|
157
|
+
roleCeiling.set(r.id, max ?? perRoleBudget);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch { /* config gone or invalid — report without budget context */ }
|
|
161
|
+
const budgetNote = (id, tokens) => {
|
|
162
|
+
const cap = roleCeiling.get(id);
|
|
163
|
+
if (!cap)
|
|
164
|
+
return '';
|
|
165
|
+
const pct = Math.round((tokens / cap) * 100);
|
|
166
|
+
return ` (${pct}% of ${cap}${pct >= 100 ? ' — EXHAUSTED' : pct >= 80 ? ' — near limit' : ''})`;
|
|
167
|
+
};
|
|
168
|
+
log(output.info(`ORG REPORT — ${name} / ${run}`));
|
|
169
|
+
log(output.info(` Duration: ${s.durationMs != null ? `${Math.round(s.durationMs / 1000)}s` : '?'} Events: ${s.events} Messages: ${s.messages}${s.xorgMessages ? ` (+${s.xorgMessages} cross-org)` : ''}`));
|
|
170
|
+
log(output.info(` Tokens: ${s.totalTokens}${perRoleBudget ? ` (budget: ${perRoleBudget}/role)` : ''}${s.totalCostUsd ? ` Cost: $${s.totalCostUsd.toFixed(4)}` : ''}`));
|
|
171
|
+
if (s.outcome)
|
|
172
|
+
log(output.success(` Outcome: ${s.outcome.status} (by ${s.outcome.by}) — ${s.outcome.summary}`));
|
|
173
|
+
else
|
|
174
|
+
log(output.warning(' Outcome: not recorded (coordinator never called org_complete)'));
|
|
175
|
+
log(output.info(' Roles:'));
|
|
176
|
+
for (const [id, r] of Object.entries(s.roles)) {
|
|
177
|
+
log(output.info(` ${r.crashed ? '✗' : '•'} ${id}: ${r.messagesSent} msgs, ${r.toolsAllowed} tools${r.toolsDenied ? ` (${r.toolsDenied} denied)` : ''}, ${r.tokens} tokens${budgetNote(id, r.tokens)}${r.crashed ? ' — CRASHED' : ''}`));
|
|
178
|
+
}
|
|
179
|
+
if (s.assets.length) {
|
|
180
|
+
log(output.info(` Assets (${s.assets.length}):`));
|
|
181
|
+
for (const a of s.assets.slice(0, 20))
|
|
182
|
+
log(output.info(` 📄 ${a}`));
|
|
183
|
+
if (s.assets.length > 20)
|
|
184
|
+
log(output.info(` … and ${s.assets.length - 20} more`));
|
|
185
|
+
}
|
|
186
|
+
return { success: true };
|
|
187
|
+
};
|
|
188
|
+
const readQuestions = (cwd, name) => {
|
|
189
|
+
try {
|
|
190
|
+
return JSON.parse(readFileSync(join(cwd, ORG_DIR, name, 'questions.json'), 'utf8')).questions ?? [];
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
return [];
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
/** `org questions <name> [--all]` — list pending (or all) ask_human questions. */
|
|
197
|
+
export const questionsAction = async (ctx, name) => {
|
|
198
|
+
const all = readQuestions(ctx.cwd, name);
|
|
199
|
+
const shown = ctx.flags['all'] === true ? all : all.filter(q => q.answer === null);
|
|
200
|
+
if (!shown.length) {
|
|
201
|
+
log(output.info(all.length ? `No pending questions for org ${name} (${all.length} answered — use --all).` : `No questions recorded for org ${name}.`));
|
|
202
|
+
return { success: true };
|
|
203
|
+
}
|
|
204
|
+
for (const q of shown) {
|
|
205
|
+
const when = new Date(q.ts).toISOString().replace('T', ' ').slice(0, 16);
|
|
206
|
+
log(output.info(`${q.answer === null ? '❓' : '✓'} [${q.questionId}] ${when} ${q.role}: ${q.question}`));
|
|
207
|
+
if (q.answer !== null)
|
|
208
|
+
log(output.info(` ↳ ${q.answer}`));
|
|
209
|
+
}
|
|
210
|
+
if (shown.some(q => q.answer === null))
|
|
211
|
+
log(output.info(`\nAnswer with: monomind org answer ${name} <question-id> "your answer"`));
|
|
212
|
+
return { success: true };
|
|
213
|
+
};
|
|
214
|
+
/** `org answer <name> <question-id> <answer...>` — answer a pending ask_human question.
|
|
215
|
+
* Delivers live via the hosting daemon's /api/answer-question when the org is running
|
|
216
|
+
* (broker lookup); otherwise records the answer and queues it for the next run. */
|
|
217
|
+
export const answerAction = async (ctx, name) => {
|
|
218
|
+
const questionId = ctx.args[1];
|
|
219
|
+
const answer = ctx.args.slice(2).join(' ').trim();
|
|
220
|
+
if (!questionId || !answer)
|
|
221
|
+
return { success: false, message: `usage: monomind org answer ${name} <question-id> "answer text"` };
|
|
222
|
+
const questions = readQuestions(ctx.cwd, name);
|
|
223
|
+
const q = questions.find(x => x.questionId === questionId);
|
|
224
|
+
if (!q) {
|
|
225
|
+
log(output.error(`Question "${questionId}" not found for org ${name} — list with: monomind org questions ${name}`));
|
|
226
|
+
return { success: false, message: 'question not found' };
|
|
227
|
+
}
|
|
228
|
+
if (q.answer !== null)
|
|
229
|
+
return { success: false, message: `question "${questionId}" was already answered` };
|
|
230
|
+
// Live path: the hosting daemon updates questions.json and pushes into the role's mailbox.
|
|
231
|
+
const { lookupOrg } = await import('../orgrt/broker.js');
|
|
232
|
+
const remote = lookupOrg(name);
|
|
233
|
+
if (remote) {
|
|
234
|
+
try {
|
|
235
|
+
const res = await fetch(`${remote.url}/api/answer-question`, {
|
|
236
|
+
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
237
|
+
body: JSON.stringify({ org: name, role: q.role, questionId, answer }),
|
|
238
|
+
signal: AbortSignal.timeout(10_000),
|
|
239
|
+
});
|
|
240
|
+
const data = await res.json().catch(() => ({}));
|
|
241
|
+
if (res.ok && data.ok) {
|
|
242
|
+
log(output.success(`Answer delivered to ${name}:${q.role} (live).`));
|
|
243
|
+
return { success: true };
|
|
244
|
+
}
|
|
245
|
+
log(output.warning(`Live delivery rejected (${data.error ?? res.status}) — falling back to offline queue.`));
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
log(output.warning(`Hosting daemon unreachable (${err instanceof Error ? err.message : 'error'}) — falling back to offline queue.`));
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// Offline path: mirror daemon.answerQuestion's org-not-running branch.
|
|
252
|
+
const updated = questions.map(x => x.questionId === questionId ? { ...x, answer, answeredAt: Date.now() } : x);
|
|
253
|
+
const dest = join(ctx.cwd, ORG_DIR, name, 'questions.json');
|
|
254
|
+
const tmp = `${dest}.${process.pid}.tmp`;
|
|
255
|
+
writeFileSync(tmp, JSON.stringify({ questions: updated }, null, 2));
|
|
256
|
+
const { renameSync } = await import('node:fs');
|
|
257
|
+
renameSync(tmp, dest);
|
|
258
|
+
const { queueMessage } = await import('../orgrt/inbox.js');
|
|
259
|
+
queueMessage(ctx.cwd, name, {
|
|
260
|
+
fromQualified: 'human', toRole: q.role,
|
|
261
|
+
subject: `answer:${questionId}`,
|
|
262
|
+
body: `question: ${q.question}\n\nanswer: ${answer}`,
|
|
263
|
+
ts: Date.now(),
|
|
264
|
+
});
|
|
265
|
+
log(output.success(`Answer recorded — ${name}:${q.role} receives it when the org next runs.`));
|
|
266
|
+
return { success: true };
|
|
267
|
+
};
|
|
268
|
+
/** `org create <name> --template <t> [--goal g] [--schedule s]` — scaffold a config from a template. */
|
|
269
|
+
export const createAction = async (ctx, name) => {
|
|
270
|
+
const templateName = typeof ctx.flags['template'] === 'string' ? ctx.flags['template'] : '';
|
|
271
|
+
if (!templateName) {
|
|
272
|
+
log(output.info(`Available templates: ${Object.keys(ORG_TEMPLATES).join(', ')}`));
|
|
273
|
+
return { success: false, message: 'usage: monomind org create <name> --template <template> [--goal "..."] [--schedule 30m]' };
|
|
274
|
+
}
|
|
275
|
+
const def = buildFromTemplate(templateName, name, typeof ctx.flags['goal'] === 'string' ? ctx.flags['goal'] : undefined);
|
|
276
|
+
if (!def) {
|
|
277
|
+
log(output.error(`Unknown template "${templateName}" — available: ${Object.keys(ORG_TEMPLATES).join(', ')}`));
|
|
278
|
+
return { success: false, message: 'unknown template' };
|
|
279
|
+
}
|
|
280
|
+
if (typeof ctx.flags['schedule'] === 'string')
|
|
281
|
+
def.schedule = ctx.flags['schedule'];
|
|
282
|
+
const file = join(ctx.cwd, ORG_DIR, `${name}.json`);
|
|
283
|
+
if (existsSync(file) && ctx.flags['force'] !== true) {
|
|
284
|
+
log(output.error(`Org "${name}" already exists — pass --force to overwrite.`));
|
|
285
|
+
return { success: false, message: 'org exists' };
|
|
286
|
+
}
|
|
287
|
+
OrgDefSchema.parse(def); // templates must always produce a runnable config
|
|
288
|
+
const { mkdirSync } = await import('node:fs');
|
|
289
|
+
mkdirSync(join(ctx.cwd, ORG_DIR), { recursive: true });
|
|
290
|
+
writeFileSync(file, JSON.stringify(def, null, 2) + '\n', 'utf8');
|
|
291
|
+
log(output.success(`Org "${name}" created from template "${templateName}" (${def.roles.length} roles).`));
|
|
292
|
+
log(output.info(` Edit the goal/roles in ${file}, then: monomind org run ${name}`));
|
|
293
|
+
return { success: true };
|
|
294
|
+
};
|
|
295
|
+
//# sourceMappingURL=org-observe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org-observe.js","sourceRoot":"","sources":["../../../src/commands/org-observe.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import type { Command } from '../types.js';
|
|
1
|
+
import type { Command, CommandResult } from '../types.js';
|
|
2
|
+
export declare function validateOrgName(name: string | undefined): {
|
|
3
|
+
ok: true;
|
|
4
|
+
name: string;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
result: CommandResult;
|
|
8
|
+
};
|
|
9
|
+
export declare function listOrgConfigFiles(orgsDir: string): string[];
|
|
2
10
|
/** Remove a lingering stopfile so a fresh `org run` doesn't self-terminate. */
|
|
3
11
|
export declare const clearStopfile: (cwd: string, name: string) => void;
|
|
4
12
|
export declare const orgCommand: Command;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"org.d.ts","sourceRoot":"","sources":["../../../src/commands/org.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"org.d.ts","sourceRoot":"","sources":["../../../src/commands/org.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAkB,aAAa,EAAE,MAAM,aAAa,CAAC;AAa1E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAO3H;AAaD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAG5D;AAED,+EAA+E;AAC/E,eAAO,MAAM,aAAa,QAAS,MAAM,QAAQ,MAAM,KAAG,IAEzD,CAAC;AAkUF,eAAO,MAAM,UAAU,EAAE,OA6HxB,CAAC;eAEa,UAAU"}
|
package/dist/src/commands/org.js
CHANGED
|
@@ -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
|
},
|