@monoes/monomindcli 2.1.0 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/.claude/commands/mastermind/createorg.md +8 -9
  2. package/.claude/helpers/handlers/capture-handler.cjs +24 -10
  3. package/.claude/helpers/handlers/gates-handler.cjs +2 -2
  4. package/.claude/helpers/handlers/route-handler.cjs +29 -0
  5. package/.claude/helpers/handlers/session-handler.cjs +35 -23
  6. package/.claude/helpers/hook-handler.cjs +21 -0
  7. package/.claude/helpers/utils/monograph.cjs +73 -2
  8. package/.claude/skills/mastermind-skills/createorg.md +91 -701
  9. package/.claude/skills/mastermind-skills/org-settings.md +46 -47
  10. package/.claude/skills/mastermind-skills/runorg.md +12 -1
  11. package/README.md +77 -94
  12. package/dist/src/agents/registry-builder.js.map +1 -1
  13. package/dist/src/browser/dashboard/server.js.map +1 -1
  14. package/dist/src/browser/workflow/engine.d.ts.map +1 -1
  15. package/dist/src/browser/workflow/engine.js.map +1 -1
  16. package/dist/src/browser/workflow/store.d.ts +2 -2
  17. package/dist/src/browser/workflow/store.d.ts.map +1 -1
  18. package/dist/src/browser/workflow/store.js.map +1 -1
  19. package/dist/src/capabilities/manager.d.ts.map +1 -1
  20. package/dist/src/capabilities/watcher.d.ts.map +1 -1
  21. package/dist/src/commands/agent-lifecycle.js.map +1 -1
  22. package/dist/src/commands/agent-ops.js.map +1 -1
  23. package/dist/src/commands/agent.d.ts.map +1 -1
  24. package/dist/src/commands/analyze-ast.js.map +1 -1
  25. package/dist/src/commands/analyze.d.ts.map +1 -1
  26. package/dist/src/commands/analyze.js.map +1 -1
  27. package/dist/src/commands/autopilot.d.ts.map +1 -1
  28. package/dist/src/commands/browse-action.d.ts.map +1 -1
  29. package/dist/src/commands/browse-action.js.map +1 -1
  30. package/dist/src/commands/browse-platform.d.ts.map +1 -1
  31. package/dist/src/commands/browse-workflow.d.ts.map +1 -1
  32. package/dist/src/commands/browse.d.ts +1 -1
  33. package/dist/src/commands/browse.d.ts.map +1 -1
  34. package/dist/src/commands/cleanup.d.ts.map +1 -1
  35. package/dist/src/commands/completions.d.ts.map +1 -1
  36. package/dist/src/commands/config.d.ts.map +1 -1
  37. package/dist/src/commands/crash-reporting.d.ts.map +1 -1
  38. package/dist/src/commands/design-detect.d.ts.map +1 -1
  39. package/dist/src/commands/design-palette.d.ts.map +1 -1
  40. package/dist/src/commands/doc.d.ts.map +1 -1
  41. package/dist/src/commands/doctor-env-checks.d.ts.map +1 -1
  42. package/dist/src/commands/doctor-env-checks.js +5 -0
  43. package/dist/src/commands/doctor-env-checks.js.map +1 -1
  44. package/dist/src/commands/doctor-project-checks.js.map +1 -1
  45. package/dist/src/commands/doctor.d.ts.map +1 -1
  46. package/dist/src/commands/guidance.d.ts.map +1 -1
  47. package/dist/src/commands/hooks.d.ts.map +1 -1
  48. package/dist/src/commands/index.d.ts.map +1 -1
  49. package/dist/src/commands/init.d.ts.map +1 -1
  50. package/dist/src/commands/mcp.d.ts.map +1 -1
  51. package/dist/src/commands/memory.d.ts.map +1 -1
  52. package/dist/src/commands/monograph.d.ts.map +1 -1
  53. package/dist/src/commands/org.d.ts.map +1 -1
  54. package/dist/src/commands/org.js +46 -29
  55. package/dist/src/commands/org.js.map +1 -1
  56. package/dist/src/commands/performance.d.ts.map +1 -1
  57. package/dist/src/commands/platforms.d.ts +1 -1
  58. package/dist/src/commands/platforms.d.ts.map +1 -1
  59. package/dist/src/commands/providers.d.ts.map +1 -1
  60. package/dist/src/commands/report-crash.d.ts.map +1 -1
  61. package/dist/src/commands/route.d.ts.map +1 -1
  62. package/dist/src/commands/search-universal.d.ts.map +1 -1
  63. package/dist/src/commands/security.d.ts.map +1 -1
  64. package/dist/src/commands/session.d.ts.map +1 -1
  65. package/dist/src/commands/start.d.ts.map +1 -1
  66. package/dist/src/commands/status.d.ts.map +1 -1
  67. package/dist/src/commands/swarm.d.ts.map +1 -1
  68. package/dist/src/commands/task.d.ts.map +1 -1
  69. package/dist/src/commands/tokens.d.ts.map +1 -1
  70. package/dist/src/commands/tokens.js.map +1 -1
  71. package/dist/src/commands/transfer-store.d.ts.map +1 -1
  72. package/dist/src/commands/update.d.ts.map +1 -1
  73. package/dist/src/consensus/audit-writer.d.ts.map +1 -1
  74. package/dist/src/index.d.ts.map +1 -1
  75. package/dist/src/index.js.map +1 -1
  76. package/dist/src/init/claudemd-generator.d.ts.map +1 -1
  77. package/dist/src/init/claudemd-generator.js.map +1 -1
  78. package/dist/src/init/executor.d.ts.map +1 -1
  79. package/dist/src/init/executor.js +30 -6
  80. package/dist/src/init/executor.js.map +1 -1
  81. package/dist/src/init/mcp-generator.js.map +1 -1
  82. package/dist/src/mcp-client.d.ts.map +1 -1
  83. package/dist/src/mcp-client.js.map +1 -1
  84. package/dist/src/mcp-server.d.ts.map +1 -1
  85. package/dist/src/mcp-server.js.map +1 -1
  86. package/dist/src/mcp-tools/analyze-tools.d.ts.map +1 -1
  87. package/dist/src/mcp-tools/auto-install.d.ts +8 -8
  88. package/dist/src/mcp-tools/auto-install.d.ts.map +1 -1
  89. package/dist/src/mcp-tools/auto-install.js.map +1 -1
  90. package/dist/src/mcp-tools/browser-tools.d.ts.map +1 -1
  91. package/dist/src/mcp-tools/browser-tools.js.map +1 -1
  92. package/dist/src/mcp-tools/claims-tools.d.ts.map +1 -1
  93. package/dist/src/mcp-tools/coherence/causal-infer.d.ts.map +1 -1
  94. package/dist/src/mcp-tools/coherence/causal-infer.js.map +1 -1
  95. package/dist/src/mcp-tools/coherence/coherence-check.d.ts.map +1 -1
  96. package/dist/src/mcp-tools/coherence/consensus-verify.d.ts.map +1 -1
  97. package/dist/src/mcp-tools/coherence/memory-gate.d.ts.map +1 -1
  98. package/dist/src/mcp-tools/coherence/quantum-topology.d.ts.map +1 -1
  99. package/dist/src/mcp-tools/coherence/spectral-analyze.d.ts.map +1 -1
  100. package/dist/src/mcp-tools/coherence/spectral-analyze.js.map +1 -1
  101. package/dist/src/mcp-tools/coherence/types.d.ts +31 -31
  102. package/dist/src/mcp-tools/embeddings-tools.js.map +1 -1
  103. package/dist/src/mcp-tools/graphify-tools.d.ts.map +1 -1
  104. package/dist/src/mcp-tools/guidance-tools.d.ts.map +1 -1
  105. package/dist/src/mcp-tools/guidance-tools.js.map +1 -1
  106. package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -1
  107. package/dist/src/mcp-tools/hive-mind-tools.js +5 -1
  108. package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -1
  109. package/dist/src/mcp-tools/hooks-embedding.js.map +1 -1
  110. package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
  111. package/dist/src/mcp-tools/monograph-tools.d.ts.map +1 -1
  112. package/dist/src/mcp-tools/monograph-tools.js +28 -3
  113. package/dist/src/mcp-tools/monograph-tools.js.map +1 -1
  114. package/dist/src/mcp-tools/neural-tools.js.map +1 -1
  115. package/dist/src/mcp-tools/quality/coverage-analysis/prioritize-gaps.d.ts +36 -36
  116. package/dist/src/mcp-tools/quality/coverage-analysis/prioritize-gaps.d.ts.map +1 -1
  117. package/dist/src/mcp-tools/quality/security-compliance/detect-secrets.d.ts +4 -4
  118. package/dist/src/mcp-tools/quality/security-compliance/detect-secrets.d.ts.map +1 -1
  119. package/dist/src/mcp-tools/security-tools.d.ts.map +1 -1
  120. package/dist/src/mcp-tools/security-tools.js.map +1 -1
  121. package/dist/src/mcp-tools/system-tools.js.map +1 -1
  122. package/dist/src/mcp-tools/transfer-tools.d.ts.map +1 -1
  123. package/dist/src/memory/ewc-consolidation.d.ts +12 -0
  124. package/dist/src/memory/ewc-consolidation.d.ts.map +1 -1
  125. package/dist/src/memory/ewc-consolidation.js.map +1 -1
  126. package/dist/src/memory/hnsw-operations.js.map +1 -1
  127. package/dist/src/memory/intelligence.d.ts.map +1 -1
  128. package/dist/src/memory/intelligence.js.map +1 -1
  129. package/dist/src/memory/memory-initializer.d.ts.map +1 -1
  130. package/dist/src/memory/sona-optimizer.d.ts +12 -0
  131. package/dist/src/memory/sona-optimizer.d.ts.map +1 -1
  132. package/dist/src/memory/sona-optimizer.js.map +1 -1
  133. package/dist/src/monovector/coverage-router.js.map +1 -1
  134. package/dist/src/monovector/coverage-tools.d.ts.map +1 -1
  135. package/dist/src/monovector/diff-classifier.d.ts.map +1 -1
  136. package/dist/src/monovector/diff-classifier.js.map +1 -1
  137. package/dist/src/monovector/init-state.js.map +1 -1
  138. package/dist/src/observability/replay-reader.d.ts.map +1 -1
  139. package/dist/src/orgrt/broker.d.ts +3 -1
  140. package/dist/src/orgrt/broker.d.ts.map +1 -1
  141. package/dist/src/orgrt/broker.js +8 -3
  142. package/dist/src/orgrt/broker.js.map +1 -1
  143. package/dist/src/orgrt/bus.d.ts +5 -1
  144. package/dist/src/orgrt/bus.d.ts.map +1 -1
  145. package/dist/src/orgrt/bus.js +5 -1
  146. package/dist/src/orgrt/bus.js.map +1 -1
  147. package/dist/src/orgrt/daemon.d.ts +35 -1
  148. package/dist/src/orgrt/daemon.d.ts.map +1 -1
  149. package/dist/src/orgrt/daemon.js +190 -21
  150. package/dist/src/orgrt/daemon.js.map +1 -1
  151. package/dist/src/orgrt/forwarder.d.ts.map +1 -1
  152. package/dist/src/orgrt/forwarder.js +47 -10
  153. package/dist/src/orgrt/forwarder.js.map +1 -1
  154. package/dist/src/orgrt/inbox.d.ts +11 -0
  155. package/dist/src/orgrt/inbox.d.ts.map +1 -0
  156. package/dist/src/orgrt/inbox.js +56 -0
  157. package/dist/src/orgrt/inbox.js.map +1 -0
  158. package/dist/src/orgrt/mailbox.d.ts.map +1 -1
  159. package/dist/src/orgrt/policy.d.ts +5 -1
  160. package/dist/src/orgrt/policy.d.ts.map +1 -1
  161. package/dist/src/orgrt/policy.js +58 -5
  162. package/dist/src/orgrt/policy.js.map +1 -1
  163. package/dist/src/orgrt/provider.js.map +1 -1
  164. package/dist/src/orgrt/scheduler.d.ts.map +1 -1
  165. package/dist/src/orgrt/scheduler.js.map +1 -1
  166. package/dist/src/orgrt/server.d.ts +3 -2
  167. package/dist/src/orgrt/server.d.ts.map +1 -1
  168. package/dist/src/orgrt/server.js +31 -40
  169. package/dist/src/orgrt/server.js.map +1 -1
  170. package/dist/src/orgrt/session.d.ts +11 -1
  171. package/dist/src/orgrt/session.d.ts.map +1 -1
  172. package/dist/src/orgrt/session.js +32 -1
  173. package/dist/src/orgrt/session.js.map +1 -1
  174. package/dist/src/orgrt/test-loop.d.ts.map +1 -1
  175. package/dist/src/orgrt/test-loop.js +8 -8
  176. package/dist/src/orgrt/test-loop.js.map +1 -1
  177. package/dist/src/orgrt/types.d.ts +53 -53
  178. package/dist/src/orgrt/types.d.ts.map +1 -1
  179. package/dist/src/output.d.ts +29 -29
  180. package/dist/src/output.d.ts.map +1 -1
  181. package/dist/src/output.js +10 -2
  182. package/dist/src/output.js.map +1 -1
  183. package/dist/src/parser.d.ts.map +1 -1
  184. package/dist/src/parser.js.map +1 -1
  185. package/dist/src/pricing/model-pricing.d.ts +1 -1
  186. package/dist/src/pricing/model-pricing.d.ts.map +1 -1
  187. package/dist/src/production/circuit-breaker.d.ts.map +1 -1
  188. package/dist/src/production/circuit-breaker.js.map +1 -1
  189. package/dist/src/production/error-handler.d.ts.map +1 -1
  190. package/dist/src/production/error-handler.js.map +1 -1
  191. package/dist/src/production/monitoring.d.ts.map +1 -1
  192. package/dist/src/production/monitoring.js.map +1 -1
  193. package/dist/src/production/rate-limiter.d.ts.map +1 -1
  194. package/dist/src/production/rate-limiter.js.map +1 -1
  195. package/dist/src/production/retry.d.ts.map +1 -1
  196. package/dist/src/production/retry.js.map +1 -1
  197. package/dist/src/prompt.d.ts.map +1 -1
  198. package/dist/src/prompt.js.map +1 -1
  199. package/dist/src/routing/llm-caller.js.map +1 -1
  200. package/dist/src/routing/route-layer-factory.js.map +1 -1
  201. package/dist/src/services/config-file-manager.d.ts.map +1 -1
  202. package/dist/src/suggest.d.ts.map +1 -1
  203. package/dist/src/suggest.js.map +1 -1
  204. package/dist/src/transfer/export.js.map +1 -1
  205. package/dist/src/transfer/ipfs/client.js.map +1 -1
  206. package/dist/src/transfer/ipfs/upload.js.map +1 -1
  207. package/dist/src/transfer/models/seraphine.d.ts.map +1 -1
  208. package/dist/src/transfer/storage/gcs.js.map +1 -1
  209. package/dist/src/transfer/store/discovery.d.ts.map +1 -1
  210. package/dist/src/transfer/store/discovery.js.map +1 -1
  211. package/dist/src/transfer/store/download.d.ts.map +1 -1
  212. package/dist/src/transfer/store/download.js.map +1 -1
  213. package/dist/src/transfer/store/index.d.ts.map +1 -1
  214. package/dist/src/transfer/store/index.js.map +1 -1
  215. package/dist/src/transfer/store/publish.d.ts.map +1 -1
  216. package/dist/src/transfer/store/publish.js.map +1 -1
  217. package/dist/src/transfer/store/search.js.map +1 -1
  218. package/dist/src/types.d.ts +2 -2
  219. package/dist/src/types.d.ts.map +1 -1
  220. package/dist/src/types.js.map +1 -1
  221. package/dist/src/ui/collector.mjs +20 -5
  222. package/dist/src/ui/dashboard.html +465 -500
  223. package/dist/src/ui/orgs-files.js +192 -0
  224. package/dist/src/ui/orgs.html +21 -52
  225. package/dist/src/ui/server.mjs +174 -164
  226. package/dist/src/update/checker.js.map +1 -1
  227. package/dist/src/update/rate-limiter.js.map +1 -1
  228. package/dist/tsconfig.tsbuildinfo +1 -1
  229. package/package.json +12 -16
  230. package/scripts/publish.sh +6 -0
  231. package/dist/src/orgrt/live.html +0 -56
