@monoes/monomindcli 1.10.54 → 1.10.55

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 (441) hide show
  1. package/.claude/agents/optimization/benchmark-suite.md +2 -0
  2. package/.claude/agents/optimization/load-balancer.md +2 -0
  3. package/.claude/agents/optimization/performance-monitor.md +2 -0
  4. package/.claude/agents/optimization/resource-allocator.md +3 -1
  5. package/.claude/agents/optimization/topology-optimizer.md +2 -0
  6. package/.claude/commands/mastermind/_repeat.md +21 -0
  7. package/.claude/commands/mastermind/_taskfile.md +235 -0
  8. package/.claude/commands/mastermind/adr.md +11 -0
  9. package/.claude/commands/mastermind/approve.md +94 -0
  10. package/.claude/commands/mastermind/autodev.md +32 -0
  11. package/.claude/commands/mastermind/budget.md +7 -0
  12. package/.claude/commands/mastermind/code-review.md +317 -0
  13. package/.claude/commands/mastermind/createorg.md +40 -1
  14. package/.claude/commands/mastermind/createtask.md +383 -0
  15. package/.claude/commands/mastermind/debug.md +22 -0
  16. package/.claude/commands/mastermind/design.md +20 -0
  17. package/.claude/commands/mastermind/do.md +526 -0
  18. package/.claude/commands/mastermind/execute.md +20 -0
  19. package/.claude/commands/mastermind/finish.md +20 -0
  20. package/.claude/commands/mastermind/graph-status.md +7 -0
  21. package/.claude/commands/mastermind/help.md +118 -0
  22. package/.claude/commands/mastermind/ideate.md +261 -0
  23. package/.claude/commands/mastermind/improve.md +345 -0
  24. package/.claude/commands/mastermind/loops.md +7 -0
  25. package/.claude/commands/mastermind/master.md +186 -6
  26. package/.claude/commands/mastermind/memory.md +230 -0
  27. package/.claude/commands/mastermind/plan.md +26 -0
  28. package/.claude/commands/mastermind/receive-review.md +20 -0
  29. package/.claude/commands/mastermind/repeat.md +257 -0
  30. package/.claude/commands/mastermind/runorg.md +3 -0
  31. package/.claude/commands/mastermind/skill-builder.md +20 -0
  32. package/.claude/commands/mastermind/specialagents.md +125 -0
  33. package/.claude/commands/mastermind/swarm.md +161 -0
  34. package/.claude/commands/mastermind/taskdev.md +26 -0
  35. package/.claude/commands/mastermind/tdd.md +22 -0
  36. package/.claude/commands/mastermind/techport.md +4 -0
  37. package/.claude/commands/mastermind/understand.md +139 -0
  38. package/.claude/commands/mastermind/verify.md +22 -0
  39. package/.claude/commands/mastermind/worktree.md +20 -0
  40. package/.claude/helpers/handlers/graph-status-handler.cjs +2 -1
  41. package/.claude/helpers/hook-handler.cjs +19 -0
  42. package/.claude/helpers/skill-registry.json +23 -0
  43. package/.claude/helpers/statusline.cjs +1 -1
  44. package/.claude/skills/mastermind/approve.md +15 -7
  45. package/.claude/skills/mastermind/autodev.md +534 -0
  46. package/.claude/skills/mastermind/createorg.md +21 -5
  47. package/.claude/skills/mastermind/debug.md +232 -0
  48. package/.claude/skills/mastermind/design.md +187 -0
  49. package/.claude/skills/mastermind/execute.md +104 -0
  50. package/.claude/skills/mastermind/finish.md +251 -0
  51. package/.claude/skills/mastermind/plan.md +180 -0
  52. package/.claude/skills/mastermind/receive-review.md +213 -0
  53. package/.claude/skills/mastermind/runorg.md +23 -8
  54. package/.claude/skills/mastermind/skill-builder.md +274 -0
  55. package/.claude/skills/mastermind/taskdev.md +307 -0
  56. package/.claude/skills/mastermind/tdd.md +394 -0
  57. package/.claude/skills/mastermind/verify.md +196 -0
  58. package/.claude/skills/mastermind/worktree.md +160 -132
  59. package/README.md +320 -253
  60. package/dist/src/commands/analyze.d.ts.map +1 -1
  61. package/dist/src/commands/analyze.js +9 -2
  62. package/dist/src/commands/analyze.js.map +1 -1
  63. package/dist/src/commands/benchmark.js.map +1 -1
  64. package/dist/src/commands/completions.js +1 -1
  65. package/dist/src/commands/guidance.js +7 -7
  66. package/dist/src/commands/hooks.d.ts.map +1 -1
  67. package/dist/src/commands/hooks.js +16 -3
  68. package/dist/src/commands/hooks.js.map +1 -1
  69. package/dist/src/commands/index.d.ts +3 -2
  70. package/dist/src/commands/index.d.ts.map +1 -1
  71. package/dist/src/commands/index.js +7 -0
  72. package/dist/src/commands/index.js.map +1 -1
  73. package/dist/src/commands/init.d.ts.map +1 -1
  74. package/dist/src/commands/init.js +47 -13
  75. package/dist/src/commands/init.js.map +1 -1
  76. package/dist/src/commands/neural.d.ts.map +1 -1
  77. package/dist/src/commands/neural.js +100 -14
  78. package/dist/src/commands/neural.js.map +1 -1
  79. package/dist/src/commands/platforms.d.ts +11 -0
  80. package/dist/src/commands/platforms.d.ts.map +1 -0
  81. package/dist/src/commands/platforms.js +195 -0
  82. package/dist/src/commands/platforms.js.map +1 -0
  83. package/dist/src/commands/ruvector/backup.js.map +1 -1
  84. package/dist/src/commands/ruvector/benchmark.js.map +1 -1
  85. package/dist/src/commands/ruvector/init.js.map +1 -1
  86. package/dist/src/commands/ruvector/migrate.js.map +1 -1
  87. package/dist/src/commands/ruvector/optimize.js.map +1 -1
  88. package/dist/src/commands/ruvector/status.js.map +1 -1
  89. package/dist/src/commands/update.js +6 -6
  90. package/dist/src/init/executor.d.ts.map +1 -1
  91. package/dist/src/init/executor.js +28 -0
  92. package/dist/src/init/executor.js.map +1 -1
  93. package/dist/src/init/statusline-generator.js +1 -1
  94. package/dist/src/init/types.d.ts +1 -0
  95. package/dist/src/init/types.d.ts.map +1 -1
  96. package/dist/src/mcp-server.d.ts.map +1 -1
  97. package/dist/src/mcp-server.js +92 -0
  98. package/dist/src/mcp-server.js.map +1 -1
  99. package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -1
  100. package/dist/src/mcp-tools/hive-mind-tools.js +52 -0
  101. package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -1
  102. package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
  103. package/dist/src/mcp-tools/hooks-tools.js +106 -5
  104. package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
  105. package/dist/src/mcp-tools/index.d.ts +0 -5
  106. package/dist/src/mcp-tools/index.d.ts.map +1 -1
  107. package/dist/src/mcp-tools/index.js +0 -5
  108. package/dist/src/mcp-tools/index.js.map +1 -1
  109. package/dist/src/mcp-tools/monograph-tools.d.ts.map +1 -1
  110. package/dist/src/mcp-tools/monograph-tools.js +507 -5587
  111. package/dist/src/mcp-tools/monograph-tools.js.map +1 -1
  112. package/dist/src/mcp-tools/neural-tools.d.ts.map +1 -1
  113. package/dist/src/mcp-tools/neural-tools.js +64 -4
  114. package/dist/src/mcp-tools/neural-tools.js.map +1 -1
  115. package/dist/src/mcp-tools/security-tools.js +4 -4
  116. package/dist/src/memory/intelligence.d.ts +2 -2
  117. package/dist/src/memory/intelligence.d.ts.map +1 -1
  118. package/dist/src/memory/intelligence.js +108 -3
  119. package/dist/src/memory/intelligence.js.map +1 -1
  120. package/dist/src/memory/memory-bridge.js +1 -1
  121. package/dist/src/memory/memory-bridge.js.map +1 -1
  122. package/dist/src/memory/sona-optimizer.d.ts +1 -10
  123. package/dist/src/memory/sona-optimizer.d.ts.map +1 -1
  124. package/dist/src/memory/sona-optimizer.js +0 -46
  125. package/dist/src/memory/sona-optimizer.js.map +1 -1
  126. package/dist/src/runtime/headless.js +3 -3
  127. package/dist/src/ruvector/diff-classifier.d.ts +0 -2
  128. package/dist/src/ruvector/diff-classifier.d.ts.map +1 -1
  129. package/dist/src/ruvector/diff-classifier.js +2 -14
  130. package/dist/src/ruvector/diff-classifier.js.map +1 -1
  131. package/dist/src/ruvector/index.d.ts +26 -9
  132. package/dist/src/ruvector/index.d.ts.map +1 -1
  133. package/dist/src/ruvector/index.js +3 -21
  134. package/dist/src/ruvector/index.js.map +1 -1
  135. package/dist/src/ruvector/ruvllm-wasm.js +2 -2
  136. package/dist/src/ruvector/ruvllm-wasm.js.map +1 -1
  137. package/dist/src/types.d.ts +0 -15
  138. package/dist/src/types.d.ts.map +1 -1
  139. package/dist/src/types.js +0 -18
  140. package/dist/src/types.js.map +1 -1
  141. package/dist/src/ui/dashboard.html +8763 -9766
  142. package/dist/src/ui/orgs.html +1 -1
  143. package/dist/src/ui/server.mjs +504 -35
  144. package/dist/src/update/index.js +1 -1
  145. package/dist/src/update/validator.js +8 -8
  146. package/dist/tsconfig.tsbuildinfo +1 -1
  147. package/package.json +2 -2
  148. package/.claude/agents/academic/academic-anthropologist.md +0 -126
  149. package/.claude/agents/academic/academic-geographer.md +0 -128
  150. package/.claude/agents/academic/academic-historian.md +0 -124
  151. package/.claude/agents/academic/academic-narratologist.md +0 -119
  152. package/.claude/agents/academic/academic-psychologist.md +0 -119
  153. package/.claude/agents/analysis/analyze-code-quality.md +0 -58
  154. package/.claude/agents/analysis/code-analyzer.md +0 -189
  155. package/.claude/agents/analysis/code-review/analyze-code-quality.md +0 -58
  156. package/.claude/agents/consensus/performance-benchmarker.md +0 -831
  157. package/.claude/agents/data/ml/data-ml-model.md +0 -76
  158. package/.claude/agents/development/dev-backend-api.md +0 -178
  159. package/.claude/agents/devops/ci-cd/ops-cicd-github.md +0 -52
  160. package/.claude/agents/documentation/api-docs/docs-api-openapi.md +0 -63
  161. package/.claude/agents/game-development/blender/blender-addon-engineer.md +0 -235
  162. package/.claude/agents/game-development/game-audio-engineer.md +0 -265
  163. package/.claude/agents/game-development/game-designer.md +0 -168
  164. package/.claude/agents/game-development/godot/godot-gameplay-scripter.md +0 -335
  165. package/.claude/agents/game-development/godot/godot-multiplayer-engineer.md +0 -298
  166. package/.claude/agents/game-development/godot/godot-shader-developer.md +0 -267
  167. package/.claude/agents/game-development/level-designer.md +0 -209
  168. package/.claude/agents/game-development/narrative-designer.md +0 -244
  169. package/.claude/agents/game-development/roblox-studio/roblox-avatar-creator.md +0 -298
  170. package/.claude/agents/game-development/roblox-studio/roblox-experience-designer.md +0 -306
  171. package/.claude/agents/game-development/roblox-studio/roblox-systems-scripter.md +0 -326
  172. package/.claude/agents/game-development/technical-artist.md +0 -230
  173. package/.claude/agents/game-development/unity/unity-architect.md +0 -272
  174. package/.claude/agents/game-development/unity/unity-editor-tool-developer.md +0 -311
  175. package/.claude/agents/game-development/unity/unity-multiplayer-engineer.md +0 -322
  176. package/.claude/agents/game-development/unity/unity-shader-graph-artist.md +0 -270
  177. package/.claude/agents/game-development/unreal-engine/unreal-multiplayer-architect.md +0 -314
  178. package/.claude/agents/game-development/unreal-engine/unreal-systems-engineer.md +0 -311
  179. package/.claude/agents/game-development/unreal-engine/unreal-technical-artist.md +0 -257
  180. package/.claude/agents/game-development/unreal-engine/unreal-world-builder.md +0 -274
  181. package/.claude/agents/github/release-swarm.md +0 -597
  182. package/.claude/agents/goal/agent.md +0 -804
  183. package/.claude/agents/goal/code-goal-planner.md +0 -445
  184. package/.claude/agents/marketing/marketing-ai-citation-strategist.md +0 -171
  185. package/.claude/agents/marketing/marketing-app-store-optimizer.md +0 -322
  186. package/.claude/agents/marketing/marketing-baidu-seo-specialist.md +0 -227
  187. package/.claude/agents/marketing/marketing-bilibili-content-strategist.md +0 -200
  188. package/.claude/agents/marketing/marketing-book-co-author.md +0 -111
  189. package/.claude/agents/marketing/marketing-carousel-growth-engine.md +0 -200
  190. package/.claude/agents/marketing/marketing-china-ecommerce-operator.md +0 -284
  191. package/.claude/agents/marketing/marketing-content-creator.md +0 -67
  192. package/.claude/agents/marketing/marketing-cross-border-ecommerce.md +0 -260
  193. package/.claude/agents/marketing/marketing-douyin-strategist.md +0 -150
  194. package/.claude/agents/marketing/marketing-growth-hacker.md +0 -54
  195. package/.claude/agents/marketing/marketing-instagram-curator.md +0 -114
  196. package/.claude/agents/marketing/marketing-kuaishou-strategist.md +0 -224
  197. package/.claude/agents/marketing/marketing-linkedin-content-creator.md +0 -215
  198. package/.claude/agents/marketing/marketing-livestream-commerce-coach.md +0 -306
  199. package/.claude/agents/marketing/marketing-podcast-strategist.md +0 -278
  200. package/.claude/agents/marketing/marketing-private-domain-operator.md +0 -309
  201. package/.claude/agents/marketing/marketing-reddit-community-builder.md +0 -124
  202. package/.claude/agents/marketing/marketing-seo-specialist.md +0 -279
  203. package/.claude/agents/marketing/marketing-short-video-editing-coach.md +0 -413
  204. package/.claude/agents/marketing/marketing-social-media-strategist.md +0 -125
  205. package/.claude/agents/marketing/marketing-tiktok-strategist.md +0 -126
  206. package/.claude/agents/marketing/marketing-twitter-engager.md +0 -127
  207. package/.claude/agents/marketing/marketing-wechat-official-account.md +0 -146
  208. package/.claude/agents/marketing/marketing-weibo-strategist.md +0 -241
  209. package/.claude/agents/marketing/marketing-xiaohongshu-specialist.md +0 -139
  210. package/.claude/agents/marketing/marketing-zhihu-strategist.md +0 -163
  211. package/.claude/agents/neural/safla-neural.md +0 -74
  212. package/.claude/agents/paid-media/paid-media-auditor.md +0 -71
  213. package/.claude/agents/paid-media/paid-media-creative-strategist.md +0 -71
  214. package/.claude/agents/paid-media/paid-media-paid-social-strategist.md +0 -71
  215. package/.claude/agents/paid-media/paid-media-ppc-strategist.md +0 -71
  216. package/.claude/agents/paid-media/paid-media-programmatic-buyer.md +0 -71
  217. package/.claude/agents/paid-media/paid-media-search-query-analyst.md +0 -71
  218. package/.claude/agents/paid-media/paid-media-tracking-specialist.md +0 -71
  219. package/.claude/agents/payments/agentic-payments.md +0 -126
  220. package/.claude/agents/product/product-behavioral-nudge-engine.md +0 -81
  221. package/.claude/agents/product/product-feedback-synthesizer.md +0 -119
  222. package/.claude/agents/product/product-manager.md +0 -469
  223. package/.claude/agents/product/product-sprint-prioritizer.md +0 -154
  224. package/.claude/agents/product/product-trend-researcher.md +0 -159
  225. package/.claude/agents/project-management/project-management-experiment-tracker.md +0 -199
  226. package/.claude/agents/project-management/project-management-jira-workflow-steward.md +0 -231
  227. package/.claude/agents/project-management/project-management-project-shepherd.md +0 -195
  228. package/.claude/agents/project-management/project-management-studio-operations.md +0 -201
  229. package/.claude/agents/project-management/project-management-studio-producer.md +0 -204
  230. package/.claude/agents/project-management/project-manager-senior.md +0 -136
  231. package/.claude/agents/reasoning/agent.md +0 -804
  232. package/.claude/agents/reasoning/goal-planner.md +0 -73
  233. package/.claude/agents/sales/sales-account-strategist.md +0 -228
  234. package/.claude/agents/sales/sales-coach.md +0 -272
  235. package/.claude/agents/sales/sales-deal-strategist.md +0 -181
  236. package/.claude/agents/sales/sales-discovery-coach.md +0 -226
  237. package/.claude/agents/sales/sales-engineer.md +0 -183
  238. package/.claude/agents/sales/sales-outbound-strategist.md +0 -202
  239. package/.claude/agents/sales/sales-pipeline-analyst.md +0 -268
  240. package/.claude/agents/sales/sales-proposal-strategist.md +0 -218
  241. package/.claude/agents/sona/sona-learning-optimizer.md +0 -65
  242. package/.claude/agents/spatial-computing/macos-spatial-metal-engineer.md +0 -338
  243. package/.claude/agents/spatial-computing/terminal-integration-specialist.md +0 -71
  244. package/.claude/agents/spatial-computing/visionos-spatial-engineer.md +0 -55
  245. package/.claude/agents/specialists/memory-specialist.md +0 -298
  246. package/.claude/agents/specialists/performance-engineer.md +0 -387
  247. package/.claude/agents/specialists/queen-coordinator.md +0 -67
  248. package/.claude/agents/specialists/security-architect.md +0 -154
  249. package/.claude/agents/specialized/accounts-payable-agent.md +0 -186
  250. package/.claude/agents/specialized/corporate-training-designer.md +0 -193
  251. package/.claude/agents/specialized/data-consolidation-agent.md +0 -61
  252. package/.claude/agents/specialized/government-digital-presales-consultant.md +0 -364
  253. package/.claude/agents/specialized/healthcare-marketing-compliance.md +0 -396
  254. package/.claude/agents/specialized/recruitment-specialist.md +0 -510
  255. package/.claude/agents/specialized/report-distribution-agent.md +0 -66
  256. package/.claude/agents/specialized/sales-data-extraction-agent.md +0 -68
  257. package/.claude/agents/specialized/specialized-french-consulting-market.md +0 -193
  258. package/.claude/agents/specialized/specialized-korean-business-navigator.md +0 -217
  259. package/.claude/agents/specialized/specialized-salesforce-architect.md +0 -181
  260. package/.claude/agents/specialized/study-abroad-advisor.md +0 -283
  261. package/.claude/agents/specialized/supply-chain-strategist.md +0 -583
  262. package/.claude/agents/sublinear/consensus-coordinator.md +0 -333
  263. package/.claude/agents/sublinear/matrix-optimizer.md +0 -180
  264. package/.claude/agents/sublinear/pagerank-analyzer.md +0 -295
  265. package/.claude/agents/sublinear/performance-optimizer.md +0 -363
  266. package/.claude/agents/sublinear/trading-predictor.md +0 -242
  267. package/.claude/agents/support/support-analytics-reporter.md +0 -366
  268. package/.claude/agents/support/support-executive-summary-generator.md +0 -213
  269. package/.claude/agents/support/support-finance-tracker.md +0 -443
  270. package/.claude/agents/support/support-infrastructure-maintainer.md +0 -619
  271. package/.claude/agents/support/support-legal-compliance-checker.md +0 -589
  272. package/.claude/agents/support/support-support-responder.md +0 -586
  273. package/.claude/agents/swarm/adaptive-coordinator.md +0 -364
  274. package/.claude/agents/swarm/hierarchical-coordinator.md +0 -318
  275. package/.claude/agents/templates/github-pr-manager.md +0 -155
  276. package/.claude/agents/templates/memory-coordinator.md +0 -163
  277. package/.claude/agents/templates/migration-plan.md +0 -724
  278. package/.claude/agents/templates/orchestrator-task.md +0 -120
  279. package/.claude/agents/templates/performance-analyzer.md +0 -179
  280. package/.claude/agents/templates/sparc-coordinator.md +0 -163
  281. package/.claude/agents/testing/testing-reality-checker.md +0 -237
  282. package/.claude/commands/analysis/token-efficiency.md +0 -42
  283. package/.claude/commands/optimization/README.md +0 -73
  284. package/.claude/commands/optimization/parallel-execution.md +0 -76
  285. package/.claude/commands/swarm/swarm-analysis.md +0 -62
  286. package/.claude/commands/swarm/swarm-background.md +0 -65
  287. package/.claude/commands/swarm/swarm-modes.md +0 -67
  288. package/.claude/commands/swarm/swarm-monitor.md +0 -54
  289. package/.claude/commands/swarm/swarm-status.md +0 -44
  290. package/.claude/commands/swarm/swarm-strategies.md +0 -76
  291. package/.claude/commands/training/model-update.md +0 -78
  292. package/.claude/commands/training/pattern-learn.md +0 -69
  293. package/.claude/commands/training/specialization.md +0 -92
  294. package/.claude/commands/verify/check.md +0 -106
  295. package/.claude/commands/verify/start.md +0 -105
  296. package/.claude/helpers/README.md +0 -105
  297. package/.claude/helpers/context-persistence-hook.mjs +0 -1988
  298. package/.claude/helpers/intelligence.cjs +0 -247
  299. package/.claude/helpers/learning-service.mjs +0 -1302
  300. package/.claude/helpers/memory-palace.cjs +0 -461
  301. package/.claude/helpers/memory.cjs +0 -84
  302. package/.claude/helpers/metrics-db.mjs +0 -488
  303. package/.claude/helpers/router.cjs +0 -559
  304. package/.claude/helpers/session.cjs +0 -126
  305. package/.claude/helpers/swarm-hooks.sh +0 -761
  306. package/.claude/helpers/toggle-statusline.cjs +0 -58
  307. package/.claude/helpers/token-tracker.cjs +0 -934
  308. package/.claude/skills/agentdb-advanced/SKILL.md +0 -549
  309. package/.claude/skills/agentdb-learning/SKILL.md +0 -544
  310. package/.claude/skills/agentdb-memory-patterns/SKILL.md +0 -337
  311. package/.claude/skills/agentdb-optimization/SKILL.md +0 -508
  312. package/.claude/skills/agentdb-vector-search/SKILL.md +0 -335
  313. package/.claude/skills/agentic-integration/SKILL.md +0 -265
  314. package/.claude/skills/cli-modernization/SKILL.md +0 -950
  315. package/.claude/skills/core-implementation/SKILL.md +0 -892
  316. package/.claude/skills/ddd-architecture/SKILL.md +0 -444
  317. package/.claude/skills/github-code-review/SKILL.md +0 -1147
  318. package/.claude/skills/github-multi-repo/SKILL.md +0 -912
  319. package/.claude/skills/github-project-management/SKILL.md +0 -1245
  320. package/.claude/skills/github-release-management/SKILL.md +0 -1118
  321. package/.claude/skills/github-workflow-automation/SKILL.md +0 -1107
  322. package/.claude/skills/mcp-optimization/SKILL.md +0 -837
  323. package/.claude/skills/memory-unification/SKILL.md +0 -196
  324. package/.claude/skills/performance-optimization/SKILL.md +0 -416
  325. package/.claude/skills/reasoningbank-agentdb/SKILL.md +0 -444
  326. package/.claude/skills/reasoningbank-intelligence/SKILL.md +0 -199
  327. package/.claude/skills/security-hardening/SKILL.md +0 -101
  328. package/.claude/skills/stream-chain/SKILL.md +0 -560
  329. package/.claude/skills/swarm-coordination/SKILL.md +0 -451
  330. package/bundled-graph/dist/src/analyze.d.ts +0 -32
  331. package/bundled-graph/dist/src/analyze.d.ts.map +0 -1
  332. package/bundled-graph/dist/src/analyze.js +0 -297
  333. package/bundled-graph/dist/src/analyze.js.map +0 -1
  334. package/bundled-graph/dist/src/build.d.ts +0 -8
  335. package/bundled-graph/dist/src/build.d.ts.map +0 -1
  336. package/bundled-graph/dist/src/build.js.map +0 -1
  337. package/bundled-graph/dist/src/cache.d.ts +0 -12
  338. package/bundled-graph/dist/src/cache.d.ts.map +0 -1
  339. package/bundled-graph/dist/src/cache.js +0 -43
  340. package/bundled-graph/dist/src/cache.js.map +0 -1
  341. package/bundled-graph/dist/src/cluster.d.ts +0 -5
  342. package/bundled-graph/dist/src/cluster.d.ts.map +0 -1
  343. package/bundled-graph/dist/src/cluster.js.map +0 -1
  344. package/bundled-graph/dist/src/detect.d.ts +0 -21
  345. package/bundled-graph/dist/src/detect.d.ts.map +0 -1
  346. package/bundled-graph/dist/src/detect.js +0 -195
  347. package/bundled-graph/dist/src/detect.js.map +0 -1
  348. package/bundled-graph/dist/src/export.d.ts +0 -21
  349. package/bundled-graph/dist/src/export.d.ts.map +0 -1
  350. package/bundled-graph/dist/src/export.js +0 -68
  351. package/bundled-graph/dist/src/export.js.map +0 -1
  352. package/bundled-graph/dist/src/extract/index.d.ts +0 -20
  353. package/bundled-graph/dist/src/extract/index.d.ts.map +0 -1
  354. package/bundled-graph/dist/src/extract/index.js +0 -158
  355. package/bundled-graph/dist/src/extract/index.js.map +0 -1
  356. package/bundled-graph/dist/src/extract/languages/c.d.ts +0 -3
  357. package/bundled-graph/dist/src/extract/languages/c.d.ts.map +0 -1
  358. package/bundled-graph/dist/src/extract/languages/c.js +0 -88
  359. package/bundled-graph/dist/src/extract/languages/c.js.map +0 -1
  360. package/bundled-graph/dist/src/extract/languages/cpp.d.ts +0 -3
  361. package/bundled-graph/dist/src/extract/languages/cpp.d.ts.map +0 -1
  362. package/bundled-graph/dist/src/extract/languages/cpp.js +0 -121
  363. package/bundled-graph/dist/src/extract/languages/cpp.js.map +0 -1
  364. package/bundled-graph/dist/src/extract/languages/csharp.d.ts +0 -3
  365. package/bundled-graph/dist/src/extract/languages/csharp.d.ts.map +0 -1
  366. package/bundled-graph/dist/src/extract/languages/csharp.js +0 -121
  367. package/bundled-graph/dist/src/extract/languages/csharp.js.map +0 -1
  368. package/bundled-graph/dist/src/extract/languages/go.d.ts +0 -3
  369. package/bundled-graph/dist/src/extract/languages/go.d.ts.map +0 -1
  370. package/bundled-graph/dist/src/extract/languages/go.js +0 -181
  371. package/bundled-graph/dist/src/extract/languages/go.js.map +0 -1
  372. package/bundled-graph/dist/src/extract/languages/java.d.ts +0 -3
  373. package/bundled-graph/dist/src/extract/languages/java.d.ts.map +0 -1
  374. package/bundled-graph/dist/src/extract/languages/java.js +0 -117
  375. package/bundled-graph/dist/src/extract/languages/java.js.map +0 -1
  376. package/bundled-graph/dist/src/extract/languages/kotlin.d.ts +0 -3
  377. package/bundled-graph/dist/src/extract/languages/kotlin.d.ts.map +0 -1
  378. package/bundled-graph/dist/src/extract/languages/kotlin.js +0 -112
  379. package/bundled-graph/dist/src/extract/languages/kotlin.js.map +0 -1
  380. package/bundled-graph/dist/src/extract/languages/php.d.ts +0 -3
  381. package/bundled-graph/dist/src/extract/languages/php.d.ts.map +0 -1
  382. package/bundled-graph/dist/src/extract/languages/php.js +0 -130
  383. package/bundled-graph/dist/src/extract/languages/php.js.map +0 -1
  384. package/bundled-graph/dist/src/extract/languages/python.d.ts +0 -3
  385. package/bundled-graph/dist/src/extract/languages/python.d.ts.map +0 -1
  386. package/bundled-graph/dist/src/extract/languages/python.js +0 -230
  387. package/bundled-graph/dist/src/extract/languages/python.js.map +0 -1
  388. package/bundled-graph/dist/src/extract/languages/ruby.d.ts +0 -3
  389. package/bundled-graph/dist/src/extract/languages/ruby.d.ts.map +0 -1
  390. package/bundled-graph/dist/src/extract/languages/ruby.js +0 -120
  391. package/bundled-graph/dist/src/extract/languages/ruby.js.map +0 -1
  392. package/bundled-graph/dist/src/extract/languages/rust.d.ts +0 -3
  393. package/bundled-graph/dist/src/extract/languages/rust.d.ts.map +0 -1
  394. package/bundled-graph/dist/src/extract/languages/rust.js +0 -195
  395. package/bundled-graph/dist/src/extract/languages/rust.js.map +0 -1
  396. package/bundled-graph/dist/src/extract/languages/scala.d.ts +0 -3
  397. package/bundled-graph/dist/src/extract/languages/scala.d.ts.map +0 -1
  398. package/bundled-graph/dist/src/extract/languages/scala.js +0 -110
  399. package/bundled-graph/dist/src/extract/languages/scala.js.map +0 -1
  400. package/bundled-graph/dist/src/extract/languages/swift.d.ts +0 -3
  401. package/bundled-graph/dist/src/extract/languages/swift.d.ts.map +0 -1
  402. package/bundled-graph/dist/src/extract/languages/swift.js +0 -122
  403. package/bundled-graph/dist/src/extract/languages/swift.js.map +0 -1
  404. package/bundled-graph/dist/src/extract/languages/typescript.d.ts +0 -3
  405. package/bundled-graph/dist/src/extract/languages/typescript.d.ts.map +0 -1
  406. package/bundled-graph/dist/src/extract/languages/typescript.js +0 -295
  407. package/bundled-graph/dist/src/extract/languages/typescript.js.map +0 -1
  408. package/bundled-graph/dist/src/extract/semantic.d.ts +0 -38
  409. package/bundled-graph/dist/src/extract/semantic.d.ts.map +0 -1
  410. package/bundled-graph/dist/src/extract/semantic.js +0 -242
  411. package/bundled-graph/dist/src/extract/semantic.js.map +0 -1
  412. package/bundled-graph/dist/src/extract/tree-sitter-runner.d.ts +0 -48
  413. package/bundled-graph/dist/src/extract/tree-sitter-runner.d.ts.map +0 -1
  414. package/bundled-graph/dist/src/extract/tree-sitter-runner.js +0 -137
  415. package/bundled-graph/dist/src/extract/tree-sitter-runner.js.map +0 -1
  416. package/bundled-graph/dist/src/extract/types.d.ts +0 -7
  417. package/bundled-graph/dist/src/extract/types.d.ts.map +0 -1
  418. package/bundled-graph/dist/src/extract/types.js +0 -2
  419. package/bundled-graph/dist/src/extract/types.js.map +0 -1
  420. package/bundled-graph/dist/src/index.d.ts +0 -28
  421. package/bundled-graph/dist/src/index.d.ts.map +0 -1
  422. package/bundled-graph/dist/src/index.js +0 -26
  423. package/bundled-graph/dist/src/index.js.map +0 -1
  424. package/bundled-graph/dist/src/pipeline.d.ts +0 -27
  425. package/bundled-graph/dist/src/pipeline.d.ts.map +0 -1
  426. package/bundled-graph/dist/src/pipeline.js +0 -269
  427. package/bundled-graph/dist/src/pipeline.js.map +0 -1
  428. package/bundled-graph/dist/src/report.d.ts +0 -26
  429. package/bundled-graph/dist/src/report.d.ts.map +0 -1
  430. package/bundled-graph/dist/src/report.js +0 -214
  431. package/bundled-graph/dist/src/report.js.map +0 -1
  432. package/bundled-graph/dist/src/types.d.ts +0 -124
  433. package/bundled-graph/dist/src/types.d.ts.map +0 -1
  434. package/bundled-graph/dist/src/types.js +0 -2
  435. package/bundled-graph/dist/src/types.js.map +0 -1
  436. package/bundled-graph/dist/src/visualize.d.ts +0 -4
  437. package/bundled-graph/dist/src/visualize.d.ts.map +0 -1
  438. package/bundled-graph/dist/src/visualize.js +0 -574
  439. package/bundled-graph/dist/src/visualize.js.map +0 -1
  440. package/bundled-graph/dist/tsconfig.tsbuildinfo +0 -1
  441. package/dist/src/ui/dashboard-v2.html +0 -5316
