monomind 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (566) hide show
  1. package/.claude/agents/design/design-monodesign.md +121 -0
  2. package/.claude/agents/github/issue-tracker.md +12 -12
  3. package/.claude/agents/github/pr-manager.md +10 -10
  4. package/.claude/agents/github/release-manager.md +49 -105
  5. package/.claude/agents/github/repo-architect.md +73 -92
  6. package/.claude/agents/github/sync-coordinator.md +55 -123
  7. package/.claude/agents/marketing/marketing-competitive-content.md +155 -0
  8. package/.claude/agents/marketing/marketing-content-creator.md +13 -0
  9. package/.claude/agents/marketing/marketing-cro-specialist.md +147 -0
  10. package/.claude/agents/marketing/marketing-email-specialist.md +90 -0
  11. package/.claude/agents/marketing/marketing-launch-strategist.md +129 -0
  12. package/.claude/agents/marketing/marketing-pricing-strategist.md +127 -0
  13. package/.claude/agents/specialists/integration-architect.md +94 -0
  14. package/.claude/commands/agents/README.md +4 -0
  15. package/.claude/commands/agents/agent-capabilities.md +6 -2
  16. package/.claude/commands/agents/agent-coordination.md +4 -0
  17. package/.claude/commands/agents/agent-spawning.md +4 -0
  18. package/.claude/commands/agents/agent-types.md +6 -2
  19. package/.claude/commands/analysis/README.md +14 -5
  20. package/.claude/commands/analysis/bottleneck-detect.md +30 -123
  21. package/.claude/commands/analysis/performance-bottlenecks.md +14 -14
  22. package/.claude/commands/analysis/performance-report.md +38 -11
  23. package/.claude/commands/analysis/token-efficiency.md +13 -16
  24. package/.claude/commands/analysis/token-usage.md +34 -12
  25. package/.claude/commands/automation/README.md +15 -5
  26. package/.claude/commands/automation/auto-agent.md +49 -85
  27. package/.claude/commands/automation/self-healing.md +20 -18
  28. package/.claude/commands/automation/session-memory.md +28 -29
  29. package/.claude/commands/automation/smart-agents.md +17 -9
  30. package/.claude/commands/automation/smart-spawn.md +52 -11
  31. package/.claude/commands/automation/workflow-select.md +46 -11
  32. package/.claude/commands/browse.md +5 -0
  33. package/.claude/commands/coordination/README.md +9 -5
  34. package/.claude/commands/coordination/agent-spawn.md +53 -9
  35. package/.claude/commands/coordination/swarm-init.md +39 -42
  36. package/.claude/commands/coordination/task-orchestrate.md +65 -11
  37. package/.claude/commands/github/README.md +21 -8
  38. package/.claude/commands/github/github-modes.md +9 -5
  39. package/.claude/commands/github/issue-tracker.md +34 -33
  40. package/.claude/commands/github/pr-manager.md +20 -17
  41. package/.claude/commands/github/release-manager.md +37 -49
  42. package/.claude/commands/github/repo-architect.md +39 -41
  43. package/.claude/commands/github/sync-coordinator.md +45 -49
  44. package/.claude/commands/hive-mind/README.md +42 -17
  45. package/.claude/commands/hive-mind/hive-mind-consensus.md +68 -4
  46. package/.claude/commands/hive-mind/hive-mind-init.md +55 -5
  47. package/.claude/commands/hive-mind/hive-mind-memory.md +69 -4
  48. package/.claude/commands/hive-mind/hive-mind-spawn.md +71 -10
  49. package/.claude/commands/hive-mind/hive-mind-status.md +52 -4
  50. package/.claude/commands/hive-mind/hive-mind-stop.md +51 -4
  51. package/.claude/commands/hive-mind/hive-mind.md +74 -14
  52. package/.claude/commands/hooks/README.md +62 -7
  53. package/.claude/commands/hooks/overview.md +94 -35
  54. package/.claude/commands/hooks/post-edit.md +48 -87
  55. package/.claude/commands/hooks/post-task.md +37 -87
  56. package/.claude/commands/hooks/pre-edit.md +52 -84
  57. package/.claude/commands/hooks/pre-task.md +46 -81
  58. package/.claude/commands/hooks/session-end.md +49 -85
  59. package/.claude/commands/hooks/setup.md +87 -58
  60. package/.claude/commands/mastermind/_repeat.md +308 -0
  61. package/.claude/commands/mastermind/architect.md +49 -0
  62. package/.claude/commands/mastermind/brain.md +98 -0
  63. package/.claude/commands/mastermind/build.md +22 -0
  64. package/.claude/commands/mastermind/content.md +22 -0
  65. package/.claude/commands/mastermind/createorg.md +94 -0
  66. package/.claude/commands/mastermind/finance.md +22 -0
  67. package/.claude/commands/mastermind/idea.md +22 -0
  68. package/.claude/commands/mastermind/marketing.md +22 -0
  69. package/.claude/commands/mastermind/master.md +379 -0
  70. package/.claude/commands/mastermind/ops.md +22 -0
  71. package/.claude/commands/mastermind/release.md +22 -0
  72. package/.claude/commands/mastermind/research.md +22 -0
  73. package/.claude/commands/mastermind/review.md +22 -0
  74. package/.claude/commands/mastermind/runorg.md +106 -0
  75. package/.claude/commands/mastermind/sales.md +22 -0
  76. package/.claude/commands/mastermind/techport.md +17 -0
  77. package/.claude/commands/memory/README.md +75 -5
  78. package/.claude/commands/memory/memory-search.md +63 -11
  79. package/.claude/commands/monitoring/README.md +64 -4
  80. package/.claude/commands/monitoring/agent-metrics.md +50 -10
  81. package/.claude/commands/monitoring/agents.md +59 -32
  82. package/.claude/commands/monitoring/status.md +96 -34
  83. package/.claude/commands/monograph/README.md +102 -0
  84. package/.claude/commands/monograph/monograph-build.md +79 -0
  85. package/.claude/commands/monograph/monograph-search.md +96 -0
  86. package/.claude/commands/monograph/monograph-stats.md +53 -0
  87. package/.claude/commands/monograph/monograph-watch.md +63 -0
  88. package/.claude/commands/monograph/monograph-wiki.md +91 -0
  89. package/.claude/commands/monomind/createtask.md +277 -0
  90. package/.claude/commands/{monomind-do.md → monomind/do.md} +21 -8
  91. package/.claude/commands/monomind/help.md +118 -0
  92. package/.claude/commands/{monomind-idea.md → monomind/idea.md} +22 -28
  93. package/.claude/commands/{monomind-improve.md → monomind/improve.md} +21 -27
  94. package/.claude/commands/monomind/memory.md +230 -0
  95. package/.claude/commands/monomind/repeat.md +201 -0
  96. package/.claude/commands/monomind/review.md +313 -0
  97. package/.claude/commands/monomind/specialagents.md +125 -0
  98. package/.claude/commands/monomind/swarm.md +161 -0
  99. package/.claude/commands/monomind/understand.md +148 -0
  100. package/.claude/commands/optimization/README.md +69 -5
  101. package/.claude/commands/optimization/auto-topology.md +66 -43
  102. package/.claude/commands/optimization/parallel-execution.md +65 -39
  103. package/.claude/commands/optimization/performance-optimize.md +79 -0
  104. package/.claude/commands/pair/README.md +48 -230
  105. package/.claude/commands/pair/examples.md +85 -441
  106. package/.claude/commands/pair/modes.md +77 -303
  107. package/.claude/commands/pair/session.md +76 -359
  108. package/.claude/commands/sparc/analyzer.md +9 -26
  109. package/.claude/commands/sparc/architect.md +8 -25
  110. package/.claude/commands/sparc/ask.md +27 -68
  111. package/.claude/commands/sparc/batch-executor.md +8 -25
  112. package/.claude/commands/sparc/code.md +12 -53
  113. package/.claude/commands/sparc/coder.md +8 -25
  114. package/.claude/commands/sparc/debug.md +12 -53
  115. package/.claude/commands/sparc/debugger.md +8 -25
  116. package/.claude/commands/sparc/designer.md +8 -25
  117. package/.claude/commands/sparc/devops.md +16 -57
  118. package/.claude/commands/sparc/docs-writer.md +12 -53
  119. package/.claude/commands/sparc/documenter.md +8 -25
  120. package/.claude/commands/sparc/innovator.md +8 -25
  121. package/.claude/commands/sparc/integration.md +12 -53
  122. package/.claude/commands/sparc/mcp.md +12 -53
  123. package/.claude/commands/sparc/memory-manager.md +28 -25
  124. package/.claude/commands/sparc/optimizer.md +8 -25
  125. package/.claude/commands/sparc/orchestrator.md +35 -97
  126. package/.claude/commands/sparc/post-deployment-monitoring-mode.md +13 -54
  127. package/.claude/commands/sparc/refinement-optimization-mode.md +13 -54
  128. package/.claude/commands/sparc/researcher.md +8 -25
  129. package/.claude/commands/sparc/reviewer.md +8 -25
  130. package/.claude/commands/sparc/security-review.md +13 -54
  131. package/.claude/commands/sparc/sparc-modes.md +97 -151
  132. package/.claude/commands/sparc/sparc.md +16 -56
  133. package/.claude/commands/sparc/spec-pseudocode.md +13 -54
  134. package/.claude/commands/sparc/supabase-admin.md +19 -66
  135. package/.claude/commands/sparc/swarm-coordinator.md +21 -25
  136. package/.claude/commands/sparc/tdd.md +8 -25
  137. package/.claude/commands/sparc/tester.md +8 -25
  138. package/.claude/commands/sparc/tutorial.md +12 -53
  139. package/.claude/commands/sparc/workflow-manager.md +8 -25
  140. package/.claude/commands/sparc.md +76 -130
  141. package/.claude/commands/stream-chain/pipeline.md +72 -77
  142. package/.claude/commands/stream-chain/run.md +133 -47
  143. package/.claude/commands/swarm/README.md +37 -12
  144. package/.claude/commands/swarm/analysis.md +47 -69
  145. package/.claude/commands/swarm/development.md +45 -69
  146. package/.claude/commands/swarm/examples.md +77 -142
  147. package/.claude/commands/swarm/maintenance.md +47 -74
  148. package/.claude/commands/swarm/optimization.md +54 -87
  149. package/.claude/commands/swarm/research.md +47 -107
  150. package/.claude/commands/swarm/swarm-analysis.md +58 -4
  151. package/.claude/commands/swarm/swarm-background.md +61 -4
  152. package/.claude/commands/swarm/swarm-modes.md +63 -4
  153. package/.claude/commands/swarm/swarm-monitor.md +50 -4
  154. package/.claude/commands/swarm/swarm-status.md +40 -4
  155. package/.claude/commands/swarm/swarm-strategies.md +73 -5
  156. package/.claude/commands/swarm/swarm.md +70 -18
  157. package/.claude/commands/swarm/testing.md +51 -102
  158. package/.claude/commands/tokens.md +6 -1
  159. package/.claude/commands/training/README.md +36 -6
  160. package/.claude/commands/training/model-update.md +68 -15
  161. package/.claude/commands/training/neural-patterns.md +54 -55
  162. package/.claude/commands/training/neural-train.md +70 -16
  163. package/.claude/commands/training/pattern-learn.md +60 -16
  164. package/.claude/commands/training/specialization.md +78 -49
  165. package/.claude/commands/truth/start.md +87 -109
  166. package/.claude/commands/ts.md +7 -2
  167. package/.claude/commands/verify/check.md +90 -34
  168. package/.claude/commands/verify/start.md +71 -94
  169. package/.claude/commands/workflows/README.md +62 -6
  170. package/.claude/commands/workflows/development.md +69 -61
  171. package/.claude/commands/workflows/research.md +73 -47
  172. package/.claude/commands/workflows/workflow-create.md +75 -16
  173. package/.claude/commands/workflows/workflow-execute.md +94 -16
  174. package/.claude/commands/workflows/workflow-export.md +81 -16
  175. package/.claude/helpers/control-start.cjs +91 -0
  176. package/.claude/helpers/extras-registry.json +4104 -1991
  177. package/.claude/helpers/graphify-freshen.cjs +44 -13
  178. package/.claude/helpers/hook-handler.cjs +256 -1
  179. package/.claude/helpers/learning-service.mjs +0 -0
  180. package/.claude/helpers/loop-tracker.cjs +107 -0
  181. package/.claude/helpers/metrics-db.mjs +0 -0
  182. package/.claude/helpers/router.cjs +48 -68
  183. package/.claude/helpers/skill-registry.json +89 -104
  184. package/.claude/helpers/statusline.cjs +33 -2
  185. package/.claude/helpers/swarm-hooks.sh +0 -0
  186. package/.claude/scheduled_tasks.lock +1 -0
  187. package/.claude/settings.json +15 -0
  188. package/.claude/skills/.monomind/data/ranked-context.json +5 -0
  189. package/.claude/skills/.monomind/sessions/current.json +13 -0
  190. package/.claude/skills/.monomind/sessions/session-1777829336455.json +15 -0
  191. package/.claude/skills/.monomind/sessions/session-1777831614725.json +15 -0
  192. package/.claude/skills/.monomind/sessions/session-1777832095857.json +15 -0
  193. package/.claude/skills/.monomind/sessions/session-1777839814183.json +15 -0
  194. package/.claude/skills/.monomind/sessions/session-1777841847131.json +15 -0
  195. package/.claude/skills/.monomind/sessions/session-1777843309463.json +15 -0
  196. package/.claude/skills/.monomind/sessions/session-1777880867159.json +15 -0
  197. package/.claude/skills/.monomind/sessions/session-1777881884593.json +15 -0
  198. package/.claude/skills/.monomind/sessions/session-1777884090471.json +15 -0
  199. package/.claude/skills/.monomind/sessions/session-1777884808221.json +15 -0
  200. package/.claude/skills/.monomind/sessions/session-1777885672155.json +15 -0
  201. package/.claude/skills/.monomind/sessions/session-1777886852818.json +15 -0
  202. package/.claude/skills/.monomind/sessions/session-1777896532690.json +15 -0
  203. package/.claude/skills/agentdb-advanced/SKILL.md +11 -12
  204. package/.claude/skills/agentdb-learning/SKILL.md +20 -21
  205. package/.claude/skills/agentdb-memory-patterns/SKILL.md +28 -30
  206. package/.claude/skills/agentdb-optimization/SKILL.md +11 -12
  207. package/.claude/skills/agentdb-vector-search/SKILL.md +37 -41
  208. package/.claude/skills/{v3-integration-deep → agentic-integration}/SKILL.md +20 -13
  209. package/.claude/skills/agentic-jujutsu/SKILL.md +22 -22
  210. package/.claude/skills/{v3-cli-modernization → cli-modernization}/SKILL.md +17 -8
  211. package/.claude/skills/{v3-core-implementation → core-implementation}/SKILL.md +33 -8
  212. package/.claude/skills/{v3-ddd-architecture → ddd-architecture}/SKILL.md +18 -25
  213. package/.claude/skills/github-code-review/SKILL.md +82 -83
  214. package/.claude/skills/github-multi-repo/SKILL.md +42 -46
  215. package/.claude/skills/github-project-management/SKILL.md +83 -88
  216. package/.claude/skills/github-release-management/SKILL.md +12 -18
  217. package/.claude/skills/github-workflow-automation/SKILL.md +70 -74
  218. package/.claude/skills/hooks-automation/SKILL.md +9 -13
  219. package/.claude/skills/mastermind/_intake.md +83 -0
  220. package/.claude/skills/mastermind/_protocol.md +275 -0
  221. package/.claude/skills/mastermind/architect.md +847 -0
  222. package/.claude/skills/mastermind/build.md +158 -0
  223. package/.claude/skills/mastermind/content.md +185 -0
  224. package/.claude/skills/mastermind/createorg.md +318 -0
  225. package/.claude/skills/mastermind/finance.md +154 -0
  226. package/.claude/skills/mastermind/idea.md +158 -0
  227. package/.claude/skills/mastermind/marketing.md +216 -0
  228. package/.claude/skills/mastermind/monotask.md +350 -0
  229. package/.claude/skills/mastermind/ops.md +156 -0
  230. package/.claude/skills/mastermind/references/copywriting-frameworks.md +181 -0
  231. package/.claude/skills/mastermind/references/persuasion-psychology.md +158 -0
  232. package/.claude/skills/mastermind/release.md +156 -0
  233. package/.claude/skills/mastermind/research.md +156 -0
  234. package/.claude/skills/mastermind/review.md +157 -0
  235. package/.claude/skills/mastermind/runorg.md +308 -0
  236. package/.claude/skills/mastermind/sales.md +158 -0
  237. package/.claude/skills/mastermind/techport.md +743 -0
  238. package/.claude/skills/{v3-mcp-optimization → mcp-optimization}/SKILL.md +35 -14
  239. package/.claude/skills/{v3-memory-unification → memory-unification}/SKILL.md +20 -4
  240. package/.claude/skills/monodesign/SKILL.md +302 -0
  241. package/.claude/skills/monodesign/reference/adapt.md +190 -0
  242. package/.claude/skills/monodesign/reference/animate.md +175 -0
  243. package/.claude/skills/monodesign/reference/antipatterns-catalog.md +187 -0
  244. package/.claude/skills/monodesign/reference/audit.md +133 -0
  245. package/.claude/skills/monodesign/reference/bolder.md +113 -0
  246. package/.claude/skills/monodesign/reference/brand-workflow.md +180 -0
  247. package/.claude/skills/monodesign/reference/brand.md +114 -0
  248. package/.claude/skills/monodesign/reference/clarify.md +174 -0
  249. package/.claude/skills/monodesign/reference/cognitive-load.md +106 -0
  250. package/.claude/skills/monodesign/reference/color-and-contrast.md +105 -0
  251. package/.claude/skills/monodesign/reference/colorize.md +154 -0
  252. package/.claude/skills/monodesign/reference/component-specs.md +260 -0
  253. package/.claude/skills/monodesign/reference/component-states.md +274 -0
  254. package/.claude/skills/monodesign/reference/component-system.md +358 -0
  255. package/.claude/skills/monodesign/reference/copy-formulas.md +160 -0
  256. package/.claude/skills/monodesign/reference/craft.md +193 -0
  257. package/.claude/skills/monodesign/reference/critique.md +213 -0
  258. package/.claude/skills/monodesign/reference/delight.md +302 -0
  259. package/.claude/skills/monodesign/reference/design-principles.md +246 -0
  260. package/.claude/skills/monodesign/reference/distill.md +111 -0
  261. package/.claude/skills/monodesign/reference/document.md +427 -0
  262. package/.claude/skills/monodesign/reference/extract.md +69 -0
  263. package/.claude/skills/monodesign/reference/harden.md +347 -0
  264. package/.claude/skills/monodesign/reference/heuristics-scoring.md +234 -0
  265. package/.claude/skills/monodesign/reference/image-prompts.md +118 -0
  266. package/.claude/skills/monodesign/reference/interaction-design.md +195 -0
  267. package/.claude/skills/monodesign/reference/layout.md +141 -0
  268. package/.claude/skills/monodesign/reference/live.md +622 -0
  269. package/.claude/skills/monodesign/reference/motion-design.md +109 -0
  270. package/.claude/skills/monodesign/reference/onboard.md +234 -0
  271. package/.claude/skills/monodesign/reference/optimize.md +258 -0
  272. package/.claude/skills/monodesign/reference/overdrive.md +130 -0
  273. package/.claude/skills/monodesign/reference/personas.md +179 -0
  274. package/.claude/skills/monodesign/reference/polish.md +233 -0
  275. package/.claude/skills/monodesign/reference/pre-delivery-checklist.md +108 -0
  276. package/.claude/skills/monodesign/reference/product.md +62 -0
  277. package/.claude/skills/monodesign/reference/quieter.md +99 -0
  278. package/.claude/skills/monodesign/reference/responsive-design.md +114 -0
  279. package/.claude/skills/monodesign/reference/shape.md +151 -0
  280. package/.claude/skills/monodesign/reference/spatial-design.md +100 -0
  281. package/.claude/skills/monodesign/reference/teach.md +156 -0
  282. package/.claude/skills/monodesign/reference/token-architecture.md +222 -0
  283. package/.claude/skills/monodesign/reference/typeset.md +124 -0
  284. package/.claude/skills/monodesign/reference/typography.md +159 -0
  285. package/.claude/skills/monodesign/reference/ux-research.md +143 -0
  286. package/.claude/skills/monodesign/reference/ux-rules.md +211 -0
  287. package/.claude/skills/monodesign/reference/ux-writing.md +107 -0
  288. package/.claude/skills/monomotion/SKILL.md +145 -0
  289. package/.claude/skills/monomotion/rules/api-control.md +139 -0
  290. package/.claude/skills/monomotion/rules/effects.md +109 -0
  291. package/.claude/skills/monomotion/rules/integration.md +140 -0
  292. package/.claude/skills/monomotion/rules/scroll.md +131 -0
  293. package/.claude/skills/monomotion/rules/sequencing.md +105 -0
  294. package/.claude/skills/monomotion/rules/svg.md +101 -0
  295. package/.claude/skills/monomotion/rules/text.md +119 -0
  296. package/.claude/skills/pair-programming/SKILL.md +1 -1
  297. package/.claude/skills/performance-analysis/SKILL.md +3 -3
  298. package/.claude/skills/{v3-performance-optimization → performance-optimization}/SKILL.md +16 -8
  299. package/.claude/skills/reasoningbank-agentdb/SKILL.md +17 -19
  300. package/.claude/skills/reasoningbank-intelligence/SKILL.md +4 -6
  301. package/.claude/skills/{v3-security-overhaul → security-hardening}/SKILL.md +13 -3
  302. package/.claude/skills/skill-builder/SKILL.md +19 -19
  303. package/.claude/skills/sparc-methodology/SKILL.md +55 -211
  304. package/.claude/skills/stop-slop/SKILL.md +67 -0
  305. package/.claude/skills/stop-slop/references/examples.md +61 -0
  306. package/.claude/skills/stop-slop/references/phrases.md +130 -0
  307. package/.claude/skills/stop-slop/references/structures.md +136 -0
  308. package/.claude/skills/swarm-advanced/SKILL.md +13 -43
  309. package/.claude/skills/{v3-swarm-coordination → swarm-coordination}/SKILL.md +39 -21
  310. package/.claude/skills/swarm-orchestration/SKILL.md +12 -12
  311. package/.claude/skills/verification-quality/SKILL.md +5 -5
  312. package/.claude/statusline-command.sh +0 -0
  313. package/.claude/statusline.sh +0 -0
  314. package/.claude-plugin/scripts/install.sh +0 -0
  315. package/.claude-plugin/scripts/uninstall.sh +0 -0
  316. package/.claude-plugin/scripts/verify.sh +0 -0
  317. package/README.md +5 -5
  318. package/package.json +17 -17
  319. package/packages/@monomind/cli/README.md +441 -0
  320. package/packages/@monomind/cli/bin/cli.js +78 -13
  321. package/packages/@monomind/cli/bin/mcp-server.js +0 -0
  322. package/packages/@monomind/cli/dist/src/agents/halt-signal.js +33 -7
  323. package/packages/@monomind/cli/dist/src/agents/managed-agent.js +5 -2
  324. package/packages/@monomind/cli/dist/src/agents/prompt-experiment.d.ts +3 -2
  325. package/packages/@monomind/cli/dist/src/agents/prompt-experiment.js +1 -1
  326. package/packages/@monomind/cli/dist/src/agents/prompt-version-manager.d.ts +5 -2
  327. package/packages/@monomind/cli/dist/src/agents/prompt-version-manager.js +26 -4
  328. package/packages/@monomind/cli/dist/src/agents/specialization-scorer.js +17 -9
  329. package/packages/@monomind/cli/dist/src/agents/trigger-scanner.d.ts +5 -3
  330. package/packages/@monomind/cli/dist/src/agents/trigger-scanner.js +58 -10
  331. package/packages/@monomind/cli/dist/src/agents/version-store.d.ts +0 -1
  332. package/packages/@monomind/cli/dist/src/agents/version-store.js +44 -21
  333. package/packages/@monomind/cli/dist/src/autopilot-state.js +79 -28
  334. package/packages/@monomind/cli/dist/src/benchmarks/benchmark-runner.d.ts +7 -2
  335. package/packages/@monomind/cli/dist/src/benchmarks/benchmark-runner.js +20 -8
  336. package/packages/@monomind/cli/dist/src/benchmarks/metric-evaluators.d.ts +2 -1
  337. package/packages/@monomind/cli/dist/src/benchmarks/metric-evaluators.js +25 -2
  338. package/packages/@monomind/cli/dist/src/commands/agent.js +6 -4
  339. package/packages/@monomind/cli/dist/src/commands/appliance-advanced.js +23 -0
  340. package/packages/@monomind/cli/dist/src/commands/autopilot.js +3 -3
  341. package/packages/@monomind/cli/dist/src/commands/benchmark.js +119 -8
  342. package/packages/@monomind/cli/dist/src/commands/claims.js +22 -14
  343. package/packages/@monomind/cli/dist/src/commands/config.js +32 -0
  344. package/packages/@monomind/cli/dist/src/commands/daemon.js +13 -11
  345. package/packages/@monomind/cli/dist/src/commands/deployment.js +21 -2
  346. package/packages/@monomind/cli/dist/src/commands/doctor.js +5 -4
  347. package/packages/@monomind/cli/dist/src/commands/embeddings.js +124 -48
  348. package/packages/@monomind/cli/dist/src/commands/hive-mind.js +15 -14
  349. package/packages/@monomind/cli/dist/src/commands/hooks.js +45 -41
  350. package/packages/@monomind/cli/dist/src/commands/index.d.ts +2 -0
  351. package/packages/@monomind/cli/dist/src/commands/index.js +20 -7
  352. package/packages/@monomind/cli/dist/src/commands/init.js +53 -19
  353. package/packages/@monomind/cli/dist/src/commands/mcp.js +31 -44
  354. package/packages/@monomind/cli/dist/src/commands/memory.js +47 -15
  355. package/packages/@monomind/cli/dist/src/commands/migrate.js +156 -108
  356. package/packages/@monomind/cli/dist/src/commands/monograph.d.ts +8 -0
  357. package/packages/@monomind/cli/dist/src/commands/monograph.js +526 -0
  358. package/packages/@monomind/cli/dist/src/commands/neural.js +96 -56
  359. package/packages/@monomind/cli/dist/src/commands/performance.js +30 -8
  360. package/packages/@monomind/cli/dist/src/commands/plugins.js +13 -37
  361. package/packages/@monomind/cli/dist/src/commands/process.js +25 -2
  362. package/packages/@monomind/cli/dist/src/commands/providers.js +37 -5
  363. package/packages/@monomind/cli/dist/src/commands/replay.js +4 -4
  364. package/packages/@monomind/cli/dist/src/commands/route.js +37 -5
  365. package/packages/@monomind/cli/dist/src/commands/ruvector/import.js +12 -2
  366. package/packages/@monomind/cli/dist/src/commands/ruvector/init.js +15 -0
  367. package/packages/@monomind/cli/dist/src/commands/ruvector/status.js +16 -3
  368. package/packages/@monomind/cli/dist/src/commands/security.js +342 -193
  369. package/packages/@monomind/cli/dist/src/commands/session.js +51 -8
  370. package/packages/@monomind/cli/dist/src/commands/start.js +18 -4
  371. package/packages/@monomind/cli/dist/src/commands/swarm.js +47 -36
  372. package/packages/@monomind/cli/dist/src/commands/tokens.js +11 -11
  373. package/packages/@monomind/cli/dist/src/commands/transfer-store.js +1 -1
  374. package/packages/@monomind/cli/dist/src/commands/workflow.js +31 -4
  375. package/packages/@monomind/cli/dist/src/config-adapter.d.ts +2 -1
  376. package/packages/@monomind/cli/dist/src/consensus/audit-writer.js +46 -13
  377. package/packages/@monomind/cli/dist/src/consensus/vote-signer.d.ts +0 -3
  378. package/packages/@monomind/cli/dist/src/consensus/vote-signer.js +9 -1
  379. package/packages/@monomind/cli/dist/src/dlq/dlq-reader.d.ts +4 -2
  380. package/packages/@monomind/cli/dist/src/dlq/dlq-reader.js +25 -8
  381. package/packages/@monomind/cli/dist/src/dlq/dlq-replayer.d.ts +10 -3
  382. package/packages/@monomind/cli/dist/src/dlq/dlq-replayer.js +50 -16
  383. package/packages/@monomind/cli/dist/src/dlq/dlq-writer.js +27 -5
  384. package/packages/@monomind/cli/dist/src/eval/dataset-manager.d.ts +2 -2
  385. package/packages/@monomind/cli/dist/src/eval/dataset-manager.js +26 -16
  386. package/packages/@monomind/cli/dist/src/eval/trace-collector.js +23 -3
  387. package/packages/@monomind/cli/dist/src/index.js +12 -10
  388. package/packages/@monomind/cli/dist/src/init/claudemd-generator.js +8 -8
  389. package/packages/@monomind/cli/dist/src/init/executor.js +153 -70
  390. package/packages/@monomind/cli/dist/src/init/helpers-generator.js +35 -22
  391. package/packages/@monomind/cli/dist/src/init/mcp-generator.js +3 -3
  392. package/packages/@monomind/cli/dist/src/init/settings-generator.js +10 -3
  393. package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.js +18 -3
  394. package/packages/@monomind/cli/dist/src/init/statusline-generator.js +3 -1
  395. package/packages/@monomind/cli/dist/src/init/types.d.ts +35 -11
  396. package/packages/@monomind/cli/dist/src/init/types.js +5 -9
  397. package/packages/@monomind/cli/dist/src/interactive/interrupt.js +8 -3
  398. package/packages/@monomind/cli/dist/src/mcp/tool-registry.js +38 -4
  399. package/packages/@monomind/cli/dist/src/mcp-client.js +10 -4
  400. package/packages/@monomind/cli/dist/src/mcp-server.d.ts +9 -2
  401. package/packages/@monomind/cli/dist/src/mcp-server.js +182 -35
  402. package/packages/@monomind/cli/dist/src/mcp-tools/agent-tools.js +66 -34
  403. package/packages/@monomind/cli/dist/src/mcp-tools/agentdb-tools.js +34 -7
  404. package/packages/@monomind/cli/dist/src/mcp-tools/analyze-tools.js +25 -16
  405. package/packages/@monomind/cli/dist/src/mcp-tools/auto-install.js +4 -6
  406. package/packages/@monomind/cli/dist/src/mcp-tools/autopilot-tools.js +12 -2
  407. package/packages/@monomind/cli/dist/src/mcp-tools/browser-tools.js +199 -20
  408. package/packages/@monomind/cli/dist/src/mcp-tools/claims-tools.js +68 -18
  409. package/packages/@monomind/cli/dist/src/mcp-tools/config-tools.js +33 -5
  410. package/packages/@monomind/cli/dist/src/mcp-tools/coordination-tools.js +59 -4
  411. package/packages/@monomind/cli/dist/src/mcp-tools/daa-tools.js +46 -10
  412. package/packages/@monomind/cli/dist/src/mcp-tools/embeddings-tools.js +46 -5
  413. package/packages/@monomind/cli/dist/src/mcp-tools/github-tools.js +29 -16
  414. package/packages/@monomind/cli/dist/src/mcp-tools/guidance-tools.js +38 -10
  415. package/packages/@monomind/cli/dist/src/mcp-tools/hive-mind-tools.js +96 -33
  416. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-tools.js +70 -37
  417. package/packages/@monomind/cli/dist/src/mcp-tools/memory-tools.js +29 -13
  418. package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +5867 -56
  419. package/packages/@monomind/cli/dist/src/mcp-tools/neural-tools.js +121 -37
  420. package/packages/@monomind/cli/dist/src/mcp-tools/performance-tools.js +21 -8
  421. package/packages/@monomind/cli/dist/src/mcp-tools/progress-tools.js +10 -8
  422. package/packages/@monomind/cli/dist/src/mcp-tools/request-tracker.js +4 -1
  423. package/packages/@monomind/cli/dist/src/mcp-tools/ruvllm-tools.js +19 -8
  424. package/packages/@monomind/cli/dist/src/mcp-tools/session-tools.js +57 -17
  425. package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +35 -17
  426. package/packages/@monomind/cli/dist/src/mcp-tools/system-tools.js +4 -3
  427. package/packages/@monomind/cli/dist/src/mcp-tools/task-tools.js +53 -13
  428. package/packages/@monomind/cli/dist/src/mcp-tools/terminal-tools.js +63 -14
  429. package/packages/@monomind/cli/dist/src/mcp-tools/transfer-tools.js +21 -16
  430. package/packages/@monomind/cli/dist/src/mcp-tools/workflow-tools.js +92 -23
  431. package/packages/@monomind/cli/dist/src/memory/ewc-consolidation.js +41 -10
  432. package/packages/@monomind/cli/dist/src/memory/intelligence.d.ts +2 -2
  433. package/packages/@monomind/cli/dist/src/memory/intelligence.js +39 -13
  434. package/packages/@monomind/cli/dist/src/memory/memory-bridge.d.ts +1 -0
  435. package/packages/@monomind/cli/dist/src/memory/memory-bridge.js +149 -56
  436. package/packages/@monomind/cli/dist/src/memory/memory-initializer.js +107 -45
  437. package/packages/@monomind/cli/dist/src/memory/sona-optimizer.d.ts +8 -1
  438. package/packages/@monomind/cli/dist/src/memory/sona-optimizer.js +25 -8
  439. package/packages/@monomind/cli/dist/src/observability/replay-reader.d.ts +40 -0
  440. package/packages/@monomind/cli/dist/src/observability/replay-reader.js +138 -0
  441. package/packages/@monomind/cli/dist/src/orchestration/routing-modes.js +35 -5
  442. package/packages/@monomind/cli/dist/src/parser.d.ts +8 -0
  443. package/packages/@monomind/cli/dist/src/parser.js +48 -14
  444. package/packages/@monomind/cli/dist/src/plugins/manager.js +112 -19
  445. package/packages/@monomind/cli/dist/src/plugins/store/discovery.d.ts +1 -1
  446. package/packages/@monomind/cli/dist/src/plugins/store/discovery.js +80 -62
  447. package/packages/@monomind/cli/dist/src/production/circuit-breaker.js +8 -1
  448. package/packages/@monomind/cli/dist/src/production/error-handler.d.ts +4 -2
  449. package/packages/@monomind/cli/dist/src/production/error-handler.js +27 -5
  450. package/packages/@monomind/cli/dist/src/production/monitoring.js +8 -4
  451. package/packages/@monomind/cli/dist/src/production/rate-limiter.js +30 -22
  452. package/packages/@monomind/cli/dist/src/ruvector/agent-wasm.js +2 -2
  453. package/packages/@monomind/cli/dist/src/ruvector/coverage-router.js +19 -9
  454. package/packages/@monomind/cli/dist/src/ruvector/diff-classifier.d.ts +1 -0
  455. package/packages/@monomind/cli/dist/src/ruvector/diff-classifier.js +26 -6
  456. package/packages/@monomind/cli/dist/src/ruvector/enhanced-model-router.js +24 -2
  457. package/packages/@monomind/cli/dist/src/ruvector/index.d.ts +1 -2
  458. package/packages/@monomind/cli/dist/src/ruvector/index.js +2 -2
  459. package/packages/@monomind/cli/dist/src/ruvector/model-router.d.ts +4 -2
  460. package/packages/@monomind/cli/dist/src/ruvector/model-router.js +30 -6
  461. package/packages/@monomind/cli/dist/src/ruvector/moe-router.d.ts +7 -0
  462. package/packages/@monomind/cli/dist/src/ruvector/moe-router.js +35 -12
  463. package/packages/@monomind/cli/dist/src/ruvector/q-learning-router.d.ts +7 -1
  464. package/packages/@monomind/cli/dist/src/ruvector/q-learning-router.js +40 -9
  465. package/packages/@monomind/cli/dist/src/services/claim-service.d.ts +3 -1
  466. package/packages/@monomind/cli/dist/src/services/claim-service.js +33 -2
  467. package/packages/@monomind/cli/dist/src/services/config-file-manager.d.ts +16 -2
  468. package/packages/@monomind/cli/dist/src/services/config-file-manager.js +105 -17
  469. package/packages/@monomind/cli/dist/src/services/container-worker-pool.js +51 -11
  470. package/packages/@monomind/cli/dist/src/services/headless-worker-executor.d.ts +7 -0
  471. package/packages/@monomind/cli/dist/src/services/headless-worker-executor.js +188 -45
  472. package/packages/@monomind/cli/dist/src/services/registry-api.js +62 -9
  473. package/packages/@monomind/cli/dist/src/services/ruvector-training.js +8 -0
  474. package/packages/@monomind/cli/dist/src/services/worker-daemon.d.ts +4 -1
  475. package/packages/@monomind/cli/dist/src/services/worker-daemon.js +112 -28
  476. package/packages/@monomind/cli/dist/src/services/worker-queue.d.ts +9 -2
  477. package/packages/@monomind/cli/dist/src/services/worker-queue.js +86 -5
  478. package/packages/@monomind/cli/dist/src/suggest.js +9 -0
  479. package/packages/@monomind/cli/dist/src/swarm/flow-enforcer.d.ts +5 -3
  480. package/packages/@monomind/cli/dist/src/swarm/flow-enforcer.js +17 -5
  481. package/packages/@monomind/cli/dist/src/swarm/flow-visualizer.d.ts +3 -0
  482. package/packages/@monomind/cli/dist/src/swarm/flow-visualizer.js +30 -6
  483. package/packages/@monomind/cli/dist/src/transfer/anonymization/index.js +5 -3
  484. package/packages/@monomind/cli/dist/src/transfer/export.js +5 -3
  485. package/packages/@monomind/cli/dist/src/transfer/ipfs/client.js +84 -7
  486. package/packages/@monomind/cli/dist/src/transfer/ipfs/upload.js +13 -4
  487. package/packages/@monomind/cli/dist/src/transfer/storage/gcs.js +19 -10
  488. package/packages/@monomind/cli/dist/src/transfer/store/discovery.d.ts +9 -2
  489. package/packages/@monomind/cli/dist/src/transfer/store/discovery.js +68 -13
  490. package/packages/@monomind/cli/dist/src/transfer/store/download.d.ts +15 -6
  491. package/packages/@monomind/cli/dist/src/transfer/store/download.js +113 -24
  492. package/packages/@monomind/cli/dist/src/transfer/store/publish.d.ts +1 -1
  493. package/packages/@monomind/cli/dist/src/transfer/store/publish.js +13 -14
  494. package/packages/@monomind/cli/dist/src/transfer/store/registry.d.ts +3 -3
  495. package/packages/@monomind/cli/dist/src/transfer/store/registry.js +32 -16
  496. package/packages/@monomind/cli/dist/src/update/checker.js +17 -4
  497. package/packages/@monomind/cli/dist/src/update/executor.js +25 -20
  498. package/packages/@monomind/cli/dist/src/update/rate-limiter.d.ts +11 -0
  499. package/packages/@monomind/cli/dist/src/update/rate-limiter.js +23 -3
  500. package/packages/@monomind/cli/dist/src/utils/parse-jsonl.d.ts +6 -0
  501. package/packages/@monomind/cli/dist/src/utils/parse-jsonl.js +22 -0
  502. package/packages/@monomind/cli/dist/src/workflow/condition-evaluator.js +37 -3
  503. package/packages/@monomind/cli/dist/src/workflow/dag-builder.js +27 -11
  504. package/packages/@monomind/cli/dist/src/workflow/dag-executor.js +51 -13
  505. package/packages/@monomind/cli/dist/src/workflow/dsl-schema.d.ts +3 -0
  506. package/packages/@monomind/cli/dist/src/workflow/dsl-schema.js +6 -2
  507. package/packages/@monomind/cli/dist/src/workflow/template-engine.js +7 -0
  508. package/packages/@monomind/cli/dist/src/workflow/workflow-executor.js +95 -14
  509. package/packages/@monomind/cli/package.json +5 -3
  510. package/packages/@monomind/guidance/README.md +1192 -0
  511. package/packages/@monomind/shared/README.md +322 -0
  512. package/packages/@monomind/shared/dist/types/consensus-audit.d.ts +3 -1
  513. package/packages/README.md +513 -0
  514. package/.claude/agents/design/design-brand-guardian.md +0 -323
  515. package/.claude/agents/design/design-image-prompt-engineer.md +0 -237
  516. package/.claude/agents/design/design-inclusive-visuals-specialist.md +0 -72
  517. package/.claude/agents/design/design-ui-designer.md +0 -384
  518. package/.claude/agents/design/design-ux-architect.md +0 -470
  519. package/.claude/agents/design/design-ux-researcher.md +0 -330
  520. package/.claude/agents/design/design-visual-storyteller.md +0 -150
  521. package/.claude/agents/design/design-whimsy-injector.md +0 -439
  522. package/.claude/agents/v3/integration-architect.md +0 -338
  523. package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +0 -54
  524. package/.claude/commands/coordination/init.md +0 -44
  525. package/.claude/commands/coordination/orchestrate.md +0 -43
  526. package/.claude/commands/coordination/spawn.md +0 -45
  527. package/.claude/commands/github/code-review-swarm.md +0 -550
  528. package/.claude/commands/github/code-review.md +0 -25
  529. package/.claude/commands/github/github-swarm.md +0 -121
  530. package/.claude/commands/github/issue-triage.md +0 -25
  531. package/.claude/commands/github/multi-repo-swarm.md +0 -519
  532. package/.claude/commands/github/pr-enhance.md +0 -26
  533. package/.claude/commands/github/project-board-sync.md +0 -471
  534. package/.claude/commands/github/release-swarm.md +0 -590
  535. package/.claude/commands/github/repo-analyze.md +0 -25
  536. package/.claude/commands/github/swarm-issue.md +0 -482
  537. package/.claude/commands/github/swarm-pr.md +0 -310
  538. package/.claude/commands/github/workflow-automation.md +0 -468
  539. package/.claude/commands/hive-mind/hive-mind-metrics.md +0 -8
  540. package/.claude/commands/hive-mind/hive-mind-resume.md +0 -8
  541. package/.claude/commands/hive-mind/hive-mind-sessions.md +0 -8
  542. package/.claude/commands/hive-mind/hive-mind-wizard.md +0 -8
  543. package/.claude/commands/list-agents.md +0 -17
  544. package/.claude/commands/memory/memory-persist.md +0 -25
  545. package/.claude/commands/memory/memory-usage.md +0 -25
  546. package/.claude/commands/memory/neural.md +0 -47
  547. package/.claude/commands/metrics.md +0 -11
  548. package/.claude/commands/monitoring/real-time-view.md +0 -25
  549. package/.claude/commands/monitoring/swarm-monitor.md +0 -25
  550. package/.claude/commands/monomind-createtask.md +0 -302
  551. package/.claude/commands/monomind-help.md +0 -103
  552. package/.claude/commands/monomind-memory.md +0 -107
  553. package/.claude/commands/monomind-repeat.md +0 -149
  554. package/.claude/commands/monomind-swarm.md +0 -205
  555. package/.claude/commands/optimization/cache-manage.md +0 -25
  556. package/.claude/commands/optimization/topology-optimize.md +0 -25
  557. package/.claude/commands/pair/commands.md +0 -546
  558. package/.claude/commands/pair/config.md +0 -510
  559. package/.claude/commands/pair/start.md +0 -209
  560. package/.claude/commands/use-agent.md +0 -67
  561. package/.claude/skills/monomind-createtask/SKILL.md +0 -269
  562. package/.claude/skills/monomind-task-engine/SKILL.md +0 -358
  563. /package/.claude/agents/{v3 → specialists}/memory-specialist.md +0 -0
  564. /package/.claude/agents/{v3 → specialists}/performance-engineer.md +0 -0
  565. /package/.claude/agents/{v3 → specialists}/queen-coordinator.md +0 -0
  566. /package/.claude/agents/{v3 → specialists}/security-architect.md +0 -0
