monomind 1.7.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 (562) 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} +22 -9
  91. package/.claude/commands/monomind/help.md +118 -0
  92. package/.claude/commands/{monomind-idea.md → monomind/idea.md} +23 -29
  93. package/.claude/commands/{monomind-improve.md → monomind/improve.md} +24 -30
  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/loop-tracker.cjs +107 -0
  180. package/.claude/helpers/router.cjs +48 -68
  181. package/.claude/helpers/skill-registry.json +89 -104
  182. package/.claude/helpers/statusline.cjs +33 -2
  183. package/.claude/scheduled_tasks.lock +1 -0
  184. package/.claude/settings.json +15 -0
  185. package/.claude/skills/.monomind/data/ranked-context.json +5 -0
  186. package/.claude/skills/.monomind/sessions/current.json +13 -0
  187. package/.claude/skills/.monomind/sessions/session-1777829336455.json +15 -0
  188. package/.claude/skills/.monomind/sessions/session-1777831614725.json +15 -0
  189. package/.claude/skills/.monomind/sessions/session-1777832095857.json +15 -0
  190. package/.claude/skills/.monomind/sessions/session-1777839814183.json +15 -0
  191. package/.claude/skills/.monomind/sessions/session-1777841847131.json +15 -0
  192. package/.claude/skills/.monomind/sessions/session-1777843309463.json +15 -0
  193. package/.claude/skills/.monomind/sessions/session-1777880867159.json +15 -0
  194. package/.claude/skills/.monomind/sessions/session-1777881884593.json +15 -0
  195. package/.claude/skills/.monomind/sessions/session-1777884090471.json +15 -0
  196. package/.claude/skills/.monomind/sessions/session-1777884808221.json +15 -0
  197. package/.claude/skills/.monomind/sessions/session-1777885672155.json +15 -0
  198. package/.claude/skills/.monomind/sessions/session-1777886852818.json +15 -0
  199. package/.claude/skills/.monomind/sessions/session-1777896532690.json +15 -0
  200. package/.claude/skills/agentdb-advanced/SKILL.md +11 -12
  201. package/.claude/skills/agentdb-learning/SKILL.md +20 -21
  202. package/.claude/skills/agentdb-memory-patterns/SKILL.md +28 -30
  203. package/.claude/skills/agentdb-optimization/SKILL.md +11 -12
  204. package/.claude/skills/agentdb-vector-search/SKILL.md +37 -41
  205. package/.claude/skills/{v3-integration-deep → agentic-integration}/SKILL.md +20 -13
  206. package/.claude/skills/agentic-jujutsu/SKILL.md +22 -22
  207. package/.claude/skills/{v3-cli-modernization → cli-modernization}/SKILL.md +17 -8
  208. package/.claude/skills/{v3-core-implementation → core-implementation}/SKILL.md +33 -8
  209. package/.claude/skills/{v3-ddd-architecture → ddd-architecture}/SKILL.md +18 -25
  210. package/.claude/skills/github-code-review/SKILL.md +82 -83
  211. package/.claude/skills/github-multi-repo/SKILL.md +42 -46
  212. package/.claude/skills/github-project-management/SKILL.md +83 -88
  213. package/.claude/skills/github-release-management/SKILL.md +12 -18
  214. package/.claude/skills/github-workflow-automation/SKILL.md +70 -74
  215. package/.claude/skills/hooks-automation/SKILL.md +9 -13
  216. package/.claude/skills/mastermind/_intake.md +83 -0
  217. package/.claude/skills/mastermind/_protocol.md +275 -0
  218. package/.claude/skills/mastermind/architect.md +847 -0
  219. package/.claude/skills/mastermind/build.md +158 -0
  220. package/.claude/skills/mastermind/content.md +185 -0
  221. package/.claude/skills/mastermind/createorg.md +318 -0
  222. package/.claude/skills/mastermind/finance.md +154 -0
  223. package/.claude/skills/mastermind/idea.md +158 -0
  224. package/.claude/skills/mastermind/marketing.md +216 -0
  225. package/.claude/skills/mastermind/monotask.md +350 -0
  226. package/.claude/skills/mastermind/ops.md +156 -0
  227. package/.claude/skills/mastermind/references/copywriting-frameworks.md +181 -0
  228. package/.claude/skills/mastermind/references/persuasion-psychology.md +158 -0
  229. package/.claude/skills/mastermind/release.md +156 -0
  230. package/.claude/skills/mastermind/research.md +156 -0
  231. package/.claude/skills/mastermind/review.md +157 -0
  232. package/.claude/skills/mastermind/runorg.md +308 -0
  233. package/.claude/skills/mastermind/sales.md +158 -0
  234. package/.claude/skills/mastermind/techport.md +743 -0
  235. package/.claude/skills/{v3-mcp-optimization → mcp-optimization}/SKILL.md +35 -14
  236. package/.claude/skills/{v3-memory-unification → memory-unification}/SKILL.md +20 -4
  237. package/.claude/skills/monodesign/SKILL.md +302 -0
  238. package/.claude/skills/monodesign/reference/adapt.md +190 -0
  239. package/.claude/skills/monodesign/reference/animate.md +175 -0
  240. package/.claude/skills/monodesign/reference/antipatterns-catalog.md +187 -0
  241. package/.claude/skills/monodesign/reference/audit.md +133 -0
  242. package/.claude/skills/monodesign/reference/bolder.md +113 -0
  243. package/.claude/skills/monodesign/reference/brand-workflow.md +180 -0
  244. package/.claude/skills/monodesign/reference/brand.md +114 -0
  245. package/.claude/skills/monodesign/reference/clarify.md +174 -0
  246. package/.claude/skills/monodesign/reference/cognitive-load.md +106 -0
  247. package/.claude/skills/monodesign/reference/color-and-contrast.md +105 -0
  248. package/.claude/skills/monodesign/reference/colorize.md +154 -0
  249. package/.claude/skills/monodesign/reference/component-specs.md +260 -0
  250. package/.claude/skills/monodesign/reference/component-states.md +274 -0
  251. package/.claude/skills/monodesign/reference/component-system.md +358 -0
  252. package/.claude/skills/monodesign/reference/copy-formulas.md +160 -0
  253. package/.claude/skills/monodesign/reference/craft.md +193 -0
  254. package/.claude/skills/monodesign/reference/critique.md +213 -0
  255. package/.claude/skills/monodesign/reference/delight.md +302 -0
  256. package/.claude/skills/monodesign/reference/design-principles.md +246 -0
  257. package/.claude/skills/monodesign/reference/distill.md +111 -0
  258. package/.claude/skills/monodesign/reference/document.md +427 -0
  259. package/.claude/skills/monodesign/reference/extract.md +69 -0
  260. package/.claude/skills/monodesign/reference/harden.md +347 -0
  261. package/.claude/skills/monodesign/reference/heuristics-scoring.md +234 -0
  262. package/.claude/skills/monodesign/reference/image-prompts.md +118 -0
  263. package/.claude/skills/monodesign/reference/interaction-design.md +195 -0
  264. package/.claude/skills/monodesign/reference/layout.md +141 -0
  265. package/.claude/skills/monodesign/reference/live.md +622 -0
  266. package/.claude/skills/monodesign/reference/motion-design.md +109 -0
  267. package/.claude/skills/monodesign/reference/onboard.md +234 -0
  268. package/.claude/skills/monodesign/reference/optimize.md +258 -0
  269. package/.claude/skills/monodesign/reference/overdrive.md +130 -0
  270. package/.claude/skills/monodesign/reference/personas.md +179 -0
  271. package/.claude/skills/monodesign/reference/polish.md +233 -0
  272. package/.claude/skills/monodesign/reference/pre-delivery-checklist.md +108 -0
  273. package/.claude/skills/monodesign/reference/product.md +62 -0
  274. package/.claude/skills/monodesign/reference/quieter.md +99 -0
  275. package/.claude/skills/monodesign/reference/responsive-design.md +114 -0
  276. package/.claude/skills/monodesign/reference/shape.md +151 -0
  277. package/.claude/skills/monodesign/reference/spatial-design.md +100 -0
  278. package/.claude/skills/monodesign/reference/teach.md +156 -0
  279. package/.claude/skills/monodesign/reference/token-architecture.md +222 -0
  280. package/.claude/skills/monodesign/reference/typeset.md +124 -0
  281. package/.claude/skills/monodesign/reference/typography.md +159 -0
  282. package/.claude/skills/monodesign/reference/ux-research.md +143 -0
  283. package/.claude/skills/monodesign/reference/ux-rules.md +211 -0
  284. package/.claude/skills/monodesign/reference/ux-writing.md +107 -0
  285. package/.claude/skills/monomotion/SKILL.md +145 -0
  286. package/.claude/skills/monomotion/rules/api-control.md +139 -0
  287. package/.claude/skills/monomotion/rules/effects.md +109 -0
  288. package/.claude/skills/monomotion/rules/integration.md +140 -0
  289. package/.claude/skills/monomotion/rules/scroll.md +131 -0
  290. package/.claude/skills/monomotion/rules/sequencing.md +105 -0
  291. package/.claude/skills/monomotion/rules/svg.md +101 -0
  292. package/.claude/skills/monomotion/rules/text.md +119 -0
  293. package/.claude/skills/pair-programming/SKILL.md +1 -1
  294. package/.claude/skills/performance-analysis/SKILL.md +3 -3
  295. package/.claude/skills/{v3-performance-optimization → performance-optimization}/SKILL.md +16 -8
  296. package/.claude/skills/reasoningbank-agentdb/SKILL.md +17 -19
  297. package/.claude/skills/reasoningbank-intelligence/SKILL.md +4 -6
  298. package/.claude/skills/{v3-security-overhaul → security-hardening}/SKILL.md +13 -3
  299. package/.claude/skills/skill-builder/SKILL.md +19 -19
  300. package/.claude/skills/sparc-methodology/SKILL.md +55 -211
  301. package/.claude/skills/stop-slop/SKILL.md +67 -0
  302. package/.claude/skills/stop-slop/references/examples.md +61 -0
  303. package/.claude/skills/stop-slop/references/phrases.md +130 -0
  304. package/.claude/skills/stop-slop/references/structures.md +136 -0
  305. package/.claude/skills/swarm-advanced/SKILL.md +13 -43
  306. package/.claude/skills/{v3-swarm-coordination → swarm-coordination}/SKILL.md +39 -21
  307. package/.claude/skills/swarm-orchestration/SKILL.md +12 -12
  308. package/.claude/skills/verification-quality/SKILL.md +5 -5
  309. package/README.md +5 -5
  310. package/package.json +1 -1
  311. package/packages/@monomind/cli/README.md +5 -5
  312. package/packages/@monomind/cli/bin/cli.js +78 -13
  313. package/packages/@monomind/cli/dist/src/agents/halt-signal.js +33 -7
  314. package/packages/@monomind/cli/dist/src/agents/managed-agent.js +5 -2
  315. package/packages/@monomind/cli/dist/src/agents/prompt-experiment.d.ts +3 -2
  316. package/packages/@monomind/cli/dist/src/agents/prompt-experiment.js +1 -1
  317. package/packages/@monomind/cli/dist/src/agents/prompt-version-manager.d.ts +5 -2
  318. package/packages/@monomind/cli/dist/src/agents/prompt-version-manager.js +26 -4
  319. package/packages/@monomind/cli/dist/src/agents/specialization-scorer.js +17 -9
  320. package/packages/@monomind/cli/dist/src/agents/trigger-scanner.d.ts +5 -3
  321. package/packages/@monomind/cli/dist/src/agents/trigger-scanner.js +58 -10
  322. package/packages/@monomind/cli/dist/src/agents/version-store.d.ts +0 -1
  323. package/packages/@monomind/cli/dist/src/agents/version-store.js +44 -21
  324. package/packages/@monomind/cli/dist/src/autopilot-state.js +79 -28
  325. package/packages/@monomind/cli/dist/src/benchmarks/benchmark-runner.d.ts +7 -2
  326. package/packages/@monomind/cli/dist/src/benchmarks/benchmark-runner.js +20 -8
  327. package/packages/@monomind/cli/dist/src/benchmarks/metric-evaluators.d.ts +2 -1
  328. package/packages/@monomind/cli/dist/src/benchmarks/metric-evaluators.js +25 -2
  329. package/packages/@monomind/cli/dist/src/commands/agent.js +6 -4
  330. package/packages/@monomind/cli/dist/src/commands/appliance-advanced.js +23 -0
  331. package/packages/@monomind/cli/dist/src/commands/autopilot.js +3 -3
  332. package/packages/@monomind/cli/dist/src/commands/benchmark.js +119 -8
  333. package/packages/@monomind/cli/dist/src/commands/claims.js +22 -14
  334. package/packages/@monomind/cli/dist/src/commands/config.js +32 -0
  335. package/packages/@monomind/cli/dist/src/commands/daemon.js +13 -11
  336. package/packages/@monomind/cli/dist/src/commands/deployment.js +21 -2
  337. package/packages/@monomind/cli/dist/src/commands/doctor.js +28 -62
  338. package/packages/@monomind/cli/dist/src/commands/embeddings.js +124 -48
  339. package/packages/@monomind/cli/dist/src/commands/hive-mind.js +15 -14
  340. package/packages/@monomind/cli/dist/src/commands/hooks.js +45 -41
  341. package/packages/@monomind/cli/dist/src/commands/index.d.ts +2 -0
  342. package/packages/@monomind/cli/dist/src/commands/index.js +20 -7
  343. package/packages/@monomind/cli/dist/src/commands/init.js +53 -19
  344. package/packages/@monomind/cli/dist/src/commands/mcp.js +31 -44
  345. package/packages/@monomind/cli/dist/src/commands/memory.js +47 -15
  346. package/packages/@monomind/cli/dist/src/commands/migrate.js +156 -108
  347. package/packages/@monomind/cli/dist/src/commands/monograph.d.ts +8 -0
  348. package/packages/@monomind/cli/dist/src/commands/monograph.js +526 -0
  349. package/packages/@monomind/cli/dist/src/commands/neural.js +96 -56
  350. package/packages/@monomind/cli/dist/src/commands/performance.js +30 -8
  351. package/packages/@monomind/cli/dist/src/commands/plugins.js +13 -37
  352. package/packages/@monomind/cli/dist/src/commands/process.js +25 -2
  353. package/packages/@monomind/cli/dist/src/commands/providers.js +37 -5
  354. package/packages/@monomind/cli/dist/src/commands/replay.js +4 -4
  355. package/packages/@monomind/cli/dist/src/commands/route.js +37 -5
  356. package/packages/@monomind/cli/dist/src/commands/ruvector/import.js +12 -2
  357. package/packages/@monomind/cli/dist/src/commands/ruvector/init.js +15 -0
  358. package/packages/@monomind/cli/dist/src/commands/ruvector/status.js +16 -3
  359. package/packages/@monomind/cli/dist/src/commands/security.js +342 -193
  360. package/packages/@monomind/cli/dist/src/commands/session.js +51 -8
  361. package/packages/@monomind/cli/dist/src/commands/start.js +18 -4
  362. package/packages/@monomind/cli/dist/src/commands/swarm.js +47 -36
  363. package/packages/@monomind/cli/dist/src/commands/tokens.js +11 -11
  364. package/packages/@monomind/cli/dist/src/commands/transfer-store.js +1 -1
  365. package/packages/@monomind/cli/dist/src/commands/workflow.js +31 -4
  366. package/packages/@monomind/cli/dist/src/config-adapter.d.ts +2 -1
  367. package/packages/@monomind/cli/dist/src/consensus/audit-writer.js +46 -13
  368. package/packages/@monomind/cli/dist/src/consensus/vote-signer.d.ts +0 -3
  369. package/packages/@monomind/cli/dist/src/consensus/vote-signer.js +9 -1
  370. package/packages/@monomind/cli/dist/src/dlq/dlq-reader.d.ts +4 -2
  371. package/packages/@monomind/cli/dist/src/dlq/dlq-reader.js +25 -8
  372. package/packages/@monomind/cli/dist/src/dlq/dlq-replayer.d.ts +10 -3
  373. package/packages/@monomind/cli/dist/src/dlq/dlq-replayer.js +50 -16
  374. package/packages/@monomind/cli/dist/src/dlq/dlq-writer.js +27 -5
  375. package/packages/@monomind/cli/dist/src/eval/dataset-manager.d.ts +2 -2
  376. package/packages/@monomind/cli/dist/src/eval/dataset-manager.js +26 -16
  377. package/packages/@monomind/cli/dist/src/eval/trace-collector.js +23 -3
  378. package/packages/@monomind/cli/dist/src/index.js +12 -10
  379. package/packages/@monomind/cli/dist/src/init/claudemd-generator.js +8 -8
  380. package/packages/@monomind/cli/dist/src/init/executor.js +163 -137
  381. package/packages/@monomind/cli/dist/src/init/helpers-generator.js +49 -36
  382. package/packages/@monomind/cli/dist/src/init/mcp-generator.js +3 -3
  383. package/packages/@monomind/cli/dist/src/init/settings-generator.js +10 -3
  384. package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.js +18 -3
  385. package/packages/@monomind/cli/dist/src/init/statusline-generator.js +3 -1
  386. package/packages/@monomind/cli/dist/src/init/types.d.ts +35 -11
  387. package/packages/@monomind/cli/dist/src/init/types.js +5 -9
  388. package/packages/@monomind/cli/dist/src/interactive/interrupt.js +8 -3
  389. package/packages/@monomind/cli/dist/src/mcp/tool-registry.js +38 -4
  390. package/packages/@monomind/cli/dist/src/mcp-client.js +15 -6
  391. package/packages/@monomind/cli/dist/src/mcp-server.d.ts +9 -2
  392. package/packages/@monomind/cli/dist/src/mcp-server.js +182 -35
  393. package/packages/@monomind/cli/dist/src/mcp-tools/agent-tools.js +66 -34
  394. package/packages/@monomind/cli/dist/src/mcp-tools/agentdb-tools.js +34 -7
  395. package/packages/@monomind/cli/dist/src/mcp-tools/analyze-tools.js +25 -16
  396. package/packages/@monomind/cli/dist/src/mcp-tools/auto-install.js +4 -6
  397. package/packages/@monomind/cli/dist/src/mcp-tools/autopilot-tools.js +12 -2
  398. package/packages/@monomind/cli/dist/src/mcp-tools/browser-tools.js +199 -20
  399. package/packages/@monomind/cli/dist/src/mcp-tools/claims-tools.js +68 -18
  400. package/packages/@monomind/cli/dist/src/mcp-tools/config-tools.js +33 -5
  401. package/packages/@monomind/cli/dist/src/mcp-tools/coordination-tools.js +59 -4
  402. package/packages/@monomind/cli/dist/src/mcp-tools/daa-tools.js +46 -10
  403. package/packages/@monomind/cli/dist/src/mcp-tools/embeddings-tools.js +46 -5
  404. package/packages/@monomind/cli/dist/src/mcp-tools/github-tools.js +29 -16
  405. package/packages/@monomind/cli/dist/src/mcp-tools/graphify-tools.d.ts +4 -67
  406. package/packages/@monomind/cli/dist/src/mcp-tools/graphify-tools.js +40 -1250
  407. package/packages/@monomind/cli/dist/src/mcp-tools/guidance-tools.js +38 -10
  408. package/packages/@monomind/cli/dist/src/mcp-tools/hive-mind-tools.js +96 -33
  409. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-tools.js +70 -37
  410. package/packages/@monomind/cli/dist/src/mcp-tools/index.d.ts +1 -0
  411. package/packages/@monomind/cli/dist/src/mcp-tools/index.js +1 -0
  412. package/packages/@monomind/cli/dist/src/mcp-tools/memory-tools.js +29 -13
  413. package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.d.ts +9 -0
  414. package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +6306 -0
  415. package/packages/@monomind/cli/dist/src/mcp-tools/neural-tools.js +121 -37
  416. package/packages/@monomind/cli/dist/src/mcp-tools/performance-tools.js +21 -8
  417. package/packages/@monomind/cli/dist/src/mcp-tools/progress-tools.js +10 -8
  418. package/packages/@monomind/cli/dist/src/mcp-tools/request-tracker.js +4 -1
  419. package/packages/@monomind/cli/dist/src/mcp-tools/ruvllm-tools.js +19 -8
  420. package/packages/@monomind/cli/dist/src/mcp-tools/session-tools.js +57 -17
  421. package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +35 -17
  422. package/packages/@monomind/cli/dist/src/mcp-tools/system-tools.js +4 -3
  423. package/packages/@monomind/cli/dist/src/mcp-tools/task-tools.js +53 -13
  424. package/packages/@monomind/cli/dist/src/mcp-tools/terminal-tools.js +63 -14
  425. package/packages/@monomind/cli/dist/src/mcp-tools/transfer-tools.js +21 -16
  426. package/packages/@monomind/cli/dist/src/mcp-tools/workflow-tools.js +92 -23
  427. package/packages/@monomind/cli/dist/src/memory/ewc-consolidation.js +41 -10
  428. package/packages/@monomind/cli/dist/src/memory/intelligence.d.ts +2 -2
  429. package/packages/@monomind/cli/dist/src/memory/intelligence.js +39 -13
  430. package/packages/@monomind/cli/dist/src/memory/memory-bridge.d.ts +1 -0
  431. package/packages/@monomind/cli/dist/src/memory/memory-bridge.js +149 -56
  432. package/packages/@monomind/cli/dist/src/memory/memory-initializer.js +107 -45
  433. package/packages/@monomind/cli/dist/src/memory/sona-optimizer.d.ts +8 -1
  434. package/packages/@monomind/cli/dist/src/memory/sona-optimizer.js +25 -8
  435. package/packages/@monomind/cli/dist/src/observability/replay-reader.d.ts +40 -0
  436. package/packages/@monomind/cli/dist/src/observability/replay-reader.js +138 -0
  437. package/packages/@monomind/cli/dist/src/orchestration/routing-modes.js +35 -5
  438. package/packages/@monomind/cli/dist/src/parser.d.ts +8 -0
  439. package/packages/@monomind/cli/dist/src/parser.js +48 -14
  440. package/packages/@monomind/cli/dist/src/plugins/manager.js +112 -19
  441. package/packages/@monomind/cli/dist/src/plugins/store/discovery.d.ts +1 -1
  442. package/packages/@monomind/cli/dist/src/plugins/store/discovery.js +80 -62
  443. package/packages/@monomind/cli/dist/src/production/circuit-breaker.js +8 -1
  444. package/packages/@monomind/cli/dist/src/production/error-handler.d.ts +4 -2
  445. package/packages/@monomind/cli/dist/src/production/error-handler.js +27 -5
  446. package/packages/@monomind/cli/dist/src/production/monitoring.js +8 -4
  447. package/packages/@monomind/cli/dist/src/production/rate-limiter.js +30 -22
  448. package/packages/@monomind/cli/dist/src/ruvector/agent-wasm.js +2 -2
  449. package/packages/@monomind/cli/dist/src/ruvector/coverage-router.js +19 -9
  450. package/packages/@monomind/cli/dist/src/ruvector/diff-classifier.d.ts +1 -0
  451. package/packages/@monomind/cli/dist/src/ruvector/diff-classifier.js +26 -6
  452. package/packages/@monomind/cli/dist/src/ruvector/enhanced-model-router.js +24 -2
  453. package/packages/@monomind/cli/dist/src/ruvector/index.d.ts +1 -2
  454. package/packages/@monomind/cli/dist/src/ruvector/index.js +2 -2
  455. package/packages/@monomind/cli/dist/src/ruvector/model-router.d.ts +4 -2
  456. package/packages/@monomind/cli/dist/src/ruvector/model-router.js +30 -6
  457. package/packages/@monomind/cli/dist/src/ruvector/moe-router.d.ts +7 -0
  458. package/packages/@monomind/cli/dist/src/ruvector/moe-router.js +35 -12
  459. package/packages/@monomind/cli/dist/src/ruvector/q-learning-router.d.ts +7 -1
  460. package/packages/@monomind/cli/dist/src/ruvector/q-learning-router.js +40 -9
  461. package/packages/@monomind/cli/dist/src/services/claim-service.d.ts +3 -1
  462. package/packages/@monomind/cli/dist/src/services/claim-service.js +33 -2
  463. package/packages/@monomind/cli/dist/src/services/config-file-manager.d.ts +16 -2
  464. package/packages/@monomind/cli/dist/src/services/config-file-manager.js +105 -17
  465. package/packages/@monomind/cli/dist/src/services/container-worker-pool.js +51 -11
  466. package/packages/@monomind/cli/dist/src/services/headless-worker-executor.d.ts +7 -0
  467. package/packages/@monomind/cli/dist/src/services/headless-worker-executor.js +188 -45
  468. package/packages/@monomind/cli/dist/src/services/registry-api.js +62 -9
  469. package/packages/@monomind/cli/dist/src/services/ruvector-training.js +8 -0
  470. package/packages/@monomind/cli/dist/src/services/worker-daemon.d.ts +4 -1
  471. package/packages/@monomind/cli/dist/src/services/worker-daemon.js +112 -28
  472. package/packages/@monomind/cli/dist/src/services/worker-queue.d.ts +9 -2
  473. package/packages/@monomind/cli/dist/src/services/worker-queue.js +86 -5
  474. package/packages/@monomind/cli/dist/src/suggest.js +9 -0
  475. package/packages/@monomind/cli/dist/src/swarm/flow-enforcer.d.ts +5 -3
  476. package/packages/@monomind/cli/dist/src/swarm/flow-enforcer.js +17 -5
  477. package/packages/@monomind/cli/dist/src/swarm/flow-visualizer.d.ts +3 -0
  478. package/packages/@monomind/cli/dist/src/swarm/flow-visualizer.js +30 -6
  479. package/packages/@monomind/cli/dist/src/transfer/anonymization/index.js +5 -3
  480. package/packages/@monomind/cli/dist/src/transfer/export.js +5 -3
  481. package/packages/@monomind/cli/dist/src/transfer/ipfs/client.js +84 -7
  482. package/packages/@monomind/cli/dist/src/transfer/ipfs/upload.js +13 -4
  483. package/packages/@monomind/cli/dist/src/transfer/storage/gcs.js +19 -10
  484. package/packages/@monomind/cli/dist/src/transfer/store/discovery.d.ts +9 -2
  485. package/packages/@monomind/cli/dist/src/transfer/store/discovery.js +68 -13
  486. package/packages/@monomind/cli/dist/src/transfer/store/download.d.ts +15 -6
  487. package/packages/@monomind/cli/dist/src/transfer/store/download.js +113 -24
  488. package/packages/@monomind/cli/dist/src/transfer/store/publish.d.ts +1 -1
  489. package/packages/@monomind/cli/dist/src/transfer/store/publish.js +13 -14
  490. package/packages/@monomind/cli/dist/src/transfer/store/registry.d.ts +3 -3
  491. package/packages/@monomind/cli/dist/src/transfer/store/registry.js +32 -16
  492. package/packages/@monomind/cli/dist/src/update/checker.js +17 -4
  493. package/packages/@monomind/cli/dist/src/update/executor.js +25 -20
  494. package/packages/@monomind/cli/dist/src/update/rate-limiter.d.ts +11 -0
  495. package/packages/@monomind/cli/dist/src/update/rate-limiter.js +23 -3
  496. package/packages/@monomind/cli/dist/src/utils/parse-jsonl.d.ts +6 -0
  497. package/packages/@monomind/cli/dist/src/utils/parse-jsonl.js +22 -0
  498. package/packages/@monomind/cli/dist/src/workflow/condition-evaluator.js +37 -3
  499. package/packages/@monomind/cli/dist/src/workflow/dag-builder.js +27 -11
  500. package/packages/@monomind/cli/dist/src/workflow/dag-executor.js +51 -13
  501. package/packages/@monomind/cli/dist/src/workflow/dsl-schema.d.ts +3 -0
  502. package/packages/@monomind/cli/dist/src/workflow/dsl-schema.js +6 -2
  503. package/packages/@monomind/cli/dist/src/workflow/template-engine.js +7 -0
  504. package/packages/@monomind/cli/dist/src/workflow/workflow-executor.js +95 -14
  505. package/packages/@monomind/cli/package.json +5 -2
  506. package/packages/@monomind/guidance/README.md +0 -3
  507. package/packages/@monomind/shared/README.md +0 -1
  508. package/packages/@monomind/shared/dist/types/consensus-audit.d.ts +3 -1
  509. package/packages/README.md +15 -16
  510. package/.claude/agents/design/design-brand-guardian.md +0 -323
  511. package/.claude/agents/design/design-image-prompt-engineer.md +0 -237
  512. package/.claude/agents/design/design-inclusive-visuals-specialist.md +0 -72
  513. package/.claude/agents/design/design-ui-designer.md +0 -384
  514. package/.claude/agents/design/design-ux-architect.md +0 -470
  515. package/.claude/agents/design/design-ux-researcher.md +0 -330
  516. package/.claude/agents/design/design-visual-storyteller.md +0 -150
  517. package/.claude/agents/design/design-whimsy-injector.md +0 -439
  518. package/.claude/agents/v3/integration-architect.md +0 -338
  519. package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +0 -54
  520. package/.claude/commands/coordination/init.md +0 -44
  521. package/.claude/commands/coordination/orchestrate.md +0 -43
  522. package/.claude/commands/coordination/spawn.md +0 -45
  523. package/.claude/commands/github/code-review-swarm.md +0 -550
  524. package/.claude/commands/github/code-review.md +0 -25
  525. package/.claude/commands/github/github-swarm.md +0 -121
  526. package/.claude/commands/github/issue-triage.md +0 -25
  527. package/.claude/commands/github/multi-repo-swarm.md +0 -519
  528. package/.claude/commands/github/pr-enhance.md +0 -26
  529. package/.claude/commands/github/project-board-sync.md +0 -471
  530. package/.claude/commands/github/release-swarm.md +0 -590
  531. package/.claude/commands/github/repo-analyze.md +0 -25
  532. package/.claude/commands/github/swarm-issue.md +0 -482
  533. package/.claude/commands/github/swarm-pr.md +0 -310
  534. package/.claude/commands/github/workflow-automation.md +0 -468
  535. package/.claude/commands/hive-mind/hive-mind-metrics.md +0 -8
  536. package/.claude/commands/hive-mind/hive-mind-resume.md +0 -8
  537. package/.claude/commands/hive-mind/hive-mind-sessions.md +0 -8
  538. package/.claude/commands/hive-mind/hive-mind-wizard.md +0 -8
  539. package/.claude/commands/list-agents.md +0 -17
  540. package/.claude/commands/memory/memory-persist.md +0 -25
  541. package/.claude/commands/memory/memory-usage.md +0 -25
  542. package/.claude/commands/memory/neural.md +0 -47
  543. package/.claude/commands/metrics.md +0 -11
  544. package/.claude/commands/monitoring/real-time-view.md +0 -25
  545. package/.claude/commands/monitoring/swarm-monitor.md +0 -25
  546. package/.claude/commands/monomind-createtask.md +0 -302
  547. package/.claude/commands/monomind-help.md +0 -103
  548. package/.claude/commands/monomind-memory.md +0 -107
  549. package/.claude/commands/monomind-repeat.md +0 -149
  550. package/.claude/commands/monomind-swarm.md +0 -205
  551. package/.claude/commands/optimization/cache-manage.md +0 -25
  552. package/.claude/commands/optimization/topology-optimize.md +0 -25
  553. package/.claude/commands/pair/commands.md +0 -546
  554. package/.claude/commands/pair/config.md +0 -510
  555. package/.claude/commands/pair/start.md +0 -209
  556. package/.claude/commands/use-agent.md +0 -67
  557. package/.claude/skills/monomind-createtask/SKILL.md +0 -269
  558. package/.claude/skills/monomind-task-engine/SKILL.md +0 -358
  559. /package/.claude/agents/{v3 → specialists}/memory-specialist.md +0 -0
  560. /package/.claude/agents/{v3 → specialists}/performance-engineer.md +0 -0
  561. /package/.claude/agents/{v3 → specialists}/queen-coordinator.md +0 -0
  562. /package/.claude/agents/{v3 → specialists}/security-architect.md +0 -0
