@monoes/monomindcli 2.10.9 → 2.10.13

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 (265) hide show
  1. package/.claude/commands/mastermind/brain.md +14 -14
  2. package/.claude/commands/mastermind/help.md +2 -2
  3. package/.claude/commands/mastermind/master.md +24 -19
  4. package/.claude/commands/mastermind/memory.md +8 -8
  5. package/.claude/commands/mastermind/monoswarm.md +4 -4
  6. package/.claude/commands/mastermind.md +7 -7
  7. package/.claude/commands/truth/start.md +3 -3
  8. package/.claude/settings.json +0 -4
  9. package/.claude/skills/mastermind/SKILL.md +7 -16
  10. package/.claude/skills/mastermind/references/antigravity-tools.md +0 -62
  11. package/.claude/skills/mastermind/references/claude-code-tools.md +0 -52
  12. package/.claude/skills/mastermind/references/codex-tools.md +0 -66
  13. package/.claude/skills/mastermind/references/copilot-tools.md +0 -51
  14. package/.claude/skills/mastermind/references/gemini-tools.md +0 -65
  15. package/.claude/skills/mastermind/references/pi-tools.md +0 -30
  16. package/.claude/skills/mastermind-createorg/SKILL.md +3 -1
  17. package/.claude/skills/mastermind-debug/SKILL.md +3 -277
  18. package/.claude/skills/mastermind-design/SKILL.md +2 -0
  19. package/.claude/skills/mastermind-execute/SKILL.md +59 -103
  20. package/.claude/skills/mastermind-idea/SKILL.md +9 -2
  21. package/.claude/skills/mastermind-intake/SKILL.md +31 -7
  22. package/.claude/skills/mastermind-issue-detail/SKILL.md +70 -16
  23. package/.claude/skills/mastermind-issues/SKILL.md +111 -16
  24. package/.claude/skills/mastermind-liveness/SKILL.md +96 -26
  25. package/.claude/skills/mastermind-memory/SKILL.md +0 -316
  26. package/.claude/skills/mastermind-my-issues/SKILL.md +40 -8
  27. package/.claude/skills/mastermind-org/SKILL.md +1 -12
  28. package/.claude/skills/mastermind-plan/SKILL.md +7 -228
  29. package/.claude/skills/mastermind-plan-to-tasks/SKILL.md +132 -24
  30. package/.claude/skills/mastermind-protocol/SKILL.md +33 -22
  31. package/.claude/skills/mastermind-research/SKILL.md +0 -163
  32. package/.claude/skills/mastermind-review/SKILL.md +0 -228
  33. package/.claude/skills/mastermind-runorg/SKILL.md +22 -3
  34. package/.claude/skills/mastermind-skill-builder/SKILL.md +1 -1
  35. package/.claude/skills/mastermind-tasks/SKILL.md +5 -0
  36. package/.claude/skills/mastermind-techport/SKILL.md +1 -1
  37. package/.claude/skills/performance-analysis/SKILL.md +1 -1
  38. package/.claude/skills/verification-quality/SKILL.md +2 -3
  39. package/README.md +2 -2
  40. package/dist/src/commands/agent-exec.d.ts +2 -0
  41. package/dist/src/commands/agent-exec.d.ts.map +1 -1
  42. package/dist/src/commands/agent-exec.js +16 -0
  43. package/dist/src/commands/agent-exec.js.map +1 -1
  44. package/dist/src/commands/doc.js +2 -2
  45. package/dist/src/commands/doc.js.map +1 -1
  46. package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
  47. package/dist/src/commands/doctor-project-checks.js +20 -1
  48. package/dist/src/commands/doctor-project-checks.js.map +1 -1
  49. package/dist/src/commands/init-wizard.d.ts.map +1 -1
  50. package/dist/src/commands/init-wizard.js +6 -0
  51. package/dist/src/commands/init-wizard.js.map +1 -1
  52. package/dist/src/commands/init.d.ts.map +1 -1
  53. package/dist/src/commands/init.js +12 -2
  54. package/dist/src/commands/init.js.map +1 -1
  55. package/dist/src/commands/monograph.d.ts.map +1 -1
  56. package/dist/src/commands/monograph.js +11 -4
  57. package/dist/src/commands/monograph.js.map +1 -1
  58. package/dist/src/commands/org-observe.d.ts +2 -0
  59. package/dist/src/commands/org-observe.d.ts.map +1 -1
  60. package/dist/src/commands/org-observe.js +115 -6
  61. package/dist/src/commands/org-observe.js.map +1 -1
  62. package/dist/src/commands/org.d.ts +26 -0
  63. package/dist/src/commands/org.d.ts.map +1 -1
  64. package/dist/src/commands/org.js +186 -28
  65. package/dist/src/commands/org.js.map +1 -1
  66. package/dist/src/init/codex-generator.d.ts +5 -0
  67. package/dist/src/init/codex-generator.d.ts.map +1 -1
  68. package/dist/src/init/codex-generator.js +12 -3
  69. package/dist/src/init/codex-generator.js.map +1 -1
  70. package/dist/src/init/executor.d.ts.map +1 -1
  71. package/dist/src/init/executor.js +10 -9
  72. package/dist/src/init/executor.js.map +1 -1
  73. package/dist/src/init/settings-generator.d.ts.map +1 -1
  74. package/dist/src/init/settings-generator.js +0 -5
  75. package/dist/src/init/settings-generator.js.map +1 -1
  76. package/dist/src/init/write-codex.d.ts.map +1 -1
  77. package/dist/src/init/write-codex.js +6 -5
  78. package/dist/src/init/write-codex.js.map +1 -1
  79. package/dist/src/knowledge/document-pipeline.d.ts +5 -0
  80. package/dist/src/knowledge/document-pipeline.d.ts.map +1 -1
  81. package/dist/src/knowledge/document-pipeline.js +32 -16
  82. package/dist/src/knowledge/document-pipeline.js.map +1 -1
  83. package/dist/src/mcp-tools/hooks-routing.d.ts +9 -0
  84. package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -1
  85. package/dist/src/mcp-tools/hooks-routing.js +12 -1
  86. package/dist/src/mcp-tools/hooks-routing.js.map +1 -1
  87. package/dist/src/mcp-tools/knowledge-tools.d.ts.map +1 -1
  88. package/dist/src/mcp-tools/knowledge-tools.js +105 -13
  89. package/dist/src/mcp-tools/knowledge-tools.js.map +1 -1
  90. package/dist/src/mcp-tools/memory-tools.d.ts +13 -0
  91. package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -1
  92. package/dist/src/mcp-tools/memory-tools.js +257 -31
  93. package/dist/src/mcp-tools/memory-tools.js.map +1 -1
  94. package/dist/src/mcp-tools/monograph/health-tools.d.ts.map +1 -1
  95. package/dist/src/mcp-tools/monograph/health-tools.js +99 -42
  96. package/dist/src/mcp-tools/monograph/health-tools.js.map +1 -1
  97. package/dist/src/mcp-tools/monograph/impact-tools.d.ts.map +1 -1
  98. package/dist/src/mcp-tools/monograph/impact-tools.js +123 -51
  99. package/dist/src/mcp-tools/monograph/impact-tools.js.map +1 -1
  100. package/dist/src/mcp-tools/monograph/query-tools.d.ts.map +1 -1
  101. package/dist/src/mcp-tools/monograph/query-tools.js +113 -96
  102. package/dist/src/mcp-tools/monograph/query-tools.js.map +1 -1
  103. package/dist/src/mcp-tools/monograph/shared.d.ts +37 -4
  104. package/dist/src/mcp-tools/monograph/shared.d.ts.map +1 -1
  105. package/dist/src/mcp-tools/monograph/shared.js +75 -56
  106. package/dist/src/mcp-tools/monograph/shared.js.map +1 -1
  107. package/dist/src/memory/embedding-operations.d.ts.map +1 -1
  108. package/dist/src/memory/embedding-operations.js +9 -4
  109. package/dist/src/memory/embedding-operations.js.map +1 -1
  110. package/dist/src/memory/memory-bridge.d.ts +60 -1
  111. package/dist/src/memory/memory-bridge.d.ts.map +1 -1
  112. package/dist/src/memory/memory-bridge.js +185 -42
  113. package/dist/src/memory/memory-bridge.js.map +1 -1
  114. package/dist/src/memory/memory-kg.d.ts +495 -28
  115. package/dist/src/memory/memory-kg.d.ts.map +1 -1
  116. package/dist/src/memory/memory-kg.js +2186 -251
  117. package/dist/src/memory/memory-kg.js.map +1 -1
  118. package/dist/src/memory/query-router.d.ts +51 -0
  119. package/dist/src/memory/query-router.d.ts.map +1 -1
  120. package/dist/src/memory/query-router.js +38 -2
  121. package/dist/src/memory/query-router.js.map +1 -1
  122. package/dist/src/orgrt/agent-exec.d.ts +14 -0
  123. package/dist/src/orgrt/agent-exec.d.ts.map +1 -1
  124. package/dist/src/orgrt/agent-exec.js +88 -4
  125. package/dist/src/orgrt/agent-exec.js.map +1 -1
  126. package/dist/src/orgrt/agent-runner.d.ts +26 -1
  127. package/dist/src/orgrt/agent-runner.d.ts.map +1 -1
  128. package/dist/src/orgrt/agent-runner.js +73 -22
  129. package/dist/src/orgrt/agent-runner.js.map +1 -1
  130. package/dist/src/orgrt/antigravity-runner.d.ts +1 -1
  131. package/dist/src/orgrt/antigravity-runner.d.ts.map +1 -1
  132. package/dist/src/orgrt/antigravity-runner.js +36 -19
  133. package/dist/src/orgrt/antigravity-runner.js.map +1 -1
  134. package/dist/src/orgrt/approvals.d.ts +26 -2
  135. package/dist/src/orgrt/approvals.d.ts.map +1 -1
  136. package/dist/src/orgrt/approvals.js +67 -7
  137. package/dist/src/orgrt/approvals.js.map +1 -1
  138. package/dist/src/orgrt/broker.d.ts +21 -2
  139. package/dist/src/orgrt/broker.d.ts.map +1 -1
  140. package/dist/src/orgrt/broker.js +56 -8
  141. package/dist/src/orgrt/broker.js.map +1 -1
  142. package/dist/src/orgrt/bus.d.ts +8 -0
  143. package/dist/src/orgrt/bus.d.ts.map +1 -1
  144. package/dist/src/orgrt/bus.js +27 -0
  145. package/dist/src/orgrt/bus.js.map +1 -1
  146. package/dist/src/orgrt/checkpoint-ops.d.ts.map +1 -1
  147. package/dist/src/orgrt/checkpoint-ops.js +15 -5
  148. package/dist/src/orgrt/checkpoint-ops.js.map +1 -1
  149. package/dist/src/orgrt/checkpoint.d.ts +42 -4
  150. package/dist/src/orgrt/checkpoint.d.ts.map +1 -1
  151. package/dist/src/orgrt/checkpoint.js +75 -4
  152. package/dist/src/orgrt/checkpoint.js.map +1 -1
  153. package/dist/src/orgrt/codex-runner.d.ts +1 -1
  154. package/dist/src/orgrt/codex-runner.d.ts.map +1 -1
  155. package/dist/src/orgrt/codex-runner.js +50 -23
  156. package/dist/src/orgrt/codex-runner.js.map +1 -1
  157. package/dist/src/orgrt/copilot-runner.d.ts +24 -2
  158. package/dist/src/orgrt/copilot-runner.d.ts.map +1 -1
  159. package/dist/src/orgrt/copilot-runner.js +257 -157
  160. package/dist/src/orgrt/copilot-runner.js.map +1 -1
  161. package/dist/src/orgrt/cross-org.d.ts +10 -3
  162. package/dist/src/orgrt/cross-org.d.ts.map +1 -1
  163. package/dist/src/orgrt/cross-org.js +225 -10
  164. package/dist/src/orgrt/cross-org.js.map +1 -1
  165. package/dist/src/orgrt/crush-runner.d.ts +22 -2
  166. package/dist/src/orgrt/crush-runner.d.ts.map +1 -1
  167. package/dist/src/orgrt/crush-runner.js +227 -120
  168. package/dist/src/orgrt/crush-runner.js.map +1 -1
  169. package/dist/src/orgrt/daemon.d.ts +77 -7
  170. package/dist/src/orgrt/daemon.d.ts.map +1 -1
  171. package/dist/src/orgrt/daemon.js +989 -385
  172. package/dist/src/orgrt/daemon.js.map +1 -1
  173. package/dist/src/orgrt/decisions.d.ts +2 -2
  174. package/dist/src/orgrt/decisions.d.ts.map +1 -1
  175. package/dist/src/orgrt/decisions.js +90 -18
  176. package/dist/src/orgrt/decisions.js.map +1 -1
  177. package/dist/src/orgrt/grok-runner.d.ts +29 -3
  178. package/dist/src/orgrt/grok-runner.d.ts.map +1 -1
  179. package/dist/src/orgrt/grok-runner.js +286 -150
  180. package/dist/src/orgrt/grok-runner.js.map +1 -1
  181. package/dist/src/orgrt/kimicode-runner.d.ts +5 -5
  182. package/dist/src/orgrt/kimicode-runner.d.ts.map +1 -1
  183. package/dist/src/orgrt/kimicode-runner.js +53 -32
  184. package/dist/src/orgrt/kimicode-runner.js.map +1 -1
  185. package/dist/src/orgrt/mailbox.d.ts +15 -0
  186. package/dist/src/orgrt/mailbox.d.ts.map +1 -1
  187. package/dist/src/orgrt/mailbox.js +29 -1
  188. package/dist/src/orgrt/mailbox.js.map +1 -1
  189. package/dist/src/orgrt/migrate.d.ts.map +1 -1
  190. package/dist/src/orgrt/migrate.js +8 -5
  191. package/dist/src/orgrt/migrate.js.map +1 -1
  192. package/dist/src/orgrt/opencode-runner.d.ts +1 -1
  193. package/dist/src/orgrt/opencode-runner.d.ts.map +1 -1
  194. package/dist/src/orgrt/opencode-runner.js +29 -3
  195. package/dist/src/orgrt/opencode-runner.js.map +1 -1
  196. package/dist/src/orgrt/org-memory.d.ts +19 -3
  197. package/dist/src/orgrt/org-memory.d.ts.map +1 -1
  198. package/dist/src/orgrt/org-memory.js +110 -38
  199. package/dist/src/orgrt/org-memory.js.map +1 -1
  200. package/dist/src/orgrt/pi-rpc-runner.d.ts +3 -1
  201. package/dist/src/orgrt/pi-rpc-runner.d.ts.map +1 -1
  202. package/dist/src/orgrt/pi-rpc-runner.js +35 -3
  203. package/dist/src/orgrt/pi-rpc-runner.js.map +1 -1
  204. package/dist/src/orgrt/pi-runner.d.ts +25 -2
  205. package/dist/src/orgrt/pi-runner.d.ts.map +1 -1
  206. package/dist/src/orgrt/pi-runner.js +271 -152
  207. package/dist/src/orgrt/pi-runner.js.map +1 -1
  208. package/dist/src/orgrt/policy.d.ts +1 -0
  209. package/dist/src/orgrt/policy.d.ts.map +1 -1
  210. package/dist/src/orgrt/policy.js +199 -39
  211. package/dist/src/orgrt/policy.js.map +1 -1
  212. package/dist/src/orgrt/provider.d.ts +4 -0
  213. package/dist/src/orgrt/provider.d.ts.map +1 -1
  214. package/dist/src/orgrt/provider.js +16 -0
  215. package/dist/src/orgrt/provider.js.map +1 -1
  216. package/dist/src/orgrt/qwen-rpc-runner.d.ts +3 -1
  217. package/dist/src/orgrt/qwen-rpc-runner.d.ts.map +1 -1
  218. package/dist/src/orgrt/qwen-rpc-runner.js +35 -3
  219. package/dist/src/orgrt/qwen-rpc-runner.js.map +1 -1
  220. package/dist/src/orgrt/qwen-runner.d.ts +30 -3
  221. package/dist/src/orgrt/qwen-runner.d.ts.map +1 -1
  222. package/dist/src/orgrt/qwen-runner.js +282 -142
  223. package/dist/src/orgrt/qwen-runner.js.map +1 -1
  224. package/dist/src/orgrt/role-slot.d.ts +88 -0
  225. package/dist/src/orgrt/role-slot.d.ts.map +1 -0
  226. package/dist/src/orgrt/role-slot.js +133 -0
  227. package/dist/src/orgrt/role-slot.js.map +1 -0
  228. package/dist/src/orgrt/runtime-options.d.ts +17 -0
  229. package/dist/src/orgrt/runtime-options.d.ts.map +1 -0
  230. package/dist/src/orgrt/runtime-options.js +32 -0
  231. package/dist/src/orgrt/runtime-options.js.map +1 -0
  232. package/dist/src/orgrt/scheduler-integration.d.ts +11 -0
  233. package/dist/src/orgrt/scheduler-integration.d.ts.map +1 -1
  234. package/dist/src/orgrt/scheduler-integration.js +75 -17
  235. package/dist/src/orgrt/scheduler-integration.js.map +1 -1
  236. package/dist/src/orgrt/scheduler.d.ts +4 -0
  237. package/dist/src/orgrt/scheduler.d.ts.map +1 -1
  238. package/dist/src/orgrt/scheduler.js +7 -1
  239. package/dist/src/orgrt/scheduler.js.map +1 -1
  240. package/dist/src/orgrt/server.d.ts +8 -3
  241. package/dist/src/orgrt/server.d.ts.map +1 -1
  242. package/dist/src/orgrt/server.js +48 -13
  243. package/dist/src/orgrt/server.js.map +1 -1
  244. package/dist/src/orgrt/session.d.ts +26 -2
  245. package/dist/src/orgrt/session.d.ts.map +1 -1
  246. package/dist/src/orgrt/session.js +99 -5
  247. package/dist/src/orgrt/session.js.map +1 -1
  248. package/dist/src/orgrt/task-dag.d.ts +5 -0
  249. package/dist/src/orgrt/task-dag.d.ts.map +1 -1
  250. package/dist/src/orgrt/task-dag.js +41 -0
  251. package/dist/src/orgrt/task-dag.js.map +1 -1
  252. package/dist/src/orgrt/test-loop.js +2 -2
  253. package/dist/src/orgrt/test-loop.js.map +1 -1
  254. package/dist/src/orgrt/types.d.ts +14 -2
  255. package/dist/src/orgrt/types.d.ts.map +1 -1
  256. package/dist/src/orgrt/types.js +15 -1
  257. package/dist/src/orgrt/types.js.map +1 -1
  258. package/dist/src/orgrt/vercel-runner.d.ts.map +1 -1
  259. package/dist/src/orgrt/vercel-runner.js +4 -0
  260. package/dist/src/orgrt/vercel-runner.js.map +1 -1
  261. package/dist/src/ui/routes-org.mjs +27 -7
  262. package/dist/src/ui/server.mjs +82 -48
  263. package/dist/tsconfig.tsbuildinfo +1 -1
  264. package/package.json +2 -1
  265. package/dist/src/ui/data/mastermind-sessions.json +0 -1
