@monoes/monomindcli 1.12.0 → 1.14.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/agents/generated/churn-analyst.md +53 -0
- package/.claude/agents/generated/code-reviewer.md +55 -0
- package/.claude/agents/generated/code-validator.md +57 -0
- package/.claude/agents/generated/complexity-scanner.md +56 -0
- package/.claude/agents/generated/devbot-orchestrator.md +58 -0
- package/.claude/agents/generated/devbot-planner.md +63 -0
- package/.claude/agents/generated/impact-assessor.md +54 -0
- package/.claude/commands/mastermind/master.md +88 -24
- package/.claude/helpers/control-start.cjs +60 -1
- package/.claude/helpers/event-logger.cjs +43 -2
- package/.claude/helpers/handlers/capture-handler.cjs +336 -0
- package/.claude/helpers/handlers/route-handler.cjs +20 -13
- package/.claude/helpers/handlers/session-restore-handler.cjs +14 -8
- package/.claude/helpers/hook-handler.cjs +57 -1
- package/.claude/helpers/intelligence.cjs +129 -57
- package/.claude/helpers/memory-palace.cjs +461 -0
- package/.claude/helpers/memory.cjs +134 -15
- package/.claude/helpers/metrics-db.mjs +87 -0
- package/.claude/helpers/router.cjs +296 -41
- package/.claude/helpers/session.cjs +107 -32
- package/.claude/helpers/statusline.cjs +138 -2
- package/.claude/helpers/toggle-statusline.cjs +73 -0
- package/.claude/helpers/token-tracker.cjs +934 -0
- package/.claude/helpers/utils/monograph.cjs +39 -4
- package/.claude/helpers/utils/telemetry.cjs +3 -3
- package/.claude/skills/mastermind/createorg.md +227 -16
- package/.claude/skills/mastermind/idea.md +15 -3
- package/.claude/skills/mastermind/runorg.md +2 -1
- package/dist/src/commands/doctor.d.ts.map +1 -1
- package/dist/src/commands/doctor.js +96 -4
- package/dist/src/commands/doctor.js.map +1 -1
- package/dist/src/commands/index.js +2 -0
- package/dist/src/commands/org.d.ts +4 -0
- package/dist/src/commands/org.d.ts.map +1 -0
- package/dist/src/commands/org.js +93 -0
- package/dist/src/commands/org.js.map +1 -0
- package/dist/src/mcp-tools/memory-tools.js +6 -6
- package/dist/src/mcp-tools/memory-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 +329 -37
- package/dist/src/mcp-tools/monograph-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 +9 -10
- package/dist/src/mcp-tools/session-tools.js.map +1 -1
- package/dist/src/mcp-tools/task-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/task-tools.js +7 -8
- package/dist/src/mcp-tools/task-tools.js.map +1 -1
- package/dist/src/mcp-tools/types.d.ts +1 -0
- package/dist/src/mcp-tools/types.d.ts.map +1 -1
- package/dist/src/mcp-tools/types.js +49 -0
- package/dist/src/mcp-tools/types.js.map +1 -1
- package/dist/src/services/worker-daemon.d.ts.map +1 -1
- package/dist/src/services/worker-daemon.js +295 -5
- package/dist/src/services/worker-daemon.js.map +1 -1
- package/dist/src/transfer/serialization/cfp.js +1 -1
- package/dist/src/transfer/serialization/cfp.js.map +1 -1
- package/dist/src/ui/dashboard.html +2235 -178
- package/dist/src/ui/orgs.html +1 -0
- package/dist/src/ui/server.mjs +532 -133
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -907,6 +907,60 @@ function getHILPending() {
|
|
|
907
907
|
return { pending };
|
|
908
908
|
}
|
|
909
909
|
|
|
910
|
+
// Active org runs — scan .monomind/orgs/*/runs/*.jsonl for recent activity
|
|
911
|
+
// Also checks .git/monomind/orgs/ (git-safe path used by mastermind orgs).
|
|
912
|
+
// An org is "active" if it has an events file modified within the last 10 minutes.
|
|
913
|
+
function getActiveOrgs() {
|
|
914
|
+
// Try git-common-dir path first (mastermind orgs store run files there)
|
|
915
|
+
let orgsDir = path.join(CWD, '.monomind', 'orgs');
|
|
916
|
+
try {
|
|
917
|
+
const gitCommon = safeExec('git rev-parse --git-common-dir 2>/dev/null', 1000);
|
|
918
|
+
if (gitCommon) {
|
|
919
|
+
const candidate = path.isAbsolute(gitCommon)
|
|
920
|
+
? path.join(gitCommon, 'monomind', 'orgs')
|
|
921
|
+
: path.join(CWD, gitCommon, 'monomind', 'orgs');
|
|
922
|
+
if (fs.existsSync(candidate)) orgsDir = candidate;
|
|
923
|
+
}
|
|
924
|
+
} catch { /* use default */ }
|
|
925
|
+
if (!fs.existsSync(orgsDir)) return { count: 0, orgs: [] };
|
|
926
|
+
const STALE_MS = 10 * 60 * 1000; // 10 min
|
|
927
|
+
const now = Date.now();
|
|
928
|
+
const active = [];
|
|
929
|
+
try {
|
|
930
|
+
const orgNames = fs.readdirSync(orgsDir).filter(f => !f.startsWith('.'));
|
|
931
|
+
for (const orgName of orgNames.slice(0, 20)) {
|
|
932
|
+
const runsDir = path.join(orgsDir, orgName, 'runs');
|
|
933
|
+
if (!fs.existsSync(runsDir)) continue;
|
|
934
|
+
try {
|
|
935
|
+
const files = fs.readdirSync(runsDir).filter(f => f.endsWith('.jsonl'));
|
|
936
|
+
if (!files.length) continue;
|
|
937
|
+
files.sort();
|
|
938
|
+
const latest = files[files.length - 1];
|
|
939
|
+
const stat = safeStat(path.join(runsDir, latest));
|
|
940
|
+
if (!stat) continue;
|
|
941
|
+
const age = now - stat.mtimeMs;
|
|
942
|
+
if (age < STALE_MS) {
|
|
943
|
+
// Check last event type to determine if still running
|
|
944
|
+
let isRunning = true;
|
|
945
|
+
try {
|
|
946
|
+
const MAX_RUN = 512 * 1024; // 512 KiB
|
|
947
|
+
if (stat.size <= MAX_RUN) {
|
|
948
|
+
const raw = fs.readFileSync(path.join(runsDir, latest), 'utf-8');
|
|
949
|
+
const lines = raw.trim().split('\n').filter(Boolean);
|
|
950
|
+
if (lines.length) {
|
|
951
|
+
const lastEv = JSON.parse(lines[lines.length - 1]);
|
|
952
|
+
if (lastEv.type === 'run:complete' || lastEv.type === 'org:complete') isRunning = false;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
} catch { /* treat as running */ }
|
|
956
|
+
active.push({ name: orgName, runId: latest.replace('.jsonl', ''), ageMs: age, running: isRunning });
|
|
957
|
+
}
|
|
958
|
+
} catch { /* skip */ }
|
|
959
|
+
}
|
|
960
|
+
} catch { /* ignore */ }
|
|
961
|
+
return { count: active.length, orgs: active };
|
|
962
|
+
}
|
|
963
|
+
|
|
910
964
|
// Monograph knowledge graph stats
|
|
911
965
|
// Sources, in priority order:
|
|
912
966
|
// 1. .monomind/graph/stats.json — explicit cached stats
|
|
@@ -960,6 +1014,36 @@ function getSIBudget() {
|
|
|
960
1014
|
} catch { return null; }
|
|
961
1015
|
}
|
|
962
1016
|
|
|
1017
|
+
// Token cost summary — reads cached .monomind/metrics/token-summary.json (no JSONL scanning).
|
|
1018
|
+
// Returns null if file absent, stale (cachedAt is not today in UTC), or cost is zero.
|
|
1019
|
+
// All costs are aggregated across ALL Claude Code projects, not just this repo.
|
|
1020
|
+
function getTokenCostSummary() {
|
|
1021
|
+
const summaryPath = path.join(CWD, '.monomind', 'metrics', 'token-summary.json');
|
|
1022
|
+
const d = readJSON(summaryPath);
|
|
1023
|
+
if (!d) return null;
|
|
1024
|
+
|
|
1025
|
+
// Staleness guard: only show "today" figures when cachedAt is today (UTC)
|
|
1026
|
+
const todayUtc = new Date().toISOString().slice(0, 10); // "YYYY-MM-DD"
|
|
1027
|
+
const cachedDate = (d.cachedAt || '').slice(0, 10);
|
|
1028
|
+
const isFresh = cachedDate === todayUtc;
|
|
1029
|
+
|
|
1030
|
+
const todayCost = isFresh ? (d.todayCost || 0) : 0;
|
|
1031
|
+
const monthCost = d.monthCost || 0;
|
|
1032
|
+
const todayCalls = isFresh ? (d.todayCalls || 0) : 0;
|
|
1033
|
+
|
|
1034
|
+
if (monthCost === 0 && todayCost === 0) return null;
|
|
1035
|
+
|
|
1036
|
+
return { todayCost, monthCost, todayCalls, isFresh };
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
// Format a dollar amount compactly: $0.0023, $1.23, $228.87
|
|
1040
|
+
function fmtCost(n) {
|
|
1041
|
+
if (n >= 100) return '$' + n.toFixed(0);
|
|
1042
|
+
if (n >= 1) return '$' + n.toFixed(2);
|
|
1043
|
+
if (n >= 0.01) return '$' + n.toFixed(3);
|
|
1044
|
+
return '$' + n.toFixed(4);
|
|
1045
|
+
}
|
|
1046
|
+
|
|
963
1047
|
// ── Single-line statusline (compact) ─────────────────────────────
|
|
964
1048
|
function generateStatusline() {
|
|
965
1049
|
const git = getGitInfo();
|
|
@@ -995,9 +1079,24 @@ function generateStatusline() {
|
|
|
995
1079
|
parts.push(`${col}${icon} ${x.bold}${activeAgent.name}${x.reset}`);
|
|
996
1080
|
}
|
|
997
1081
|
|
|
998
|
-
//
|
|
1082
|
+
// Active org runs — high signal for users tracking autonomous orgs
|
|
1083
|
+
const orgStatus = getActiveOrgs();
|
|
1084
|
+
if (orgStatus.count > 0) {
|
|
1085
|
+
const runningOrgs = orgStatus.orgs.filter(o => o.running);
|
|
1086
|
+
const doneOrgs = orgStatus.orgs.filter(o => !o.running);
|
|
1087
|
+
if (runningOrgs.length > 0) {
|
|
1088
|
+
const names = runningOrgs.slice(0, 2).map(o => o.name).join(', ');
|
|
1089
|
+
parts.push(`${x.green}🏛 ${x.bold}${names}${x.reset}${runningOrgs.length > 2 ? ` +${runningOrgs.length - 2}` : ''}`);
|
|
1090
|
+
} else if (doneOrgs.length > 0) {
|
|
1091
|
+
parts.push(`${x.slate}🏛 ${doneOrgs[0].name} done${x.reset}`);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
// Intelligence — only show when non-trivial (>15%) to avoid misleading 0%/noise
|
|
999
1096
|
const ic = pctColor(system.intelligencePct);
|
|
1000
|
-
|
|
1097
|
+
if (system.intelligencePct > 15) {
|
|
1098
|
+
parts.push(`${ic}💡 ${system.intelligencePct}%${x.reset}`);
|
|
1099
|
+
}
|
|
1001
1100
|
|
|
1002
1101
|
// Knowledge chunks (Task 28) — show when populated
|
|
1003
1102
|
if (knowledge.chunks > 0) {
|
|
@@ -1019,6 +1118,17 @@ function generateStatusline() {
|
|
|
1019
1118
|
parts.push(`${x.mint}⚡ ${hooks.enabled}h${x.reset}`);
|
|
1020
1119
|
}
|
|
1021
1120
|
|
|
1121
|
+
// Token cost — today's spend across all projects (from cached summary)
|
|
1122
|
+
const tokenCost = getTokenCostSummary();
|
|
1123
|
+
if (tokenCost) {
|
|
1124
|
+
if (tokenCost.isFresh && tokenCost.todayCost > 0) {
|
|
1125
|
+
const col = tokenCost.todayCost > 50 ? x.coral : tokenCost.todayCost > 10 ? x.gold : x.mint;
|
|
1126
|
+
parts.push(`${col}${fmtCost(tokenCost.todayCost)} today${x.reset}`);
|
|
1127
|
+
} else if (tokenCost.monthCost > 0) {
|
|
1128
|
+
parts.push(`${x.slate}${fmtCost(tokenCost.monthCost)} mo${x.reset}`);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1022
1132
|
return parts.join(` ${DIV} `);
|
|
1023
1133
|
}
|
|
1024
1134
|
|
|
@@ -1061,6 +1171,17 @@ function generateDashboard() {
|
|
|
1061
1171
|
hdr += ` ${DIV} 🤖 ${x.violet}${x.bold}${modelName}${x.reset}`;
|
|
1062
1172
|
if (session.duration) hdr += ` ${x.dim}⏱ ${session.duration}${x.reset}`;
|
|
1063
1173
|
|
|
1174
|
+
// Token cost in dashboard header — today's spend (all projects)
|
|
1175
|
+
const tokenCost = getTokenCostSummary();
|
|
1176
|
+
if (tokenCost) {
|
|
1177
|
+
if (tokenCost.isFresh && tokenCost.todayCost > 0) {
|
|
1178
|
+
const col = tokenCost.todayCost > 50 ? x.coral : tokenCost.todayCost > 10 ? x.gold : x.mint;
|
|
1179
|
+
hdr += ` ${DIV} ${col}${fmtCost(tokenCost.todayCost)} today${x.reset}${x.dim} · ${fmtCost(tokenCost.monthCost)} mo${x.reset}`;
|
|
1180
|
+
} else if (tokenCost.monthCost > 0) {
|
|
1181
|
+
hdr += ` ${DIV} ${x.slate}${fmtCost(tokenCost.monthCost)} mo${x.reset}`;
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1064
1185
|
lines.push(hdr);
|
|
1065
1186
|
lines.push(SEP);
|
|
1066
1187
|
|
|
@@ -1139,6 +1260,20 @@ function generateDashboard() {
|
|
|
1139
1260
|
|
|
1140
1261
|
lines.push(`${x.teal}🧠 CONTEXT${x.reset} ${graphStr} ${DIV} ${hilStr}`);
|
|
1141
1262
|
|
|
1263
|
+
// ── Row 3: Active org runs ───────────────────────────────────
|
|
1264
|
+
const orgStatus = getActiveOrgs();
|
|
1265
|
+
if (orgStatus.count > 0) {
|
|
1266
|
+
lines.push(SEP);
|
|
1267
|
+
const orgParts = orgStatus.orgs.slice(0, 5).map(o => {
|
|
1268
|
+
const ageMin = Math.floor(o.ageMs / 60000);
|
|
1269
|
+
const ageFmt = ageMin < 1 ? 'just now' : ageMin < 60 ? `${ageMin}m ago` : `${Math.floor(ageMin / 60)}h ago`;
|
|
1270
|
+
const col = o.running ? x.green : x.slate;
|
|
1271
|
+
const dot2 = o.running ? `${x.green}●${x.reset}` : `${x.slate}◌${x.reset}`;
|
|
1272
|
+
return `${dot2} ${col}${x.bold}${o.name}${x.reset} ${x.dim}${ageFmt}${x.reset}`;
|
|
1273
|
+
});
|
|
1274
|
+
lines.push(`${x.purple}🏛 ORGS${x.reset} ${orgParts.join(` ${DIV} `)}`);
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1142
1277
|
return lines.join('\n');
|
|
1143
1278
|
}
|
|
1144
1279
|
|
|
@@ -1156,6 +1291,7 @@ function generateJSON() {
|
|
|
1156
1291
|
agentdb: getAgentDBStats(),
|
|
1157
1292
|
tests: getTestStats(),
|
|
1158
1293
|
git: { modified: git.modified, untracked: git.untracked, staged: git.staged, ahead: git.ahead, behind: git.behind },
|
|
1294
|
+
tokenCost: getTokenCostSummary(),
|
|
1159
1295
|
lastUpdated: new Date().toISOString(),
|
|
1160
1296
|
};
|
|
1161
1297
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
/**
|
|
4
|
+
* toggle-statusline.cjs — Toggle or set the monomind statusline display mode.
|
|
5
|
+
*
|
|
6
|
+
* Modes: full | compact
|
|
7
|
+
* Storage: $CLAUDE_PROJECT_DIR/.monomind/statusline-mode.txt
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* node toggle-statusline.cjs # toggle current mode
|
|
11
|
+
* node toggle-statusline.cjs --get # print current mode
|
|
12
|
+
* node toggle-statusline.cjs --set <mode> # set mode (full|compact)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
const path = require('path');
|
|
17
|
+
|
|
18
|
+
const CWD = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
19
|
+
const MODE_FILE = path.join(CWD, '.monomind', 'statusline-mode.txt');
|
|
20
|
+
const VALID_MODES = ['full', 'compact'];
|
|
21
|
+
|
|
22
|
+
function ensureDir() {
|
|
23
|
+
try { fs.mkdirSync(path.dirname(MODE_FILE), { recursive: true }); } catch (_) {}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function readMode() {
|
|
27
|
+
try {
|
|
28
|
+
if (!fs.existsSync(MODE_FILE)) return 'full';
|
|
29
|
+
var val = fs.readFileSync(MODE_FILE, 'utf-8').trim();
|
|
30
|
+
return VALID_MODES.includes(val) ? val : 'full';
|
|
31
|
+
} catch (_) {
|
|
32
|
+
return 'full';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function writeMode(mode) {
|
|
37
|
+
ensureDir();
|
|
38
|
+
fs.writeFileSync(MODE_FILE, mode, 'utf-8');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function printUsage() {
|
|
42
|
+
process.stderr.write(
|
|
43
|
+
'Usage: toggle-statusline.cjs [--get | --set <full|compact>]\n' +
|
|
44
|
+
' (no args) toggle between full and compact\n' +
|
|
45
|
+
' --get print current mode\n' +
|
|
46
|
+
' --set <mode> set mode to full or compact\n'
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
var args = process.argv.slice(2);
|
|
51
|
+
|
|
52
|
+
if (args[0] === '--get') {
|
|
53
|
+
process.stdout.write(readMode() + '\n');
|
|
54
|
+
process.exit(0);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (args[0] === '--set') {
|
|
58
|
+
var newMode = args[1];
|
|
59
|
+
if (!newMode || !VALID_MODES.includes(newMode)) {
|
|
60
|
+
printUsage();
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
writeMode(newMode);
|
|
64
|
+
process.stdout.write('statusline mode → ' + newMode + '\n');
|
|
65
|
+
process.exit(0);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// No args: toggle
|
|
69
|
+
var current = readMode();
|
|
70
|
+
var toggled = current === 'full' ? 'compact' : 'full';
|
|
71
|
+
writeMode(toggled);
|
|
72
|
+
process.stdout.write('statusline mode → ' + toggled + ' (was: ' + current + ')\n');
|
|
73
|
+
process.exit(0);
|