@mycelish/cli 0.1.0 → 0.2.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 (296) hide show
  1. package/dist/__tests__/mcp-server.test.d.ts +2 -0
  2. package/dist/__tests__/mcp-server.test.d.ts.map +1 -0
  3. package/dist/__tests__/mcp-server.test.js +60 -0
  4. package/dist/__tests__/mcp-server.test.js.map +1 -0
  5. package/dist/__tests__/unified-item-state.integration.test.d.ts +7 -0
  6. package/dist/__tests__/unified-item-state.integration.test.d.ts.map +1 -0
  7. package/dist/__tests__/unified-item-state.integration.test.js +217 -0
  8. package/dist/__tests__/unified-item-state.integration.test.js.map +1 -0
  9. package/dist/commands/add.d.ts.map +1 -1
  10. package/dist/commands/add.js +9 -0
  11. package/dist/commands/add.js.map +1 -1
  12. package/dist/commands/disable.d.ts +8 -6
  13. package/dist/commands/disable.d.ts.map +1 -1
  14. package/dist/commands/disable.js +143 -136
  15. package/dist/commands/disable.js.map +1 -1
  16. package/dist/commands/disable.test.js +117 -23
  17. package/dist/commands/disable.test.js.map +1 -1
  18. package/dist/commands/doctor.d.ts +1 -1
  19. package/dist/commands/doctor.d.ts.map +1 -1
  20. package/dist/commands/doctor.js +1 -1
  21. package/dist/commands/doctor.js.map +1 -1
  22. package/dist/commands/enable.d.ts +8 -6
  23. package/dist/commands/enable.d.ts.map +1 -1
  24. package/dist/commands/enable.js +128 -133
  25. package/dist/commands/enable.js.map +1 -1
  26. package/dist/commands/enable.test.js +192 -24
  27. package/dist/commands/enable.test.js.map +1 -1
  28. package/dist/commands/health-checks/index.d.ts +2 -1
  29. package/dist/commands/health-checks/index.d.ts.map +1 -1
  30. package/dist/commands/health-checks/index.js +2 -1
  31. package/dist/commands/health-checks/index.js.map +1 -1
  32. package/dist/commands/health-checks/mcp-check.d.ts +5 -1
  33. package/dist/commands/health-checks/mcp-check.d.ts.map +1 -1
  34. package/dist/commands/health-checks/mcp-check.js +32 -1
  35. package/dist/commands/health-checks/mcp-check.js.map +1 -1
  36. package/dist/commands/health-checks/plugin-takeover-check.d.ts +15 -0
  37. package/dist/commands/health-checks/plugin-takeover-check.d.ts.map +1 -0
  38. package/dist/commands/health-checks/plugin-takeover-check.js +274 -0
  39. package/dist/commands/health-checks/plugin-takeover-check.js.map +1 -0
  40. package/dist/commands/health-checks/runner.d.ts.map +1 -1
  41. package/dist/commands/health-checks/runner.js +18 -0
  42. package/dist/commands/health-checks/runner.js.map +1 -1
  43. package/dist/commands/init.d.ts.map +1 -1
  44. package/dist/commands/init.js +33 -0
  45. package/dist/commands/init.js.map +1 -1
  46. package/dist/commands/mcp.d.ts +9 -0
  47. package/dist/commands/mcp.d.ts.map +1 -0
  48. package/dist/commands/mcp.js +17 -0
  49. package/dist/commands/mcp.js.map +1 -0
  50. package/dist/commands/migrate.d.ts.map +1 -1
  51. package/dist/commands/migrate.js +51 -0
  52. package/dist/commands/migrate.js.map +1 -1
  53. package/dist/commands/preset.test.js +7 -3
  54. package/dist/commands/preset.test.js.map +1 -1
  55. package/dist/commands/remove.d.ts +25 -23
  56. package/dist/commands/remove.d.ts.map +1 -1
  57. package/dist/commands/remove.js +118 -247
  58. package/dist/commands/remove.js.map +1 -1
  59. package/dist/commands/remove.test.js +152 -78
  60. package/dist/commands/remove.test.js.map +1 -1
  61. package/dist/commands/report.d.ts +8 -0
  62. package/dist/commands/report.d.ts.map +1 -0
  63. package/dist/commands/report.js +149 -0
  64. package/dist/commands/report.js.map +1 -0
  65. package/dist/commands/report.test.d.ts +2 -0
  66. package/dist/commands/report.test.d.ts.map +1 -0
  67. package/dist/commands/report.test.js +23 -0
  68. package/dist/commands/report.test.js.map +1 -0
  69. package/dist/commands/status.d.ts +9 -4
  70. package/dist/commands/status.d.ts.map +1 -1
  71. package/dist/commands/status.js +81 -10
  72. package/dist/commands/status.js.map +1 -1
  73. package/dist/commands/status.test.js +92 -0
  74. package/dist/commands/status.test.js.map +1 -1
  75. package/dist/commands/sync.d.ts.map +1 -1
  76. package/dist/commands/sync.js +138 -7
  77. package/dist/commands/sync.js.map +1 -1
  78. package/dist/commands/sync.test.js +91 -6
  79. package/dist/commands/sync.test.js.map +1 -1
  80. package/dist/core/adapter-base.d.ts +2 -0
  81. package/dist/core/adapter-base.d.ts.map +1 -1
  82. package/dist/core/adapter-base.js +2 -1
  83. package/dist/core/adapter-base.js.map +1 -1
  84. package/dist/core/auto-adapter.d.ts.map +1 -1
  85. package/dist/core/auto-adapter.js +58 -3
  86. package/dist/core/auto-adapter.js.map +1 -1
  87. package/dist/core/auto-adapter.test.js +155 -0
  88. package/dist/core/auto-adapter.test.js.map +1 -1
  89. package/dist/core/config-merger.d.ts +6 -5
  90. package/dist/core/config-merger.d.ts.map +1 -1
  91. package/dist/core/config-merger.js +119 -136
  92. package/dist/core/config-merger.js.map +1 -1
  93. package/dist/core/config-merger.test.d.ts +1 -1
  94. package/dist/core/config-merger.test.js +72 -88
  95. package/dist/core/config-merger.test.js.map +1 -1
  96. package/dist/core/file-syncer.d.ts +33 -0
  97. package/dist/core/file-syncer.d.ts.map +1 -0
  98. package/dist/core/file-syncer.js +138 -0
  99. package/dist/core/file-syncer.js.map +1 -0
  100. package/dist/core/file-syncer.test.d.ts +2 -0
  101. package/dist/core/file-syncer.test.d.ts.map +1 -0
  102. package/dist/core/file-syncer.test.js +131 -0
  103. package/dist/core/file-syncer.test.js.map +1 -0
  104. package/dist/core/global-tracer.d.ts +4 -0
  105. package/dist/core/global-tracer.d.ts.map +1 -0
  106. package/dist/core/global-tracer.js +36 -0
  107. package/dist/core/global-tracer.js.map +1 -0
  108. package/dist/core/item-loader.d.ts +18 -0
  109. package/dist/core/item-loader.d.ts.map +1 -0
  110. package/dist/core/item-loader.js +40 -0
  111. package/dist/core/item-loader.js.map +1 -0
  112. package/dist/core/item-loader.test.d.ts +2 -0
  113. package/dist/core/item-loader.test.d.ts.map +1 -0
  114. package/dist/core/item-loader.test.js +52 -0
  115. package/dist/core/item-loader.test.js.map +1 -0
  116. package/dist/core/manifest-migrator.d.ts +15 -0
  117. package/dist/core/manifest-migrator.d.ts.map +1 -0
  118. package/dist/core/manifest-migrator.js +38 -0
  119. package/dist/core/manifest-migrator.js.map +1 -0
  120. package/dist/core/manifest-migrator.test.d.ts +2 -0
  121. package/dist/core/manifest-migrator.test.d.ts.map +1 -0
  122. package/dist/core/manifest-migrator.test.js +53 -0
  123. package/dist/core/manifest-migrator.test.js.map +1 -0
  124. package/dist/core/manifest-state.d.ts +117 -0
  125. package/dist/core/manifest-state.d.ts.map +1 -0
  126. package/dist/core/manifest-state.js +218 -0
  127. package/dist/core/manifest-state.js.map +1 -0
  128. package/dist/core/manifest-state.test.d.ts +2 -0
  129. package/dist/core/manifest-state.test.d.ts.map +1 -0
  130. package/dist/core/manifest-state.test.js +130 -0
  131. package/dist/core/manifest-state.test.js.map +1 -0
  132. package/dist/core/marketplace-registry.d.ts +0 -1
  133. package/dist/core/marketplace-registry.d.ts.map +1 -1
  134. package/dist/core/marketplace-registry.js +0 -16
  135. package/dist/core/marketplace-registry.js.map +1 -1
  136. package/dist/core/marketplace-registry.test.js +1 -14
  137. package/dist/core/marketplace-registry.test.js.map +1 -1
  138. package/dist/core/mcp-injector.d.ts +2 -2
  139. package/dist/core/mcp-injector.d.ts.map +1 -1
  140. package/dist/core/mcp-injector.js +6 -6
  141. package/dist/core/mcp-injector.js.map +1 -1
  142. package/dist/core/mcp-injector.test.js +33 -26
  143. package/dist/core/mcp-injector.test.js.map +1 -1
  144. package/dist/core/mcp-registry.js +1 -1
  145. package/dist/core/mcp-registry.js.map +1 -1
  146. package/dist/core/mcp-registry.test.js +1 -1
  147. package/dist/core/mcp-registry.test.js.map +1 -1
  148. package/dist/core/memory-scoper.test.js +2 -13
  149. package/dist/core/memory-scoper.test.js.map +1 -1
  150. package/dist/core/migrator/executor.js +2 -2
  151. package/dist/core/migrator/executor.js.map +1 -1
  152. package/dist/core/plugin-state.d.ts +7 -0
  153. package/dist/core/plugin-state.d.ts.map +1 -0
  154. package/dist/core/plugin-state.js +88 -0
  155. package/dist/core/plugin-state.js.map +1 -0
  156. package/dist/core/plugin-takeover.d.ts +50 -0
  157. package/dist/core/plugin-takeover.d.ts.map +1 -0
  158. package/dist/core/plugin-takeover.js +263 -0
  159. package/dist/core/plugin-takeover.js.map +1 -0
  160. package/dist/core/plugin-takeover.test.d.ts +2 -0
  161. package/dist/core/plugin-takeover.test.d.ts.map +1 -0
  162. package/dist/core/plugin-takeover.test.js +243 -0
  163. package/dist/core/plugin-takeover.test.js.map +1 -0
  164. package/dist/core/self-register.d.ts +5 -0
  165. package/dist/core/self-register.d.ts.map +1 -0
  166. package/dist/core/self-register.js +43 -0
  167. package/dist/core/self-register.js.map +1 -0
  168. package/dist/core/self-register.test.d.ts +2 -0
  169. package/dist/core/self-register.test.d.ts.map +1 -0
  170. package/dist/core/self-register.test.js +77 -0
  171. package/dist/core/self-register.test.js.map +1 -0
  172. package/dist/core/smart-memory.d.ts +5 -5
  173. package/dist/core/smart-memory.d.ts.map +1 -1
  174. package/dist/core/smart-memory.js +1 -10
  175. package/dist/core/smart-memory.js.map +1 -1
  176. package/dist/core/smart-memory.test.js +3 -30
  177. package/dist/core/smart-memory.test.js.map +1 -1
  178. package/dist/core/state-verifier.d.ts +36 -0
  179. package/dist/core/state-verifier.d.ts.map +1 -0
  180. package/dist/core/state-verifier.js +159 -0
  181. package/dist/core/state-verifier.js.map +1 -0
  182. package/dist/core/state-verifier.test.d.ts +2 -0
  183. package/dist/core/state-verifier.test.d.ts.map +1 -0
  184. package/dist/core/state-verifier.test.js +188 -0
  185. package/dist/core/state-verifier.test.js.map +1 -0
  186. package/dist/core/symlink-manager.d.ts +1 -1
  187. package/dist/core/symlink-manager.d.ts.map +1 -1
  188. package/dist/core/symlink-manager.js +1 -1
  189. package/dist/core/symlink-manager.js.map +1 -1
  190. package/dist/core/symlink-manager.test.js +4 -4
  191. package/dist/core/symlink-manager.test.js.map +1 -1
  192. package/dist/core/sync-writer.d.ts +2 -1
  193. package/dist/core/sync-writer.d.ts.map +1 -1
  194. package/dist/core/sync-writer.js +108 -22
  195. package/dist/core/sync-writer.js.map +1 -1
  196. package/dist/core/sync-writer.test.js +31 -0
  197. package/dist/core/sync-writer.test.js.map +1 -1
  198. package/dist/core/tool-adapter.d.ts.map +1 -1
  199. package/dist/core/tool-adapter.js +45 -6
  200. package/dist/core/tool-adapter.js.map +1 -1
  201. package/dist/core/trace-store.d.ts +36 -0
  202. package/dist/core/trace-store.d.ts.map +1 -0
  203. package/dist/core/trace-store.js +145 -0
  204. package/dist/core/trace-store.js.map +1 -0
  205. package/dist/core/trace-store.test.d.ts +2 -0
  206. package/dist/core/trace-store.test.d.ts.map +1 -0
  207. package/dist/core/trace-store.test.js +102 -0
  208. package/dist/core/trace-store.test.js.map +1 -0
  209. package/dist/core/tracer.d.ts +27 -0
  210. package/dist/core/tracer.d.ts.map +1 -0
  211. package/dist/core/tracer.js +62 -0
  212. package/dist/core/tracer.js.map +1 -0
  213. package/dist/core/tracer.test.d.ts +2 -0
  214. package/dist/core/tracer.test.d.ts.map +1 -0
  215. package/dist/core/tracer.test.js +54 -0
  216. package/dist/core/tracer.test.js.map +1 -0
  217. package/dist/core/watcher.d.ts.map +1 -1
  218. package/dist/core/watcher.js +9 -2
  219. package/dist/core/watcher.js.map +1 -1
  220. package/dist/core/watcher.test.js +9 -0
  221. package/dist/core/watcher.test.js.map +1 -1
  222. package/dist/index.js +4 -0
  223. package/dist/index.js.map +1 -1
  224. package/dist/mcp/prompts.d.ts +3 -0
  225. package/dist/mcp/prompts.d.ts.map +1 -0
  226. package/dist/mcp/prompts.js +40 -0
  227. package/dist/mcp/prompts.js.map +1 -0
  228. package/dist/mcp/resources.d.ts +6 -0
  229. package/dist/mcp/resources.d.ts.map +1 -0
  230. package/dist/mcp/resources.js +24 -0
  231. package/dist/mcp/resources.js.map +1 -0
  232. package/dist/mcp/server.d.ts +7 -0
  233. package/dist/mcp/server.d.ts.map +1 -0
  234. package/dist/mcp/server.js +27 -0
  235. package/dist/mcp/server.js.map +1 -0
  236. package/dist/mcp/server.test.d.ts +2 -0
  237. package/dist/mcp/server.test.d.ts.map +1 -0
  238. package/dist/mcp/server.test.js +9 -0
  239. package/dist/mcp/server.test.js.map +1 -0
  240. package/dist/mcp/tools/config-tools.d.ts +3 -0
  241. package/dist/mcp/tools/config-tools.d.ts.map +1 -0
  242. package/dist/mcp/tools/config-tools.js +80 -0
  243. package/dist/mcp/tools/config-tools.js.map +1 -0
  244. package/dist/mcp/tools/config-tools.test.d.ts +2 -0
  245. package/dist/mcp/tools/config-tools.test.d.ts.map +1 -0
  246. package/dist/mcp/tools/config-tools.test.js +207 -0
  247. package/dist/mcp/tools/config-tools.test.js.map +1 -0
  248. package/dist/mcp/tools/item-tools.d.ts +3 -0
  249. package/dist/mcp/tools/item-tools.d.ts.map +1 -0
  250. package/dist/mcp/tools/item-tools.js +95 -0
  251. package/dist/mcp/tools/item-tools.js.map +1 -0
  252. package/dist/mcp/tools/item-tools.test.d.ts +2 -0
  253. package/dist/mcp/tools/item-tools.test.d.ts.map +1 -0
  254. package/dist/mcp/tools/item-tools.test.js +184 -0
  255. package/dist/mcp/tools/item-tools.test.js.map +1 -0
  256. package/dist/mcp/tools/marketplace-tools.d.ts +3 -0
  257. package/dist/mcp/tools/marketplace-tools.d.ts.map +1 -0
  258. package/dist/mcp/tools/marketplace-tools.js +35 -0
  259. package/dist/mcp/tools/marketplace-tools.js.map +1 -0
  260. package/dist/mcp/tools/marketplace-tools.test.d.ts +2 -0
  261. package/dist/mcp/tools/marketplace-tools.test.d.ts.map +1 -0
  262. package/dist/mcp/tools/marketplace-tools.test.js +48 -0
  263. package/dist/mcp/tools/marketplace-tools.test.js.map +1 -0
  264. package/dist/mcp/tools/memory-tools.d.ts +3 -0
  265. package/dist/mcp/tools/memory-tools.d.ts.map +1 -0
  266. package/dist/mcp/tools/memory-tools.js +68 -0
  267. package/dist/mcp/tools/memory-tools.js.map +1 -0
  268. package/dist/mcp/tools/memory-tools.test.d.ts +2 -0
  269. package/dist/mcp/tools/memory-tools.test.d.ts.map +1 -0
  270. package/dist/mcp/tools/memory-tools.test.js +144 -0
  271. package/dist/mcp/tools/memory-tools.test.js.map +1 -0
  272. package/dist/mcp/tools/observe-tools.d.ts +3 -0
  273. package/dist/mcp/tools/observe-tools.d.ts.map +1 -0
  274. package/dist/mcp/tools/observe-tools.js +37 -0
  275. package/dist/mcp/tools/observe-tools.js.map +1 -0
  276. package/dist/mcp/tools/observe-tools.test.d.ts +2 -0
  277. package/dist/mcp/tools/observe-tools.test.d.ts.map +1 -0
  278. package/dist/mcp/tools/observe-tools.test.js +71 -0
  279. package/dist/mcp/tools/observe-tools.test.js.map +1 -0
  280. package/dist/routes/plugins.d.ts.map +1 -1
  281. package/dist/routes/plugins.js +63 -37
  282. package/dist/routes/plugins.js.map +1 -1
  283. package/dist/routes/plugins.test.d.ts +2 -0
  284. package/dist/routes/plugins.test.d.ts.map +1 -0
  285. package/dist/routes/plugins.test.js +56 -0
  286. package/dist/routes/plugins.test.js.map +1 -0
  287. package/dist/routes/remove.d.ts.map +1 -1
  288. package/dist/routes/remove.js +6 -15
  289. package/dist/routes/remove.js.map +1 -1
  290. package/dist/routes/state.d.ts.map +1 -1
  291. package/dist/routes/state.js +35 -70
  292. package/dist/routes/state.js.map +1 -1
  293. package/dist/routes/sync.d.ts.map +1 -1
  294. package/dist/routes/sync.js +10 -3
  295. package/dist/routes/sync.js.map +1 -1
  296. package/package.json +6 -2