@@ -100,7 +100,54 @@ function liveServeDaemonPid(cwd) {
100
100
  return null;
101
101
  }
102
102
  }
103
+ /** Mutual-exclusion check for `org serve` startup.
104
+ *
105
+ * Two `org serve` processes started against the same project root have zero
106
+ * visibility into each other — each builds its own in-memory `OrgDaemon` and
107
+ * independently decides which orgs are "due now", so both can call
108
+ * `daemon.startOrg(name)` for the same org and have both processes write to
109
+ * the same on-disk state (runtime.json, decisions.jsonl, history.jsonl,
110
+ * .mail/) at once. `liveServeDaemonPid` already knows how to read this
111
+ * project's serve-heartbeat.json and tell a live daemon's heartbeat from a
112
+ * stale one (dead pid, or aged past a few missed 30s beats) — reused here
113
+ * as the actual pidfile lock, rather than inventing a second file, since it
114
+ * already IS a pidfile (pid + timestamp, written at startup and every
115
+ * heartbeat, removed on clean shutdown by `daemon.clearHeartbeat()`).
116
+ *
117
+ * Call this before the daemon/server/scheduler are constructed, so a
118
+ * refusal never opens a port, binds a broker lease, or touches any org's
119
+ * state. */
120
+ export function checkServeLock(cwd) {
121
+ const owner = liveServeDaemonPid(cwd);
122
+ if (owner != null)
123
+ return { ok: false, pid: owner };
124
+ // liveServeDaemonPid() has already ruled out a live owner — any heartbeat
125
+ // file still on disk here is stale (dead pid, or a SIGKILLed daemon that
126
+ // never reached clearHeartbeat()). Remove it so it can't be misread by
127
+ // `org run`/`org status` before this daemon's own writeHeartbeat() lands.
128
+ const heartbeatPath = join(cwd, '.monomind', 'serve-heartbeat.json');
129
+ const staleHeartbeatRemoved = existsSync(heartbeatPath);
130
+ if (staleHeartbeatRemoved)
131
+ rmSync(heartbeatPath, { force: true });
132
+ return { ok: true, staleHeartbeatRemoved };
133
+ }
103
134
  const runAction = async (ctx) => {
135
+ // Org runs skip local embeddings entirely — on some machines
136
+ // @huggingface/transformers' native ONNX runtime crashes the whole
137
+ // process (a libc++abi terminate, not a catchable JS error) the moment
138
+ // any memory/KG lookup tries to load its model. A crashed unattended org
139
+ // run is much worse than one that falls back to keyword-only memory
140
+ // search — see the matching guards in memory-bridge.ts/embedding-operations.ts.
141
+ process.env.MONOMIND_NO_LOCAL_EMBEDDINGS = '1';
142
+ // The embedding-model crash above has a sibling: loadReranker() in
143
+ // memory-bridge.ts loads a SEPARATE cross-encoder model
144
+ // (cross-encoder/ettin-reranker-32m-v1, its own tokenizer architecture)
145
+ // for search-result reranking, independent of the embedder guard above —
146
+ // reranking runs on (query, passage) text pairs directly, so it can
147
+ // still fire and hit the same native crash even with embeddings off.
148
+ // MONOMIND_RERANKER=0 is an existing, already-wired guard (see
149
+ // loadReranker's own early-return) — just never set for org runs before.
150
+ process.env.MONOMIND_RERANKER = '0';
104
151
  if (!ctx.args[0])
105
152
  return { success: false, message: 'org name required: monomind org run <name> [--task "..."]' };
106
153
  const validated = validateOrgName(ctx.args[0]);
@@ -136,7 +183,11 @@ const runAction = async (ctx) => {
136
183
  const glossary = await (async () => {
137
184
  try {
138
185
  const kg = await import('../memory/memory-kg.js');
139
- return await kg.kgGlossary({ dbPath: join(process.cwd(), '.monomind', 'org-memory') });
186
+ const { orgKgScope } = await import('../orgrt/org-memory.js');
187
+ return await kg.kgGlossary({
188
+ dbPath: join(process.cwd(), '.monomind', 'org-memory'),
189
+ scope: orgKgScope(name),
190
+ });
140
191
  }
141
192
  catch {
142
193
  return [];
@@ -327,7 +378,7 @@ const runAction = async (ctx) => {
327
378
  let srv;
328
379
  if (crossProcess) {
329
380
  srv = await startOrgServer(daemon, 0);
330
- daemon.setInboxUrl(`http://127.0.0.1:${srv.port}`, srv.credential);
381
+ daemon.setInboxUrl(`http://127.0.0.1:${srv.port}`, srv.operatorCredential);
331
382
  }
332
383
  let running;
333
384
  try {
@@ -988,21 +1039,58 @@ WantedBy=default.target
988
1039
  return { success: true, message: `${format} unit emitted` };
989
1040
  };
990
1041
  const serveAction = async (ctx) => {
1042
+ // Mutual exclusion: refuse to start a second `org serve` for this project
1043
+ // root. Checked before anything else so a refusal never opens a port,
1044
+ // registers a broker lease, or starts a scheduled org that a live daemon
1045
+ // is already running — see checkServeLock's header for the failure mode
1046
+ // this prevents.
1047
+ const lock = checkServeLock(ctx.cwd);
1048
+ if (!lock.ok) {
1049
+ log(output.error(`org serve: another daemon (pid ${lock.pid}) is already running for this project root.`));
1050
+ log(output.info(` Check what it's doing with: monomind org status`));
1051
+ log(output.info(` Stop it first (Ctrl-C in its terminal, or "kill ${lock.pid}"), then retry.`));
1052
+ return { success: false, message: `org serve already running (pid ${lock.pid})` };
1053
+ }
1054
+ if (lock.staleHeartbeatRemoved) {
1055
+ log(output.warning('org serve: cleaned up a stale heartbeat left by a previous daemon that did not shut down cleanly.'));
1056
+ }
1057
+ // See the matching comment in runAction — same rationale, same guard.
1058
+ process.env.MONOMIND_NO_LOCAL_EMBEDDINGS = '1';
1059
+ // The embedding-model crash above has a sibling: loadReranker() in
1060
+ // memory-bridge.ts loads a SEPARATE cross-encoder model
1061
+ // (cross-encoder/ettin-reranker-32m-v1, its own tokenizer architecture)
1062
+ // for search-result reranking, independent of the embedder guard above —
1063
+ // reranking runs on (query, passage) text pairs directly, so it can
1064
+ // still fire and hit the same native crash even with embeddings off.
1065
+ // MONOMIND_RERANKER=0 is an existing, already-wired guard (see
1066
+ // loadReranker's own early-return) — just never set for org runs before.
1067
+ process.env.MONOMIND_RERANKER = '0';
991
1068
  const crossProcess = ctx.flags.crossProcess !== false;
992
1069
  const daemon = new OrgDaemon(ctx.cwd, { crossProcess });
993
1070
  let srv;
994
1071
  if (crossProcess) {
995
1072
  srv = await startOrgServer(daemon, 0);
996
- daemon.setInboxUrl(`http://127.0.0.1:${srv.port}`, srv.credential);
1073
+ daemon.setInboxUrl(`http://127.0.0.1:${srv.port}`, srv.operatorCredential);
997
1074
  }
998
1075
  // Crash handlers: log the reason and persist crashed state so `org status`
999
- // shows what happened instead of a silent "pid is gone".
1076
+ // shows what happened instead of a silent "pid is gone". A truly unknown
1077
+ // uncaught exception's blast radius can't always be attributed to one org,
1078
+ // so the whole process still exits (the safety-first default) — but naming
1079
+ // which orgs were in flight at the moment it fired at least tells the
1080
+ // operator the blast radius they actually hit, instead of leaving them to
1081
+ // guess from an error with no org context.
1000
1082
  const crashExit = (label, err) => {
1001
1083
  try {
1002
- console.error(`[org serve] ${label}:`, err);
1084
+ const running = daemon.listRunning();
1085
+ console.error(`[org serve] ${label}:`, err, running.length ? `— orgs in flight: ${running.join(', ')}` : '— no orgs were running');
1003
1086
  }
1004
1087
  catch {
1005
- /* stderr gone */
1088
+ try {
1089
+ console.error(`[org serve] ${label}:`, err);
1090
+ }
1091
+ catch {
1092
+ /* stderr gone */
1093
+ }
1006
1094
  }
1007
1095
  daemon.persistCrashStateAll(`${label}: ${err instanceof Error ? err.message : String(err)}`);
1008
1096
  daemon.clearHeartbeat();
@@ -1180,16 +1268,30 @@ const serveAction = async (ctx) => {
1180
1268
  }
1181
1269
  }
1182
1270
  }
1271
+ // Each poll pass already wraps its own per-org daemon calls in try/catch,
1272
+ // but a synchronous throw from something ahead of those (e.g.
1273
+ // daemon.listRunning(), listOrgConfigFiles()) still rejects the async
1274
+ // function itself. `void`-ing that call, as before, discards the promise
1275
+ // without observing a rejection — which becomes an unhandled rejection at
1276
+ // the process level and takes down every other org's in-flight run via
1277
+ // crashExit, even though the failure was local to one poll pass. .catch()
1278
+ // keeps it a per-pass, logged failure instead.
1183
1279
  const stopPoll = setInterval(() => {
1184
- void pollStopfiles(ctx.cwd, daemon);
1280
+ pollStopfiles(ctx.cwd, daemon).catch((err) => {
1281
+ console.error('[org serve] stopfile poll failed:', err);
1282
+ });
1185
1283
  }, 2000);
1186
1284
  stopPoll.unref?.();
1187
1285
  const runPoll = setInterval(() => {
1188
- void pollRunfiles(ctx.cwd, daemon);
1286
+ pollRunfiles(ctx.cwd, daemon).catch((err) => {
1287
+ console.error('[org serve] runfile poll failed:', err);
1288
+ });
1189
1289
  }, 2000);
1190
1290
  runPoll.unref?.();
1191
1291
  const reloadPoll = setInterval(() => {
1192
- void pollReloadfiles(ctx.cwd, daemon);
1292
+ pollReloadfiles(ctx.cwd, daemon).catch((err) => {
1293
+ console.error('[org serve] reloadfile poll failed:', err);
1294
+ });
1193
1295
  }, 2000);
1194
1296
  reloadPoll.unref?.();
1195
1297
  await new Promise((r) => {
@@ -1771,7 +1873,7 @@ export const orgCommand = {
1771
1873
  },
1772
1874
  {
1773
1875
  name: 'memory',
1774
- description: "Inspect an org's cross-run memory and knowledge graph (stats | search <query> | rules | rollback <run-ref>)",
1876
+ description: "Inspect an org's cross-run memory and knowledge graph (stats | search <query> | rules | rollback <run-ref> | promote <run-ref>)",
1775
1877
  examples: [
1776
1878
  { command: 'monomind org memory growth stats', description: 'KG size and namespaces' },
1777
1879
  {
@@ -1780,7 +1882,11 @@ export const orgCommand = {
1780
1882
  },
1781
1883
  {
1782
1884
  command: 'monomind org memory growth rollback run:m4x2',
1783
- description: 'Delete everything one run wrote to the KG',
1885
+ description: "Withdraw one run's support from this org's KG",
1886
+ },
1887
+ {
1888
+ command: 'monomind org memory growth promote run:m4x2',
1889
+ description: "Share one run's claims with project-wide knowledge",
1784
1890
  },
1785
1891
  ],
1786
1892
  action: async (ctx) => {
@@ -1789,31 +1895,47 @@ export const orgCommand = {
1789
1895
  return v.result;
1790
1896
  const sub = String(ctx.args[1] ?? 'stats');
1791
1897
  const { join } = await import('node:path');
1792
- const dbPath = join(process.cwd(), '.monomind', 'org-memory');
1898
+ const cwd = ctx.cwd || process.cwd();
1899
+ const dbPath = join(cwd, '.monomind', 'org-memory');
1793
1900
  const kg = await import('../memory/memory-kg.js');
1794
1901
  const bridge = await import('../memory/memory-bridge.js');
1902
+ const { orgKgScope, orgMemoryNamespace } = await import('../orgrt/org-memory.js');
1903
+ // Every KG operation below is scoped to the requested org, so the org
1904
+ // name in the output describes what was actually read, not just what
1905
+ // was asked for. Reads of the shared store are unchanged.
1906
+ const scope = orgKgScope(v.name);
1907
+ const kgNs = kg.kgNamespaces(scope);
1908
+ // Flat org memory is namespaced by the org DEFINITION, not by name —
1909
+ // resolve it the way the runtime writes it (B4), so a configured
1910
+ // `memory_namespace` is searched instead of a guessed `org:<name>`.
1911
+ const defPath = join(cwd, ORG_DIR, `${v.name}.json`);
1912
+ const flatNs = existsSync(defPath)
1913
+ ? orgMemoryNamespace(v.name, OrgDefSchema.parse(JSON.parse(readFileSync(defPath, 'utf8'))))
1914
+ : `org:${v.name}`;
1795
1915
  try {
1796
1916
  if (sub === 'stats') {
1797
1917
  const [stats, glossary, backend] = await Promise.all([
1798
- kg.kgStats({ dbPath }),
1799
- kg.kgGlossary({ dbPath, limit: 15 }),
1918
+ kg.kgStats({ dbPath, scope }),
1919
+ kg.kgGlossary({ dbPath, limit: 15, scope }),
1800
1920
  bridge.bridgeGetBackendStats(dbPath),
1801
1921
  ]);
1922
+ // The backend reports every namespace in the SHARED store, so
1923
+ // listing it raw put other orgs' namespaces (and their counts)
1924
+ // under this org's name. Keep only what this org owns.
1925
+ // Spread kgNs rather than listing namespaces: the identity work
1926
+ // added `names` (the entity name index), and a hand-written list
1927
+ // silently omits any namespace added later, hiding rows this org
1928
+ // does own.
1929
+ const owned = new Set([...Object.values(kgNs), flatNs]);
1930
+ const byNs = Object.fromEntries(Object.entries(backend?.entriesByNamespace ?? {}).filter(([ns]) => owned.has(ns) || ns.startsWith(`agent:${flatNs}:`)));
1802
1931
  if (ctx.flags.format === 'json') {
1803
- const payload = {
1804
- v: 1,
1805
- org: v.name,
1806
- ...stats,
1807
- glossary,
1808
- namespaces: backend?.entriesByNamespace ?? {},
1809
- };
1932
+ const payload = { v: 1, org: v.name, ...stats, glossary, namespaces: byNs };
1810
1933
  process.stdout.write(`${JSON.stringify(payload)}\n`);
1811
1934
  return { success: true, data: payload };
1812
1935
  }
1813
1936
  log(output.info(`Knowledge graph: ${stats.nodes} entities, ${stats.edges} relations, ${stats.rules} rules`));
1814
1937
  if (glossary.length)
1815
1938
  log(output.info(`Top entities: ${glossary.join(', ')}`));
1816
- const byNs = backend?.entriesByNamespace ?? {};
1817
1939
  for (const [ns, count] of Object.entries(byNs))
1818
1940
  log(output.info(` ${ns}: ${count} entries`));
1819
1941
  return {
@@ -1829,11 +1951,11 @@ export const orgCommand = {
1829
1951
  const [mem, graph] = await Promise.all([
1830
1952
  bridge.bridgeSearchEntries({
1831
1953
  query: q,
1832
- namespace: `org:${v.name}`,
1954
+ namespace: flatNs,
1833
1955
  limit: 5,
1834
1956
  dbPath,
1835
1957
  }),
1836
- kg.kgSearch({ query: q, dbPath, limit: 8 }),
1958
+ kg.kgSearch({ query: q, dbPath, limit: 8, scope }),
1837
1959
  ]);
1838
1960
  if (ctx.flags.format === 'json') {
1839
1961
  const payload = {
@@ -1857,7 +1979,7 @@ export const orgCommand = {
1857
1979
  };
1858
1980
  }
1859
1981
  if (sub === 'rules') {
1860
- const rules = await kg.kgListRules({ dbPath, limit: 50 });
1982
+ const rules = await kg.kgListRules({ dbPath, limit: 50, scope });
1861
1983
  if (ctx.flags.format === 'json') {
1862
1984
  const payload = { v: 1, org: v.name, items: rules };
1863
1985
  process.stdout.write(`${JSON.stringify(payload)}\n`);
@@ -1874,18 +1996,39 @@ export const orgCommand = {
1874
1996
  success: false,
1875
1997
  message: 'usage: org memory <org> rollback <origin-ref> (e.g. run:m4x2)',
1876
1998
  };
1877
- const res = await kg.kgRollback({ originRef: ref, dbPath });
1999
+ // Scoped: the ref is resolved inside this org's namespaces and
2000
+ // origin space, so the org name in the command is an ownership
2001
+ // restriction rather than a label on an unfiltered rollback.
2002
+ const res = await kg.kgRollback({ originRef: ref, scope, dbPath });
1878
2003
  if (ctx.flags.format === 'json') {
1879
2004
  const payload = { v: 1, org: v.name, ref, ...res };
1880
2005
  process.stdout.write(`${JSON.stringify(payload)}\n`);
1881
2006
  return { success: res.success, data: payload };
1882
2007
  }
1883
- log(output.info(`Rolled back ${ref}: ${res.deleted} deleted, ${res.retained} retained (shared with other origins)`));
2008
+ log(output.info(`Rolled back ${ref} for org ${v.name}: ${res.deleted} deleted, ${res.retained} retained (shared with other origins)`));
1884
2009
  return { success: res.success, message: `rollback ${ref}`, data: res };
1885
2010
  }
2011
+ if (sub === 'promote') {
2012
+ const ref = ctx.args[2];
2013
+ if (!ref)
2014
+ return {
2015
+ success: false,
2016
+ message: 'usage: org memory <org> promote <origin-ref> (e.g. run:m4x2)',
2017
+ };
2018
+ const res = await kg.kgPromote({ originRef: ref, from: scope, dbPath });
2019
+ if (ctx.flags.format === 'json') {
2020
+ const payload = { v: 1, org: v.name, ref, ...res };
2021
+ process.stdout.write(`${JSON.stringify(payload)}\n`);
2022
+ return { success: res.success, data: payload };
2023
+ }
2024
+ log(output.info(res.success
2025
+ ? `Promoted ${ref} from org ${v.name} to project-shared knowledge: ${res.nodes} entities, ${res.edges} relations, ${res.rules} rules. Withdraw with origin ref ${res.promotedAs}.`
2026
+ : `Promotion of ${ref} failed: ${res.error ?? 'unknown error'}`));
2027
+ return { success: res.success, message: `promote ${ref}`, data: res };
2028
+ }
1886
2029
  return {
1887
2030
  success: false,
1888
- message: `unknown subcommand "${sub}" — use stats | search | rules | rollback`,
2031
+ message: `unknown subcommand "${sub}" — use stats | search | rules | rollback | promote`,
1889
2032
  };
1890
2033
  }
1891
2034
  finally {
@@ -1979,6 +2122,21 @@ export const orgCommand = {
1979
2122
  return questionsAction(ctx, v.name);
1980
2123
  },
1981
2124
  },
2125
+ {
2126
+ name: 'approvals',
2127
+ description: "List pending tool/action approval requests from an org's agents",
2128
+ options: [{ name: 'all', description: 'Include resolved approvals', type: 'boolean' }],
2129
+ examples: [
2130
+ { command: 'monomind org approvals growth', description: 'Show pending approvals' },
2131
+ ],
2132
+ action: async (ctx) => {
2133
+ const v = validateOrgName(ctx.args[0]);
2134
+ if (!v.ok)
2135
+ return v.result;
2136
+ const { approvalsAction } = await import('./org-observe.js');
2137
+ return approvalsAction(ctx, v.name);
2138
+ },
2139
+ },
1982
2140
  {
1983
2141
  name: 'answer',
1984
2142
  description: 'Answer a pending ask_human question (live if the org is running, queued otherwise)',