@@ -1,4 +1,4 @@
1
- <!-- Define and save an autonomous agent organization — roles, hierarchy, and communication topology. Suggest or confirm roles, then persist the org for use with runorg. -->
1
+ <!-- Define and save an autonomous agent organization (Org Runtime v2) — roles and hierarchy. Suggest or confirm roles, then persist the org config for `monomind org run`/`serve`. -->
2
2
 
3
3
  **If $ARGUMENTS is empty:** Output the following and wait.
4
4
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  **MASTERMIND: CREATE ORG**
8
8
 
9
- An org is a named, persistent agent team — not a one-shot Mastermind run. Once created, the org runs autonomously across sessions: a boss agent coordinates specialists who pick up tasks from a shared board, execute them, and loop until stopped.
9
+ An org is a named, persistent agent team, run by the Org Runtime v2 daemon — not a one-shot Mastermind run and not a Task-tool-spawned boss. Once created, every role in the config starts as its own live agent session the moment you run the org; roles message each other directly (no shared task board) and the org keeps running until stopped.
10
10
 
11
11
  Use orgs when the work is ongoing, not single-shot. A content team that ships 10 posts a month. A research squad that runs competitive scans weekly. A dev team with a permanent backlog.
12
12
 
@@ -25,16 +25,15 @@ Use orgs when the work is ongoing, not single-shot. A content team that ships 10
25
25
  ```
26
26
 
27
27
  **Options:**
28
- `--name <slug>` — org identifier used with `/mastermind:runorg` (derived from goal if omitted)
28
+ `--name <slug>` — org identifier used with `monomind org run <name>` (derived from goal if omitted)
29
29
  `--roles <list>` — explicit role list (e.g. "boss, writer, reviewer, marketer")
30
- `--schedule <interval>` — make this a self-scheduling loop org (e.g. `"every 30 minutes"`, `"every hour"`, `"daily"`)
30
+ `--schedule <interval>` — daemon schedule for `monomind org serve` to pick up, e.g. `"30m"`, `"2h"`, `"1440m"` for daily (omit for a manual, one-shot org)
31
31
  `--auto` — skip confirmation, create immediately
32
32
  `--confirm` — always ask before saving (default)
33
- `--delete <name>` — delete a saved org and all associated data files
34
- `--list` — list all saved orgs with their status
33
+ `--delete <name>` — delete a saved org and all associated data files (`monomind org delete <name> --yes`)
34
+ `--list` — list all saved orgs with their status (`monomind org list`)
35
35
 
36
- Once created, start the org with `/mastermind:runorg --org <name>`.
37
- For scheduled orgs: `runorg` activates the loop; `stoporg` stops it; `orgs` lists all.
36
+ Once created, start the org with `monomind org run <name>` (foreground, one-shot) or let `monomind org serve` pick it up if `--schedule` was set. Check status with `monomind org status <name>`; stop with `monomind org stop <name>`.
38
37
 
39
38
  ---
40
39
 
@@ -47,7 +46,7 @@ Parse `$ARGUMENTS` for:
47
46
  - `--confirm` flag → mode = confirm
48
47
  - `--name <name>` → org_name = <name> (must match `^[a-z0-9][a-z0-9-]{0,63}$`; if omitted, derived from goal)
49
48
  - `--roles <desc>` → roles_desc = <desc> (explicit role list, e.g. "boss, writer, reviewer, marketer")
50
- - `--schedule <interval>` → schedule = <interval> (e.g. `"every 30 minutes"`, `"every hour"`, `"daily"`; triggers loop org generation)
49
+ - `--schedule <interval>` → schedule = <interval>, daemon format only: `"<N>s"`, `"<N>m"`, or `"<N>h"` (e.g. `"30m"`, `"2h"`) — this is passed straight into `parseSchedule()` in `orgrt/scheduler.ts`, whose regex `^(\d+)\s*(s|m|h)$` rejects anything else (e.g. `"every 30 minutes"`, `"daily"`) and silently leaves the org unscheduled
51
50
  - `--delete <name>` → delete_mode = true, delete_name = <name>
52
51
  - `--list` flag → list_mode = true
53
52
  - Remaining text = prompt (goal description)
@@ -41,6 +41,18 @@ function subagentKey(hookInput) {
41
41
  return crypto.createHash('md5').update(String(raw)).digest('hex').slice(0, 16);
42
42
  }
43
43
 
44
+ // Determine subagent success from its result summary — errors/failures/
45
+ // exceptions indicate failure. Shared by the Monograph `success` column and
46
+ // the intelligence.feedback() call below, so both use one definition.
47
+ function deriveSubagentSuccess(summary) {
48
+ if (!summary) return true;
49
+ var sumLower = summary.toLowerCase();
50
+ if (sumLower.includes('error') || sumLower.includes('failed') || sumLower.includes('exception') || sumLower.includes('fatal')) {
51
+ return false;
52
+ }
53
+ return true;
54
+ }
55
+
44
56
  // Delete snap-*.json files older than SNAP_MAX_AGE_MS — orphaned when a
45
57
  // SubagentStop never arrived (crash, forced-stop) or was matched to a
46
58
  // different snapshot before keyed matching existed.
@@ -345,6 +357,17 @@ async function handleSubagentStop(hookInput) {
345
357
  + (session ? ' · sess=' + session : '')
346
358
  + (org ? ' · ' + org + '/' + runId : ''));
347
359
 
360
+ // Feed the real per-subagent success/failure signal into the same
361
+ // intelligence-outcomes.jsonl that session-handler.cjs's SessionEnd
362
+ // heuristic reads (via outcomesSignal) to veto a commit-based "success".
363
+ // Without this, that veto path never fires — SubagentStop is the only
364
+ // remaining event that carries a genuine failure signal, since post-task
365
+ // (TeammateIdle/TaskCompleted) is dead code (those aren't valid Claude
366
+ // Code hook events and are stripped from settings.json on init).
367
+ try {
368
+ require('../intelligence.cjs').feedback(deriveSubagentSuccess(summary));
369
+ } catch (e) { /* non-fatal — feedback recording must never block subagent-stop */ }
370
+
348
371
  if (!org && !session) {
349
372
  // No active org or session — log to general capture file only
350
373
  // P2-26: rotate — was a pure appendFileSync with no cap, unlike
@@ -486,16 +509,7 @@ async function handleSubagentStop(hookInput) {
486
509
  tokens_in: totalTin || 0,
487
510
  tokens_out: totalTout || 0,
488
511
  cost_usd: costUsd || 0,
489
- success: (function() {
490
- // Determine success from result summary — errors/failures/exceptions indicate failure
491
- if (summary) {
492
- var sumLower = summary.toLowerCase();
493
- if (sumLower.includes('error') || sumLower.includes('failed') || sumLower.includes('exception') || sumLower.includes('fatal')) {
494
- return 0;
495
- }
496
- }
497
- return 1;
498
- })(),
512
+ success: deriveSubagentSuccess(summary) ? 1 : 0,
499
513
  duration_ms: snap.ts ? (Date.now() - snap.ts) : 0,
500
514
  timestamp: Date.now(),
501
515
  });
@@ -6,7 +6,7 @@
6
6
  * @monomind/guidance package it mirrored has been removed.
7
7
  *
8
8
  * Gates enforced at runtime:
9
- * pre-bash → destructive-ops (require-confirmation block)
9
+ * pre-bash → destructive-ops (hard block; no confirm-and-proceed path exists)
10
10
  * pre-write → secrets (block)
11
11
  */
12
12
 
@@ -60,7 +60,7 @@ function checkDestructive(command) {
60
60
  return {
61
61
  triggered: true,
62
62
  matched: match[0],
63
- reason: `Destructive operation detected: "${match[0]}". Confirm this is intentional and document a rollback plan before proceeding.`,
63
+ reason: `Destructive operation blocked: "${match[0]}". This hook always blocks (Claude Code's PreToolUse protocol has no confirm-and-proceed path) — there is no way to run this exact command after confirming. If it's genuinely intended, use a non-destructive equivalent instead (e.g. move the target aside, or scope the operation more narrowly).`,
64
64
  };
65
65
  }
66
66
  }
@@ -299,6 +299,35 @@ module.exports = {
299
299
  console.log('[CODEBASE] Graph index ' + mapData.graphStaleness.commitsBehind + ' commits behind HEAD — run monograph build');
300
300
  }
301
301
  }
302
+ // Graph gate connectivity nudge — the pre-search/pre-bash gate
303
+ // (utils/monograph.cjs _graphGateShouldBlock) hard-blocks the first
304
+ // Grep/Glob/bash-grep-or-find call each session until a real
305
+ // monograph_query/monograph_suggest call fires. If that block was
306
+ // never followed by a real graph call, the monomind MCP server is
307
+ // most likely not connected this session (config present but
308
+ // unapproved/not started) — surface it once so the user can fix the
309
+ // actual cause instead of the gate silently degrading to a no-op.
310
+ var graphGateFile = path.join(CWD, '.monomind', 'graph-gate-state.json');
311
+ var mcpWarnFile = path.join(CWD, '.monomind', 'mcp-not-connected-warned.json');
312
+ if (fs.existsSync(graphGateFile) && fs.statSync(graphGateFile).size < 4096) {
313
+ var gateState = JSON.parse(fs.readFileSync(graphGateFile, 'utf-8'));
314
+ var gateSessId = String((hCtx.hookInput && (hCtx.hookInput.sessionId || hCtx.hookInput.session_id)) || '');
315
+ if (gateState && gateState.sessionId === gateSessId && gateState.blockedOnce && !gateState.queried) {
316
+ var alreadyWarnedMcp = false;
317
+ if (fs.existsSync(mcpWarnFile)) {
318
+ try {
319
+ var mcpWarnData = JSON.parse(fs.readFileSync(mcpWarnFile, 'utf-8'));
320
+ if (mcpWarnData && mcpWarnData.sessionId === gateSessId) alreadyWarnedMcp = true;
321
+ } catch (e) { /* corrupt — warn again to be safe */ }
322
+ }
323
+ if (!alreadyWarnedMcp) {
324
+ console.log('[MCP] The graph gate blocked a search but no monograph_query/monograph_suggest call followed — the monomind MCP server is likely not connected this session. Run `claude mcp add monomind -- npx monomind@latest mcp start` (then restart), or approve the .mcp.json trust prompt if one is pending.');
325
+ try {
326
+ fs.writeFileSync(mcpWarnFile, JSON.stringify({ sessionId: gateSessId, warnedAt: new Date().toISOString() }));
327
+ } catch (e) { /* non-fatal */ }
328
+ }
329
+ }
330
+ }
302
331
  // Deep dive findings (god nodes, high-degree files from background analysis)
303
332
  var deepdiveFile = path.join(metricsDir, 'deepdive.json');
304
333
  if (fs.existsSync(deepdiveFile) && fs.statSync(deepdiveFile).size < 32768) {
@@ -41,34 +41,46 @@ module.exports = {
41
41
  if (fs.existsSync(lastRoutePath) && (function() { try { return fs.statSync(lastRoutePath).size <= MAX_ROUTE; } catch(_) { return false; } }())) {
42
42
  var lastRoute = JSON.parse(fs.readFileSync(lastRoutePath, 'utf-8'));
43
43
 
44
- // Derive sessionSuccess from git commits (strongest signal: user committed = success)
44
+ // Derive sessionSuccess. A commit alone is not proof of success — a
45
+ // session can commit a partial fix and then hit repeated failures —
46
+ // so recent intelligence-outcomes are checked FIRST and can veto a
47
+ // commit-based "true" when they show a majority of failures.
45
48
  try {
46
49
  var execSync = require('child_process').execSync;
47
- var recentCommits = execSync('git log --oneline --since="30 minutes ago" 2>/dev/null || true', { cwd: CWD, timeout: 3000, encoding: 'utf-8' }).trim();
48
- if (recentCommits.length > 0) {
49
- sessionSuccess = true;
50
+
51
+ var outcomesSignal = null; // majority success/failure from intelligence-outcomes, if any
52
+ var outcomesPath = path.join(CWD, '.monomind', 'data', 'intelligence-outcomes.jsonl');
53
+ var MAX_OUTCOMES = 512 * 1024;
54
+ if (fs.existsSync(outcomesPath) && (function() { try { return fs.statSync(outcomesPath).size <= MAX_OUTCOMES; } catch(_) { return false; } }())) {
55
+ var windowMs = 30 * 60 * 1000;
56
+ var cutoff = Date.now() - windowMs;
57
+ var outcomeLines = fs.readFileSync(outcomesPath, 'utf-8').trim().split('\n').filter(Boolean);
58
+ var recent = outcomeLines.map(function(l) {
59
+ try { return JSON.parse(l); } catch { return null; }
60
+ }).filter(function(e) { return e && e.ts && e.ts >= cutoff; });
61
+ if (recent.length > 0) {
62
+ var failures = recent.filter(function(e) { return e.success === false; }).length;
63
+ outcomesSignal = failures / recent.length < 0.5;
64
+ }
65
+ }
66
+
67
+ if (outcomesSignal === false) {
68
+ // Recent tool/command outcomes were majority failures — this
69
+ // overrides a commit, since committing doesn't undo those failures.
70
+ sessionSuccess = false;
50
71
  } else {
51
- // No commits check if files were modified (work in progress, not failure)
52
- var gitStatus = execSync('git diff --name-only 2>/dev/null || true', { cwd: CWD, timeout: 3000, encoding: 'utf-8' }).trim();
53
- // Modified files = probably still working; no changes at all = exploration or failure
54
- if (gitStatus.length === 0) {
55
- // Fall back to intelligence-outcomes as a weak signal
56
- var outcomesPath = path.join(CWD, '.monomind', 'data', 'intelligence-outcomes.jsonl');
57
- var MAX_OUTCOMES = 512 * 1024;
58
- if (fs.existsSync(outcomesPath) && (function() { try { return fs.statSync(outcomesPath).size <= MAX_OUTCOMES; } catch(_) { return false; } }())) {
59
- var windowMs = 30 * 60 * 1000;
60
- var cutoff = Date.now() - windowMs;
61
- var outcomeLines = fs.readFileSync(outcomesPath, 'utf-8').trim().split('\n').filter(Boolean);
62
- var recent = outcomeLines.map(function(l) {
63
- try { return JSON.parse(l); } catch { return null; }
64
- }).filter(function(e) { return e && e.ts && e.ts >= cutoff; });
65
- if (recent.length > 0) {
66
- var failures = recent.filter(function(e) { return e.success === false; }).length;
67
- sessionSuccess = failures / recent.length < 0.5;
68
- }
72
+ var recentCommits = execSync('git log --oneline --since="30 minutes ago" 2>/dev/null || true', { cwd: CWD, timeout: 3000, encoding: 'utf-8' }).trim();
73
+ if (recentCommits.length > 0) {
74
+ sessionSuccess = true;
75
+ } else {
76
+ // No commits check if files were modified (work in progress, not failure)
77
+ var gitStatus = execSync('git diff --name-only 2>/dev/null || true', { cwd: CWD, timeout: 3000, encoding: 'utf-8' }).trim();
78
+ // Modified files = probably still working; no changes at all = exploration or failure
79
+ if (gitStatus.length === 0 && outcomesSignal !== null) {
80
+ sessionSuccess = outcomesSignal;
69
81
  }
82
+ // else: modified files exist, or no evidence either way (leave null)
70
83
  }
71
- // else: modified files exist — work in progress, not evidence either way (leave null)
72
84
  }
73
85
  } catch (e) { /* non-critical — leave null (no evidence) */ }
74
86
 
@@ -55,6 +55,7 @@ const {
55
55
  getMonographSuggestions, getMonographNeighbors,
56
56
  _recordGraphTelemetry, _injectCompactGraphMap,
57
57
  _findAffectedTests, _maybeRebuildMonograph,
58
+ _graphGateShouldBlock, _graphGateMarkQueried,
58
59
  } = monograph;
59
60
 
60
61
  const {
@@ -409,6 +410,15 @@ const handlers = {
409
410
  var isGrep = /\b(?:grep|rg|ag)\b/.test(cmd);
410
411
  var isFind = /\b(?:find|fd)\b/.test(cmd) && !isGrep;
411
412
  if (isGrep || isFind) {
413
+ var sessIdGate = String((hCtx.hookInput && (hCtx.hookInput.sessionId || hCtx.hookInput.session_id)) || '');
414
+ if (_graphGateShouldBlock(sessIdGate)) {
415
+ process.stderr.write(JSON.stringify({
416
+ decision: 'block',
417
+ reason: '[graph-gate] Call mcp__monomind__monograph_query or monograph_suggest before grep/rg/find for code exploration (CLAUDE.md). This blocks once per session — after your first monograph call (or this one warning), Bash grep/find work normally for the rest of the session.',
418
+ }) + '\n');
419
+ process.exitCode = 2;
420
+ return;
421
+ }
412
422
  var graphAssisted = false;
413
423
  if (_isGraphFresh()) {
414
424
  try {
@@ -659,6 +669,15 @@ const handlers = {
659
669
 
660
670
  'pre-search': () => {
661
671
  var tool = hCtx.toolName || '';
672
+ var sessIdGate = String((hCtx.hookInput && (hCtx.hookInput.sessionId || hCtx.hookInput.session_id)) || '');
673
+ if (_graphGateShouldBlock(sessIdGate)) {
674
+ process.stderr.write(JSON.stringify({
675
+ decision: 'block',
676
+ reason: '[graph-gate] Call mcp__monomind__monograph_query or monograph_suggest before ' + (tool || 'Grep/Glob') + ' for code exploration (CLAUDE.md). This blocks once per session — after your first monograph call (or this one warning), search tools work normally for the rest of the session.',
677
+ }) + '\n');
678
+ process.exitCode = 2;
679
+ return;
680
+ }
662
681
  var graphResolved = false;
663
682
  try {
664
683
  var grepPattern = (typeof toolInput === 'object' && toolInput !== null)
@@ -817,6 +836,8 @@ const handlers = {
817
836
  'post-graph-tool': () => {
818
837
  // Record monograph MCP tool calls as graph wins
819
838
  _recordGraphTelemetry('monograph_call');
839
+ var sessIdGate = String((hCtx.hookInput && (hCtx.hookInput.sessionId || hCtx.hookInput.session_id)) || '');
840
+ _graphGateMarkQueried(sessIdGate);
820
841
  },
821
842
 
822
843
  'graph-status': () => {
@@ -9,6 +9,25 @@ const { _getRecentEdits } = require('./telemetry.cjs');
9
9
 
10
10
  const CWD = process.env.CLAUDE_PROJECT_DIR || process.cwd();
11
11
 
12
+ // @monoes/monograph is "type":"module" with an exports map that has no
13
+ // "require" condition — a bare `require('@monoes/monograph')` (or
14
+ // require() of its package directory) always throws "No exports main
15
+ // defined", regardless of whether the package is actually installed.
16
+ // require()-ing the package's *resolved entry file* directly bypasses the
17
+ // exports-map restriction and works via Node's require(esm) support (this
18
+ // codebase targets Node 20+, which has it). Reads the entry path from the
19
+ // package's own package.json instead of hardcoding "dist/src/index.js" so
20
+ // this survives a future monograph dist-layout change.
21
+ function _resolvePkgEntryFile(pkgDir) {
22
+ try {
23
+ var pkg = JSON.parse(fs.readFileSync(path.join(pkgDir, 'package.json'), 'utf-8'));
24
+ var entry = (pkg.exports && pkg.exports['.'] && (pkg.exports['.'].import || pkg.exports['.'].default)) || pkg.main;
25
+ if (!entry) return null;
26
+ var full = path.join(pkgDir, entry);
27
+ return fs.existsSync(full) ? full : null;
28
+ } catch (e) { return null; }
29
+ }
30
+
12
31
  function _requireMonograph() {
13
32
  var candidates = [
14
33
  path.join(CWD, 'node_modules/.pnpm/node_modules/@monoes/monograph'),
@@ -16,9 +35,21 @@ function _requireMonograph() {
16
35
  path.join(CWD, 'node_modules/@monoes/monograph'),
17
36
  ];
18
37
  for (var i = 0; i < candidates.length; i++) {
19
- try { if (fs.existsSync(candidates[i])) return require(candidates[i]); } catch(e) {}
38
+ var entry = fs.existsSync(candidates[i]) ? _resolvePkgEntryFile(candidates[i]) : null;
39
+ if (entry) { try { return require(entry); } catch (e) {} }
40
+ }
41
+ // Ancestor-directory search — the equivalent of bare `require('@monoes/
42
+ // monograph')`'s own node_modules walk, needed since that call form can
43
+ // never succeed against this package's exports map.
44
+ var dir = CWD;
45
+ for (;;) {
46
+ var pkgDir = path.join(dir, 'node_modules', '@monoes', 'monograph');
47
+ var entry = fs.existsSync(pkgDir) ? _resolvePkgEntryFile(pkgDir) : null;
48
+ if (entry) { try { return require(entry); } catch (e) {} break; }
49
+ var parent = path.dirname(dir);
50
+ if (parent === dir) break;
51
+ dir = parent;
20
52
  }
21
- try { return require('@monoes/monograph'); } catch(e) {}
22
53
  return null;
23
54
  }
24
55
 
@@ -257,6 +288,44 @@ function _recordGraphTelemetry(event) {
257
288
  } catch (e) { /* non-fatal */ }
258
289
  }