@@ -1,182 +1,186 @@
1
1
  /**
2
2
  * Disable Command Module
3
3
  *
4
- * Disable a skill or MCP globally or for a specific tool:
5
- * - mycelium disable <name> # Disable skill/MCP at project level
6
- * - mycelium disable <name> --global # Disable skill/MCP globally
7
- * - mycelium disable <name> --tool <id> # Disable skill/MCP for specific tool only
4
+ * Disable a skill, MCP, hook, or memory item globally or for a specific tool:
5
+ * - mycelium disable <name> # Disable item at project level
6
+ * - mycelium disable <name> --global # Disable item globally
7
+ * - mycelium disable <name> --tool <id> # Disable item for specific tool only
8
8
  */
9
9
  import { Command } from "commander";
10
- import * as fs from "node:fs/promises";
11
- import * as path from "node:path";
12
- import { parse as yamlParse, stringify as yamlStringify } from "yaml";
13
- import { TOOL_REGISTRY, ALL_TOOL_IDS, expandPath } from "@mycelish/core";
14
- // ============================================================================
15
- // Helper Functions
16
- // ============================================================================
17
- /**
18
- * Load manifest from a path
19
- */
20
- async function loadManifest(manifestDir) {
21
- const manifestPath = path.join(manifestDir, "manifest.yaml");
22
- try {
23
- const content = await fs.readFile(manifestPath, "utf-8");
24
- return yamlParse(content);
25
- }
26
- catch {
27
- return null;
28
- }
29
- }
30
- /**
31
- * Save manifest to a path
32
- */
33
- async function saveManifest(manifestDir, manifest) {
34
- const manifestPath = path.join(manifestDir, "manifest.yaml");
35
- const content = yamlStringify(manifest);
36
- await fs.writeFile(manifestPath, content, "utf-8");
37
- }
38
- /**
39
- * Check if a tool ID is valid
40
- */
41
- function isValidToolId(toolId) {
42
- return toolId in TOOL_REGISTRY;
43
- }
44
- /**
45
- * Find what type an item is (skill or MCP)
46
- */
47
- function findItemType(manifest, name) {
48
- if (manifest.skills && name in manifest.skills) {
49
- return { type: "skill", config: manifest.skills[name] };
50
- }
51
- if (manifest.mcps && name in manifest.mcps) {
52
- return { type: "mcp", config: manifest.mcps[name] };
53
- }
54
- return null;
55
- }
56
- /**
57
- * Check if item is already disabled (globally or for a specific tool)
58
- */
59
- function isAlreadyDisabled(config, tool) {
60
- if (tool) {
61
- // Check tool-specific disablement
62
- if (config.excludeTools?.includes(tool)) {
63
- return true;
64
- }
65
- // If tools array exists and doesn't include this tool, it's effectively disabled
66
- if (config.tools && !config.tools.includes(tool)) {
67
- return true;
68
- }
69
- return false;
70
- }
71
- // Check global disablement
72
- return config.enabled === false;
73
- }
10
+ import { ALL_TOOL_IDS } from "@mycelish/core";
11
+ import { getTracer } from "../core/global-tracer.js";
12
+ import { loadStateManifest, saveStateManifest, ensureItem, findItemType, setItemInManifest, isValidToolId, resolveManifestDir, } from "../core/manifest-state.js";
13
+ import { getAllPluginsForComponent, setPluginEnabled, syncPluginSymlinks } from "../core/plugin-takeover.js";
14
+ import { scanPluginComponents } from "../core/plugin-scanner.js";
74
15
  // ============================================================================
