@monoes/monomindcli 1.10.6 → 1.10.8

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.
@@ -828,6 +828,68 @@ function getTriggerStats() {
828
828
  } catch { return { triggers: 0, agents: 0 }; }
829
829
  }
830
830
 
831
+ // Graph freshness — compare last build time vs commits since
832
+ function getGraphFreshness() {
833
+ const lockPath = path.join(CWD, '.monomind', 'graph', '.rebuild-lock');
834
+ const dbPath = path.join(CWD, '.monomind', 'monograph.db');
835
+ let buildMs = 0;
836
+ try {
837
+ const lockStat = safeStat(lockPath);
838
+ const dbStat = safeStat(dbPath);
839
+ buildMs = Math.max(lockStat?.mtimeMs || 0, dbStat?.mtimeMs || 0);
840
+ } catch { /* ignore */ }
841
+ if (!buildMs) return { commitsBehind: -1, stale: true, fresh: false };
842
+ const buildIso = new Date(buildMs).toISOString();
843
+ const out = safeExec(\`git rev-list --count --since='\${buildIso}' HEAD 2>/dev/null\`, 1500);
844
+ const commitsBehind = parseInt(out, 10) || 0;
845
+ return { commitsBehind, stale: commitsBehind > 5, fresh: commitsBehind === 0 };
846
+ }
847
+
848
+ // Active loops — scan .monomind/loops/*.json, skip stale (>6h)
849
+ function getLoopStatus() {
850
+ const loopsDir = path.join(CWD, '.monomind', 'loops');
851
+ if (!fs.existsSync(loopsDir)) return { count: 0, loops: [] };
852
+ const STALE_MS = 6 * 60 * 60 * 1000;
853
+ const now = Date.now();
854
+ const loops = [];
855
+ try {
856
+ const files = fs.readdirSync(loopsDir).filter(f =>
857
+ f.endsWith('.json') && !f.includes('-hil') && !f.endsWith('.stop'));
858
+ for (const f of files) {
859
+ const d = readJSON(path.join(loopsDir, f));
860
+ if (!d || !d.command) continue;
861
+ const last = d.lastRunAt || d.nextRunAt || d.startedAt || 0;
862
+ if (last && (now - last) > STALE_MS) continue;
863
+ loops.push({
864
+ cmd: String(d.command).replace(/^\\//,''),
865
+ type: d.type || 'repeat',
866
+ rep: d.currentRep || 0,
867
+ max: d.maxReps || 0,
868
+ status: d.status || 'running',
869
+ });
870
+ }
871
+ } catch { /* ignore */ }
872
+ return { count: loops.length, loops };
873
+ }
874
+
875
+ // HIL pending — count <id>-hil.md files with no human response yet
876
+ function getHILPending() {
877
+ const loopsDir = path.join(CWD, '.monomind', 'loops');
878
+ if (!fs.existsSync(loopsDir)) return { pending: 0 };
879
+ let pending = 0;
880
+ try {
881
+ const files = fs.readdirSync(loopsDir).filter(f => f.endsWith('-hil.md'));
882
+ for (const f of files) {
883
+ try {
884
+ const txt = fs.readFileSync(path.join(loopsDir, f), 'utf-8');
885
+ const answered = /^[ \\t]*>[ \\t]+\\S/m.test(txt);
886
+ if (!answered) pending++;
887
+ } catch { /* ignore */ }
888
+ }
889
+ } catch { /* ignore */ }
890
+ return { pending };
891
+ }
892
+
831
893
  // Monograph knowledge graph stats
832
894
  // Sources, in priority order:
833
895
  // 1. .monomind/graph/stats.json — explicit cached stats
@@ -979,144 +1041,60 @@ function generateDashboard() {
979
1041
  lines.push(hdr);
980
1042
  lines.push(SEP);
981
1043
 
982
- // ── Row 1: Intelligence & Learning ───────────────────────────
983
- const intellCol = pctColor(system.intelligencePct);
984
- const intellBar = blockBar(system.intelligencePct, 100, 6);
985
-
986
- // Knowledge (Task 28)
987
- const knowStr = knowledge.chunks > 0
988
- ? \`\${x.teal}📚 \${x.bold}\${knowledge.chunks}\${x.reset}\${x.slate} chunks\${x.reset}\`
989
- : \`\${x.slate}📚 no chunks\${x.reset}\`;
990
-
991
- // Skills (Task 45)
992
- const skillStr = knowledge.skills > 0
993
- ? \` \${x.mint}✦ \${knowledge.skills} skills\${x.reset}\`
994
- : '';
995
-
996
- // Patterns
997
- const patStr = progress.patternsLearned > 0
998
- ? \`\${x.gold}\${progress.patternsLearned >= 1000 ? (progress.patternsLearned / 1000).toFixed(1) + 'k' : progress.patternsLearned} patterns\${x.reset}\`
999
- : \`\${x.slate}0 patterns\${x.reset}\`;
1000
-
1001
- // Graph (monograph)
1002
- const graph = getGraphifyStats();
1003
- const graphStr = graph.exists
1004
- ? \`\${x.sky}🔗 \${x.bold}\${graph.nodes}\${x.reset}\${x.slate} nodes · \${x.reset}\${x.sky}\${x.bold}\${graph.edges}\${x.reset}\${x.slate} edges\${x.reset}\`
1005
- : \`\${x.slate}🔗 no graph\${x.reset}\`;
1006
-
1007
- lines.push(
1008
- \`\${x.purple}💡 INTEL\${x.reset} \` +
1009
- \`\${intellCol}\${intellBar} \${x.bold}\${system.intelligencePct}%\${x.reset} \${DIV} \` +
1010
- \`\${knowStr}\${skillStr} \${DIV} \` +
1011
- \`\${patStr} \${DIV} \` +
1012
- graphStr
1013
- );
1014
- lines.push(SEP);
1015
-
1016
- // ── Row 2: Agents & Triggers ──────────────────────────────────
1017
- const agentCol = swarm.activeAgents > 0 ? x.green : x.slate;
1018
- const hookCol = hooks.enabled > 0 ? x.mint : x.slate;
1019
-
1020
- // Triggers (Task 32)
1021
- const trigStr = triggers.triggers > 0
1022
- ? \`\${x.mint}🎯 \${x.bold}\${triggers.triggers}\${x.reset}\${x.slate} triggers · \${triggers.agents} agents\${x.reset}\`
1023
- : \`\${x.slate}🎯 no triggers\${x.reset}\`;
1024
-
1025
- // Active agent badge
1026
- let agentBadge;
1044
+ // ── Row 1: Active agent + Loop status ────────────────────────
1045
+ let agentStr;
1027
1046
  if (activeAgent) {
1028
1047
  const col = activeAgent.activated ? x.green : x.sky;
1029
- const mark = activeAgent.activated ? '● ACTIVE' : '→ ROUTED';
1048
+ const mark = activeAgent.activated ? \`\${col}\${x.bold}● ACTIVE\${x.reset} \` : '';
1030
1049
  const conf = activeAgent.activated ? '' : \` \${x.slate}\${(activeAgent.confidence * 100).toFixed(0)}%\${x.reset}\`;
1031
- const cat = activeAgent.category ? \` \${x.slate}[\${activeAgent.category}]\${x.reset}\` : '';
1032
- agentBadge = \`\${col}\${x.bold}\${mark}\${x.reset} \${col}👤 \${x.bold}\${activeAgent.name}\${x.reset}\${cat}\${conf}\`;
1050
+ agentStr = \`\${mark}\${col}👤 \${x.bold}\${activeAgent.name}\${x.reset}\${conf}\`;
1033
1051
  } else {
1034
- agentBadge = \`\${x.slate}👤 no agent routed\${x.reset}\`;
1052
+ agentStr = \`\${x.slate}👤 no agent routed\${x.reset}\`;
1035
1053
  }
1036
1054
 
1037
- lines.push(
1038
- \`\${x.gold}🐝 SWARM\${x.reset} \` +
1039
- \`\${agentCol}\${x.bold}\${swarm.activeAgents}\${x.reset}\${x.slate}/\${x.reset}\${x.white}\${swarm.maxAgents}\${x.reset} agents \` +
1040
- \`\${hookCol}⚡ \${hooks.enabled}/\${hooks.total} hooks\${x.reset} \${DIV} \` +
1041
- \`\${trigStr} \${DIV} \` +
1042
- agentBadge
1043
- );
1044
- lines.push(SEP);
1045
-
1046
- // ── Row 3: Architecture & Security ───────────────────────────
1047
- const adrCol = adrs.count > 0
1048
- ? (adrs.implemented >= adrs.count ? x.green : x.gold)
1049
- : x.slate;
1050
- const adrStr = adrs.count > 0
1051
- ? \`\${adrCol}\${x.bold}\${adrs.implemented}\${x.reset}\${x.slate}/\${x.reset}\${x.white}\${adrs.count}\${x.reset} ADRs\`
1052
- : \`\${x.slate}no ADRs\${x.reset}\`;
1053
-
1054
- const dddCol = pctColor(progress.dddProgress);
1055
- const dddBar = blockBar(progress.dddProgress, 100, 5);
1056
-
1057
- const cveStatus = security.totalCves === 0
1058
- ? (security.status === 'NONE' ? \`\${x.slate}not scanned\${x.reset}\` : \`\${x.green}✔ clean\${x.reset}\`)
1059
- : \`\${x.coral}\${security.cvesFixed}/\${security.totalCves} fixed\${x.reset}\`;
1060
-
1061
- lines.push(
1062
- \`\${x.purple}🧩 ARCH\${x.reset} \` +
1063
- \`\${adrStr} \${DIV} \` +
1064
- \`DDD \${dddBar} \${dddCol}\${x.bold}\${progress.dddProgress}%\${x.reset} \${DIV} \` +
1065
- \`🛡️ \${sec.col}\${sec.label}\${x.reset} \${DIV} \` +
1066
- \`CVE \${cveStatus}\`
1067
- );
1068
- lines.push(SEP);
1069
-
1070
- // ── Row 4: Memory & Tests ─────────────────────────────────────
1071
- const vecCol = agentdb.vectorCount > 0 ? x.green : x.slate;
1072
- const hnswTag = agentdb.hasHnsw && agentdb.vectorCount > 0 ? \` \${x.green}⚡ HNSW\${x.reset}\` : '';
1073
- const sizeDisp = agentdb.dbSizeKB >= 1024
1074
- ? \`\${(agentdb.dbSizeKB / 1024).toFixed(1)} MB\` : \`\${agentdb.dbSizeKB} KB\`;
1075
- const testCol = tests.testFiles > 0 ? x.green : x.slate;
1076
- const memCol = system.memoryMB > 200 ? x.orange : x.sky;
1077
-
1078
- const chips = [];
1079
- if (integration.mcpServers.total > 0) {
1080
- const mc = integration.mcpServers.enabled === integration.mcpServers.total ? x.green
1081
- : integration.mcpServers.enabled > 0 ? x.gold : x.coral;
1082
- chips.push(\`\${mc}MCP \${integration.mcpServers.enabled}/\${integration.mcpServers.total}\${x.reset}\`);
1055
+ const loopState = getLoopStatus();
1056
+ let loopStr;
1057
+ if (loopState.count > 0) {
1058
+ const parts = loopState.loops.slice(0, 2).map(l => {
1059
+ const status = l.status === 'hil:pending'
1060
+ ? \`\${x.coral}⏳ HIL\${x.reset}\`
1061
+ : \`\${x.green}⟳\${x.reset}\`;
1062
+ const tag = l.type === 'tillend'
1063
+ ? \`\${x.bold}\${l.cmd}\${x.reset}\${x.slate} run \${l.rep}\${x.reset}\`
1064
+ : \`\${x.bold}\${l.cmd}\${x.reset}\${x.slate} \${l.rep}/\${l.max}\${x.reset}\`;
1065
+ return \`\${status} \${tag}\`;
1066
+ });
1067
+ loopStr = \`\${x.gold}🔄\${x.reset} \${parts.join(\`\${x.slate} · \${x.reset}\`)}\`;
1068
+ if (loopState.count > 2) loopStr += \`\${x.slate} +\${loopState.count - 2} more\${x.reset}\`;
1069
+ } else {
1070
+ loopStr = \`\${x.slate}🔄 no active loops\${x.reset}\`;
1083
1071
  }
1084
- if (integration.hasDatabase) chips.push(\`\${x.green}DB ✔\${x.reset}\`);
1085
- if (integration.hasApi) chips.push(\`\${x.green}API ✔\${x.reset}\`);
1086
- const integStr = chips.length ? chips.join(' ') : \`\${x.slate}none\${x.reset}\`;
1087
-
1088
- lines.push(
1089
- \`\${x.teal}🗄️ MEMORY\${x.reset} \` +
1090
- \`\${vecCol}\${x.bold}\${agentdb.vectorCount}\${x.reset}\${x.slate} vectors\${x.reset}\${hnswTag} \${DIV} \` +
1091
- \`\${x.white}\${sizeDisp}\${x.reset} \${DIV} \` +
1092
- \`\${testCol}🧪 \${tests.testFiles} test files\${x.reset} \${DIV} \` +
1093
- integStr
1094
- );
1072
+
1073
+ lines.push(\`\${x.purple}🤖 AGENT\${x.reset} \${agentStr} \${DIV} \${loopStr}\`);
1095
1074
  lines.push(SEP);
1096
1075
 
1097
- // ── Row 5: Context budget ─────────────────────────────────────
1098
- // SI budget (Task 23 monitor)
1099
- let siStr;
1100
- if (si) {
1101
- const siCol = si.pct > 100 ? x.coral : si.pct > 80 ? x.gold : x.green;
1102
- siStr = \`\${siCol}📄 SI \${si.pct}% budget\${x.reset} \${x.dim}(\${si.len}/\${si.limit} chars)\${x.reset}\`;
1076
+ // ── Row 2: Graph freshness + Pending HIL ─────────────────────
1077
+ const gf = getGraphifyStats();
1078
+ const freshness = getGraphFreshness();
1079
+ let graphStr;
1080
+ if (gf.exists) {
1081
+ const nodesFmt = gf.nodes >= 1000 ? \`\${(gf.nodes / 1000).toFixed(0)}k\` : \`\${gf.nodes}\`;
1082
+ const freshTag = freshness.fresh
1083
+ ? \`\${x.green}● fresh\${x.reset}\`
1084
+ : freshness.stale
1085
+ ? \`\${x.coral}● \${freshness.commitsBehind} commits stale\${x.reset}\`
1086
+ : \`\${x.gold}● \${freshness.commitsBehind} behind\${x.reset}\`;
1087
+ graphStr = \`\${x.sky}🔗 \${x.bold}\${nodesFmt}\${x.reset}\${x.slate} nodes\${x.reset} \${freshTag}\`;
1103
1088
  } else {
1104
- siStr = \`\${x.slate}📄 no shared instructions\${x.reset}\`;
1089
+ graphStr = \`\${x.slate}🔗 no graph\${x.reset}\`;
1105
1090
  }
1106
1091
 
1107
- // Domains
1108
- const domCol = progress.domainsCompleted >= 4 ? x.green
1109
- : progress.domainsCompleted >= 2 ? x.gold
1110
- : progress.domainsCompleted >= 1 ? x.orange
1111
- : x.slate;
1112
- const domBar = blockBar(progress.domainsCompleted, progress.totalDomains);
1113
-
1114
- lines.push(
1115
- \`\${x.slate}📋 CONTEXT\${x.reset} \` +
1116
- \`\${siStr} \${DIV} \` +
1117
- \`\${x.teal}🏗 \${domBar} \${domCol}\${x.bold}\${progress.domainsCompleted}\${x.reset}\${x.slate}/\${x.reset}\${x.white}\${progress.totalDomains}\${x.reset} domains \${DIV} \` +
1118
- \`\${x.dim}💾 \${system.memoryMB} MB RAM\${x.reset}\`
1119
- );
1092
+ const hil = getHILPending();
1093
+ const hilStr = hil.pending > 0
1094
+ ? \`\${x.coral}✨ \${x.bold}\${hil.pending}\${x.reset}\${x.coral} HIL pending\${x.reset}\`
1095
+ : \`\${x.slate}✨ no pending HIL\${x.reset}\`;
1096
+
1097
+ lines.push(\`\${x.teal}🧠 CONTEXT\${x.reset} \${graphStr} \${DIV} \${hilStr}\`);
1120
1098
 
1121
1099
  return lines.join('\\n');
1122
1100
  }
@@ -1 +1 @@
1
- {"version":3,"file":"statusline-generator.js","sourceRoot":"","sources":["../../../src/init/statusline-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAAoB;IAC3D,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;IAC5C,OAAO;;;;;;;;;;;;;;;;;;;;;;;eAuBM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgnCvB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAoB;IACzD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QAChC,OAAO,sCAAsC,CAAC;IAChD,CAAC;IAED,OAAO;;;;;;;;;;;;;;;;;;;;;;;;CAwBR,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"statusline-generator.js","sourceRoot":"","sources":["../../../src/init/statusline-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB,CAAC,OAAoB;IAC3D,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;IAC5C,OAAO;;;;;;;;;;;;;;;;;;;;;;;eAuBM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0lCvB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAoB;IACzD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QAChC,OAAO,sCAAsC,CAAC;IAChD,CAAC;IAED,OAAO;;;;;;;;;;;;;;;;;;;;;;;;CAwBR,CAAC;AACF,CAAC"}