@@ -3,8 +3,9 @@
3
3
  *
4
4
  * Tool definitions for session management with file persistence.
5
5
  */
6
- import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, unlinkSync, statSync } from 'node:fs';
6
+ import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync, readdirSync, unlinkSync, statSync } from 'node:fs';
7
7
  import { join } from 'node:path';
8
+ import { randomBytes } from 'node:crypto';
8
9
  import { getProjectCwd } from './types.js';
9
10
  // Storage paths
10
11
  const STORAGE_DIR = '.monomind';
@@ -23,10 +24,13 @@ function ensureSessionDir() {
23
24
  mkdirSync(dir, { recursive: true });
24
25
  }
25
26
  }
27
+ const MAX_SESSION_BYTES = 50 * 1024 * 1024;
26
28
  function loadSession(sessionId) {
27
29
  try {
28
30
  const path = getSessionPath(sessionId);
29
31
  if (existsSync(path)) {
32
+ if (statSync(path).size > MAX_SESSION_BYTES)
33
+ return null;
30
34
  const data = readFileSync(path, 'utf-8');
31
35
  return JSON.parse(data);
32
36
  }
@@ -38,16 +42,37 @@ function loadSession(sessionId) {
38
42
  }
39
43
  function saveSession(session) {
40
44
  ensureSessionDir();
41
- writeFileSync(getSessionPath(session.sessionId), JSON.stringify(session, null, 2), 'utf-8');
45
+ const sessionPath = getSessionPath(session.sessionId);
46
+ // Unique tmp filename so concurrent session_save calls cannot collide on
47
+ // the same .tmp path (which would corrupt the rename target).
48
+ const tmpPath = `${sessionPath}.${process.pid}.${Date.now()}.tmp`;
49
+ writeFileSync(tmpPath, JSON.stringify(session, null, 2), 'utf-8');
50
+ renameSync(tmpPath, sessionPath);
42
51
  }
43
- function listSessions() {
52
+ function listSessions(limit = 200) {
44
53
  ensureSessionDir();
45
54
  const dir = getSessionDir();
46
- const files = readdirSync(dir).filter(f => f.endsWith('.json'));
55
+ // Sort by mtime DESC, then bound reads to `limit` files to prevent DoS
56
+ const files = readdirSync(dir)
57
+ .filter(f => f.endsWith('.json'))
58
+ .map(f => {
59
+ try {
60
+ const stat = statSync(join(dir, f));
61
+ return { name: f, mtimeMs: stat.mtimeMs };
62
+ }
63
+ catch {
64
+ return { name: f, mtimeMs: 0 };
65
+ }
66
+ })
67
+ .sort((a, b) => b.mtimeMs - a.mtimeMs)
68
+ .slice(0, Math.max(1, Math.min(limit, 1000)));
47
69
  const sessions = [];
48
70
  for (const file of files) {
49
71
  try {
50
- const data = readFileSync(join(dir, file), 'utf-8');
72
+ const filePath = join(dir, file.name);
73
+ if (statSync(filePath).size > MAX_SESSION_BYTES)
74
+ continue;
75
+ const data = readFileSync(filePath, 'utf-8');
51
76
  sessions.push(JSON.parse(data));
52
77
  }
53
78
  catch {
@@ -62,7 +87,7 @@ function loadRelatedStores(options) {
62
87
  if (options.includeMemory) {
63
88
  try {
64
89
  const memoryPath = join(getProjectCwd(), STORAGE_DIR, 'memory', 'store.json');
65
- if (existsSync(memoryPath)) {
90
+ if (existsSync(memoryPath) && statSync(memoryPath).size <= MAX_SESSION_BYTES) {
66
91
  data.memory = JSON.parse(readFileSync(memoryPath, 'utf-8'));
67
92
  }
68
93
  }
@@ -71,7 +96,7 @@ function loadRelatedStores(options) {
71
96
  if (options.includeTasks) {
72
97
  try {
73
98
  const taskPath = join(getProjectCwd(), STORAGE_DIR, 'tasks', 'store.json');
74
- if (existsSync(taskPath)) {
99
+ if (existsSync(taskPath) && statSync(taskPath).size <= MAX_SESSION_BYTES) {
75
100
  data.tasks = JSON.parse(readFileSync(taskPath, 'utf-8'));
76
101
  }
77
102
  }
@@ -80,7 +105,7 @@ function loadRelatedStores(options) {
80
105
  if (options.includeAgents) {
81
106
  try {
82
107
  const agentPath = join(getProjectCwd(), STORAGE_DIR, 'agents', 'store.json');
83
- if (existsSync(agentPath)) {
108
+ if (existsSync(agentPath) && statSync(agentPath).size <= MAX_SESSION_BYTES) {
84
109
  data.agents = JSON.parse(readFileSync(agentPath, 'utf-8'));
85
110
  }
86
111
  }
@@ -105,7 +130,7 @@ export const sessionTools = [
105
130
  required: ['name'],
106
131
  },
107
132
  handler: async (input) => {
108
- const sessionId = `session-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
133
+ const sessionId = `session-${Date.now()}-${randomBytes(6).toString('hex')}`;
109
134
  // Load related data based on options
110
135
  const data = loadRelatedStores({
111
136
  includeMemory: input.includeMemory,
@@ -136,7 +161,6 @@ export const sessionTools = [
136
161
  name: session.name,
137
162
  savedAt: session.savedAt,
138
163
  stats: session.stats,
139
- path: getSessionPath(sessionId),
140
164
  };
141
165
  },
142
166
  },
@@ -176,7 +200,12 @@ export const sessionTools = [
176
200
  const memoryDir = join(getProjectCwd(), STORAGE_DIR, 'memory');
177
201
  if (!existsSync(memoryDir))
178
202
  mkdirSync(memoryDir, { recursive: true });
179
- writeFileSync(join(memoryDir, 'store.json'), JSON.stringify(session.data.memory, null, 2), 'utf-8');
203
+ const memoryStorePath = join(memoryDir, 'store.json');
204
+ {
205
+ const tmp = `${memoryStorePath}.${process.pid}.${Date.now()}.tmp`;
206
+ writeFileSync(tmp, JSON.stringify(session.data.memory, null, 2), 'utf-8');
207
+ renameSync(tmp, memoryStorePath);
208
+ }
180
209
  // Also populate active sql.js SQLite database so memory-tools can find entries
181
210
  try {
182
211
  const { storeEntry } = await import('../memory/memory-initializer.js');
@@ -204,13 +233,23 @@ export const sessionTools = [
204
233
  const taskDir = join(getProjectCwd(), STORAGE_DIR, 'tasks');
205
234
  if (!existsSync(taskDir))
206
235
  mkdirSync(taskDir, { recursive: true });
207
- writeFileSync(join(taskDir, 'store.json'), JSON.stringify(session.data.tasks, null, 2), 'utf-8');
236
+ const taskStorePath = join(taskDir, 'store.json');
237
+ {
238
+ const tmp = `${taskStorePath}.${process.pid}.${Date.now()}.tmp`;
239
+ writeFileSync(tmp, JSON.stringify(session.data.tasks, null, 2), 'utf-8');
240
+ renameSync(tmp, taskStorePath);
241
+ }
208
242
  }
209
243
  if (session.data?.agents) {
210
244
  const agentDir = join(getProjectCwd(), STORAGE_DIR, 'agents');
211
245
  if (!existsSync(agentDir))
212
246
  mkdirSync(agentDir, { recursive: true });
213
- writeFileSync(join(agentDir, 'store.json'), JSON.stringify(session.data.agents, null, 2), 'utf-8');
247
+ const agentStorePath = join(agentDir, 'store.json');
248
+ {
249
+ const tmp = `${agentStorePath}.${process.pid}.${Date.now()}.tmp`;
250
+ writeFileSync(tmp, JSON.stringify(session.data.agents, null, 2), 'utf-8');
251
+ renameSync(tmp, agentStorePath);
252
+ }
214
253
  }
215
254
  return {
216
255
  sessionId: session.sessionId,
@@ -251,8 +290,10 @@ export const sessionTools = [
251
290
  else if (sortBy === 'size') {
252
291
  sessions.sort((a, b) => b.stats.totalSize - a.stats.totalSize);
253
292
  }
254
- // Apply limit
255
- const limit = input.limit || 10;
293
+ // Apply limit — clamp to [1, 200] to prevent negative-slice and OOM
294
+ const rawLimit = typeof input.limit === 'number' ? input.limit : 10;
295
+ const limit = Math.max(1, Math.min(rawLimit, 200));
296
+ const totalCount = sessions.length;
256
297
  sessions = sessions.slice(0, limit);
257
298
  return {
258
299
  sessions: sessions.map(s => ({
@@ -262,7 +303,7 @@ export const sessionTools = [
262
303
  savedAt: s.savedAt,
263
304
  stats: s.stats,
264
305
  })),
265
- total: sessions.length,
306
+ total: totalCount,
266
307
  limit,
267
308
  };
268
309
  },
@@ -320,7 +361,6 @@ export const sessionTools = [
320
361
  savedAt: session.savedAt,
321
362
  stats: session.stats,
322
363
  fileSize: stat.size,
323
- path,
324
364
  hasData: {
325
365
  memory: !!session.data?.memory,
326
366
  tasks: !!session.data?.tasks,
@@ -4,17 +4,10 @@
4
4
  * Tool definitions for swarm coordination with file-based state persistence.
5
5
  * Replaces previous stub implementations with real state tracking.
6
6
  */
7
- import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync } from 'node:fs';
7
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, statSync } from 'node:fs';
8
8
  import { join } from 'node:path';
9
+ import { randomBytes } from 'node:crypto';
9
10
  import { getProjectCwd } from './types.js';
10
- function logEvent(kind, data) {
11
- try {
12
- const dir = join(getProjectCwd(), '.monomind', 'swarm');
13
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
14
- const event = { ts: new Date().toISOString(), source: 'mcp', kind, ...data };
15
- appendFileSync(join(dir, 'events.jsonl'), JSON.stringify(event) + '\n');
16
- } catch { }
17
- }
18
11
  // Swarm state persistence
19
12
  const SWARM_DIR = '.monomind/swarm';
20
13
  const SWARM_STATE_FILE = 'swarm-state.json';
@@ -30,10 +23,13 @@ function ensureSwarmDir() {
30
23
  mkdirSync(dir, { recursive: true, mode: 0o700 });
31
24
  }
32
25
  }
26
+ const MAX_SWARM_STORE_BYTES = 10 * 1024 * 1024;
33
27
  function loadSwarmStore() {
34
28
  try {
35
29
  const path = getSwarmStatePath();
36
30
  if (existsSync(path)) {
31
+ if (statSync(path).size > MAX_SWARM_STORE_BYTES)
32
+ return { swarms: {}, version: '3.0.0' };
37
33
  return JSON.parse(readFileSync(path, 'utf-8'));
38
34
  }
39
35
  }
@@ -42,7 +38,10 @@ function loadSwarmStore() {
42
38
  }
43
39
  function saveSwarmStore(store) {
44
40
  ensureSwarmDir();
45
- writeFileSync(getSwarmStatePath(), JSON.stringify(store, null, 2), 'utf-8');
41
+ const dest = getSwarmStatePath();
42
+ const tmp = `${dest}.${process.pid}.${Date.now()}.tmp`;
43
+ writeFileSync(tmp, JSON.stringify(store, null, 2), 'utf-8');
44
+ renameSync(tmp, dest);
46
45
  }
47
46
  // Input validation
48
47
  const VALID_TOPOLOGIES = new Set([
@@ -64,7 +63,7 @@ export const swarmTools = [
64
63
  },
65
64
  handler: async (input) => {
66
65
  const topology = input.topology || 'hierarchical-mesh';
67
- const maxAgents = Math.min(Math.max(input.maxAgents || 15, 1), 50);
66
+ const maxAgents = Math.min(Math.max(input.maxAgents || 8, 1), 50);
68
67
  const strategy = input.strategy || 'specialized';
69
68
  const config = (input.config || {});
70
69
  if (!VALID_TOPOLOGIES.has(topology)) {
@@ -73,7 +72,7 @@ export const swarmTools = [
73
72
  error: `Invalid topology: ${topology}. Valid: ${[...VALID_TOPOLOGIES].join(', ')}`,
74
73
  };
75
74
  }
76
- const swarmId = `swarm-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
75
+ const swarmId = `swarm-${Date.now()}-${randomBytes(6).toString('hex')}`;
77
76
  const now = new Date().toISOString();
78
77
  const swarmState = {
79
78
  swarmId,
@@ -94,9 +93,17 @@ export const swarmTools = [
94
93
  updatedAt: now,
95
94
  };
96
95
  const store = loadSwarmStore();
96
+ const MAX_SWARMS = 500;
97
+ // Evict terminated swarms first to free space
98
+ for (const [id, s] of Object.entries(store.swarms)) {
99
+ if (s.status === 'terminated')
100
+ delete store.swarms[id];
101
+ }
102
+ if (Object.keys(store.swarms).length >= MAX_SWARMS) {
103
+ return { success: false, error: 'Swarm limit reached' };
104
+ }
97
105
  store.swarms[swarmId] = swarmState;
98
106
  saveSwarmStore(store);
99
- logEvent('swarm.init', { swarmId, topology, strategy, maxAgents, config: swarmState.config });
100
107
  return {
101
108
  success: true,
102
109
  swarmId,
@@ -122,7 +129,11 @@ export const swarmTools = [
122
129
  handler: async (input) => {
123
130
  const store = loadSwarmStore();
124
131
  const swarmId = input.swarmId;
125
- if (swarmId && store.swarms[swarmId]) {
132
+ const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
133
+ if (swarmId && FORBIDDEN_KEYS.has(swarmId)) {
134
+ return { status: 'not_found', message: `Swarm ${swarmId} not found` };
135
+ }
136
+ if (swarmId && Object.hasOwn(store.swarms, swarmId)) {
126
137
  const swarm = store.swarms[swarmId];
127
138
  return {
128
139
  swarmId: swarm.swarmId,
@@ -176,9 +187,13 @@ export const swarmTools = [
176
187
  handler: async (input) => {
177
188
  const store = loadSwarmStore();
178
189
  const swarmId = input.swarmId;
190
+ const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
191
+ if (swarmId && FORBIDDEN_KEYS.has(swarmId)) {
192
+ return { success: false, error: `Swarm ${swarmId} not found` };
193
+ }
179
194
  // Find the swarm
180
195
  let target;
181
- if (swarmId && store.swarms[swarmId]) {
196
+ if (swarmId && Object.hasOwn(store.swarms, swarmId)) {
182
197
  target = store.swarms[swarmId];
183
198
  }
184
199
  else {
@@ -204,7 +219,6 @@ export const swarmTools = [
204
219
  target.status = 'terminated';
205
220
  target.updatedAt = new Date().toISOString();
206
221
  saveSwarmStore(store);
207
- logEvent('swarm.shutdown', { swarmId: target.swarmId, topology: target.topology, agentCount: target.agents.length, graceful: input.graceful ?? true });
208
222
  return {
209
223
  success: true,
210
224
  swarmId: target.swarmId,
@@ -228,10 +242,14 @@ export const swarmTools = [
228
242
  handler: async (input) => {
229
243
  const store = loadSwarmStore();
230
244
  const swarmId = input.swarmId;
245
+ const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
246
+ if (swarmId && FORBIDDEN_KEYS.has(swarmId)) {
247
+ return { status: 'not_found', healthy: false, checks: [{ name: 'swarm_exists', status: 'fail', message: `Swarm ${swarmId} not found` }], checkedAt: new Date().toISOString() };
248
+ }
231
249
  // Find the swarm
232
250
  let target;
233
251
  if (swarmId) {
234
- target = store.swarms[swarmId];
252
+ target = Object.hasOwn(store.swarms, swarmId) ? store.swarms[swarmId] : undefined;
235
253
  if (!target) {
236
254
  return {
237
255
  status: 'not_found',
@@ -9,7 +9,7 @@
9
9
  * - os module for system information
10
10
  */
11
11
  import { getProjectCwd } from './types.js';
12
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
12
+ import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync } from 'node:fs';
13
13
  import { join, dirname } from 'node:path';
14
14
  import { fileURLToPath } from 'node:url';
15
15
  import * as os from 'node:os';
@@ -68,7 +68,9 @@ function loadMetrics() {
68
68
  function saveMetrics(metrics) {
69
69
  ensureSystemDir();
70
70
  metrics.lastCheck = new Date().toISOString();
71
- writeFileSync(getMetricsPath(), JSON.stringify(metrics, null, 2), 'utf-8');
71
+ const tmpPath = getMetricsPath() + '.tmp';
72
+ writeFileSync(tmpPath, JSON.stringify(metrics, null, 2), 'utf-8');
73
+ renameSync(tmpPath, getMetricsPath());
72
74
  }
73
75
  export const systemTools = [
74
76
  {
@@ -403,7 +405,6 @@ export const systemTools = [
403
405
  platform: process.platform,
404
406
  arch: process.arch,
405
407
  pid: process.pid,
406
- cwd: getProjectCwd(),
407
408
  env: process.env.NODE_ENV || 'development',
408
409
  features: {
409
410
  swarm: true,
@@ -3,8 +3,9 @@
3
3
  *
4
4
  * Tool definitions for task management with file persistence.
5
5
  */
6
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
6
+ import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync, statSync } from 'node:fs';
7
7
  import { join } from 'node:path';
8
+ import { randomBytes } from 'node:crypto';
8
9
  import { getProjectCwd } from './types.js';
9
10
  // Storage paths
10
11
  const STORAGE_DIR = '.monomind';
@@ -22,12 +23,18 @@ function ensureTaskDir() {
22
23
  mkdirSync(dir, { recursive: true });
23
24
  }
24
25
  }
26
+ const MAX_TASK_STORE_BYTES = 50 * 1024 * 1024;
25
27
  function loadTaskStore() {
26
28
  try {
27
29
  const path = getTaskPath();
28
30
  if (existsSync(path)) {
31
+ if (statSync(path).size > MAX_TASK_STORE_BYTES)
32
+ return { tasks: {}, version: '3.0.0' };
29
33
  const data = readFileSync(path, 'utf-8');
30
- return JSON.parse(data);
34
+ const parsed = JSON.parse(data);
35
+ if (parsed && typeof parsed === 'object' && Object.prototype.hasOwnProperty.call(parsed, '__proto__'))
36
+ return { tasks: {}, version: '3.0.0' };
37
+ return parsed;
31
38
  }
32
39
  }
33
40
  catch {
@@ -37,8 +44,14 @@ function loadTaskStore() {
37
44
  }
38
45
  function saveTaskStore(store) {
39
46
  ensureTaskDir();
40
- writeFileSync(getTaskPath(), JSON.stringify(store, null, 2), 'utf-8');
47
+ const taskPath = getTaskPath();
48
+ // Unique tmp filename — concurrent task_assign/complete calls would
49
+ // otherwise race on the same .tmp file.
50
+ const tmpPath = `${taskPath}.${process.pid}.${Date.now()}.tmp`;
51
+ writeFileSync(tmpPath, JSON.stringify(store, null, 2), 'utf-8');
52
+ renameSync(tmpPath, taskPath);
41
53
  }
54
+ const FORBIDDEN_TASK_IDS = new Set(['__proto__', 'constructor', 'prototype']);
42
55
  export const taskTools = [
43
56
  {
44
57
  name: 'task_create',
@@ -57,7 +70,7 @@ export const taskTools = [
57
70
  },
58
71
  handler: async (input) => {
59
72
  const store = loadTaskStore();
60
- const taskId = `task-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
73
+ const taskId = `task-${Date.now()}-${randomBytes(4).toString('hex')}`;
61
74
  const task = {
62
75
  taskId,
63
76
  type: input.type,
@@ -99,6 +112,8 @@ export const taskTools = [
99
112
  handler: async (input) => {
100
113
  const store = loadTaskStore();
101
114
  const taskId = input.taskId;
115
+ if (FORBIDDEN_TASK_IDS.has(taskId))
116
+ return { taskId, status: 'not_found', error: 'Task not found' };
102
117
  const task = store.tasks[taskId];
103
118
  if (task) {
104
119
  return {
@@ -196,6 +211,8 @@ export const taskTools = [
196
211
  handler: async (input) => {
197
212
  const store = loadTaskStore();
198
213
  const taskId = input.taskId;
214
+ if (FORBIDDEN_TASK_IDS.has(taskId))
215
+ return { taskId, status: 'not_found', error: 'Task not found' };
199
216
  const task = store.tasks[taskId];
200
217
  if (task) {
201
218
  task.status = 'completed';
@@ -209,17 +226,27 @@ export const taskTools = [
209
226
  try {
210
227
  let agentStore = { agents: {} };
211
228
  if (existsSync(agentStorePath)) {
212
- agentStore = JSON.parse(readFileSync(agentStorePath, 'utf-8'));
229
+ const agentRaw = JSON.parse(readFileSync(agentStorePath, 'utf-8'));
230
+ if (agentRaw && typeof agentRaw === 'object' && !Object.prototype.hasOwnProperty.call(agentRaw, '__proto__')) {
231
+ agentStore = agentRaw;
232
+ }
213
233
  }
214
234
  for (const agentId of task.assignedTo) {
215
- if (agentStore.agents[agentId]) {
235
+ const FORBIDDEN_AGENT_IDS_TC = new Set(['__proto__', 'constructor', 'prototype']);
236
+ if (typeof agentId === 'string' && agentId.length > 0 && agentId.length <= 128 &&
237
+ !FORBIDDEN_AGENT_IDS_TC.has(agentId) && Object.hasOwn(agentStore.agents, agentId)) {
216
238
  agentStore.agents[agentId].status = 'idle';
217
239
  agentStore.agents[agentId].currentTask = null;
218
240
  agentStore.agents[agentId].taskCount =
219
241
  (agentStore.agents[agentId].taskCount || 0) + 1;
220
242
  }
221
243
  }
222
- writeFileSync(agentStorePath, JSON.stringify(agentStore, null, 2), 'utf-8');
244
+ const agentDir = join(getProjectCwd(), STORAGE_DIR, 'agents');
245
+ if (!existsSync(agentDir))
246
+ mkdirSync(agentDir, { recursive: true });
247
+ const tmpAgent1 = `${agentStorePath}.${process.pid}.${Date.now()}.tmp`;
248
+ writeFileSync(tmpAgent1, JSON.stringify(agentStore, null, 2), 'utf-8');
249
+ renameSync(tmpAgent1, agentStorePath);
223
250
  }
224
251
  catch {
225
252
  // Best-effort agent sync
@@ -256,6 +283,8 @@ export const taskTools = [
256
283
  handler: async (input) => {
257
284
  const store = loadTaskStore();
258
285
  const taskId = input.taskId;
286
+ if (FORBIDDEN_TASK_IDS.has(taskId))
287
+ return { success: false, taskId, error: 'Task not found' };
259
288
  const task = store.tasks[taskId];
260
289
  if (task) {
261
290
  if (input.status) {
@@ -303,6 +332,8 @@ export const taskTools = [
303
332
  handler: async (input) => {
304
333
  const store = loadTaskStore();
305
334
  const taskId = input.taskId;
335
+ if (FORBIDDEN_TASK_IDS.has(taskId))
336
+ return { taskId, error: 'Task not found' };
306
337
  const task = store.tasks[taskId];
307
338
  if (!task) {
308
339
  return { taskId, error: 'Task not found' };
@@ -317,10 +348,14 @@ export const taskTools = [
317
348
  }
318
349
  }
319
350
  catch { /* ignore */ }
351
+ // Reject IDs that would mutate Object.prototype when used as a key in
352
+ // the JSON-loaded plain object `agentStore.agents`.
353
+ const FORBIDDEN_AGENT_IDS = new Set(['__proto__', 'constructor', 'prototype']);
354
+ const isValidAgentId = (id) => typeof id === 'string' && id.length > 0 && id.length <= 128 && !FORBIDDEN_AGENT_IDS.has(id);
320
355
  if (input.unassign) {
321
356
  // Revert previously assigned agents to idle
322
357
  for (const agentId of previouslyAssigned) {
323
- if (agentStore.agents[agentId]) {
358
+ if (isValidAgentId(agentId) && Object.hasOwn(agentStore.agents, agentId)) {
324
359
  agentStore.agents[agentId].status = 'idle';
325
360
  agentStore.agents[agentId].currentTask = null;
326
361
  }
@@ -328,18 +363,19 @@ export const taskTools = [
328
363
  task.assignedTo = [];
329
364
  }
330
365
  else {
331
- const agentIds = input.agentIds || [];
366
+ const rawIds = input.agentIds || [];
367
+ const agentIds = rawIds.filter(isValidAgentId);
332
368
  // Revert old agents to idle
333
369
  for (const agentId of previouslyAssigned) {
334
- if (!agentIds.includes(agentId) && agentStore.agents[agentId]) {
370
+ if (isValidAgentId(agentId) && !agentIds.includes(agentId) && Object.hasOwn(agentStore.agents, agentId)) {
335
371
  agentStore.agents[agentId].status = 'idle';
336
372
  agentStore.agents[agentId].currentTask = null;
337
373
  }
338
374
  }
339
375
  // Set new agents to active
340
376
  for (const agentId of agentIds) {
341
- if (agentStore.agents[agentId]) {
342
- agentStore.agents[agentId].status = 'active';
377
+ if (Object.hasOwn(agentStore.agents, agentId)) {
378
+ agentStore.agents[agentId].status = 'busy';
343
379
  agentStore.agents[agentId].currentTask = taskId;
344
380
  }
345
381
  }
@@ -358,7 +394,9 @@ export const taskTools = [
358
394
  if (!existsSync(agentDir)) {
359
395
  mkdirSync(agentDir, { recursive: true });
360
396
  }
361
- writeFileSync(agentStorePath, JSON.stringify(agentStore, null, 2), 'utf-8');
397
+ const tmpAgent2 = `${agentStorePath}.${process.pid}.${Date.now()}.tmp`;
398
+ writeFileSync(tmpAgent2, JSON.stringify(agentStore, null, 2), 'utf-8');
399
+ renameSync(tmpAgent2, agentStorePath);
362
400
  return {
363
401
  taskId: task.taskId,
364
402
  assignedTo: task.assignedTo,
@@ -382,6 +420,8 @@ export const taskTools = [
382
420
  handler: async (input) => {
383
421
  const store = loadTaskStore();
384
422
  const taskId = input.taskId;
423
+ if (FORBIDDEN_TASK_IDS.has(taskId))
424
+ return { success: false, taskId, error: 'Task not found' };
385
425
  const task = store.tasks[taskId];
386
426
  if (task) {
387
427
  task.status = 'cancelled';
@@ -4,9 +4,10 @@
4
4
  * Terminal session management with real command execution.
5
5
  */
6
6
  import { getProjectCwd } from './types.js';
7
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
7
+ import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync } from 'node:fs';
8
8
  import { join } from 'node:path';
9
9
  import { execSync } from 'node:child_process';
10
+ import { randomBytes } from 'node:crypto';
10
11
  // Storage paths
11
12
  const STORAGE_DIR = '.monomind';
12
13
  const TERMINAL_DIR = 'terminals';
@@ -37,7 +38,11 @@ function loadTerminalStore() {
37
38
  }
38
39
  function saveTerminalStore(store) {
39
40
  ensureTerminalDir();
40
- writeFileSync(getTerminalPath(), JSON.stringify(store, null, 2), 'utf-8');
41
+ // Unique tmp filename so concurrent handler invocations cannot clobber each
42
+ // other's .tmp mid-write (which would produce a partial JSON on rename).
43
+ const tmpPath = `${getTerminalPath()}.${process.pid}.${Date.now()}.tmp`;
44
+ writeFileSync(tmpPath, JSON.stringify(store, null, 2), 'utf-8');
45
+ renameSync(tmpPath, getTerminalPath());
41
46
  }
42
47
  export const terminalTools = [
43
48
  {
@@ -54,7 +59,19 @@ export const terminalTools = [
54
59
  },
55
60
  handler: async (input) => {
56
61
  const store = loadTerminalStore();
57
- const id = `term-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
62
+ const MAX_SESSIONS = 1000;
63
+ if (Object.keys(store.sessions).length >= MAX_SESSIONS) {
64
+ return { success: false, error: 'Session limit reached' };
65
+ }
66
+ const FORBIDDEN_ENV_KEYS = new Set(['PATH', 'LD_PRELOAD', 'LD_LIBRARY_PATH', 'NODE_OPTIONS', 'NODE_PATH', 'DYLD_INSERT_LIBRARIES', 'DYLD_LIBRARY_PATH']);
67
+ const rawEnv = input.env || {};
68
+ const safeEnv = {};
69
+ for (const [k, v] of Object.entries(rawEnv)) {
70
+ if (!FORBIDDEN_ENV_KEYS.has(k) && /^[A-Z_][A-Z0-9_]*$/i.test(k)) {
71
+ safeEnv[k] = String(v);
72
+ }
73
+ }
74
+ const id = `term-${Date.now()}-${randomBytes(4).toString('hex')}`;
58
75
  const session = {
59
76
  id,
60
77
  name: input.name || `Terminal ${Object.keys(store.sessions).length + 1}`,
@@ -63,7 +80,7 @@ export const terminalTools = [
63
80
  lastActivity: new Date().toISOString(),
64
81
  workingDir: input.workingDir || getProjectCwd(),
65
82
  history: [],
66
- env: input.env || {},
83
+ env: safeEnv,
67
84
  };
68
85
  store.sessions[id] = session;
69
86
  saveTerminalStore(store);
@@ -95,11 +112,17 @@ export const terminalTools = [
95
112
  const store = loadTerminalStore();
96
113
  const sessionId = input.sessionId;
97
114
  const command = input.command;
115
+ const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
116
+ // Reject inherited keys (incl. toString/hasOwnProperty/etc.) so a tampered
117
+ // store.json can't redirect bracket access into Object.prototype.
118
+ if (sessionId && (typeof sessionId !== 'string' || FORBIDDEN_KEYS.has(sessionId) || !Object.hasOwn(store.sessions, sessionId))) {
119
+ return { success: false, error: 'Invalid sessionId' };
120
+ }
98
121
  // Find or create default session
99
122
  let session = sessionId ? store.sessions[sessionId] : Object.values(store.sessions).find(s => s.status === 'active');
100
123
  if (!session) {
101
124
  // Create default session
102
- const id = `term-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
125
+ const id = `term-${Date.now()}-${randomBytes(4).toString('hex')}`;
103
126
  session = {
104
127
  id,
105
128
  name: 'Default Terminal',
@@ -112,7 +135,22 @@ export const terminalTools = [
112
135
  };
113
136
  store.sessions[id] = session;
114
137
  }
115
- const timeout = input.timeout || 30_000;
138
+ // Reject shell metacharacters AND env-prefix syntax. The previous regex
139
+ // allowed `=`, which `/bin/sh` interprets as a per-command env override
140
+ // (`PATH=/tmp/evil ls`, `LD_PRELOAD=/tmp/x.so cmd`) — turning the
141
+ // metacharacter denylist into RCE. Also reject leading-dash so the
142
+ // first arg can't be misinterpreted by the spawned binary as a flag,
143
+ // and reject glob/expansion characters that may evaluate paths.
144
+ if (/[|;&`$\n\r<>=*?~(){}[\]#!\\"']/.test(command)) {
145
+ return { error: 'Command contains disallowed shell metacharacters', allowed: false };
146
+ }
147
+ if (/^\s*-/.test(command)) {
148
+ return { error: 'Command must not start with "-"', allowed: false };
149
+ }
150
+ const rawTimeout = Number(input.timeout);
151
+ const timeout = Number.isFinite(rawTimeout) && rawTimeout > 0
152
+ ? Math.min(rawTimeout, 5 * 60_000)
153
+ : 30_000;
116
154
  const cwd = session.workingDir || getProjectCwd();
117
155
  const startTime = Date.now();
118
156
  let output;
@@ -134,13 +172,16 @@ export const terminalTools = [
134
172
  }
135
173
  const duration = Date.now() - startTime;
136
174
  const timestamp = new Date().toISOString();
137
- // Record in history
138
- session.history.push({
139
- command,
140
- output,
141
- timestamp,
142
- exitCode,
143
- });
175
+ // Record in history (cap output size and total entries to prevent unbounded growth)
176
+ const MAX_OUTPUT_BYTES = 64 * 1024;
177
+ const MAX_HISTORY = 200;
178
+ const truncatedOutput = output.length > MAX_OUTPUT_BYTES
179
+ ? output.slice(0, MAX_OUTPUT_BYTES) + '\n[... truncated ...]'
180
+ : output;
181
+ session.history.push({ command, output: truncatedOutput, timestamp, exitCode });
182
+ if (session.history.length > MAX_HISTORY) {
183
+ session.history.splice(0, session.history.length - MAX_HISTORY);
184
+ }
144
185
  session.lastActivity = timestamp;
145
186
  session.status = 'active';
146
187
  saveTerminalStore(store);
@@ -203,7 +244,11 @@ export const terminalTools = [
203
244
  handler: async (input) => {
204
245
  const store = loadTerminalStore();
205
246
  const sessionId = input.sessionId;
206
- const session = store.sessions[sessionId];
247
+ const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
248
+ if (!sessionId || FORBIDDEN_KEYS.has(sessionId)) {
249
+ return { success: false, error: 'Invalid sessionId' };
250
+ }
251
+ const session = Object.hasOwn(store.sessions, sessionId) ? store.sessions[sessionId] : undefined;
207
252
  if (!session) {
208
253
  return { success: false, error: 'Session not found' };
209
254
  }
@@ -233,7 +278,11 @@ export const terminalTools = [
233
278
  const sessionId = input.sessionId;
234
279
  const limit = input.limit || 50;
235
280
  const offset = input.offset || 0;
281
+ const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
236
282
  if (sessionId) {
283
+ if (typeof sessionId !== 'string' || FORBIDDEN_KEYS.has(sessionId) || !Object.hasOwn(store.sessions, sessionId)) {
284
+ return { success: false, error: 'Invalid sessionId' };
285
+ }
237
286
  const session = store.sessions[sessionId];
238
287
  if (!session) {
239
288
  return { success: false, error: 'Session not found' };