259
290
 
291
+ // ─── Graph gate ─────────────────────────────────────────────────────────────
292
+ // The pre-search/pre-bash heuristic assist above silently resolves Grep/Bash
293
+ // patterns against the graph and counts that as a "graph win" even when the
294
+ // agent never actually called monograph_query — so the graph-usage % can look
295
+ // healthy while zero real monograph_call events ever fire. This gate forces
296
+ // at least one real monograph_query/monograph_suggest call per session before
297
+ // Grep/Glob/bash grep|find are allowed, by hard-blocking (exitCode 2) the
298
+ // first such call each session. Capped at ONE block per session (never a
299
+ // second) so a subagent with no monograph MCP tool access can't deadlock.
300
+ function _graphGateStateFile() {
301
+ return path.join(CWD, '.monomind', 'graph-gate-state.json');
302
+ }
303
+
304
+ function _graphGateMarkQueried(sessionId) {
305
+ if (!sessionId) return;
306
+ try {
307
+ fs.mkdirSync(path.join(CWD, '.monomind'), { recursive: true });
308
+ fs.writeFileSync(_graphGateStateFile(), JSON.stringify({ sessionId: sessionId, queried: true }));
309
+ } catch (e) { /* non-fatal */ }
310
+ }
311
+
312
+ function _graphGateShouldBlock(sessionId) {
313
+ if (!sessionId || !_isGraphFresh()) return false;
314
+ var f = _graphGateStateFile();
315
+ var d = {};
316
+ try { d = JSON.parse(fs.readFileSync(f, 'utf-8')); } catch (e) {}
317
+ if (typeof d !== 'object' || d === null || d.sessionId !== sessionId) {
318
+ d = { sessionId: sessionId, queried: false, blockedOnce: false };
319
+ }
320
+ if (d.queried || d.blockedOnce) return false;
321
+ d.blockedOnce = true;
322
+ try {
323
+ fs.mkdirSync(path.join(CWD, '.monomind'), { recursive: true });
324
+ fs.writeFileSync(f, JSON.stringify(d));
325
+ } catch (e) { return false; }
326
+ return true;
327
+ }
328
+
260
329
  function _injectCompactGraphMap() {
261
330
  try {
262
331
  var db = _openMonographDb();
@@ -476,5 +545,7 @@ module.exports = {
476
545
  _injectCompactGraphMap,
477
546
  _findAffectedTests,
478
547
  _maybeRebuildMonograph,
548
+ _graphGateShouldBlock,
549
+ _graphGateMarkQueried,
479
550
  injectGodNodesContext,
480
551
  };