75
16
  // Core Disable Function
76
17
  // ============================================================================
77
18
  /**
78
- * Disable a skill or MCP
19
+ * Disable a skill, MCP, hook, or memory item
79
20
  */
80
21
  export async function disableSkillOrMcp(options) {
81
22
  const { name, tool, global: isGlobal } = options;
23
+ const tracer = getTracer();
24
+ const log = tracer.createTrace("disable");
25
+ log.info({ scope: "manifest", op: "disable", msg: `Disabling ${name}`, item: name, tool });
82
26
  // Validate tool if provided
83
27
  if (tool && !isValidToolId(tool)) {
84
- return {
85
- success: false,
86
- name,
87
- error: `Invalid tool: ${tool}. Supported tools: ${ALL_TOOL_IDS.join(", ")}`,
88
- };
28
+ const error = `Invalid tool: ${tool}. Supported tools: ${ALL_TOOL_IDS.join(", ")}`;
29
+ log.error({ scope: "manifest", op: "disable", msg: error, item: name, error });
30
+ return { success: false, name, error };
89
31
  }
90
- // Determine which manifest to use
91
- const manifestDir = isGlobal
92
- ? options.globalPath || expandPath("~/.mycelium")
93
- : options.projectPath || path.join(process.cwd(), ".mycelium");
94
- // Load manifest
95
- const manifest = await loadManifest(manifestDir);
32
+ const manifestDir = resolveManifestDir(options);
33
+ const manifest = await loadStateManifest(manifestDir);
96
34
  if (!manifest) {
97
- return {
98
- success: false,
99
- name,
100
- error: `Could not load manifest from ${manifestDir}`,
101
- };
35
+ const error = `Could not load manifest from ${manifestDir}`;
36
+ log.error({ scope: "manifest", op: "disable", msg: error, item: name, error });
37
+ return { success: false, name, error };
102
38
  }
103
- // Find the item (skill or MCP)
104
- const item = findItemType(manifest, name);
105
- if (!item) {
106
- return {
107
- success: false,
108
- name,
109
- error: `'${name}' not found in manifest (checked skills and mcps)`,
110
- };
39
+ // Pre-fetch matching plugins (used for type detection and takeover)
40
+ const matchingPlugins = !tool ? await getAllPluginsForComponent(name) : [];
41
+ // Detect type from plugin cache if available (agents/commands shouldn't default to "skill")
42
+ let typeHint;
43
+ for (const p of matchingPlugins) {
44
+ const components = await scanPluginComponents(p.cachePath, p.plugin, p.marketplace);
45
+ const match = components.find(c => c.name === name);
46
+ if (match) {
47
+ typeHint = match.type;
48
+ break;
49
+ }
50
+ }
51
+ // Detect MCP type from config files (mcps.yaml)
52
+ if (!typeHint) {
53
+ const { loadGlobalConfig } = await import("../core/config-merger.js");
54
+ const globalConfig = await loadGlobalConfig();
55
+ if (globalConfig.mcps?.[name])
56
+ typeHint = "mcp";
57
+ }
58
+ // Find or auto-register item
59
+ const { type, config, autoRegistered } = ensureItem(manifest, name, "enabled", typeHint);
60
+ if (autoRegistered) {
61
+ log.info({ scope: "manifest", op: "disable", msg: `Auto-registered '${name}' as ${type} in manifest`, item: name });
111
62
  }
112
- const { type, config } = item;
113
63
  const level = isGlobal ? "global" : "project";
114
64
  // Check if already disabled
115
65
  if (isAlreadyDisabled(config, tool)) {
116
66
  const toolMsg = tool ? ` for ${tool}` : "";
117
- return {
118
- success: true,
119
- name,
120
- type,
121
- level,
122
- tool,
123
- alreadyDisabled: true,
124
- message: `${type} '${name}' is already disabled${toolMsg}`,
125
- };
67
+ return { success: true, name, type, level, tool, alreadyDisabled: true, message: `${type} '${name}' is already disabled${toolMsg}` };
126
68
  }
127
- // Disable the item
69
+ // Apply disable
128
70
  if (tool) {
129
- // Disable for specific tool
130
- // Add to excludeTools
131
- if (!config.excludeTools) {
71
+ if (!config.excludeTools)
132
72
  config.excludeTools = [];
133
- }
134
- if (!config.excludeTools.includes(tool)) {
73
+ if (!config.excludeTools.includes(tool))
135
74
  config.excludeTools.push(tool);
136
- }
137
- // Remove from tools array if present
138
75
  if (config.tools) {
139
76
  config.tools = config.tools.filter((t) => t !== tool);
140
77
  }
141
- // Remove from enabledTools if present
142
78
  if (config.enabledTools) {
143
79
  config.enabledTools = config.enabledTools.filter((t) => t !== tool);
144
80
  }
145
81
  }
146
82
  else {
147
- // Disable globally
148
- config.enabled = false;
83
+ config.state = "disabled";
149
84
  }
150
- // Update manifest
151
- if (type === "skill") {
152
- if (!manifest.skills)
153
- manifest.skills = {};
154
- manifest.skills[name] = config;
85
+ setItemInManifest(manifest, name, type, config);
86
+ await saveStateManifest(manifestDir, manifest);
87
+ // Remove MCP from tool configs immediately
88
+ if (type === "mcp") {
89
+ const { getAdapter } = await import("../core/tool-adapter.js");
90
+ const toolIds = tool ? [tool] : ALL_TOOL_IDS;
91
+ for (const tid of toolIds) {
92
+ try {
93
+ await getAdapter(tid).remove(name);
94
+ }
95
+ catch { /* tool may not be installed */ }
96
+ }
155
97
  }
156
- else {
157
- if (!manifest.mcps)
158
- manifest.mcps = {};
159
- manifest.mcps[name] = config;
98
+ // Plugin takeover: if disabling any component that belongs to a Claude Code plugin,
99
+ // take over ALL enabled plugins containing it so Mycelium manages their skills.
100
+ let pluginTakeover = false;
101
+ if (!tool && matchingPlugins.length > 0) {
102
+ for (const pluginInfo of matchingPlugins) {
103
+ // Scan all component types from plugin cache
104
+ const allPluginComponents = await scanPluginComponents(pluginInfo.cachePath, pluginInfo.plugin, pluginInfo.marketplace);
105
+ const allComponentNames = allPluginComponents.map(c => c.name);
106
+ // Collect all disabled items from ALL sections for this plugin
107
+ const disabledItems = [];
108
+ const allPluginItemNames = new Set([...pluginInfo.allSkills, ...allComponentNames]);
109
+ for (const itemName of allPluginItemNames) {
110
+ const found = findItemType(manifest, itemName);
111
+ if (found?.config.state === "disabled")
112
+ disabledItems.push(itemName);
113
+ }
114
+ // Include the current item being disabled
115
+ if (allPluginItemNames.has(name) && !disabledItems.includes(name)) {
116
+ disabledItems.push(name);
117
+ }
118
+ // Disable plugin in Claude Code settings
119
+ await setPluginEnabled(pluginInfo.pluginId, false);
120
+ // Register plugin in takenOverPlugins with all component types
121
+ if (!manifest.takenOverPlugins)
122
+ manifest.takenOverPlugins = {};
123
+ manifest.takenOverPlugins[pluginInfo.pluginId] = {
124
+ version: pluginInfo.version,
125
+ cachePath: pluginInfo.cachePath,
126
+ allSkills: pluginInfo.allSkills,
127
+ allComponents: allComponentNames,
128
+ };
129
+ // Register all plugin components in manifest with pluginOrigin
130
+ const pluginOrigin = { pluginId: pluginInfo.pluginId, cachePath: pluginInfo.cachePath };
131
+ for (const comp of allPluginComponents) {
132
+ const sectionKey = comp.type === "skill" ? "skills" : comp.type === "agent" ? "agents" : comp.type === "command" ? "commands" : comp.type === "hook" ? "hooks" : null;
133
+ if (!sectionKey)
134
+ continue;
135
+ if (!manifest[sectionKey])
136
+ manifest[sectionKey] = {};
137
+ const section = manifest[sectionKey];
138
+ const existing = section[comp.name] ?? { state: "enabled" };
139
+ existing.pluginOrigin = pluginOrigin;
140
+ section[comp.name] = existing;
141
+ }
142
+ // Also register skills from pluginInfo.allSkills (fallback when cache scan returns partial/empty)
143
+ if (!manifest.skills)
144
+ manifest.skills = {};
145
+ for (const skillName of pluginInfo.allSkills) {
146
+ const existing = manifest.skills[skillName] ?? { state: "enabled" };
147
+ if (!existing.pluginOrigin)
148
+ existing.pluginOrigin = pluginOrigin;
149
+ manifest.skills[skillName] = existing;
150
+ }
151
+ log.info({ scope: "plugin", op: "takeover", msg: `Took over plugin: ${pluginInfo.pluginId}`, item: pluginInfo.pluginId, itemType: typeHint });
152
+ }
153
+ await saveStateManifest(manifestDir, manifest);
154
+ // Sync symlinks declaratively — single source of truth
155
+ await syncPluginSymlinks(manifestDir);
156
+ pluginTakeover = true;
157
+ }
158
+ // If the item belongs to an already-taken-over plugin, syncPluginSymlinks
159
+ // wasn't called above (matchingPlugins is empty for already-disabled plugins).
160
+ // Re-sync to remove the newly disabled item's symlink.
161
+ if (!pluginTakeover && !tool && manifest.takenOverPlugins && Object.keys(manifest.takenOverPlugins).length > 0) {
162
+ await syncPluginSymlinks(manifestDir);
160
163
  }
161
- // Save manifest
162
- await saveManifest(manifestDir, manifest);
163
- // Build success message
164
164
  const toolMsg = tool ? ` for ${tool}` : "";
165
- return {
166
- success: true,
167
- name,
168
- type,
169
- level,
170
- tool,
171
- message: `${type} '${name}' disabled${toolMsg}`,
172
- };
165
+ log.info({ scope: "manifest", op: "disable", msg: `${type} '${name}' disabled${toolMsg}`, item: name, tool });
166
+ return { success: true, name, type, level, tool, pluginTakeover, message: `${type} '${name}' disabled${toolMsg}` };
167
+ }
168
+ function isAlreadyDisabled(config, tool) {
169
+ if (tool) {
170
+ if (config.excludeTools?.includes(tool))
171
+ return true;
172
+ if (config.tools && !config.tools.includes(tool))
173
+ return true;
174
+ return false;
175
+ }
176
+ return config.state === "disabled";
173
177
  }
174
178
  // ============================================================================
175
179
  // Commander.js Command
176
180
  // ============================================================================
177
181
  export const disableCommand = new Command("disable")
178
- .description("Disable a skill or MCP")
179
- .argument("<name>", "Name of the skill or MCP to disable")
182
+ .description("Disable a skill, MCP, hook, or memory item")
183
+ .argument("<name>", "Name of the item to disable")
180
184
  .option("-t, --tool <tool>", "Disable only for a specific tool")
181
185
  .option("-g, --global", "Disable in global configuration (~/.mycelium/)")
182
186
  .action(async (name, options) => {
@@ -191,6 +195,9 @@ export const disableCommand = new Command("disable")
191
195
  }
192
196
  else {
193
197
  console.log(`\u2713 ${result.message}`);
198
+ if (result.pluginTakeover) {
199
+ console.log(` [experimental] Plugin takeover: plugin disabled in Claude Code, skills now managed by Mycelium`);
200
+ }
194
201
  }
195
202
  }
196
203
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"disable.js","sourceRoot":"","sources":["../../src/commands/disable.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AACtE,OAAO,EAAe,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AA+CtF,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E;;GAEG;AACH,KAAK,UAAU,YAAY,CAAC,WAAmB;IAC7C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IAC7D,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACzD,OAAO,SAAS,CAAC,OAAO,CAAmB,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,YAAY,CAAC,WAAmB,EAAE,QAAwB;IACvE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,MAAc;IACnC,OAAO,MAAM,IAAI,aAAa,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CACnB,QAAwB,EACxB,IAAY;IAEZ,IAAI,QAAQ,CAAC,MAAM,IAAI,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC/C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;IAC1D,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,IAAI,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC3C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IACtD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CACxB,MAA+B,EAC/B,IAAa;IAEb,IAAI,IAAI,EAAE,CAAC;QACT,kCAAkC;QAClC,IAAI,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,iFAAiF;QACjF,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACjD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,2BAA2B;IAC3B,OAAO,MAAM,CAAC,OAAO,KAAK,KAAK,CAAC;AAClC,CAAC;AAED,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAuB;IAC7D,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAEjD,4BAA4B;IAC5B,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,OAAO;YACL,OAAO,EAAE,KAAK;YACd,IAAI;YACJ,KAAK,EAAE,iBAAiB,IAAI,sBAAsB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;SAC5E,CAAC;IACJ,CAAC;IAED,kCAAkC;IAClC,MAAM,WAAW,GAAG,QAAQ;QAC1B,CAAC,CAAC,OAAO,CAAC,UAAU,IAAI,UAAU,CAAC,aAAa,CAAC;QACjD,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;IAEjE,gBAAgB;IAChB,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;IACjD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO;YACL,OAAO,EAAE,KAAK;YACd,IAAI;YACJ,KAAK,EAAE,gCAAgC,WAAW,EAAE;SACrD,CAAC;IACJ,CAAC;IAED,+BAA+B;IAC/B,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO;YACL,OAAO,EAAE,KAAK;YACd,IAAI;YACJ,KAAK,EAAE,IAAI,IAAI,mDAAmD;SACnE,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC9B,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IAE9C,4BAA4B;IAC5B,IAAI,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI;YACJ,IAAI;YACJ,KAAK;YACL,IAAI;YACJ,eAAe,EAAE,IAAI;YACrB,OAAO,EAAE,GAAG,IAAI,KAAK,IAAI,wBAAwB,OAAO,EAAE;SAC3D,CAAC;IACJ,CAAC;IAED,mBAAmB;IACnB,IAAI,IAAI,EAAE,CAAC;QACT,4BAA4B;QAC5B,sBAAsB;QACtB,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;YACzB,MAAM,CAAC,YAAY,GAAG,EAAE,CAAC;QAC3B,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC;QACD,qCAAqC;QACrC,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QACxD,CAAC;QACD,sCAAsC;QACtC,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;SAAM,CAAC;QACN,mBAAmB;QACnB,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC;IACzB,CAAC;IAED,kBAAkB;IAClB,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,IAAI,CAAC,QAAQ,CAAC,MAAM;YAAE,QAAQ,CAAC,MAAM,GAAG,EAAE,CAAC;QAC3C,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,MAAqB,CAAC;IAChD,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,QAAQ,CAAC,IAAI;YAAE,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC;QACvC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,MAAmB,CAAC;IAC5C,CAAC;IAED,gBAAgB;IAChB,MAAM,YAAY,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAE1C,wBAAwB;IACxB,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3C,OAAO;QACL,OAAO,EAAE,IAAI;QACb,IAAI;QACJ,IAAI;QACJ,KAAK;QACL,IAAI;QACJ,OAAO,EAAE,GAAG,IAAI,KAAK,IAAI,aAAa,OAAO,EAAE;KAChD,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,wBAAwB,CAAC;KACrC,QAAQ,CAAC,QAAQ,EAAE,qCAAqC,CAAC;KACzD,MAAM,CAAC,mBAAmB,EAAE,kCAAkC,CAAC;KAC/D,MAAM,CAAC,cAAc,EAAE,gDAAgD,CAAC;KACxE,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,OAA4C,EAAE,EAAE;IAC3E,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC;QACrC,IAAI;QACJ,IAAI,EAAE,OAAO,CAAC,IAA0B;QACxC,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,iBAAiB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"disable.js","sourceRoot":"","sources":["../../src/commands/disable.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAe,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GAGnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAC7G,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AA0BjE,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAE/E;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAuB;IAC7D,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IACjD,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAC1C,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAE3F,4BAA4B;IAC5B,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,iBAAiB,IAAI,sBAAsB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACnF,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACzC,CAAC;IAED,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,gCAAgC,WAAW,EAAE,CAAC;QAC5D,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACzC,CAAC;IAED,oEAAoE;IACpE,MAAM,eAAe,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE3E,4FAA4F;IAC5F,IAAI,QAA8B,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;QAChC,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;QACpF,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACpD,IAAI,KAAK,EAAE,CAAC;YAAC,QAAQ,GAAG,KAAK,CAAC,IAAgB,CAAC;YAAC,MAAM;QAAC,CAAC;IAC1D,CAAC;IAED,gDAAgD;IAChD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,CAAC;QACtE,MAAM,YAAY,GAAG,MAAM,gBAAgB,EAAE,CAAC;QAC9C,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC;YAAE,QAAQ,GAAG,KAAK,CAAC;IAClD,CAAC;IAED,6BAA6B;IAC7B,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACzF,IAAI,cAAc,EAAE,CAAC;QACnB,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,oBAAoB,IAAI,QAAQ,IAAI,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACtH,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IAE9C,4BAA4B;IAC5B,IAAI,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,KAAK,IAAI,wBAAwB,OAAO,EAAE,EAAE,CAAC;IACvI,CAAC;IAED,gBAAgB;IAChB,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,CAAC,MAAM,CAAC,YAAY;YAAE,MAAM,CAAC,YAAY,GAAG,EAAE,CAAC;QACnD,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxE,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,KAAK,GAAG,UAAU,CAAC;IAC5B,CAAC;IAED,iBAAiB,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,iBAAiB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAE/C,2CAA2C;IAC3C,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;QAC7C,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,CAAC;gBAAC,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,+BAA+B,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;IAED,oFAAoF;IACpF,gFAAgF;IAChF,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,IAAI,CAAC,IAAI,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAEtC,KAAK,MAAM,UAAU,IAAI,eAAe,EAAE,CAAC;YACzC,6CAA6C;YAC7C,MAAM,mBAAmB,GAAG,MAAM,oBAAoB,CAAC,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;YACxH,MAAM,iBAAiB,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAE/D,+DAA+D;YAC/D,MAAM,aAAa,GAAa,EAAE,CAAC;YACnC,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,SAAS,EAAE,GAAG,iBAAiB,CAAC,CAAC,CAAC;YACpF,KAAK,MAAM,QAAQ,IAAI,kBAAkB,EAAE,CAAC;gBAC1C,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBAC/C,IAAI,KAAK,EAAE,MAAM,CAAC,KAAK,KAAK,UAAU;oBAAE,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvE,CAAC;YACD,0CAA0C;YAC1C,IAAI,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3B,CAAC;YAED,yCAAyC;YACzC,MAAM,gBAAgB,CAAC,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAEnD,+DAA+D;YAC/D,IAAI,CAAC,QAAQ,CAAC,gBAAgB;gBAAE,QAAQ,CAAC,gBAAgB,GAAG,EAAE,CAAC;YAC/D,QAAQ,CAAC,gBAAgB,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG;gBAC/C,OAAO,EAAE,UAAU,CAAC,OAAO;gBAC3B,SAAS,EAAE,UAAU,CAAC,SAAS;gBAC/B,SAAS,EAAE,UAAU,CAAC,SAAS;gBAC/B,aAAa,EAAE,iBAAiB;aACjC,CAAC;YAEF,+DAA+D;YAC/D,MAAM,YAAY,GAAG,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC;YACxF,KAAK,MAAM,IAAI,IAAI,mBAAmB,EAAE,CAAC;gBACvC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;gBACtK,IAAI,CAAC,UAAU;oBAAE,SAAS;gBAC1B,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;oBAAG,QAAgB,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;gBAC9D,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAwB,CAAC;gBAC5D,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,SAAkB,EAAE,CAAC;gBACrE,QAAQ,CAAC,YAAY,GAAG,YAAY,CAAC;gBACrC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC;YAChC,CAAC;YACD,kGAAkG;YAClG,IAAI,CAAC,QAAQ,CAAC,MAAM;gBAAE,QAAQ,CAAC,MAAM,GAAG,EAAE,CAAC;YAC3C,KAAK,MAAM,SAAS,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;gBAC7C,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,SAAkB,EAAE,CAAC;gBAC7E,IAAI,CAAC,QAAQ,CAAC,YAAY;oBAAE,QAAQ,CAAC,YAAY,GAAG,YAAY,CAAC;gBACjE,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,QAAQ,CAAC;YACxC,CAAC;YAED,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,qBAAqB,UAAU,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QAChJ,CAAC;QAED,MAAM,iBAAiB,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAE/C,uDAAuD;QACvD,MAAM,kBAAkB,CAAC,WAAW,CAAC,CAAC;QACtC,cAAc,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED,0EAA0E;IAC1E,+EAA+E;IAC/E,uDAAuD;IACvD,IAAI,CAAC,cAAc,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,gBAAgB,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/G,MAAM,kBAAkB,CAAC,WAAW,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3C,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,IAAI,KAAK,IAAI,aAAa,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9G,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,IAAI,KAAK,IAAI,aAAa,OAAO,EAAE,EAAE,CAAC;AACrH,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAkB,EAAE,IAAa;IAC1D,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACrD,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAC9D,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,KAAK,UAAU,CAAC;AACrC,CAAC;AAED,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACjD,WAAW,CAAC,4CAA4C,CAAC;KACzD,QAAQ,CAAC,QAAQ,EAAE,6BAA6B,CAAC;KACjD,MAAM,CAAC,mBAAmB,EAAE,kCAAkC,CAAC;KAC/D,MAAM,CAAC,cAAc,EAAE,gDAAgD,CAAC;KACxE,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,OAA4C,EAAE,EAAE;IAC3E,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC;QACrC,IAAI;QACJ,IAAI,EAAE,OAAO,CAAC,IAA0B;QACxC,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;YACxC,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;gBAC1B,OAAO,CAAC,GAAG,CAAC,kGAAkG,CAAC,CAAC;YAClH,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,iBAAiB,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -2,17 +2,17 @@
2
2
  * Tests for disable command module
3
3
  * Tests written FIRST following TDD
4
4
  */
5
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
5
+ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
6
6
  import * as fs from "node:fs/promises";
7
7
  import * as path from "node:path";
8
8
  import * as os from "node:os";
9
9
  import { parse as yamlParse, stringify as yamlStringify } from "yaml";
10
- // Import the module under test (doesn't exist yet - tests will fail)
11
10
  import { disableSkillOrMcp, } from "./disable.js";
11
+ import * as pluginTakeover from "../core/plugin-takeover.js";
12
12
  describe("Disable Command", () => {
13
13
  let tempDir;
14
14
  let globalMyceliumPath;
15
- // Sample manifest configuration
15
+ // Sample manifest configuration using state instead of enabled
16
16
  const sampleManifest = {
17
17
  version: "1.0",
18
18
  tools: {
@@ -25,33 +25,42 @@ describe("Disable Command", () => {
25
25
  },
26
26
  skills: {
27
27
  superpowers: {
28
- enabled: true,
28
+ state: "enabled",
29
29
  },
30
30
  "disabled-skill": {
31
- enabled: false,
31
+ state: "disabled",
32
32
  },
33
33
  "tool-specific-skill": {
34
- enabled: true,
34
+ state: "enabled",
35
35
  tools: ["claude-code", "codex"],
36
36
  },
37
37
  },
38
38
  mcps: {
39
39
  "whark-trading": {
40
- enabled: true,
40
+ state: "enabled",
41
41
  },
42
42
  "disabled-mcp": {
43
- enabled: false,
43
+ state: "disabled",
44
44
  },
45
45
  "tool-specific-mcp": {
46
- enabled: true,
46
+ state: "enabled",
47
47
  tools: ["claude-code", "codex"],
48
48
  },
49
49
  },
50
+ hooks: {
51
+ "pre-commit": {
52
+ state: "enabled",
53
+ source: "project",
54
+ },
55
+ "disabled-hook": {
56
+ state: "disabled",
57
+ source: "global",
58
+ },
59
+ },
50
60
  memory: {
51
- scopes: {
52
- shared: { sync_to: ["claude-code"], path: "global/memory/shared/", files: [] },
53
- coding: { sync_to: ["claude-code"], path: "global/memory/coding/", files: [] },
54
- personal: { sync_to: ["openclaw"], path: "global/memory/personal/", files: [] },
61
+ "shared-context": {
62
+ state: "enabled",
63
+ source: "global",
55
64
  },
56
65
  },
57
66
  };
@@ -80,7 +89,7 @@ describe("Disable Command", () => {
80
89
  // Verify manifest was updated
81
90
  const manifestContent = await fs.readFile(path.join(globalMyceliumPath, "manifest.yaml"), "utf-8");
82
91
  const updatedManifest = yamlParse(manifestContent);
83
- expect(updatedManifest.skills["superpowers"].enabled).toBe(false);
92
+ expect(updatedManifest.skills["superpowers"].state).toBe("disabled");
84
93
  });
85
94
  it("disables MCP globally", async () => {
86
95
  const options = {
@@ -94,7 +103,7 @@ describe("Disable Command", () => {
94
103
  // Verify manifest was updated
95
104
  const manifestContent = await fs.readFile(path.join(globalMyceliumPath, "manifest.yaml"), "utf-8");
96
105
  const updatedManifest = yamlParse(manifestContent);
97
- expect(updatedManifest.mcps["whark-trading"].enabled).toBe(false);
106
+ expect(updatedManifest.mcps["whark-trading"].state).toBe("disabled");
98
107
  });
99
108
  });
100
109
  describe("tool-specific disabling", () => {
@@ -147,7 +156,7 @@ describe("Disable Command", () => {
147
156
  await disableSkillOrMcp(options);
148
157
  const manifestContent = await fs.readFile(path.join(globalMyceliumPath, "manifest.yaml"), "utf-8");
149
158
  const updatedManifest = yamlParse(manifestContent);
150
- expect(updatedManifest.skills["superpowers"].enabled).toBe(false);
159
+ expect(updatedManifest.skills["superpowers"].state).toBe("disabled");
151
160
  });
152
161
  it("preserves other manifest settings when updating", async () => {
153
162
  const options = {
@@ -161,8 +170,8 @@ describe("Disable Command", () => {
161
170
  // Other settings should be preserved
162
171
  expect(updatedManifest.version).toBe("1.0");
163
172
  expect(updatedManifest.tools["claude-code"].enabled).toBe(true);
164
- expect(updatedManifest.skills["disabled-skill"].enabled).toBe(false);
165
- expect(updatedManifest.mcps["whark-trading"].enabled).toBe(true);
173
+ expect(updatedManifest.skills["disabled-skill"].state).toBe("disabled");
174
+ expect(updatedManifest.mcps["whark-trading"].state).toBe("enabled");
166
175
  });
167
176
  });
168
177
  describe("success messages", () => {
@@ -233,7 +242,7 @@ describe("Disable Command", () => {
233
242
  const projectManifest = {
234
243
  version: "1.0",
235
244
  skills: {
236
- "project-skill": { enabled: true },
245
+ "project-skill": { state: "enabled" },
237
246
  },
238
247
  mcps: {},
239
248
  };
@@ -249,7 +258,48 @@ describe("Disable Command", () => {
249
258
  // Verify project manifest was updated
250
259
  const manifestContent = await fs.readFile(path.join(projectPath, "manifest.yaml"), "utf-8");
251
260
  const updatedManifest = yamlParse(manifestContent);
252
- expect(updatedManifest.skills["project-skill"].enabled).toBe(false);
261
+ expect(updatedManifest.skills["project-skill"].state).toBe("disabled");
262
+ });
263
+ });
264
+ describe("hook and memory disabling", () => {
265
+ it("disables a hook globally", async () => {
266
+ const options = {
267
+ name: "pre-commit",
268
+ global: true,
269
+ globalPath: globalMyceliumPath,
270
+ };
271
+ const result = await disableSkillOrMcp(options);
272
+ expect(result.success).toBe(true);
273
+ expect(result.type).toBe("hook");
274
+ // Verify manifest was updated
275
+ const manifestContent = await fs.readFile(path.join(globalMyceliumPath, "manifest.yaml"), "utf-8");
276
+ const updatedManifest = yamlParse(manifestContent);
277
+ expect(updatedManifest.hooks["pre-commit"].state).toBe("disabled");
278
+ });
279
+ it("handles already disabled hook case", async () => {
280
+ const options = {
281
+ name: "disabled-hook",
282
+ global: true,
283
+ globalPath: globalMyceliumPath,
284
+ };
285
+ const result = await disableSkillOrMcp(options);
286
+ expect(result.success).toBe(true);
287
+ expect(result.alreadyDisabled).toBe(true);
288
+ expect(result.type).toBe("hook");
289
+ });
290
+ it("disables a memory item globally", async () => {
291
+ const options = {
292
+ name: "shared-context",
293
+ global: true,
294
+ globalPath: globalMyceliumPath,
295
+ };
296
+ const result = await disableSkillOrMcp(options);
297
+ expect(result.success).toBe(true);
298
+ expect(result.type).toBe("memory");
299
+ // Verify manifest was updated
300
+ const manifestContent = await fs.readFile(path.join(globalMyceliumPath, "manifest.yaml"), "utf-8");
301
+ const updatedManifest = yamlParse(manifestContent);
302
+ expect(updatedManifest.memory["shared-context"].state).toBe("disabled");
253
303
  });
254
304
  });
255
305
  describe("error handling", () => {
@@ -263,15 +313,15 @@ describe("Disable Command", () => {
263
313
  expect(result.success).toBe(false);
264
314
  expect(result.error).toContain("manifest");
265
315
  });
266
- it("validates name exists in manifest", async () => {
316
+ it("auto-registers unknown item as skill and disables it", async () => {
267
317
  const options = {
268
318
  name: "non-existent-skill",
269
319
  global: true,
270
320
  globalPath: globalMyceliumPath,
271
321
  };
272
322
  const result = await disableSkillOrMcp(options);
273
- expect(result.success).toBe(false);
274
- expect(result.error).toContain("not found");
323
+ expect(result.success).toBe(true);
324
+ expect(result.type).toBe("skill");
275
325
  });
276
326
  it("returns error for invalid tool name", async () => {
277
327
  const options = {
@@ -285,6 +335,50 @@ describe("Disable Command", () => {
285
335
  expect(result.error).toContain("Invalid tool");
286
336
  });
287
337
  });
338
+ describe("plugin takeover integration", () => {
339
+ it("triggers takeover when disabling a plugin skill", async () => {
340
+ const spy = vi.spyOn(pluginTakeover, "getAllPluginsForComponent").mockResolvedValue([{
341
+ pluginId: "my-plugin@skillsmp",
342
+ marketplace: "skillsmp",
343
+ plugin: "my-plugin",
344
+ version: "1.0.0",
345
+ cachePath: "/fake/cache/path",
346
+ allSkills: ["superpowers", "bonus-skill"],
347
+ enabledSkills: ["superpowers", "bonus-skill"],
348
+ }]);
349
+ const setEnabledSpy = vi.spyOn(pluginTakeover, "setPluginEnabled").mockResolvedValue(undefined);
350
+ const syncSpy = vi.spyOn(pluginTakeover, "syncPluginSymlinks").mockResolvedValue({ created: ["bonus-skill"], removed: [] });
351
+ const result = await disableSkillOrMcp({
352
+ name: "superpowers",
353
+ global: true,
354
+ globalPath: globalMyceliumPath,
355
+ });
356
+ expect(result.success).toBe(true);
357
+ expect(result.pluginTakeover).toBe(true);
358
+ expect(spy).toHaveBeenCalledWith("superpowers");
359
+ expect(setEnabledSpy).toHaveBeenCalledWith("my-plugin@skillsmp", false);
360
+ expect(syncSpy).toHaveBeenCalled();
361
+ // Verify manifest has takenOverPlugins
362
+ const manifest = yamlParse(await fs.readFile(path.join(globalMyceliumPath, "manifest.yaml"), "utf-8"));
363
+ expect(manifest.takenOverPlugins?.["my-plugin@skillsmp"]).toBeDefined();
364
+ expect(manifest.skills?.["superpowers"]?.pluginOrigin?.pluginId).toBe("my-plugin@skillsmp");
365
+ spy.mockRestore();
366
+ setEnabledSpy.mockRestore();
367
+ syncSpy.mockRestore();
368
+ });
369
+ it("does NOT trigger takeover for non-plugin skills", async () => {
370
+ const spy = vi.spyOn(pluginTakeover, "getAllPluginsForComponent").mockResolvedValue([]);
371
+ const result = await disableSkillOrMcp({
372
+ name: "superpowers",
373
+ global: true,
374
+ globalPath: globalMyceliumPath,
375
+ });
376
+ expect(result.success).toBe(true);
377
+ expect(result.pluginTakeover).toBeFalsy();
378
+ expect(spy).toHaveBeenCalledWith("superpowers");
379
+ spy.mockRestore();
380
+ });
381
+ });
288
382
  });
289
383
  });
290
384
  //# sourceMappingURL=disable.test.js.map