@@ -251,6 +251,48 @@ function bindServer(server, port) {
251
251
  * @param {boolean} [options.openBrowser=true] - Whether to open the dashboard in the default browser.
252
252
  * @returns {Promise<{port: number, url: string, server: http.Server}>}
253
253
  */
254
+ /**
255
+ * Resolve a Claude project slug back to the real filesystem path.
256
+ * Slugs are created by replacing all '/' with '-', so paths containing
257
+ * hyphens (like agent-f/agf-accounting) are ambiguous. This function
258
+ * uses a greedy BFS over the real filesystem to find the correct path.
259
+ * Falls back to cwd in session files, then to direct slug replacement.
260
+ */
261
+ function resolveSlugToPath(slug, projDir) {
262
+ // 1. Try filesystem BFS (most reliable)
263
+ const parts = slug.replace(/^-/, '').split('-');
264
+ function tryPaths(idx, current) {
265
+ if (idx === parts.length) return fs.existsSync(current) ? current : null;
266
+ // Option A: next part is a new path component
267
+ const asDir = path.join(current, parts[idx]);
268
+ const r1 = tryPaths(idx + 1, asDir);
269
+ if (r1) return r1;
270
+ // Option B: combine with hyphen into current basename
271
+ if (current !== '/') {
272
+ const combined = path.join(path.dirname(current), path.basename(current) + '-' + parts[idx]);
273
+ const r2 = tryPaths(idx + 1, combined);
274
+ if (r2) return r2;
275
+ }
276
+ return null;
277
+ }
278
+ const fsResolved = parts.length ? tryPaths(1, '/' + parts[0]) : null;
279
+ if (fsResolved) return fsResolved;
280
+
281
+ // 2. Try reading cwd from a session file
282
+ try {
283
+ const sfiles = fs.readdirSync(projDir).filter(f => f.endsWith('.jsonl'));
284
+ for (const sf of sfiles) {
285
+ try {
286
+ const line = fs.readFileSync(path.join(projDir, sf), 'utf-8').split('\n').find(l => l.includes('"cwd"'));
287
+ if (line) { const m = line.match(/"cwd"\s*:\s*"([^"]+)"/); if (m?.[1]) return m[1]; }
288
+ } catch {}
289
+ }
290
+ } catch {}
291
+
292
+ // 3. Dumb fallback (known-broken for hyphenated dirs, but last resort)
293
+ return slug.replace(/-/g, '/');
294
+ }
295
+
254
296
  export async function startServer({ port = 4242, projectDir, openBrowser = true } = {}) {
255
297
  const server = http.createServer(async (req, res) => {
256
298
  const url = req.url.split('?')[0];
@@ -269,17 +311,10 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
269
311
  return;
270
312
  }
271
313
 
272
- // ----------------------------------------------------------------- GET /v2
314
+ // ----------------------------------------------------------------- GET /v2 (alias → /)
273
315
  if (req.method === 'GET' && url === '/v2') {
274
- const htmlPath = path.join(__dirname, 'dashboard-v2.html');
275
- try {
276
- const html = fs.readFileSync(htmlPath, 'utf8');
277
- res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
278
- res.end(html);
279
- } catch (err) {
280
- res.writeHead(500, { 'Content-Type': 'text/plain' });
281
- res.end(`Failed to load dashboard-v2.html: ${err.message}`);
282
- }
316
+ res.writeHead(301, { 'Location': '/' });
317
+ res.end();
283
318
  return;
284
319
  }
285
320
 
@@ -601,7 +636,7 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
601
636
  const projectCosts = [];
602
637
  for (const slug of slugDirs) {
603
638
  const projDir = path.join(projectsBase, slug);
604
- const projPath = '/' + slug.replace(/^-/, '').replace(/-/g, '/');
639
+ const projPath = resolveSlugToPath(slug, projDir);
605
640
  let sessionFiles = [];
606
641
  try { sessionFiles = fs.readdirSync(projDir).filter(f => f.endsWith('.jsonl')).map(f => path.join(projDir, f)); } catch {}
607
642
  if (!sessionFiles.length) continue;
@@ -635,9 +670,8 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
635
670
  try { slugDirs = fs.readdirSync(projectsBase, { withFileTypes: true }).filter(e => e.isDirectory()).map(e => e.name); } catch {}
636
671
  const projects = slugDirs.map(slug => {
637
672
  const projDir = path.join(projectsBase, slug);
638
- // convert slug back to path: replace leading - and then each - that was /
639
- const projPath = slug.replace(/-/g, '/');
640
- const name = slug.split('-').filter(Boolean).pop() || slug;
673
+ const projPath = resolveSlugToPath(slug, projDir);
674
+ const name = projPath.split('/').filter(Boolean).pop() || slug.split('-').filter(Boolean).pop() || slug;
641
675
  let sessionCount = 0; let lastActivity = 0; let memoryCount = 0;
642
676
  try {
643
677
  const files = fs.readdirSync(projDir).filter(f => f.endsWith('.jsonl'));
@@ -850,6 +884,79 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
850
884
  return;
851
885
  }
852
886
 
887
+ // ------------------------------------------------- GET /api/routing-feedback
888
+ if (req.method === 'GET' && url === '/api/routing-feedback') {
889
+ try {
890
+ const qs = new URL(req.url, 'http://localhost').searchParams;
891
+ const d = path.resolve(qs.get('dir') || projectDir || process.cwd());
892
+ const feedbackPath = path.join(d, '.monomind', 'routing-feedback.jsonl');
893
+ let rows = [];
894
+ if (fs.existsSync(feedbackPath)) {
895
+ const raw = fs.readFileSync(feedbackPath, 'utf-8');
896
+ rows = raw.split('\n').filter(Boolean).map(l => { try { return JSON.parse(l); } catch { return null; } }).filter(Boolean);
897
+ }
898
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
899
+ res.end(JSON.stringify(rows));
900
+ } catch (err) {
901
+ res.writeHead(500, { 'Content-Type': 'application/json' });
902
+ res.end(JSON.stringify({ error: err.message }));
903
+ }
904
+ return;
905
+ }
906
+
907
+ // ---------------------------------------------------- GET /api/memory/stats
908
+ if (req.method === 'GET' && url === '/api/memory/stats') {
909
+ try {
910
+ const qs = new URL(req.url, 'http://localhost').searchParams;
911
+ const d = path.resolve(qs.get('dir') || projectDir || process.cwd());
912
+ const slug = d.replace(/\//g, '-');
913
+ const memDir = path.join(os.homedir(), '.claude', 'projects', slug, 'memory');
914
+
915
+ let total = 0, namespaces = 0, size = 0, lastWrite = null;
916
+ const byType = {};
917
+ if (fs.existsSync(memDir)) {
918
+ const files = fs.readdirSync(memDir).filter(f => f.endsWith('.md'));
919
+ total = files.length;
920
+ namespaces = files.length; // each .md file is a memory namespace
921
+ files.forEach(f => {
922
+ const fp = path.join(memDir, f);
923
+ try {
924
+ const st = fs.statSync(fp);
925
+ size += st.size;
926
+ if (!lastWrite || st.mtimeMs > lastWrite) lastWrite = st.mtimeMs;
927
+ } catch {}
928
+ const type = f.replace('.md', '');
929
+ byType[type] = (byType[type] || 0) + 1;
930
+ });
931
+ }
932
+
933
+ // Check for AgentDB / HNSW / RVF backends
934
+ const dbPath = path.join(d, '.monomind', 'agentdb.db');
935
+ const hnswPath = path.join(d, '.monomind', 'hnsw.index');
936
+ const rvfPath = path.join(d, '.monomind', 'memory.rvf');
937
+
938
+ const stats = {
939
+ total,
940
+ count: total,
941
+ namespaces,
942
+ ns: Object.keys(byType).length,
943
+ size,
944
+ byType,
945
+ hnsw: fs.existsSync(hnswPath),
946
+ agentdb: fs.existsSync(dbPath),
947
+ rvf: fs.existsSync(rvfPath),
948
+ lastWrite,
949
+ memDir,
950
+ };
951
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
952
+ res.end(JSON.stringify({ stats }));
953
+ } catch (err) {
954
+ res.writeHead(500, { 'Content-Type': 'application/json' });
955
+ res.end(JSON.stringify({ error: err.message }));
956
+ }
957
+ return;
958
+ }
959
+
853
960
  // ---------------------------------------------------------- GET /api/loops
854
961
  if (req.method === 'GET' && url === '/api/loops') {
855
962
  try {
@@ -1165,7 +1272,8 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1165
1272
 
1166
1273
  // Generate HTML on-the-fly from SQLite DB using the improved toHtml export
1167
1274
  if (fs.existsSync(dbPath)) {
1168
- const { openDb, closeDb, toHtml } = await import('@monoes/monograph');
1275
+ const { openDb, closeDb } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/db.js');
1276
+ const { toHtml } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/export/html.js');
1169
1277
  const db = openDb(dbPath);
1170
1278
  let html;
1171
1279
  try {
@@ -1225,7 +1333,7 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1225
1333
  let report = null, exists = false, stats = null;
1226
1334
  if (fs.existsSync(dbPath)) {
1227
1335
  exists = true;
1228
- const { openDb, closeDb } = await import('@monoes/monograph');
1336
+ const { openDb, closeDb } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/db.js');
1229
1337
  const db = openDb(dbPath);
1230
1338
  try {
1231
1339
  const nodeCount = db.prepare('SELECT COUNT(*) AS c FROM nodes').get().c;
@@ -1268,7 +1376,7 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1268
1376
  const dbPath = path.join(d, '.monomind', 'monograph.db');
1269
1377
  let nodes = [], edges = [];
1270
1378
  if (fs.existsSync(dbPath)) {
1271
- const { openDb, closeDb } = await import('@monoes/monograph');
1379
+ const { openDb, closeDb } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/db.js');
1272
1380
  const db = openDb(dbPath);
1273
1381
  try {
1274
1382
  const nodeLimit = Math.min(parseInt(qs.get('limit') || '500', 10), 5000);
@@ -1406,7 +1514,8 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1406
1514
 
1407
1515
  // Run doc parsing in background
1408
1516
  (async () => {
1409
- const { openDb, closeDb, isFileCached, updateFileCache, hashFileContent } = await import('@monoes/monograph');
1517
+ const { openDb, closeDb } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/db.js');
1518
+ const { isFileCached, updateFileCache, hashFileContent } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/file-cache.js');
1410
1519
  const { readFileSync, readdirSync, statSync } = fs;
1411
1520
 
1412
1521
  const docExts = new Set(['.md', '.mdx', '.txt', '.rst']);
@@ -1569,7 +1678,7 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1569
1678
  const dbPath = path.join(d, '.monomind', 'monograph.db');
1570
1679
  if (!id) { res.writeHead(400); res.end(JSON.stringify({ error: 'Missing ?id=' })); return; }
1571
1680
  if (!fs.existsSync(dbPath)) { res.writeHead(404); res.end(JSON.stringify({ error: 'Graph not built' })); return; }
1572
- const { openDb, closeDb } = await import('@monoes/monograph');
1681
+ const { openDb, closeDb } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/db.js');
1573
1682
  const db = openDb(dbPath);
1574
1683
  let content = '', filePath = '', startLine = 0, endLine = 0, language = '', name = '', type = '';
1575
1684
  try {
@@ -1619,7 +1728,8 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1619
1728
  const dbPath = path.join(d, '.monomind', 'monograph.db');
1620
1729
  if (!q) { res.writeHead(400); res.end(JSON.stringify({ error: 'Missing ?q=' })); return; }
1621
1730
  if (!fs.existsSync(dbPath)) { res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }); res.end(JSON.stringify({ nodes: [] })); return; }
1622
- const { openDb, closeDb, ftsSearch } = await import('@monoes/monograph');
1731
+ const { openDb, closeDb } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/db.js');
1732
+ const { ftsSearch } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/fts-store.js');
1623
1733
  const db = openDb(dbPath);
1624
1734
  let nodes = [];
1625
1735
  try {
@@ -1650,7 +1760,7 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1650
1760
  const d = path.resolve(dir || process.cwd());
1651
1761
  const dbPath = path.join(d, '.monomind', 'monograph.db');
1652
1762
  if (!id || !fs.existsSync(dbPath)) { res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }); res.end(JSON.stringify({ related: [] })); return; }
1653
- const { openDb, closeDb } = await import('@monoes/monograph');
1763
+ const { openDb, closeDb } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/db.js');
1654
1764
  const db = openDb(dbPath);
1655
1765
  const related = [];
1656
1766
  try {
@@ -1691,7 +1801,7 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1691
1801
  const d = path.resolve(dir || process.cwd());
1692
1802
  const dbPath = path.join(d, '.monomind', 'monograph.db');
1693
1803
  if (!id || !fs.existsSync(dbPath)) { res.writeHead(404); res.end(JSON.stringify({ error: 'Not found' })); return; }
1694
- const { openDb, closeDb } = await import('@monoes/monograph');
1804
+ const { openDb, closeDb } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/db.js');
1695
1805
  const db = openDb(dbPath);
1696
1806
  let result = { node: null, content: '', neighbors: [], markdown: '' };
1697
1807
  try {
@@ -1751,7 +1861,8 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1751
1861
  const dbPath = path.join(d, '.monomind', 'monograph.db');
1752
1862
  if (!q) { res.writeHead(400); res.end(JSON.stringify({ error: 'Missing ?q= parameter' })); return; }
1753
1863
  if (!fs.existsSync(dbPath)) { res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }); res.end(JSON.stringify({ success: false, result: 'Graph not built yet. Run: monomind monograph build' })); return; }
1754
- const { openDb, closeDb, ftsSearch } = await import('@monoes/monograph');
1864
+ const { openDb, closeDb } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/db.js');
1865
+ const { ftsSearch } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/fts-store.js');
1755
1866
  const db = openDb(dbPath);
1756
1867
  let result = '';
1757
1868
  try {
@@ -1787,7 +1898,8 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1787
1898
  const dbPath = path.join(d, '.monomind', 'monograph.db');
1788
1899
  if (!nodeQ) { res.writeHead(400); res.end(JSON.stringify({ error: 'Missing ?node= parameter' })); return; }
1789
1900
  if (!fs.existsSync(dbPath)) { res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }); res.end(JSON.stringify({ success: false, explanation: 'Graph not built yet. Run: monomind monograph build' })); return; }
1790
- const { openDb, closeDb, ftsSearch } = await import('@monoes/monograph');
1901
+ const { openDb, closeDb } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/db.js');
1902
+ const { ftsSearch } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/fts-store.js');
1791
1903
  const db = openDb(dbPath);
1792
1904
  let explanation = '';
1793
1905
  try {
@@ -1829,7 +1941,33 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1829
1941
  const dbPath = path.join(d, '.monomind', 'monograph.db');
1830
1942
  if (!from || !to) { res.writeHead(400); res.end(JSON.stringify({ error: 'Missing ?from= and ?to= parameters' })); return; }
1831
1943
  if (!fs.existsSync(dbPath)) { res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }); res.end(JSON.stringify({ success: false, path: 'Graph not built yet.' })); return; }
1832
- const { openDb, closeDb, getShortestPath, ftsSearch } = await import('@monoes/monograph');
1944
+ // Import only graphology-free storage modules to avoid broken graphology dep
1945
+ const { openDb, closeDb } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/db.js');
1946
+ const { ftsSearch } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/fts-store.js');
1947
+ // SQL-based BFS for shortest path (avoids graphology)
1948
+ const getShortestPath = (db, fromId, toId, maxDepth = 6) => {
1949
+ if (fromId === toId) return [fromId];
1950
+ const visited = new Set([fromId]);
1951
+ let frontier = [[fromId]];
1952
+ for (let depth = 0; depth < maxDepth; depth++) {
1953
+ const next = [];
1954
+ for (const chain of frontier) {
1955
+ const cur = chain[chain.length - 1];
1956
+ const neighbors = db.prepare('SELECT target_id AS id FROM edges WHERE source_id=? UNION SELECT source_id AS id FROM edges WHERE target_id=?').all(cur, cur);
1957
+ for (const { id } of neighbors) {
1958
+ if (!visited.has(id)) {
1959
+ const newChain = [...chain, id];
1960
+ if (id === toId) return newChain;
1961
+ visited.add(id);
1962
+ next.push(newChain);
1963
+ }
1964
+ }
1965
+ }
1966
+ if (!next.length) break;
1967
+ frontier = next;
1968
+ }
1969
+ return null;
1970
+ };
1833
1971
  const db = openDb(dbPath);
1834
1972
  let pathResult = '';
1835
1973
  try {
@@ -1924,13 +2062,41 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
1924
2062
  const ok = (data) => { json(res); res.end(JSON.stringify({ content: [{ type: 'text', text: typeof data === 'string' ? data : JSON.stringify(data, null, 2) }] })); };
1925
2063
  const err = (msg) => { json(res); res.end(JSON.stringify({ error: msg })); };
1926
2064
  try {
1927
- const { tool, input = {} } = JSON.parse(body);
2065
+ const { tool, input = {}, args = {} } = JSON.parse(body);
1928
2066
  const qs2 = new URL(req.url, 'http://localhost').searchParams;
1929
- const dir2 = qs2.get('dir') || projectDir;
2067
+ // dir can come from: URL query string, body.args.dir, body.input.dir, or server default
2068
+ const dir2 = qs2.get('dir') || args.dir || input.dir || projectDir;
1930
2069
  const d2 = path.resolve(dir2 || process.cwd());
1931
2070
  const dbPath2 = path.join(d2, '.monomind', 'monograph.db');
1932
2071
  if (!fs.existsSync(dbPath2)) { err('monograph.db not found — run monograph build first'); return; }
1933
- const { openDb, closeDb, ftsSearch, getShortestPath, countNodes, countEdges } = await import('@monoes/monograph');
2072
+ // Import only graphology-free storage modules to avoid broken graphology dep
2073
+ const { openDb, closeDb } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/db.js');
2074
+ const { ftsSearch } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/fts-store.js');
2075
+ const { countNodes } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/node-store.js');
2076
+ const { countEdges } = await import('/Users/morteza/Desktop/tools/monomind/packages/@monomind/monograph/dist/src/storage/edge-store.js');
2077
+ const getShortestPath = (db, fromId, toId, maxDepth = 6) => {
2078
+ if (fromId === toId) return [fromId];
2079
+ const visited = new Set([fromId]);
2080
+ let frontier = [[fromId]];
2081
+ for (let depth = 0; depth < maxDepth; depth++) {
2082
+ const next = [];
2083
+ for (const chain of frontier) {
2084
+ const cur = chain[chain.length - 1];
2085
+ const neighbors = db.prepare('SELECT target_id AS id FROM edges WHERE source_id=? UNION SELECT source_id AS id FROM edges WHERE target_id=?').all(cur, cur);
2086
+ for (const { id } of neighbors) {
2087
+ if (!visited.has(id)) {
2088
+ const newChain = [...chain, id];
2089
+ if (id === toId) return newChain;
2090
+ visited.add(id);
2091
+ next.push(newChain);
2092
+ }
2093
+ }
2094
+ }
2095
+ if (!next.length) break;
2096
+ frontier = next;
2097
+ }
2098
+ return null;
2099
+ };
1934
2100
  const db2 = openDb(dbPath2);
1935
2101
  try {
1936
2102
  if (tool === 'monograph_stats') {
@@ -2181,6 +2347,145 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
2181
2347
  else { ok(`Author Analytics (by commit count):\n${'─'.repeat(50)}\n${log.trim().split('\n').map(l => { const m = l.trim().match(/^(\d+)\s+(.+)$/); return m ? ` ${m[2].padEnd(45)} ${m[1]} commits` : l; }).join('\n')}`); }
2182
2348
  } catch { ok('Author analytics requires git. Ensure this directory is a git repository.'); }
2183
2349
 
2350
+ } else if (tool === 'monograph_reachability') {
2351
+ // Files with no inbound edges (nothing imports them)
2352
+ const allNodes = db2.prepare(`SELECT id, name, file_path FROM nodes WHERE label IN ('File','Module') LIMIT 5000`).all();
2353
+ const inboundSet = new Set(db2.prepare(`SELECT DISTINCT target_id FROM edges`).all().map(r => r.target_id));
2354
+ const unreachable = allNodes.filter(n => !inboundSet.has(n.id)).slice(0, 40);
2355
+ const outdeg = db2.prepare(`SELECT source_id, COUNT(*) as c FROM edges GROUP BY source_id`);
2356
+ const degMap = {};
2357
+ for (const r of outdeg.all()) degMap[r.source_id] = r.c;
2358
+ if (!unreachable.length) { ok('All files have at least one inbound reference.'); }
2359
+ else ok(`Unreachable Files (${unreachable.length} of ${allNodes.length} total):\n${'─'.repeat(50)}\n${unreachable.slice(0,30).map(n => ` ${n.name || n.id.split('/').pop()} (imports ${degMap[n.id]||0} others)\n ${n.file_path||''}`).join('\n\n')}`);
2360
+
2361
+ } else if (tool === 'monograph_vital_signs_snapshot') {
2362
+ // Same as health_score — kept for backward compatibility
2363
+ const n = db2.prepare('SELECT COUNT(*) as c FROM nodes').get().c;
2364
+ const e = db2.prepare('SELECT COUNT(*) as c FROM edges').get().c;
2365
+ const dead = db2.prepare(`SELECT COUNT(*) as c FROM nodes n WHERE NOT EXISTS (SELECT 1 FROM edges WHERE source_id=n.id OR target_id=n.id)`).get().c;
2366
+ const hubs = db2.prepare(`SELECT COUNT(*) as c FROM (SELECT source_id FROM edges GROUP BY source_id HAVING COUNT(*)>20)`).get().c;
2367
+ const density = n > 1 ? (e / (n * (n-1))).toFixed(6) : '0';
2368
+ const score = Math.max(0, Math.min(100, Math.round(100 - (dead/Math.max(n,1)*30) - (hubs/Math.max(n,1)*500))));
2369
+ ok(`Vital Signs — ${new Date().toISOString()}\n${'─'.repeat(50)}\n Health Score: ${score}/100 ${score>=80?'✓ OK':score>=60?'⚠ Warning':'✗ Critical'}\n Nodes: ${n}\n Edges: ${e}\n Density: ${density}\n Dead symbols: ${dead} (${(dead/Math.max(n,1)*100).toFixed(1)}%)\n Hub nodes: ${hubs} nodes with >20 edges`);
2370
+
2371
+ } else if (tool === 'monograph_circular_deps') {
2372
+ // Find import cycles using iterative DFS
2373
+ const limit = Math.min(parseInt(input.limit||'10'), 20);
2374
+ const importEdges = db2.prepare(`SELECT source_id, target_id FROM edges WHERE relation IN ('IMPORTS','REQUIRES','USES','DEPENDS_ON') LIMIT 50000`).all();
2375
+ const adj = {};
2376
+ for (const e of importEdges) { (adj[e.source_id] = adj[e.source_id]||[]).push(e.target_id); }
2377
+ const cycles = [];
2378
+ const visited = new Set(), inStack = new Set();
2379
+ function dfs(node, path) {
2380
+ if (cycles.length >= limit) return;
2381
+ if (inStack.has(node)) {
2382
+ const cycleStart = path.indexOf(node);
2383
+ if (cycleStart >= 0) cycles.push(path.slice(cycleStart).concat(node));
2384
+ return;
2385
+ }
2386
+ if (visited.has(node)) return;
2387
+ visited.add(node); inStack.add(node); path.push(node);
2388
+ for (const nb of (adj[node]||[])) dfs(nb, path);
2389
+ path.pop(); inStack.delete(node);
2390
+ }
2391
+ for (const node of Object.keys(adj).slice(0, 2000)) dfs(node, []);
2392
+ const getName = id => id.split('/').slice(-2).join('/');
2393
+ if (!cycles.length) ok(`No circular dependencies found among ${Object.keys(adj).length} nodes with import edges.`);
2394
+ else ok(`Circular Dependencies (${cycles.length} found):\n${'─'.repeat(50)}\n${cycles.slice(0,limit).map((c,i) => ` ${i+1}. ${c.map(getName).join(' → ')}`).join('\n')}`);
2395
+
2396
+ } else if (tool === 'monograph_largest_files') {
2397
+ const limit2 = Math.min(parseInt(input.limit||'25'), 50);
2398
+ const rows = db2.prepare(`SELECT file_path, MAX(end_line) as lines, COUNT(*) as symbols FROM nodes WHERE file_path IS NOT NULL AND end_line IS NOT NULL AND end_line > 0 GROUP BY file_path ORDER BY lines DESC LIMIT ${limit2}`).all();
2399
+ if (!rows.length) ok('No line-count data available. Ensure the index was built with source parsing enabled.');
2400
+ else ok(`Largest Files by Line Count:\n${'─'.repeat(50)}\n${rows.map((r,i) => ` ${String(i+1).padStart(2)}. ${r.lines.toString().padStart(5)} lines ${r.symbols} symbols ${r.file_path.split('/').slice(-2).join('/')}`).join('\n')}`);
2401
+
2402
+ } else if (tool === 'monograph_coupling_balance') {
2403
+ // Fan-out (what this file uses) vs Fan-in (what uses this file)
2404
+ const limit3 = Math.min(parseInt(input.limit||'20'), 40);
2405
+ const fanOut = db2.prepare(`SELECT source_id, COUNT(*) as c FROM edges GROUP BY source_id`).all();
2406
+ const fanIn = db2.prepare(`SELECT target_id, COUNT(*) as c FROM edges GROUP BY target_id`).all();
2407
+ const outMap = {}, inMap = {};
2408
+ for (const r of fanOut) outMap[r.source_id] = r.c;
2409
+ for (const r of fanIn) inMap[r.target_id] = r.c;
2410
+ const allIds = new Set([...Object.keys(outMap), ...Object.keys(inMap)]);
2411
+ const nodes3 = db2.prepare(`SELECT id, name, file_path FROM nodes WHERE label='File' LIMIT 10000`).all();
2412
+ const fileSet = new Set(nodes3.map(n => n.id));
2413
+ const entries = [...allIds].filter(id => fileSet.has(id)).map(id => {
2414
+ const o = outMap[id]||0, i = inMap[id]||0;
2415
+ const n = nodes3.find(x=>x.id===id);
2416
+ return { name: n?.name || id.split('/').pop(), path: n?.file_path||'', out: o, inn: i, ratio: i > 0 ? (o/i).toFixed(1) : '∞' };
2417
+ }).filter(x => x.out > 0 || x.inn > 0).sort((a,b) => (b.out+b.inn) - (a.out+a.inn)).slice(0, limit3);
2418
+ ok(`Coupling Balance (Fan-out vs Fan-in, top ${limit3} by activity):\n${'─'.repeat(60)}\n ${'File'.padEnd(35)} Out In Ratio\n${'─'.repeat(60)}\n${entries.map(e => ` ${e.name.slice(0,35).padEnd(35)} ${String(e.out).padStart(3)} ${String(e.inn).padStart(2)} ${e.ratio}`).join('\n')}`);
2419
+
2420
+ } else if (tool === 'monograph_dead_exports') {
2421
+ // Exported symbols with zero inbound edges
2422
+ const exported = db2.prepare(`SELECT id, name, label, file_path FROM nodes WHERE is_exported=1 LIMIT 10000`).all();
2423
+ const inbound = new Set(db2.prepare(`SELECT DISTINCT target_id FROM edges`).all().map(r => r.target_id));
2424
+ const dead2 = exported.filter(n => !inbound.has(n.id));
2425
+ if (!dead2.length) ok('No dead exports found — all exported symbols have at least one inbound reference.');
2426
+ else ok(`Dead Exports — exported but never imported (${dead2.length} of ${exported.length} exported symbols):\n${'─'.repeat(50)}\n${dead2.slice(0,30).map(n => ` ${n.label.padEnd(12)} ${n.name} → ${(n.file_path||'').split('/').slice(-2).join('/')}`).join('\n')}`);
2427
+
2428
+ } else if (tool === 'monograph_language_breakdown') {
2429
+ const rows2 = db2.prepare(`SELECT language, COUNT(*) as c FROM nodes WHERE language IS NOT NULL AND language != '' GROUP BY language ORDER BY c DESC`).all();
2430
+ if (!rows2.length) ok('No language metadata available in this graph index.');
2431
+ else {
2432
+ const total2 = rows2.reduce((s,r) => s+r.c, 0);
2433
+ const maxC = rows2[0].c;
2434
+ ok(`Language Breakdown:\n${'─'.repeat(50)}\n${rows2.map(r => { const bar = '█'.repeat(Math.round(r.c/maxC*20)); const pct = (r.c/total2*100).toFixed(1); return ` ${r.language.padEnd(15)} ${bar.padEnd(20)} ${String(r.c).padStart(6)} (${pct}%)`; }).join('\n')}\n\n Total nodes: ${total2}`);
2435
+ }
2436
+
2437
+ } else if (tool === 'monograph_instability') {
2438
+ // Robert Martin's Instability = Ce / (Ca + Ce)
2439
+ // Ca = afferent coupling (in-degree), Ce = efferent coupling (out-degree)
2440
+ const limit4 = Math.min(parseInt(input.limit||'25'), 50);
2441
+ const outRows = db2.prepare(`SELECT source_id, COUNT(*) as c FROM edges GROUP BY source_id`).all();
2442
+ const inRows = db2.prepare(`SELECT target_id, COUNT(*) as c FROM edges GROUP BY target_id`).all();
2443
+ const Ce = {}, Ca = {};
2444
+ for (const r of outRows) Ce[r.source_id] = r.c;
2445
+ for (const r of inRows) Ca[r.target_id] = r.c;
2446
+ const fileNodes = db2.prepare(`SELECT id, name, file_path FROM nodes WHERE label='File' LIMIT 10000`).all();
2447
+ const entries4 = fileNodes.map(n => {
2448
+ const ca = Ca[n.id]||0, ce = Ce[n.id]||0;
2449
+ const total = ca + ce;
2450
+ const inst = total > 0 ? ce / total : 0;
2451
+ return { name: n.name||n.id.split('/').pop(), ca, ce, inst };
2452
+ }).filter(x => x.ca+x.ce > 0).sort((a,b) => b.inst - a.inst);
2453
+ const risky = entries4.filter(x => x.inst > 0.7 && x.ca > 3);
2454
+ const stable = entries4.filter(x => x.inst < 0.2 && x.ce > 3);
2455
+ ok(`Instability Index (Ce÷(Ca+Ce), 0=stable 1=unstable):\n${'─'.repeat(60)}\n\n ⚠ High instability + high dependents (blast radius risk):\n${risky.slice(0,10).map(x => ` ${x.name.slice(0,40).padEnd(40)} I=${x.inst.toFixed(2)} Ca=${x.ca} Ce=${x.ce}`).join('\n')||' none'}\n\n ✓ Stable (low instability, many dependents on them):\n${stable.slice(0,8).map(x => ` ${x.name.slice(0,40).padEnd(40)} I=${x.inst.toFixed(2)} Ca=${x.ca} Ce=${x.ce}`).join('\n')||' none'}\n\n Total files analyzed: ${entries4.length}`);
2456
+
2457
+ } else if (tool === 'monograph_churn_hotspots') {
2458
+ // Combines git churn frequency with structural complexity (out-degree)
2459
+ const limit5 = Math.min(parseInt(input.limit||'15'), 30);
2460
+ const { execSync: execS2 } = await import('child_process');
2461
+ let churnMap = {};
2462
+ try {
2463
+ const since = input.since || '6 months ago';
2464
+ const log2 = execS2(`git log --since="${since}" --name-only --format="" -- . 2>/dev/null | grep -v '^$' | sort | uniq -c | sort -rn | head -200`, { cwd: d2, encoding: 'utf-8', timeout: 8000 });
2465
+ for (const line of log2.trim().split('\n')) {
2466
+ const m = line.trim().match(/^(\d+)\s+(.+)$/);
2467
+ if (m) churnMap[m[2]] = parseInt(m[1]);
2468
+ }
2469
+ } catch {}
2470
+ if (!Object.keys(churnMap).length) { ok('No git history found — churn analysis requires a git repository.'); }
2471
+ else {
2472
+ const outDeg = db2.prepare(`SELECT source_id, COUNT(*) as c FROM edges GROUP BY source_id`).all();
2473
+ const degMap2 = {};
2474
+ for (const r of outDeg) degMap2[r.source_id] = r.c;
2475
+ const fileNodes2 = db2.prepare(`SELECT id, name, file_path FROM nodes WHERE label='File' LIMIT 10000`).all();
2476
+ const maxChurn = Math.max(...Object.values(churnMap), 1);
2477
+ const maxDeg2 = Math.max(...Object.values(degMap2), 1);
2478
+ const scored = fileNodes2.map(n => {
2479
+ const fp = n.file_path || '';
2480
+ const churn = churnMap[fp] || Object.entries(churnMap).find(([k]) => fp.endsWith(k))?.[1] || 0;
2481
+ const deg = degMap2[n.id] || 0;
2482
+ const score2 = (churn/maxChurn * 0.6) + (deg/maxDeg2 * 0.4);
2483
+ return { name: n.name||fp.split('/').pop(), fp, churn, deg, score: score2 };
2484
+ }).filter(x => x.churn > 0 || x.deg > 5).sort((a,b) => b.score - a.score).slice(0, limit5);
2485
+ if (!scored.length) ok('No files matched both churn and complexity criteria.');
2486
+ else ok(`Churn × Complexity Hotspots (60% churn weight + 40% coupling weight):\n${'─'.repeat(60)}\n ${'File'.padEnd(38)} Churn Deps Score\n${'─'.repeat(60)}\n${scored.map(x => ` ${x.name.slice(0,38).padEnd(38)} ${String(x.churn).padStart(5)} ${String(x.deg).padStart(4)} ${(x.score*100).toFixed(0)}%`).join('\n')}\n\n Analyzed: ${scored.length} hotspot candidates from last ${input.since||'6 months'}`);
2487
+ }
2488
+
2184
2489
  } else {
2185
2490
  ok(`Tool "${tool}" not implemented in control panel`);
2186
2491
  }
@@ -2938,7 +3243,7 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
2938
3243
  Object.values(agents).forEach(a => {
2939
3244
  if (a.status === 'running') agentsRunning++;
2940
3245
  else agentsIdle++;
2941
- budgetUsedTokens += (a.tokens_used || 0);
3246
+ budgetUsedTokens += (a.tokens_used || ((a.tokens_in || 0) + (a.tokens_out || 0)));
2942
3247
  });
2943
3248
  } catch(_) {}
2944
3249
 
@@ -2977,13 +3282,16 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
2977
3282
  res.end(JSON.stringify({
2978
3283
  agents_running: agentsRunning,
2979
3284
  agents_idle: agentsIdle,
3285
+ agents_active: agentsRunning,
2980
3286
  open_issues: openIssues,
2981
3287
  in_progress_issues: inProgressIssues,
3288
+ tasks_pending: openIssues + inProgressIssues,
2982
3289
  budget_used_tokens: budgetUsedTokens,
2983
3290
  budget_max_tokens: budgetMaxTokens,
2984
3291
  budget_used_pct: budgetUsedPct,
2985
3292
  run_success_rate_7d: successRate,
2986
3293
  total_runs_7d: totalRuns,
3294
+ errors: [],
2987
3295
  }));
2988
3296
  } catch(_) { res.writeHead(500); res.end('{}'); }
2989
3297
  return;
@@ -3174,18 +3482,25 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
3174
3482
  const readJsonSafe = (f) => { try { return JSON.parse(fs.readFileSync(f, 'utf8')); } catch(_) { return null; } };
3175
3483
  const data = readJsonSafe(path.join(base, `${orgName}-approvals.json`)) || { approvals: [] };
3176
3484
  const approvals = (data.approvals || [])
3177
- .sort((a, b) => new Date(b.createdAt || 0) - new Date(a.createdAt || 0))
3485
+ .sort((a, b) => new Date(b.createdAt || b.created_at || b.requested_at || 0) - new Date(a.createdAt || a.created_at || a.requested_at || 0))
3178
3486
  .map(a => ({
3179
3487
  id: a.id,
3180
3488
  title: a.title || a.action || null,
3489
+ action: a.action || a.title || null,
3490
+ description: a.description || a.action || a.title || null,
3181
3491
  status: a.status || 'pending',
3182
3492
  agentId: a.agentId || a.agent_id || null,
3183
3493
  agentTitle: a.agentTitle || null,
3494
+ requester: a.requester || a.agentTitle || a.agent_id || a.agentId || null,
3495
+ agent: a.agent || a.agent_id || a.agentId || null,
3184
3496
  payload: a.payload || null,
3185
- createdAt: a.createdAt || null,
3497
+ risk_level: a.risk_level || 'medium',
3498
+ created_at: a.created_at || a.createdAt || a.requested_at || null,
3499
+ createdAt: a.createdAt || a.created_at || a.requested_at || null,
3186
3500
  updatedAt: a.updatedAt || null,
3187
3501
  resolvedAt: a.resolvedAt || null,
3188
3502
  resolvedBy: a.resolvedBy || null,
3503
+ ts: a.ts || null,
3189
3504
  }));
3190
3505
  const pending = approvals.filter(a => a.status === 'pending' || a.status === 'revision_requested').length;
3191
3506
  res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
@@ -3194,6 +3509,49 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
3194
3509
  return;
3195
3510
  }
3196
3511
 
3512
+ // POST /api/org/:name/approvals/:id — approve or reject a pending approval request
3513
+ // Body: { action: "approve" | "reject" | "revision_requested" }
3514
+ if (req.method === 'POST' && url.match(/^\/api\/org\/[a-z0-9][a-z0-9_-]{0,63}\/approvals\/[^/]+$/i)) {
3515
+ let body = '';
3516
+ for await (const chunk of req) body += chunk;
3517
+ try {
3518
+ const parts = url.split('/');
3519
+ const orgName = decodeURIComponent(parts[3]);
3520
+ const approvalId = decodeURIComponent(parts[5]);
3521
+ if (orgName.length > 64 || !/^[a-z0-9][a-z0-9_-]*$/i.test(orgName)) { res.writeHead(400); res.end('Invalid org name'); return; }
3522
+ if (!approvalId) { res.writeHead(400); res.end('{"error":"approval id required"}'); return; }
3523
+ const parsed = JSON.parse(body);
3524
+ const action = parsed.action;
3525
+ if (!['approve', 'reject', 'revision_requested'].includes(action)) {
3526
+ res.writeHead(400); res.end('{"error":"action must be approve, reject, or revision_requested"}'); return;
3527
+ }
3528
+ const base = path.join(projectDir || process.cwd(), '.monomind', 'orgs');
3529
+ const approvalsFile = path.join(base, `${orgName}-approvals.json`);
3530
+ let data = { approvals: [] };
3531
+ try { data = JSON.parse(fs.readFileSync(approvalsFile, 'utf8')); } catch(_) {}
3532
+ const idx = (data.approvals || []).findIndex(a => a.id === approvalId);
3533
+ if (idx === -1) { res.writeHead(404); res.end('{"error":"approval not found"}'); return; }
3534
+ const status = action === 'approve' ? 'approved' : action === 'reject' ? 'rejected' : 'revision_requested';
3535
+ data.approvals[idx] = {
3536
+ ...data.approvals[idx],
3537
+ status,
3538
+ resolvedAt: new Date().toISOString(),
3539
+ resolvedBy: 'operator',
3540
+ };
3541
+ const tmp = `${approvalsFile}.tmp`;
3542
+ fs.writeFileSync(tmp, JSON.stringify(data, null, 2), 'utf-8');
3543
+ fs.renameSync(tmp, approvalsFile);
3544
+ // Emit org:approval:resolved event so boss agent unblocks
3545
+ const event = { type: 'org:approval:resolved', org: orgName, approval_id: approvalId, status, ts: Date.now() };
3546
+ try { fs.appendFileSync(path.join(projectDir || process.cwd(), 'data', 'mastermind-events.jsonl'), JSON.stringify(event) + '\n'); } catch(_) {}
3547
+ const msg = `data: ${JSON.stringify(event)}\n\n`;
3548
+ for (const c of mmSseClients) { try { c.write(msg); } catch(_) { mmSseClients.delete(c); } }
3549
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
3550
+ res.end(JSON.stringify({ ok: true, status }));
3551
+ } catch(_) { res.writeHead(500); res.end('{}'); }
3552
+ return;
3553
+ }
3554
+
3197
3555
  // GET /api/org/:name/secrets — masked secrets list (NEVER exposes values)
3198
3556
  if (req.method === 'GET' && url.match(/^\/api\/org\/[a-z0-9][a-z0-9_-]{0,63}\/secrets$/i)) {
3199
3557
  try {
@@ -3229,13 +3587,25 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
3229
3587
  const base = path.join(projectDir || process.cwd(), '.monomind', 'orgs');
3230
3588
  let budgetData = { org_budget: {}, agent_budgets: {}, period: 'monthly', currency: 'USD' };
3231
3589
  try { budgetData = JSON.parse(fs.readFileSync(path.join(base, `${orgName}-budgets.json`), 'utf8')); } catch(_) {}
3232
- // Enrich with per-agent spend from state file
3590
+ // Enrich with per-agent spend from state file.
3591
+ // State file format: { agents: { "<role_id>": { tokens_in, tokens_out, ... } } }
3233
3592
  let agents = [];
3234
3593
  try {
3235
3594
  const state = JSON.parse(fs.readFileSync(path.join(base, `${orgName}-state.json`), 'utf8'));
3236
- agents = (state.roles || []).map(r => ({
3237
- id: r.id, title: r.title,
3238
- tokens_in: r.tokens_in || 0, tokens_out: r.tokens_out || 0, total_cost_usd: r.total_cost_usd || 0
3595
+ const agentMap = state.agents || {};
3596
+ // Also load role titles from org config for enrichment
3597
+ let roleMap = {};
3598
+ try {
3599
+ const cfg = JSON.parse(fs.readFileSync(path.join(base, `${orgName}.json`), 'utf8'));
3600
+ (cfg.roles || []).forEach(r => { roleMap[r.id] = r.title || r.id; });
3601
+ } catch(_) {}
3602
+ agents = Object.entries(agentMap).map(([id, s]) => ({
3603
+ id,
3604
+ title: roleMap[id] || s.title || id,
3605
+ tokens_in: s.tokens_in || 0,
3606
+ tokens_out: s.tokens_out || 0,
3607
+ tokens_used: s.tokens_used || (s.tokens_in || 0) + (s.tokens_out || 0),
3608
+ total_cost_usd: s.total_cost_usd || 0,
3239
3609
  }));
3240
3610
  } catch(_) {}
3241
3611
  // Also include roles from org config if state is empty
@@ -3298,6 +3668,105 @@ export async function startServer({ port = 4242, projectDir, openBrowser = true
3298
3668
  return;
3299
3669
  }
3300
3670
 
3671
+ // GET /api/org/:name/goals — read org goals
3672
+ if (req.method === 'GET' && url.match(/^\/api\/org\/[a-z0-9][a-z0-9_-]{0,63}\/goals$/i)) {
3673
+ try {
3674
+ const orgName = decodeURIComponent(url.split('/')[3]);
3675
+ if (orgName.length > 64 || !/^[a-z0-9][a-z0-9_-]*$/i.test(orgName)) { res.writeHead(400); res.end('Invalid org name'); return; }
3676
+ const goalsFile = path.join(projectDir || process.cwd(), '.monomind', 'orgs', `${orgName}-goals.json`);
3677
+ let data = { goals: [] };
3678
+ try { data = JSON.parse(fs.readFileSync(goalsFile, 'utf8')); } catch(_) {}
3679
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
3680
+ res.end(JSON.stringify({ goals: data.goals || [] }));
3681
+ } catch(_) { res.writeHead(500); res.end('{"goals":[]}'); }
3682
+ return;
3683
+ }
3684
+
3685
+ // GET /api/org/:name/routines — read org routines
3686
+ if (req.method === 'GET' && url.match(/^\/api\/org\/[a-z0-9][a-z0-9_-]{0,63}\/routines$/i)) {
3687
+ try {
3688
+ const orgName = decodeURIComponent(url.split('/')[3]);
3689
+ if (orgName.length > 64 || !/^[a-z0-9][a-z0-9_-]*$/i.test(orgName)) { res.writeHead(400); res.end('Invalid org name'); return; }
3690
+ const routinesFile = path.join(projectDir || process.cwd(), '.monomind', 'orgs', `${orgName}-routines.json`);
3691
+ let data = { routines: [] };
3692
+ try { data = JSON.parse(fs.readFileSync(routinesFile, 'utf8')); } catch(_) {}
3693
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
3694
+ res.end(JSON.stringify({ routines: data.routines || [] }));
3695
+ } catch(_) { res.writeHead(500); res.end('{"routines":[]}'); }
3696
+ return;
3697
+ }
3698
+
3699
+ // POST /api/org/:name/goals — upsert the org goals file
3700
+ // Body: { goals: [{id, title, description, status, priority, assignee_id, created_at}] }
3701
+ if (req.method === 'POST' && url.match(/^\/api\/org\/[a-z0-9][a-z0-9_-]{0,63}\/goals$/i)) {
3702
+ let body = '';
3703
+ for await (const chunk of req) body += chunk;
3704
+ try {
3705
+ const orgName = decodeURIComponent(url.split('/')[3]);
3706
+ if (orgName.length > 64 || !/^[a-z0-9][a-z0-9_-]*$/i.test(orgName)) { res.writeHead(400); res.end('Invalid org name'); return; }
3707
+ const parsed = JSON.parse(body);
3708
+ if (!parsed || !Array.isArray(parsed.goals)) { res.writeHead(400); res.end('{"error":"goals array required"}'); return; }
3709
+ const goalsFile = path.join(projectDir || process.cwd(), '.monomind', 'orgs', `${orgName}-goals.json`);
3710
+ const tmp = `${goalsFile}.tmp`;
3711
+ const payload = { org: orgName, updated_at: new Date().toISOString(), goals: parsed.goals };
3712
+ fs.writeFileSync(tmp, JSON.stringify(payload, null, 2), 'utf-8');
3713
+ fs.renameSync(tmp, goalsFile);
3714
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
3715
+ res.end(JSON.stringify({ ok: true, count: parsed.goals.length }));
3716
+ } catch(_) { res.writeHead(500); res.end('{"error":"' + String(_).replace(/"/g, '\\"') + '"}'); }
3717
+ return;
3718
+ }
3719
+
3720
+ // POST /api/org/:name/routines — upsert the org routines file
3721
+ // Body: { routines: [{name, description, schedule, enabled, last_run, next_run}] }
3722
+ if (req.method === 'POST' && url.match(/^\/api\/org\/[a-z0-9][a-z0-9_-]{0,63}\/routines$/i)) {
3723
+ let body = '';
3724
+ for await (const chunk of req) body += chunk;
3725
+ try {
3726
+ const orgName = decodeURIComponent(url.split('/')[3]);
3727
+ if (orgName.length > 64 || !/^[a-z0-9][a-z0-9_-]*$/i.test(orgName)) { res.writeHead(400); res.end('Invalid org name'); return; }
3728
+ const parsed = JSON.parse(body);
3729
+ if (!parsed || !Array.isArray(parsed.routines)) { res.writeHead(400); res.end('{"error":"routines array required"}'); return; }
3730
+ const routinesFile = path.join(projectDir || process.cwd(), '.monomind', 'orgs', `${orgName}-routines.json`);
3731
+ const tmp = `${routinesFile}.tmp`;
3732
+ const payload = { org: orgName, updated_at: new Date().toISOString(), routines: parsed.routines };
3733
+ fs.writeFileSync(tmp, JSON.stringify(payload, null, 2), 'utf-8');
3734
+ fs.renameSync(tmp, routinesFile);
3735
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
3736
+ res.end(JSON.stringify({ ok: true, count: parsed.routines.length }));
3737
+ } catch(_) { res.writeHead(500); res.end('{"error":"' + String(_).replace(/"/g, '\\"') + '"}'); }
3738
+ return;
3739
+ }
3740
+
3741
+ // DELETE /api/orgs/:name — delete an org config and all associated data files
3742
+ if (req.method === 'DELETE' && url.match(/^\/api\/orgs\/[a-z0-9][a-z0-9_-]{0,63}$/i)) {
3743
+ try {
3744
+ const orgName = decodeURIComponent(url.split('/')[3]);
3745
+ if (orgName.length > 64 || !/^[a-z0-9][a-z0-9_-]*$/i.test(orgName)) { res.writeHead(400); res.end('Invalid org name'); return; }
3746
+ const orgsDir = path.join(projectDir || process.cwd(), '.monomind', 'orgs');
3747
+ const configFile = path.join(orgsDir, `${orgName}.json`);
3748
+ if (!fs.existsSync(configFile)) { res.writeHead(404); res.end('{"error":"org not found"}'); return; }
3749
+ // Remove all org-associated files (config + state + data)
3750
+ const suffixes = ['', '-state', '-goals', '-routines', '-approvals', '-activity', '-issues', '-members', '-projects', '-workspaces', '-worktrees', '-environments', '-plugins', '-adapters'];
3751
+ for (const suf of suffixes) {
3752
+ const f = path.join(orgsDir, `${orgName}${suf}.json`);
3753
+ try { if (fs.existsSync(f)) fs.unlinkSync(f); } catch(_) {}
3754
+ const fjsonl = path.join(orgsDir, `${orgName}${suf}.jsonl`);
3755
+ try { if (fs.existsSync(fjsonl)) fs.unlinkSync(fjsonl); } catch(_) {}
3756
+ }
3757
+ // Remove stop file if present
3758
+ try { fs.unlinkSync(path.join(orgsDir, '.stops', `${orgName}.stop`)); } catch(_) {}
3759
+ // Emit org:delete event
3760
+ const deleteEvent = { type: 'org:delete', org: orgName, ts: Date.now() };
3761
+ try { fs.appendFileSync(path.join(projectDir || process.cwd(), 'data', 'mastermind-events.jsonl'), JSON.stringify(deleteEvent) + '\n'); } catch(_) {}
3762
+ const msg = `data: ${JSON.stringify(deleteEvent)}\n\n`;
3763
+ for (const c of mmSseClients) { try { c.write(msg); } catch(_) { mmSseClients.delete(c); } }
3764
+ res.writeHead(200, { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' });
3765
+ res.end('{"ok":true}');
3766
+ } catch(_) { res.writeHead(500); res.end('{}'); }
3767
+ return;
3768
+ }
3769
+
3301
3770
  // POST /api/orgs/:name/stop — send stop signal to a running org
3302
3771
  if (req.method === 'POST' && url.match(/^\/api\/orgs\/[a-z0-9][a-z0-9_-]{0,63}\/stop$/i)) {
3303
3772
  try {