@@ -7,6 +7,7 @@ import { confirm, input, select } from '../prompt.js';
7
7
  import { callMCPTool, MCPClientError } from '../mcp-client.js';
8
8
  import * as fs from 'fs';
9
9
  import * as path from 'path';
10
+ import { gzipSync } from 'node:zlib';
10
11
  // Format date for display
11
12
  function formatDate(dateStr) {
12
13
  const date = new Date(dateStr);
@@ -472,11 +473,27 @@ const exportCommand = {
472
473
  else {
473
474
  content = JSON.stringify(result.data, null, 2);
474
475
  }
475
- // Write to file
476
+ // Path traversal protection: resolved path must stay within CWD
477
+ const effectiveCwd = ctx.cwd || process.cwd();
476
478
  const absolutePath = path.isAbsolute(outputPath)
477
479
  ? outputPath
478
- : path.join(ctx.cwd, outputPath);
479
- fs.writeFileSync(absolutePath, content, 'utf-8');
480
+ : path.join(effectiveCwd, outputPath);
481
+ const resolvedOutputPath = path.resolve(absolutePath);
482
+ const resolvedCwd = path.resolve(effectiveCwd);
483
+ if (!resolvedOutputPath.startsWith(resolvedCwd + path.sep) && resolvedOutputPath !== resolvedCwd) {
484
+ output.printError(`Output path must be within the working directory.`);
485
+ return { success: false, exitCode: 1 };
486
+ }
487
+ // Write atomically (tmp + rename) to avoid partial writes — use resolvedOutputPath
488
+ const tmpPath = `${resolvedOutputPath}.${process.pid}.${Date.now()}.tmp`;
489
+ if (compress) {
490
+ const compressed = gzipSync(Buffer.from(content, 'utf-8'));
491
+ fs.writeFileSync(tmpPath, compressed);
492
+ }
493
+ else {
494
+ fs.writeFileSync(tmpPath, content, 'utf-8');
495
+ }
496
+ fs.renameSync(tmpPath, resolvedOutputPath);
480
497
  spinner.succeed('Session exported');
481
498
  output.writeln();
482
499
  output.printTable({
@@ -542,10 +559,27 @@ const importCommand = {
542
559
  const absolutePath = path.isAbsolute(filePath)
543
560
  ? filePath
544
561
  : path.join(ctx.cwd, filePath);
562
+ // Path traversal protection: resolved path must stay within cwd or home
563
+ const resolvedPath = path.resolve(absolutePath);
564
+ const cwd = process.cwd();
565
+ const home = process.env.HOME || '';
566
+ const underCwd = resolvedPath === cwd || resolvedPath.startsWith(cwd + path.sep);
567
+ const underHome = home && (resolvedPath === home || resolvedPath.startsWith(home + path.sep));
568
+ if (!underCwd && !underHome) {
569
+ output.printError(`Path '${filePath}' escapes the allowed directories.`);
570
+ return { success: false, exitCode: 1 };
571
+ }
545
572
  if (!fs.existsSync(absolutePath)) {
546
573
  output.printError(`File not found: ${absolutePath}`);
547
574
  return { success: false, exitCode: 1 };
548
575
  }
576
+ // Reject oversized files before reading into memory
577
+ const MAX_IMPORT_BYTES = 50 * 1024 * 1024; // 50 MB
578
+ const stat = fs.statSync(absolutePath);
579
+ if (stat.size > MAX_IMPORT_BYTES) {
580
+ output.printError(`File too large: ${absolutePath} (${(stat.size / 1024 / 1024).toFixed(1)} MB > 50 MB limit)`);
581
+ return { success: false, exitCode: 1 };
582
+ }
549
583
  const spinner = output.createSpinner({ text: 'Importing session...' });
550
584
  spinner.start();
551
585
  try {
@@ -553,11 +587,16 @@ const importCommand = {
553
587
  let data;
554
588
  // Parse based on extension
555
589
  if (absolutePath.endsWith('.yaml') || absolutePath.endsWith('.yml')) {
556
- // Simple YAML parsing (basic implementation)
557
- data = JSON.parse(content); // Would need proper YAML parser
590
+ output.printError('YAML import is not supported. Please convert to JSON first.');
591
+ spinner.fail('Import failed');
592
+ return { success: false, exitCode: 1 };
558
593
  }
559
594
  else {
560
- data = JSON.parse(content);
595
+ data = JSON.parse(content, (key, value) => {
596
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype')
597
+ return undefined;
598
+ return value;
599
+ });
561
600
  }
562
601
  const result = await callMCPTool('session_import', {
563
602
  data,
@@ -678,8 +717,12 @@ function toSimpleYaml(obj, indent = 0) {
678
717
  return String(obj);
679
718
  if (typeof obj === 'number')
680
719
  return String(obj);
681
- if (typeof obj === 'string')
682
- return obj.includes(':') ? `"${obj}"` : obj;
720
+ if (typeof obj === 'string') {
721
+ const needsQuoting = /[:"'\n\r\\]|^(true|false|null|yes|no|on|off)$/i.test(obj) || /^\s|\s$/.test(obj) || /^[!&|>{\[]/.test(obj);
722
+ if (needsQuoting)
723
+ return `"${obj.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
724
+ return obj;
725
+ }
683
726
  const spaces = ' '.repeat(indent);
684
727
  let result = '';
685
728
  if (Array.isArray(obj)) {
@@ -83,8 +83,8 @@ function loadConfig(cwd) {
83
83
  // Main start action
84
84
  const startAction = async (ctx) => {
85
85
  const daemon = ctx.flags.daemon;
86
- const port = ctx.flags.port || DEFAULT_PORT;
87
- const topology = ctx.flags.topology || DEFAULT_TOPOLOGY;
86
+ const port = ctx.flags.port;
87
+ const topology = ctx.flags.topology;
88
88
  const skipMcp = ctx.flags['skip-mcp'];
89
89
  const cwd = ctx.cwd;
90
90
  // Check initialization
@@ -174,9 +174,23 @@ const startAction = async (ctx) => {
174
174
  if (daemon) {
175
175
  output.writeln();
176
176
  output.printInfo('Running in daemon mode. Use "monomind stop" to stop.');
177
- // Store PID for daemon management
177
+ // Store PID for daemon management.
178
+ // wx flag refuses to follow a pre-staged symlink at the path; mode 0o600
179
+ // keeps the file from being world-readable on multi-user systems.
178
180
  const daemonPidPath = path.join(cwd, '.monomind', 'daemon.pid');
179
- fs.writeFileSync(daemonPidPath, String(process.pid));
181
+ try {
182
+ fs.writeFileSync(daemonPidPath, String(process.pid), { flag: 'wx', mode: 0o600 });
183
+ }
184
+ catch (e) {
185
+ if (e.code === 'EEXIST') {
186
+ // Stale PID file — caller should have verified the prior daemon is dead
187
+ fs.unlinkSync(daemonPidPath);
188
+ fs.writeFileSync(daemonPidPath, String(process.pid), { flag: 'wx', mode: 0o600 });
189
+ }
190
+ else {
191
+ throw e;
192
+ }
193
+ }
180
194
  // Detach from parent process for true daemon behavior
181
195
  if (process.platform !== 'win32') {
182
196
  // Unix-like systems: create new session
@@ -221,7 +221,7 @@ const initCommand = {
221
221
  ],
222
222
  action: async (ctx) => {
223
223
  let topology = ctx.flags.topology;
224
- const maxAgents = ctx.flags.maxAgents || 15;
224
+ const maxAgents = ctx.flags['max-agents'] || 15;
225
225
  const v1Mode = ctx.flags.v1Mode;
226
226
  // mode enables hierarchical-mesh hybrid
227
227
  if (v1Mode) {
@@ -248,7 +248,7 @@ const initCommand = {
248
248
  consensusMechanism: 'majority',
249
249
  failureHandling: 'retry',
250
250
  loadBalancing: true,
251
- autoScaling: ctx.flags.autoScale ?? true,
251
+ autoScaling: ctx.flags['auto-scale'] ?? true,
252
252
  },
253
253
  metadata: {
254
254
  v1Mode,
@@ -288,7 +288,8 @@ const initCommand = {
288
288
  fs.mkdirSync(swarmDir, { recursive: true });
289
289
  }
290
290
  const stateFile = path.join(swarmDir, 'state.json');
291
- fs.writeFileSync(stateFile, JSON.stringify({
291
+ const tmpStateFile1 = stateFile + '.tmp';
292
+ fs.writeFileSync(tmpStateFile1, JSON.stringify({
292
293
  id: result.swarmId,
293
294
  topology: result.topology,
294
295
  maxAgents: result.config.maxAgents,
@@ -297,6 +298,7 @@ const initCommand = {
297
298
  initializedAt: result.initializedAt,
298
299
  status: 'ready'
299
300
  }, null, 2));
301
+ fs.renameSync(tmpStateFile1, stateFile);
300
302
  }
301
303
  catch {
302
304
  // Ignore errors writing state file
@@ -402,6 +404,7 @@ const startCommand = {
402
404
  output.writeln();
403
405
  const spinner = output.createSpinner({ text: 'Initializing swarm via MCP...', spinner: 'dots' });
404
406
  spinner.start();
407
+ let resolvedSwarmId = swarmId;
405
408
  try {
406
409
  // Actually call MCP to initialize the swarm
407
410
  const initResult = await callMCPTool('swarm_init', {
@@ -409,6 +412,9 @@ const startCommand = {
409
412
  maxAgents: totalAgents,
410
413
  strategy: strategy === 'development' ? 'specialized' : strategy,
411
414
  });
415
+ const mcpData = typeof initResult === 'string' ? JSON.parse(initResult) : initResult;
416
+ // Prefer the canonical ID assigned by the MCP server over the locally generated one
417
+ resolvedSwarmId = mcpData?.swarmId ?? mcpData?.id ?? swarmId;
412
418
  spinner.succeed('Swarm initialized via MCP');
413
419
  }
414
420
  catch (err) {
@@ -421,7 +427,7 @@ const startCommand = {
421
427
  if (!fs.existsSync(swarmDir))
422
428
  fs.mkdirSync(swarmDir, { recursive: true });
423
429
  const executionState = {
424
- swarmId,
430
+ swarmId: resolvedSwarmId,
425
431
  objective,
426
432
  strategy,
427
433
  status: 'initialized',
@@ -430,12 +436,15 @@ const startCommand = {
430
436
  startedAt: new Date().toISOString(),
431
437
  parallel: ctx.flags.parallel ?? true
432
438
  };
433
- fs.writeFileSync(path.join(swarmDir, 'state.json'), JSON.stringify(executionState, null, 2));
439
+ const stateFile2 = path.join(swarmDir, 'state.json');
440
+ const tmpStateFile2 = stateFile2 + '.tmp';
441
+ fs.writeFileSync(tmpStateFile2, JSON.stringify(executionState, null, 2));
442
+ fs.renameSync(tmpStateFile2, stateFile2);
434
443
  output.writeln();
435
- output.printSuccess(`Swarm ${swarmId} initialized with ${totalAgents} agent slots`);
444
+ output.printSuccess(`Swarm ${resolvedSwarmId} initialized with ${totalAgents} agent slots`);
436
445
  output.writeln(output.dim(' Note: Agents are registered but actual task execution requires'));
437
446
  output.writeln(output.dim(' Claude Code Task tool or hive-mind spawn --claude to drive work.'));
438
- output.writeln(output.dim(` Monitor: monomind swarm status ${swarmId}`));
447
+ output.writeln(output.dim(` Monitor: monomind swarm status ${resolvedSwarmId}`));
439
448
  return { success: true, data: executionState };
440
449
  }
441
450
  };
@@ -457,8 +466,8 @@ const statusCommand = {
457
466
  output.writeln(output.warning('No active swarm'));
458
467
  output.writeln();
459
468
  output.writeln(output.dim('Start a swarm with:'));
460
- output.writeln(output.dim(' npx @monoes/cli@latest swarm init'));
461
- output.writeln(output.dim(' npx @monoes/cli@latest swarm start'));
469
+ output.writeln(output.dim(' npx @monomind/cli@latest swarm init'));
470
+ output.writeln(output.dim(' npx @monomind/cli@latest swarm start'));
462
471
  output.writeln();
463
472
  return { success: true, data: status };
464
473
  }
@@ -553,27 +562,34 @@ const stopCommand = {
553
562
  }
554
563
  }
555
564
  output.printInfo(`Stopping swarm ${swarmId}...`);
556
- // Update persisted swarm state if it exists (#1423)
557
- const swarmStateFile = path.join(process.cwd(), '.swarm', 'state.json');
558
- if (fs.existsSync(swarmStateFile)) {
559
- try {
560
- const state = JSON.parse(fs.readFileSync(swarmStateFile, 'utf-8'));
561
- state.status = 'stopped';
562
- state.stoppedAt = new Date().toISOString();
563
- fs.writeFileSync(swarmStateFile, JSON.stringify(state, null, 2));
564
- output.writeln(output.dim(' Swarm state updated'));
565
- }
566
- catch {
567
- output.writeln(output.dim(' Could not update swarm state file'));
568
- }
569
- }
570
- // Attempt MCP cleanup
565
+ // Attempt MCP cleanup first — only persist 'stopped' state if it succeeds
566
+ let mcpStopped = false;
571
567
  try {
572
568
  await callMCPTool('swarm_stop', { swarmId, force });
573
569
  output.writeln(output.dim(' MCP swarm stopped'));
570
+ mcpStopped = true;
574
571
  }
575
- catch {
576
- // MCP may not be available
572
+ catch (err) {
573
+ output.printWarning(`MCP stop failed: ${String(err)}`);
574
+ return { success: false, message: `MCP stop failed: ${String(err)}`, exitCode: 1 };
575
+ }
576
+ // Only update persisted swarm state if the MCP call succeeded (#1423)
577
+ if (mcpStopped) {
578
+ const swarmStateFile = path.join(process.cwd(), '.swarm', 'state.json');
579
+ if (fs.existsSync(swarmStateFile)) {
580
+ try {
581
+ const state = JSON.parse(fs.readFileSync(swarmStateFile, 'utf-8'));
582
+ state.status = 'stopped';
583
+ state.stoppedAt = new Date().toISOString();
584
+ const tmpSwarmStop = swarmStateFile + '.tmp';
585
+ fs.writeFileSync(tmpSwarmStop, JSON.stringify(state, null, 2));
586
+ fs.renameSync(tmpSwarmStop, swarmStateFile);
587
+ output.writeln(output.dim(' Swarm state updated'));
588
+ }
589
+ catch {
590
+ output.writeln(output.dim(' Could not update swarm state file'));
591
+ }
592
+ }
577
593
  }
578
594
  output.printSuccess(`Swarm ${swarmId} stopped`);
579
595
  return { success: true, data: { swarmId, stopped: true, force } };
@@ -614,7 +630,7 @@ const scaleCommand = {
614
630
  // Calculate scaling delta — fetch actual count instead of hardcoded 8 (#1425)
615
631
  let currentAgents = 0;
616
632
  try {
617
- const statusResult = await callMCPTool('swarm_status', {});
633
+ const statusResult = await callMCPTool('swarm_status', { swarmId });
618
634
  const statusData = typeof statusResult === 'string' ? JSON.parse(statusResult) : statusResult;
619
635
  currentAgents = statusData?.agentCount ?? statusData?.agents?.length ?? 0;
620
636
  }
@@ -623,18 +639,13 @@ const scaleCommand = {
623
639
  currentAgents = 0;
624
640
  }
625
641
  const delta = targetAgents - currentAgents;
626
- if (delta > 0) {
627
- output.writeln(output.dim(` Spawning ${delta} new agents...`));
628
- }
629
- else if (delta < 0) {
630
- output.writeln(output.dim(` Gracefully stopping ${-delta} agents...`));
631
- }
632
- else {
642
+ if (delta === 0) {
633
643
  output.printInfo('Swarm already at target size');
634
644
  return { success: true };
635
645
  }
636
- output.printSuccess(`Swarm scaled to ${targetAgents} agents`);
637
- return { success: true, data: { swarmId, agents: targetAgents, delta } };
646
+ // No swarm_scale MCP tool is available — report the computed delta but do not pretend to act
647
+ output.printWarning('Swarm scaling is not yet implemented. The target count was computed but no agents were spawned or stopped.');
648
+ return { success: false, message: 'Scaling not implemented', exitCode: 1 };
638
649
  }
639
650
  };
640
651
  // Coordinate command (v1 specific)
@@ -56,23 +56,23 @@ const summarySubcommand = {
56
56
  const range = tracker.getDateRange(period);
57
57
  const projects = tracker.parseAllSessions(range.start, range.end);
58
58
  if (asJson) {
59
- output.log(JSON.stringify(projects, null, 2));
59
+ output.writeln(JSON.stringify(projects, null, 2));
60
60
  return { success: true, data: projects };
61
61
  }
62
62
  const totalCost = projects.reduce((s, p) => s + p.totalCost, 0);
63
63
  const totalCalls = projects.reduce((s, p) => s + p.totalApiCalls, 0);
64
- output.log('');
65
- output.log(`Token Usage — ${period}`);
66
- output.log('─'.repeat(50));
67
- output.log(`Total Cost: ${tracker.fmt$(totalCost)}`);
68
- output.log(`API Calls: ${totalCalls}`);
69
- output.log(`Projects: ${projects.length}`);
70
- output.log('');
64
+ output.writeln('');
65
+ output.writeln(`Token Usage — ${period}`);
66
+ output.writeln('─'.repeat(50));
67
+ output.writeln(`Total Cost: ${tracker.fmt$(totalCost)}`);
68
+ output.writeln(`API Calls: ${totalCalls}`);
69
+ output.writeln(`Projects: ${projects.length}`);
70
+ output.writeln('');
71
71
  for (const p of projects.slice(0, 10)) {
72
72
  const name = p.projectPath.split('/').pop() || p.projectPath;
73
- output.log(` ${name.padEnd(30)} ${tracker.fmt$(p.totalCost).padStart(10)} ${p.totalApiCalls} calls`);
73
+ output.writeln(` ${name.padEnd(30)} ${tracker.fmt$(p.totalCost).padStart(10)} ${p.totalApiCalls} calls`);
74
74
  }
75
- output.log('');
75
+ output.writeln('');
76
76
  return { success: true, data: { totalCost, totalCalls, projects } };
77
77
  }
78
78
  catch (err) {
@@ -89,7 +89,7 @@ const todaySubcommand = {
89
89
  try {
90
90
  const tracker = loadTracker();
91
91
  const summary = tracker.quickSummary();
92
- output.log(summary || 'No token data available for today.');
92
+ output.writeln(summary || 'No token data available for today.');
93
93
  return { success: true };
94
94
  }
95
95
  catch (err) {
@@ -140,7 +140,7 @@ export const storeSearchCommand = {
140
140
  language: ctx.flags.language,
141
141
  framework: ctx.flags.framework,
142
142
  tags: ctx.flags.tags ? ctx.flags.tags.split(',') : undefined,
143
- minRating: ctx.flags.minRating,
143
+ minRating: ctx.flags['min-rating'],
144
144
  verified: ctx.flags.verified,
145
145
  limit: ctx.flags.limit || 20,
146
146
  };
@@ -77,9 +77,9 @@ const runCommand = {
77
77
  const file = ctx.flags.file;
78
78
  const task = ctx.flags.task || ctx.args[0];
79
79
  const parallel = ctx.flags.parallel;
80
- const maxAgents = ctx.flags.maxAgents;
80
+ const maxAgents = ctx.flags['max-agents'];
81
81
  const timeout = ctx.flags.timeout;
82
- const dryRun = ctx.flags.dryRun;
82
+ const dryRun = ctx.flags['dry-run'];
83
83
  if (!template && !file && ctx.interactive) {
84
84
  template = await select({
85
85
  message: 'Select workflow template:',
@@ -503,8 +503,35 @@ const templateCommand = {
503
503
  output.printError('Template name is required');
504
504
  return { success: false, exitCode: 1 };
505
505
  }
506
- output.printSuccess(`Template "${name}" created`);
507
- output.writeln(output.dim(' Use with: monomind workflow run -t ' + name));
506
+ if (!/^[a-zA-Z0-9_-]{1,64}$/.test(name)) {
507
+ output.printError('Template name must be 1-64 alphanumeric, underscore, or dash characters.');
508
+ return { success: false, exitCode: 1 };
509
+ }
510
+ const { writeFileSync, renameSync: renameTemplate, mkdirSync, existsSync } = await import('fs');
511
+ const { join, resolve: resolvePath, sep } = await import('path');
512
+ const templatesDir = join(ctx.cwd, '.monomind', 'workflows', 'templates');
513
+ if (!existsSync(templatesDir)) {
514
+ mkdirSync(templatesDir, { recursive: true });
515
+ }
516
+ const templatePath = join(templatesDir, `${name}.json`);
517
+ if (!resolvePath(templatePath).startsWith(resolvePath(templatesDir) + sep)) {
518
+ output.printError('Template name attempts path traversal.');
519
+ return { success: false, exitCode: 1 };
520
+ }
521
+ if (existsSync(templatePath) && !ctx.flags.force) {
522
+ output.writeln(output.error(`Template "${name}" already exists. Use --force to overwrite.`));
523
+ return { success: false, exitCode: 1 };
524
+ }
525
+ const template = {
526
+ name,
527
+ description: ctx.flags.description || '',
528
+ steps: [],
529
+ variables: {},
530
+ createdAt: new Date().toISOString(),
531
+ };
532
+ writeFileSync(templatePath + '.tmp', JSON.stringify(template, null, 2));
533
+ renameTemplate(templatePath + '.tmp', templatePath);
534
+ output.writeln(output.success(`✓ Template "${name}" created at ${templatePath.replace(ctx.cwd, '.')}`));
508
535
  return { success: true, data: { name, created: true } };
509
536
  }
510
537
  }
@@ -2,7 +2,7 @@
2
2
  * Configuration Adapter
3
3
  * Converts between SystemConfig and MonomindConfig types
4
4
  */
5
- import type { SystemConfig } from '@monoes/shared';
5
+ type SystemConfig = any;
6
6
  import type { MonomindConfig } from './types.js';
7
7
  /**
8
8
  * Convert SystemConfig to MonomindConfig (CLI-specific format)
@@ -12,4 +12,5 @@ export declare function systemConfigToMonomindConfig(systemConfig: SystemConfig)
12
12
  * Convert MonomindConfig to SystemConfig
13
13
  */
14
14
  export declare function configToSystemConfig(config: MonomindConfig): Partial<SystemConfig>;
15
+ export {};
15
16
  //# sourceMappingURL=config-adapter.d.ts.map
@@ -3,18 +3,26 @@
3
3
  *
4
4
  * Append-only JSONL storage for consensus audit records and individual votes.
5
5
  */
6
- import { appendFileSync, readFileSync, existsSync, mkdirSync } from 'fs';
7
- import { dirname, join } from 'path';
6
+ import { appendFileSync, readFileSync, existsSync, mkdirSync, statSync } from 'fs';
7
+ import { createHmac, timingSafeEqual } from 'crypto';
8
+ import { dirname, join, resolve, relative } from 'path';
9
+ import { parseJsonl } from '../utils/parse-jsonl.js';
8
10
  import { deriveSigningKey, signVote, verifyVote } from './vote-signer.js';
9
11
  export class AuditWriter {
10
12
  auditPath;
11
13
  votesPath;
12
14
  constructor(dataDir) {
13
- if (!existsSync(dataDir)) {
14
- mkdirSync(dataDir, { recursive: true });
15
+ const resolved = resolve(dataDir);
16
+ const cwd = process.cwd();
17
+ const rel = relative(cwd, resolved);
18
+ if (rel.startsWith('..') || resolve(rel) === resolve('/')) {
19
+ throw new Error(`AuditWriter: dataDir must be within the working directory: ${dataDir}`);
15
20
  }
16
- this.auditPath = join(dataDir, 'consensus-audit.jsonl');
17
- this.votesPath = join(dataDir, 'consensus-votes.jsonl');
21
+ if (!existsSync(resolved)) {
22
+ mkdirSync(resolved, { recursive: true });
23
+ }
24
+ this.auditPath = join(resolved, 'consensus-audit.jsonl');
25
+ this.votesPath = join(resolved, 'consensus-votes.jsonl');
18
26
  }
19
27
  /**
20
28
  * Record a consensus decision: sign all votes, compute quorum proof,
@@ -38,9 +46,11 @@ export class AuditWriter {
38
46
  threshold: input.quorumThreshold,
39
47
  satisfied: achieved >= input.quorumRequired,
40
48
  };
41
- // Compute duration
42
- const durationMs = new Date(input.completedAt).getTime() - new Date(input.startedAt).getTime();
43
- const record = {
49
+ // Compute duration (guard against invalid date strings)
50
+ const startMs = new Date(input.startedAt).getTime();
51
+ const endMs = new Date(input.completedAt).getTime();
52
+ const durationMs = isNaN(startMs) || isNaN(endMs) ? null : endMs - startMs;
53
+ const recordWithoutSig = {
44
54
  decisionId: input.decisionId,
45
55
  swarmId: input.swarmId,
46
56
  protocol: input.protocol,
@@ -54,6 +64,12 @@ export class AuditWriter {
54
64
  completedAt: input.completedAt,
55
65
  durationMs,
56
66
  };
67
+ // Sign the full outer record so decision, quorumProof, and metadata are tamper-evident.
68
+ // Previously only individual votes were signed; this extends coverage to all fields.
69
+ const recordSignature = createHmac('sha256', key)
70
+ .update(JSON.stringify(recordWithoutSig))
71
+ .digest('hex');
72
+ const record = { ...recordWithoutSig, recordSignature };
57
73
  // Persist audit record
58
74
  this.appendLine(this.auditPath, record);
59
75
  // Persist individual votes
@@ -87,10 +103,20 @@ export class AuditWriter {
87
103
  invalidVotes.push(vote.agentId);
88
104
  }
89
105
  }
90
- return { valid: invalidVotes.length === 0, invalidVotes };
106
+ // Verify the outer record signature for tamper-evidence
107
+ const { recordSignature, ...recordWithoutSig } = record;
108
+ const expectedSig = createHmac('sha256', key)
109
+ .update(JSON.stringify(recordWithoutSig))
110
+ .digest('hex');
111
+ const expBuf = Buffer.from(expectedSig, 'hex');
112
+ const gotBuf = Buffer.from(typeof recordSignature === 'string' ? recordSignature : '', 'hex');
113
+ const recordTampered = gotBuf.length !== expBuf.length || !timingSafeEqual(gotBuf, expBuf);
114
+ return { valid: invalidVotes.length === 0 && !recordTampered, invalidVotes };
91
115
  }
92
116
  // ── helpers ──
93
117
  appendLine(filePath, data) {
118
+ // Audit writes must be reliable — propagate errors so callers know the audit trail
119
+ // is incomplete (silent failure defeats tamper-evidence)
94
120
  const dir = dirname(filePath);
95
121
  if (!existsSync(dir)) {
96
122
  mkdirSync(dir, { recursive: true });
@@ -100,10 +126,17 @@ export class AuditWriter {
100
126
  readLines(filePath) {
101
127
  if (!existsSync(filePath))
102
128
  return [];
103
- const content = readFileSync(filePath, 'utf-8').trim();
104
- if (!content)
129
+ try {
130
+ const MAX_BYTES = 50 * 1024 * 1024;
131
+ if (statSync(filePath).size > MAX_BYTES) {
132
+ throw new Error(`Audit log ${filePath} exceeds 50MB — run rotation/cleanup`);
133
+ }
134
+ const content = readFileSync(filePath, 'utf-8');
135
+ return parseJsonl(content);
136
+ }
137
+ catch {
105
138
  return [];
106
- return content.split('\n').map((line) => JSON.parse(line));
139
+ }
107
140
  }
108
141
  }
109
142
  //# sourceMappingURL=audit-writer.js.map
@@ -7,9 +7,6 @@
7
7
  * Derive a signing key from a swarmId and session secret using HMAC-SHA256.
8
8
  */
9
9
  export declare function deriveSigningKey(swarmId: string, sessionSecret: string): Buffer;
10
- /**
11
- * Sign a vote, producing a hex-encoded HMAC-SHA256 signature.
12
- */
13
10
  export declare function signVote(agentId: string, vote: unknown, decisionId: string, key: Buffer): string;
14
11
  /**
15
12
  * CP-WBFT: Compute confidence-weighted vote tally.
@@ -13,8 +13,16 @@ export function deriveSigningKey(swarmId, sessionSecret) {
13
13
  /**
14
14
  * Sign a vote, producing a hex-encoded HMAC-SHA256 signature.
15
15
  */
16
+ function canonicalize(val) {
17
+ if (val === null || typeof val !== 'object')
18
+ return JSON.stringify(val);
19
+ if (Array.isArray(val))
20
+ return '[' + val.map(canonicalize).join(',') + ']';
21
+ const sorted = Object.keys(val).sort().map(k => JSON.stringify(k) + ':' + canonicalize(val[k]));
22
+ return '{' + sorted.join(',') + '}';
23
+ }
16
24
  export function signVote(agentId, vote, decisionId, key) {
17
- const payload = JSON.stringify({ agentId, vote, decisionId });
25
+ const payload = JSON.stringify({ agentId, vote: canonicalize(vote), decisionId });
18
26
  return createHmac('sha256', key).update(payload).digest('hex');
19
27
  }
20
28
  /**
@@ -15,9 +15,11 @@ export interface DLQListOptions {
15
15
  export declare class DLQReader {
16
16
  private readonly filePath;
17
17
  constructor(filePath: string);
18
- /** Read all entries from the JSONL file */
18
+ /** Read all entries from the JSONL file with a hard size cap.
19
+ * The DLQ is append-only with no rotation — without this guard a long-running
20
+ * process can grow the file to GBs and OOM on every list/get/purge call. */
19
21
  private readAll;
20
- /** Write all entries back (used for purge) */
22
+ /** Write all entries back (used for purge) — uses unique tmp filename to avoid concurrent writer collisions */
21
23
  private writeAll;
22
24
  /** List entries with optional filters (defaults to status='pending') */
23
25
  list(opts?: DLQListOptions): DLQEntry[];
@@ -3,25 +3,42 @@
3
3
  *
4
4
  * Reads, filters, and purges DLQ entries from JSONL storage.
5
5
  */
6
- import { existsSync, readFileSync, writeFileSync } from 'fs';
6
+ import { randomUUID } from 'crypto';
7
+ import { existsSync, readFileSync, writeFileSync, renameSync, statSync, unlinkSync } from 'fs';
8
+ import { parseJsonl } from '../utils/parse-jsonl.js';
7
9
  export class DLQReader {
8
10
  filePath;
9
11
  constructor(filePath) {
10
12
  this.filePath = filePath;
11
13
  }
12
- /** Read all entries from the JSONL file */
14
+ /** Read all entries from the JSONL file with a hard size cap.
15
+ * The DLQ is append-only with no rotation — without this guard a long-running
16
+ * process can grow the file to GBs and OOM on every list/get/purge call. */
13
17
  readAll() {
14
18
  if (!existsSync(this.filePath))
15
19
  return [];
16
- const raw = readFileSync(this.filePath, 'utf-8').trim();
17
- if (!raw)
18
- return [];
19
- return raw.split('\n').map((line) => JSON.parse(line));
20
+ const stat = statSync(this.filePath);
21
+ if (stat.size > 256 * 1024 * 1024) {
22
+ throw new Error(`DLQ file exceeds 256MB (${stat.size} bytes). Run rotation/cleanup.`);
23
+ }
24
+ const raw = readFileSync(this.filePath, 'utf-8');
25
+ return parseJsonl(raw);
20
26
  }
21
- /** Write all entries back (used for purge) */
27
+ /** Write all entries back (used for purge) — uses unique tmp filename to avoid concurrent writer collisions */
22
28
  writeAll(entries) {
23
29
  const content = entries.map((e) => JSON.stringify(e)).join('\n') + (entries.length ? '\n' : '');
24
- writeFileSync(this.filePath, content, 'utf-8');
30
+ const tmp = `${this.filePath}.${randomUUID()}.tmp`;
31
+ try {
32
+ writeFileSync(tmp, content, 'utf-8');
33
+ renameSync(tmp, this.filePath);
34
+ }
35
+ catch (err) {
36
+ try {
37
+ unlinkSync(tmp);
38
+ }
39
+ catch { /* ignore cleanup failure */ }
40
+ throw err;
41
+ }
25
42
  }
26
43
  /** List entries with optional filters (defaults to status='pending') */
27
44
  list(opts = {}) {