@goondocks/myco 0.4.4 → 0.5.1

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 (84) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +5 -1
  4. package/dist/{chunk-TK2ZYIAL.js → chunk-7KQB22DP.js} +2 -2
  5. package/dist/{chunk-TDLQBGKA.js → chunk-B6WVNDA5.js} +10 -2
  6. package/dist/{chunk-TDLQBGKA.js.map → chunk-B6WVNDA5.js.map} +1 -1
  7. package/dist/chunk-FIA5NTRH.js +159 -0
  8. package/dist/chunk-FIA5NTRH.js.map +1 -0
  9. package/dist/{chunk-5FIIK27E.js → chunk-FIRMTYFH.js} +3 -3
  10. package/dist/{chunk-6CAKKNGD.js → chunk-HJG7Z6SJ.js} +2 -2
  11. package/dist/{chunk-3F63SFZZ.js → chunk-HL2S5QZG.js} +8 -4
  12. package/dist/chunk-HL2S5QZG.js.map +1 -0
  13. package/dist/{chunk-42R7KVAW.js → chunk-IURC35BF.js} +2 -2
  14. package/dist/{chunk-OPO47BVS.js → chunk-JI6M2L2W.js} +2 -2
  15. package/dist/{chunk-PD7LV22R.js → chunk-KYL67SKZ.js} +50 -50
  16. package/dist/chunk-KYL67SKZ.js.map +1 -0
  17. package/dist/{chunk-XIIVIMFC.js → chunk-ND4VK6C7.js} +2 -2
  18. package/dist/{chunk-DKHYIA2V.js → chunk-R6LQT3U7.js} +11 -11
  19. package/dist/{chunk-OSZRLHIJ.js → chunk-RCV2I4AI.js} +3 -3
  20. package/dist/{chunk-EQVQEFOA.js → chunk-X6TKHO22.js} +2 -2
  21. package/dist/{chunk-KDWBZSOB.js → chunk-ZWUFTOG3.js} +4 -4
  22. package/dist/{cli-WOM4Z2Z4.js → cli-BLYNNKGJ.js} +21 -18
  23. package/dist/cli-BLYNNKGJ.js.map +1 -0
  24. package/dist/{client-XCNF6NFT.js → client-5GB4WVXE.js} +5 -5
  25. package/dist/curate-S4HOYWXA.js +231 -0
  26. package/dist/curate-S4HOYWXA.js.map +1 -0
  27. package/dist/{detect-providers-CQSPTW2B.js → detect-providers-BIHYFK5M.js} +3 -3
  28. package/dist/{digest-WTS6S4XP.js → digest-7NKYXM6G.js} +8 -8
  29. package/dist/{init-VPLUEULI.js → init-HPQ77WWF.js} +5 -5
  30. package/dist/{main-OGXH6XWO.js → main-NFQ4II75.js} +36 -14
  31. package/dist/main-NFQ4II75.js.map +1 -0
  32. package/dist/{rebuild-Z4YUY6HT.js → rebuild-KQ6G2GZM.js} +4 -4
  33. package/dist/{reprocess-DMGPZTLC.js → reprocess-ZL4HKTSC.js} +13 -13
  34. package/dist/{restart-QCQQ55KX.js → restart-FYW662DR.js} +6 -6
  35. package/dist/{search-ACEFQOUW.js → search-E5JQMTXV.js} +4 -4
  36. package/dist/{server-BQ3DWKZ6.js → server-TV3D35HZ.js} +30 -9
  37. package/dist/{server-BQ3DWKZ6.js.map → server-TV3D35HZ.js.map} +1 -1
  38. package/dist/{session-start-BXRTKS4X.js → session-start-5MFEOVQ5.js} +6 -6
  39. package/dist/{setup-digest-EJXSQGZ5.js → setup-digest-DZAFIBEF.js} +5 -5
  40. package/dist/{setup-llm-P3MLWUDR.js → setup-llm-4BZM33YT.js} +5 -5
  41. package/dist/src/cli.js +4 -4
  42. package/dist/src/daemon/main.js +4 -4
  43. package/dist/src/hooks/post-tool-use.js +5 -5
  44. package/dist/src/hooks/session-end.js +5 -5
  45. package/dist/src/hooks/session-start.js +4 -4
  46. package/dist/src/hooks/stop.js +5 -5
  47. package/dist/src/hooks/user-prompt-submit.js +5 -5
  48. package/dist/src/mcp/server.js +4 -4
  49. package/dist/src/prompts/supersession.md +32 -0
  50. package/dist/{stats-3FAP5FKV.js → stats-ZIIJ2GB3.js} +5 -5
  51. package/dist/{verify-3FTCOULE.js → verify-RACBFT2P.js} +4 -4
  52. package/dist/{version-AL67JH7X.js → version-HJTVNPOO.js} +4 -4
  53. package/package.json +1 -1
  54. package/skills/myco/SKILL.md +20 -1
  55. package/skills/myco/references/cli-usage.md +48 -0
  56. package/skills/myco/references/wisdom.md +11 -1
  57. package/dist/chunk-3F63SFZZ.js.map +0 -1
  58. package/dist/chunk-PD7LV22R.js.map +0 -1
  59. package/dist/cli-WOM4Z2Z4.js.map +0 -1
  60. package/dist/main-OGXH6XWO.js.map +0 -1
  61. /package/dist/{chunk-TK2ZYIAL.js.map → chunk-7KQB22DP.js.map} +0 -0
  62. /package/dist/{chunk-5FIIK27E.js.map → chunk-FIRMTYFH.js.map} +0 -0
  63. /package/dist/{chunk-6CAKKNGD.js.map → chunk-HJG7Z6SJ.js.map} +0 -0
  64. /package/dist/{chunk-42R7KVAW.js.map → chunk-IURC35BF.js.map} +0 -0
  65. /package/dist/{chunk-OPO47BVS.js.map → chunk-JI6M2L2W.js.map} +0 -0
  66. /package/dist/{chunk-XIIVIMFC.js.map → chunk-ND4VK6C7.js.map} +0 -0
  67. /package/dist/{chunk-DKHYIA2V.js.map → chunk-R6LQT3U7.js.map} +0 -0
  68. /package/dist/{chunk-OSZRLHIJ.js.map → chunk-RCV2I4AI.js.map} +0 -0
  69. /package/dist/{chunk-EQVQEFOA.js.map → chunk-X6TKHO22.js.map} +0 -0
  70. /package/dist/{chunk-KDWBZSOB.js.map → chunk-ZWUFTOG3.js.map} +0 -0
  71. /package/dist/{client-XCNF6NFT.js.map → client-5GB4WVXE.js.map} +0 -0
  72. /package/dist/{detect-providers-CQSPTW2B.js.map → detect-providers-BIHYFK5M.js.map} +0 -0
  73. /package/dist/{digest-WTS6S4XP.js.map → digest-7NKYXM6G.js.map} +0 -0
  74. /package/dist/{init-VPLUEULI.js.map → init-HPQ77WWF.js.map} +0 -0
  75. /package/dist/{rebuild-Z4YUY6HT.js.map → rebuild-KQ6G2GZM.js.map} +0 -0
  76. /package/dist/{reprocess-DMGPZTLC.js.map → reprocess-ZL4HKTSC.js.map} +0 -0
  77. /package/dist/{restart-QCQQ55KX.js.map → restart-FYW662DR.js.map} +0 -0
  78. /package/dist/{search-ACEFQOUW.js.map → search-E5JQMTXV.js.map} +0 -0
  79. /package/dist/{session-start-BXRTKS4X.js.map → session-start-5MFEOVQ5.js.map} +0 -0
  80. /package/dist/{setup-digest-EJXSQGZ5.js.map → setup-digest-DZAFIBEF.js.map} +0 -0
  81. /package/dist/{setup-llm-P3MLWUDR.js.map → setup-llm-4BZM33YT.js.map} +0 -0
  82. /package/dist/{stats-3FAP5FKV.js.map → stats-ZIIJ2GB3.js.map} +0 -0
  83. /package/dist/{verify-3FTCOULE.js.map → verify-RACBFT2P.js.map} +0 -0
  84. /package/dist/{version-AL67JH7X.js.map → version-HJTVNPOO.js.map} +0 -0
@@ -12,21 +12,21 @@ import {
12
12
  import "./chunk-6UJWI4IW.js";
13
13
  import {
14
14
  readStdin
15
- } from "./chunk-XIIVIMFC.js";
15
+ } from "./chunk-ND4VK6C7.js";
16
16
  import {
17
17
  DaemonClient
18
- } from "./chunk-KDWBZSOB.js";
19
- import "./chunk-TK2ZYIAL.js";
18
+ } from "./chunk-ZWUFTOG3.js";
19
+ import "./chunk-7KQB22DP.js";
20
20
  import {
21
21
  resolveVaultDir
22
22
  } from "./chunk-N33KUCFP.js";
23
- import "./chunk-EQVQEFOA.js";
23
+ import "./chunk-X6TKHO22.js";
24
24
  import {
25
25
  CONTEXT_PLAN_PREVIEW_CHARS,
26
26
  CONTEXT_SESSION_PREVIEW_CHARS,
27
27
  CONTEXT_SPORE_PREVIEW_CHARS,
28
28
  estimateTokens
29
- } from "./chunk-TDLQBGKA.js";
29
+ } from "./chunk-B6WVNDA5.js";
30
30
  import "./chunk-PZUWP5VK.js";
31
31
 
32
32
  // src/context/relevance.ts
@@ -189,4 +189,4 @@ async function main() {
189
189
  }
190
190
  }
191
191
  main();
192
- //# sourceMappingURL=session-start-BXRTKS4X.js.map
192
+ //# sourceMappingURL=session-start-5MFEOVQ5.js.map
@@ -2,14 +2,14 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  run
4
4
  } from "./chunk-UKWO26VI.js";
5
- import "./chunk-5FIIK27E.js";
5
+ import "./chunk-FIRMTYFH.js";
6
6
  import "./chunk-SAKJMNSR.js";
7
- import "./chunk-OPO47BVS.js";
7
+ import "./chunk-JI6M2L2W.js";
8
8
  import "./chunk-6UJWI4IW.js";
9
- import "./chunk-EQVQEFOA.js";
10
- import "./chunk-TDLQBGKA.js";
9
+ import "./chunk-X6TKHO22.js";
10
+ import "./chunk-B6WVNDA5.js";
11
11
  import "./chunk-PZUWP5VK.js";
12
12
  export {
13
13
  run
14
14
  };
15
- //# sourceMappingURL=setup-digest-EJXSQGZ5.js.map
15
+ //# sourceMappingURL=setup-digest-DZAFIBEF.js.map
@@ -2,14 +2,14 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  run
4
4
  } from "./chunk-T7OC6GH5.js";
5
- import "./chunk-5FIIK27E.js";
5
+ import "./chunk-FIRMTYFH.js";
6
6
  import "./chunk-SAKJMNSR.js";
7
- import "./chunk-OPO47BVS.js";
7
+ import "./chunk-JI6M2L2W.js";
8
8
  import "./chunk-6UJWI4IW.js";
9
- import "./chunk-EQVQEFOA.js";
10
- import "./chunk-TDLQBGKA.js";
9
+ import "./chunk-X6TKHO22.js";
10
+ import "./chunk-B6WVNDA5.js";
11
11
  import "./chunk-PZUWP5VK.js";
12
12
  export {
13
13
  run
14
14
  };
15
- //# sourceMappingURL=setup-llm-P3MLWUDR.js.map
15
+ //# sourceMappingURL=setup-llm-4BZM33YT.js.map
package/dist/src/cli.js CHANGED
@@ -2,12 +2,12 @@
2
2
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
3
3
  import {
4
4
  ensureNativeDeps
5
- } from "../chunk-6CAKKNGD.js";
6
- import "../chunk-EQVQEFOA.js";
7
- import "../chunk-TDLQBGKA.js";
5
+ } from "../chunk-HJG7Z6SJ.js";
6
+ import "../chunk-X6TKHO22.js";
7
+ import "../chunk-B6WVNDA5.js";
8
8
  import "../chunk-PZUWP5VK.js";
9
9
 
10
10
  // src/entries/cli.ts
11
11
  ensureNativeDeps();
12
- await import("../cli-WOM4Z2Z4.js");
12
+ await import("../cli-BLYNNKGJ.js");
13
13
  //# sourceMappingURL=cli.js.map
@@ -1,13 +1,13 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  ensureNativeDeps
4
- } from "../../chunk-6CAKKNGD.js";
5
- import "../../chunk-EQVQEFOA.js";
6
- import "../../chunk-TDLQBGKA.js";
4
+ } from "../../chunk-HJG7Z6SJ.js";
5
+ import "../../chunk-X6TKHO22.js";
6
+ import "../../chunk-B6WVNDA5.js";
7
7
  import "../../chunk-PZUWP5VK.js";
8
8
 
9
9
  // src/entries/daemon.ts
10
10
  ensureNativeDeps();
11
- var { main } = await import("../../main-OGXH6XWO.js");
11
+ var { main } = await import("../../main-NFQ4II75.js");
12
12
  await main();
13
13
  //# sourceMappingURL=main.js.map
@@ -4,18 +4,18 @@ import {
4
4
  } from "../../chunk-HIN3UVOG.js";
5
5
  import {
6
6
  readStdin
7
- } from "../../chunk-XIIVIMFC.js";
7
+ } from "../../chunk-ND4VK6C7.js";
8
8
  import {
9
9
  DaemonClient
10
- } from "../../chunk-KDWBZSOB.js";
11
- import "../../chunk-TK2ZYIAL.js";
10
+ } from "../../chunk-ZWUFTOG3.js";
11
+ import "../../chunk-7KQB22DP.js";
12
12
  import {
13
13
  resolveVaultDir
14
14
  } from "../../chunk-N33KUCFP.js";
15
- import "../../chunk-EQVQEFOA.js";
15
+ import "../../chunk-X6TKHO22.js";
16
16
  import {
17
17
  TOOL_OUTPUT_PREVIEW_CHARS
18
- } from "../../chunk-TDLQBGKA.js";
18
+ } from "../../chunk-B6WVNDA5.js";
19
19
  import "../../chunk-PZUWP5VK.js";
20
20
 
21
21
  // src/hooks/post-tool-use.ts
@@ -1,16 +1,16 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  readStdin
4
- } from "../../chunk-XIIVIMFC.js";
4
+ } from "../../chunk-ND4VK6C7.js";
5
5
  import {
6
6
  DaemonClient
7
- } from "../../chunk-KDWBZSOB.js";
8
- import "../../chunk-TK2ZYIAL.js";
7
+ } from "../../chunk-ZWUFTOG3.js";
8
+ import "../../chunk-7KQB22DP.js";
9
9
  import {
10
10
  resolveVaultDir
11
11
  } from "../../chunk-N33KUCFP.js";
12
- import "../../chunk-EQVQEFOA.js";
13
- import "../../chunk-TDLQBGKA.js";
12
+ import "../../chunk-X6TKHO22.js";
13
+ import "../../chunk-B6WVNDA5.js";
14
14
  import "../../chunk-PZUWP5VK.js";
15
15
 
16
16
  // src/hooks/session-end.ts
@@ -1,12 +1,12 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  ensureNativeDeps
4
- } from "../../chunk-6CAKKNGD.js";
5
- import "../../chunk-EQVQEFOA.js";
6
- import "../../chunk-TDLQBGKA.js";
4
+ } from "../../chunk-HJG7Z6SJ.js";
5
+ import "../../chunk-X6TKHO22.js";
6
+ import "../../chunk-B6WVNDA5.js";
7
7
  import "../../chunk-PZUWP5VK.js";
8
8
 
9
9
  // src/entries/session-start.ts
10
10
  ensureNativeDeps();
11
- await import("../../session-start-BXRTKS4X.js");
11
+ await import("../../session-start-5MFEOVQ5.js");
12
12
  //# sourceMappingURL=session-start.js.map
@@ -5,16 +5,16 @@ import {
5
5
  import "../../chunk-6UJWI4IW.js";
6
6
  import {
7
7
  readStdin
8
- } from "../../chunk-XIIVIMFC.js";
8
+ } from "../../chunk-ND4VK6C7.js";
9
9
  import {
10
10
  DaemonClient
11
- } from "../../chunk-KDWBZSOB.js";
12
- import "../../chunk-TK2ZYIAL.js";
11
+ } from "../../chunk-ZWUFTOG3.js";
12
+ import "../../chunk-7KQB22DP.js";
13
13
  import {
14
14
  resolveVaultDir
15
15
  } from "../../chunk-N33KUCFP.js";
16
- import "../../chunk-EQVQEFOA.js";
17
- import "../../chunk-TDLQBGKA.js";
16
+ import "../../chunk-X6TKHO22.js";
17
+ import "../../chunk-B6WVNDA5.js";
18
18
  import "../../chunk-PZUWP5VK.js";
19
19
 
20
20
  // src/hooks/stop.ts
@@ -4,16 +4,16 @@ import {
4
4
  } from "../../chunk-HIN3UVOG.js";
5
5
  import {
6
6
  readStdin
7
- } from "../../chunk-XIIVIMFC.js";
7
+ } from "../../chunk-ND4VK6C7.js";
8
8
  import {
9
9
  DaemonClient
10
- } from "../../chunk-KDWBZSOB.js";
11
- import "../../chunk-TK2ZYIAL.js";
10
+ } from "../../chunk-ZWUFTOG3.js";
11
+ import "../../chunk-7KQB22DP.js";
12
12
  import {
13
13
  resolveVaultDir
14
14
  } from "../../chunk-N33KUCFP.js";
15
- import "../../chunk-EQVQEFOA.js";
16
- import "../../chunk-TDLQBGKA.js";
15
+ import "../../chunk-X6TKHO22.js";
16
+ import "../../chunk-B6WVNDA5.js";
17
17
  import "../../chunk-PZUWP5VK.js";
18
18
 
19
19
  // src/hooks/user-prompt-submit.ts
@@ -1,13 +1,13 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  ensureNativeDeps
4
- } from "../../chunk-6CAKKNGD.js";
5
- import "../../chunk-EQVQEFOA.js";
6
- import "../../chunk-TDLQBGKA.js";
4
+ } from "../../chunk-HJG7Z6SJ.js";
5
+ import "../../chunk-X6TKHO22.js";
6
+ import "../../chunk-B6WVNDA5.js";
7
7
  import "../../chunk-PZUWP5VK.js";
8
8
 
9
9
  // src/entries/mcp-server.ts
10
10
  ensureNativeDeps();
11
- var { main } = await import("../../server-BQ3DWKZ6.js");
11
+ var { main } = await import("../../server-TV3D35HZ.js");
12
12
  await main();
13
13
  //# sourceMappingURL=server.js.map
@@ -0,0 +1,32 @@
1
+ You are evaluating whether a new observation supersedes any existing observations in a knowledge vault.
2
+
3
+ An observation is superseded ONLY when the new one makes it factually outdated or incorrect.
4
+ Do NOT supersede observations that:
5
+ - Discuss the same topic from a different angle
6
+ - Record a different decision about the same component
7
+ - Describe a trade-off that was considered (even if a different choice was made later)
8
+
9
+ Examples of supersession:
10
+ - New: "The unload API uses instance_id field" → Supersedes: "The unload API uses model field"
11
+ - New: "ensureLoaded runs every cycle" → Supersedes: "ensureLoaded runs once via modelReady flag"
12
+
13
+ Examples of NOT supersession:
14
+ - New: "We chose Ollama for digest" → Does NOT supersede: "LM Studio requires KV cache management"
15
+ (Both are valid observations about different providers)
16
+ - New: "Added retry logic to summarize" → Does NOT supersede: "summarize throws on 404"
17
+ (The 404 behavior is still true; retry is additive)
18
+
19
+ ## New Observation
20
+
21
+ {{new_spore}}
22
+
23
+ ## Existing Observations
24
+
25
+ {{candidates}}
26
+
27
+ ---
28
+
29
+ Return a JSON array of IDs from the existing observations that the new observation supersedes.
30
+ If none are superseded, return an empty array: []
31
+
32
+ Return ONLY the JSON array, no other text.
@@ -7,11 +7,11 @@ import {
7
7
  } from "./chunk-AK6GNLPV.js";
8
8
  import {
9
9
  isProcessAlive
10
- } from "./chunk-5FIIK27E.js";
10
+ } from "./chunk-FIRMTYFH.js";
11
11
  import "./chunk-SAKJMNSR.js";
12
- import "./chunk-OPO47BVS.js";
13
- import "./chunk-EQVQEFOA.js";
14
- import "./chunk-TDLQBGKA.js";
12
+ import "./chunk-JI6M2L2W.js";
13
+ import "./chunk-X6TKHO22.js";
14
+ import "./chunk-B6WVNDA5.js";
15
15
  import "./chunk-PZUWP5VK.js";
16
16
 
17
17
  // src/cli/stats.ts
@@ -74,4 +74,4 @@ Vectors: error \u2014 ${e.message}`);
74
74
  export {
75
75
  run
76
76
  };
77
- //# sourceMappingURL=stats-3FAP5FKV.js.map
77
+ //# sourceMappingURL=stats-ZIIJ2GB3.js.map
@@ -2,13 +2,13 @@ import { createRequire as __cr } from 'node:module'; const require = __cr(import
2
2
  import {
3
3
  createEmbeddingProvider,
4
4
  createLlmProvider
5
- } from "./chunk-OSZRLHIJ.js";
6
- import "./chunk-OPO47BVS.js";
5
+ } from "./chunk-RCV2I4AI.js";
6
+ import "./chunk-JI6M2L2W.js";
7
7
  import {
8
8
  loadConfig
9
9
  } from "./chunk-TBRZAJ7W.js";
10
10
  import "./chunk-6UJWI4IW.js";
11
- import "./chunk-TDLQBGKA.js";
11
+ import "./chunk-B6WVNDA5.js";
12
12
  import "./chunk-PZUWP5VK.js";
13
13
 
14
14
  // src/cli/verify.ts
@@ -47,4 +47,4 @@ async function run(_args, vaultDir) {
47
47
  export {
48
48
  run
49
49
  };
50
- //# sourceMappingURL=verify-3FTCOULE.js.map
50
+ //# sourceMappingURL=verify-RACBFT2P.js.map
@@ -1,11 +1,11 @@
1
1
  import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
2
2
  import {
3
3
  getPluginVersion
4
- } from "./chunk-TK2ZYIAL.js";
5
- import "./chunk-EQVQEFOA.js";
6
- import "./chunk-TDLQBGKA.js";
4
+ } from "./chunk-7KQB22DP.js";
5
+ import "./chunk-X6TKHO22.js";
6
+ import "./chunk-B6WVNDA5.js";
7
7
  import "./chunk-PZUWP5VK.js";
8
8
  export {
9
9
  getPluginVersion
10
10
  };
11
- //# sourceMappingURL=version-AL67JH7X.js.map
11
+ //# sourceMappingURL=version-HJTVNPOO.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goondocks/myco",
3
- "version": "0.4.4",
3
+ "version": "0.5.1",
4
4
  "description": "Collective agent intelligence — Claude Code plugin",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -140,7 +140,7 @@ View daemon logs for debugging when sessions aren't being captured, observations
140
140
  { "level": "warn", "component": "processor", "limit": 20 }
141
141
  ```
142
142
 
143
- Components: `daemon`, `processor`, `hooks`, `lifecycle`, `embeddings`, `lineage`, `watcher`.
143
+ Components: `daemon`, `processor`, `hooks`, `lifecycle`, `embeddings`, `lineage`, `watcher`, `digest`, `curation`.
144
144
 
145
145
  ### myco_supersede — Mark a spore as replaced
146
146
 
@@ -237,6 +237,25 @@ Options:
237
237
  - `--session <id>` — reprocess a single session (partial ID match)
238
238
  - `--index-only` — skip LLM extraction, just re-index and re-embed existing notes
239
239
 
240
+ ### Digest management
241
+
242
+ ```
243
+ node <plugin-root>/dist/src/cli.js digest # Run incremental digest cycle
244
+ node <plugin-root>/dist/src/cli.js digest --tier 3000 # Reprocess a specific tier (clean slate)
245
+ node <plugin-root>/dist/src/cli.js digest --full # Reprocess all tiers from scratch
246
+ ```
247
+
248
+ ### Vault curation
249
+
250
+ Supersession happens automatically on every spore write. For vault-wide cleanup, see `references/cli-usage.md` for full flags:
251
+
252
+ ```
253
+ node <plugin-root>/dist/src/cli.js curate # Scan and supersede stale spores
254
+ node <plugin-root>/dist/src/cli.js curate --dry-run # Preview without writing
255
+ ```
256
+
257
+ For patterns on when to manually supersede or consolidate, see `references/wisdom.md`.
258
+
240
259
  ### Other maintenance commands
241
260
 
242
261
  ```
@@ -287,6 +287,54 @@ Run this after changing the embedding model (via `setup-llm`) to regenerate all
287
287
 
288
288
  ---
289
289
 
290
+ ### `digest` — Run a digest cycle on demand
291
+
292
+ Trigger a digest cycle manually. Use `--tier` to reprocess a specific tier from scratch (all substrate, no previous extract), or `--full` for a complete rebuild of all tiers.
293
+
294
+ | Flag | Type | Description |
295
+ |------|------|-------------|
296
+ | `--tier <number>` | number | Reprocess a specific tier (clean slate) |
297
+ | `--full` | boolean | Reprocess all tiers from scratch |
298
+
299
+ When `--tier` or `--full` is used, the cycle reads all vault notes (ignoring the last-cycle timestamp) and skips the previous extract, producing a fresh synthesis.
300
+
301
+ **Examples:**
302
+
303
+ ```sh
304
+ # Run an incremental cycle (same as what the metabolism timer does)
305
+ node ${CLAUDE_PLUGIN_ROOT}/dist/src/cli.js digest
306
+
307
+ # Reprocess tier 3000 from scratch
308
+ node ${CLAUDE_PLUGIN_ROOT}/dist/src/cli.js digest --tier 3000
309
+
310
+ # Full rebuild of all tiers
311
+ node ${CLAUDE_PLUGIN_ROOT}/dist/src/cli.js digest --full
312
+ ```
313
+
314
+ ---
315
+
316
+ ### `curate` — Scan vault and supersede stale spores
317
+
318
+ Scans all active spores, clusters them by semantic similarity within each observation type, and asks the LLM which older spores are outdated. Superseded spores are preserved with lineage metadata — never deleted.
319
+
320
+ | Flag | Type | Description |
321
+ |------|------|-------------|
322
+ | `--dry-run` | boolean | Run LLM evaluation but print results without writing |
323
+
324
+ **Examples:**
325
+
326
+ ```sh
327
+ # Scan and supersede stale spores
328
+ node ${CLAUDE_PLUGIN_ROOT}/dist/src/cli.js curate
329
+
330
+ # Preview what would be superseded
331
+ node ${CLAUDE_PLUGIN_ROOT}/dist/src/cli.js curate --dry-run
332
+ ```
333
+
334
+ Note: `--dry-run` still runs LLM calls (to evaluate clusters) — it just skips the writes. Use it to review before running on a vault for the first time.
335
+
336
+ ---
337
+
290
338
  ### `reprocess` — Re-extract observations from transcripts
291
339
 
292
340
  Re-reads session transcripts, re-extracts observations with the current LLM, and re-indexes. Existing spores are preserved — new extractions are additive.
@@ -2,9 +2,19 @@
2
2
 
3
3
  When you notice patterns in vault spores — recurring themes, conflicting advice, outdated observations — use these tools to keep the vault clean and its knowledge sharp.
4
4
 
5
+ ## Automatic Curation
6
+
7
+ Myco automatically checks for supersession every time a new spore is written. After the spore is saved and embedded, a fire-and-forget pipeline searches for semantically similar active spores of the same observation type and asks the LLM whether any are now outdated. If so, they're marked superseded automatically. This means most vault hygiene happens without manual intervention.
8
+
9
+ For vault-wide cleanup (e.g., after a large refactor), use the CLI:
10
+ ```sh
11
+ node ${CLAUDE_PLUGIN_ROOT}/dist/src/cli.js curate --dry-run # preview
12
+ node ${CLAUDE_PLUGIN_ROOT}/dist/src/cli.js curate # execute
13
+ ```
14
+
5
15
  ## Supersede
6
16
 
7
- Use `myco_supersede` when a newer spore replaces an older one.
17
+ Use `myco_supersede` for manual supersession when you spot a stale spore that automatic curation missed.
8
18
 
9
19
  **Signals:**
10
20
  - A decision was reversed in a later session
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/daemon/digest.ts"],"sourcesContent":["/**\n * DigestEngine — synthesizes vault knowledge into tiered context extracts.\n * Metabolism — adaptive timer that throttles digest cycles based on activity.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport YAML from 'yaml';\n\nimport type { MycoIndex, IndexedNote } from '@myco/index/sqlite.js';\nimport type { LlmProvider, LlmRequestOptions } from '@myco/intelligence/llm.js';\nimport type { MycoConfig } from '@myco/config/schema.js';\nimport { loadPrompt } from '@myco/prompts/index.js';\nimport { stripReasoningTokens } from '@myco/intelligence/response.js';\nimport { stripFrontmatter } from '@myco/vault/frontmatter.js';\nimport {\n estimateTokens,\n CHARS_PER_TOKEN,\n DIGEST_TIER_MIN_CONTEXT,\n DIGEST_SUBSTRATE_TYPE_WEIGHTS,\n DIGEST_LLM_REQUEST_TIMEOUT_MS,\n LLM_REASONING_MODE,\n} from '@myco/constants.js';\n\n// --- Interfaces ---\n\nexport interface DigestCycleResult {\n cycleId: string;\n timestamp: string;\n substrate: {\n sessions: string[];\n spores: string[];\n plans: string[];\n artifacts: string[];\n team: string[];\n };\n tiersGenerated: number[];\n model: string;\n durationMs: number;\n tokensUsed: number;\n}\n\n/** Simple log function signature for digest progress reporting. */\nexport type DigestLogFn = (level: 'debug' | 'info' | 'warn', message: string, data?: Record<string, unknown>) => void;\n\nexport interface DigestCycleOptions {\n /** Process all substrate regardless of last cycle timestamp. */\n fullReprocess?: boolean;\n /** Only generate these tiers (default: all eligible). */\n tiers?: number[];\n /** Skip previous extract — start from clean slate. */\n cleanSlate?: boolean;\n}\n\nexport interface DigestEngineConfig {\n vaultDir: string;\n index: MycoIndex;\n llmProvider: LlmProvider;\n config: MycoConfig;\n log?: DigestLogFn;\n}\n\n// --- Constants ---\n\n/** Token overhead estimate for previous extract section wrapper. */\nconst PREVIOUS_EXTRACT_OVERHEAD_TOKENS = 50;\n\n/** Safety margin for context window — our CHARS_PER_TOKEN=4 heuristic significantly\n * underestimates real token counts (observed ~3.2 chars/token for mixed content).\n * 0.70 provides a safe buffer: 32K * 0.70 = 22.4K usable tokens. */\nconst CONTEXT_SAFETY_MARGIN = 0.70;\n\n/** Types that are digest output — excluded from substrate to avoid self-digestion. */\nconst EXTRACT_TYPE = 'extract';\n\n// --- DigestEngine ---\n\nexport class DigestEngine {\n private vaultDir: string;\n private index: MycoIndex;\n private llm: LlmProvider;\n private config: MycoConfig;\n private log: DigestLogFn;\n private lastCycleTimestampCache: string | null | undefined = undefined;\n private cycleInProgress = false;\n\n constructor(engineConfig: DigestEngineConfig) {\n this.vaultDir = engineConfig.vaultDir;\n this.index = engineConfig.index;\n this.llm = engineConfig.llmProvider;\n this.config = engineConfig.config;\n this.log = engineConfig.log ?? (() => {});\n }\n\n /**\n * Query index for recent vault notes to feed into the digest.\n * Filters out extract notes (our own output) and caps at max_notes_per_cycle.\n */\n discoverSubstrate(lastCycleTimestamp: string | null): IndexedNote[] {\n const maxNotes = this.config.digest.substrate.max_notes_per_cycle;\n\n const notes = lastCycleTimestamp\n ? this.index.query({ updatedSince: lastCycleTimestamp, limit: maxNotes })\n : this.index.query({ limit: maxNotes });\n\n // Guard against self-digestion: extract files are not currently indexed,\n // but this filter prevents feedback loops if they ever are (e.g., via rebuild)\n const filtered = notes.filter((n) => n.type !== EXTRACT_TYPE);\n\n // Sort by type weight (descending) then by recency (descending)\n filtered.sort((a, b) => {\n const weightA = DIGEST_SUBSTRATE_TYPE_WEIGHTS[a.type] ?? 0;\n const weightB = DIGEST_SUBSTRATE_TYPE_WEIGHTS[b.type] ?? 0;\n if (weightB !== weightA) return weightB - weightA;\n // More recent first — created is ISO string, lexicographic sort works\n return b.created.localeCompare(a.created);\n });\n\n return filtered.slice(0, maxNotes);\n }\n\n /**\n * Filter configured tiers by the context window available.\n * Only tiers whose minimum context requirement is met are eligible.\n */\n getEligibleTiers(): number[] {\n const contextWindow = this.config.digest.intelligence.context_window;\n return this.config.digest.tiers.filter((tier) => {\n const minContext = DIGEST_TIER_MIN_CONTEXT[tier];\n return minContext !== undefined && minContext <= contextWindow;\n });\n }\n\n /**\n * Format notes compactly for inclusion in the digest prompt.\n * Stops adding notes once the token budget is exceeded.\n */\n formatSubstrate(notes: IndexedNote[], tokenBudget: number): string {\n const charBudget = tokenBudget * CHARS_PER_TOKEN;\n const parts: string[] = [];\n let usedChars = 0;\n\n for (const note of notes) {\n const entry = `### [${note.type}] ${note.id} — \"${note.title}\"\\n${note.content}`;\n if (usedChars + entry.length > charBudget && parts.length > 0) break;\n parts.push(entry);\n usedChars += entry.length;\n }\n\n return parts.join('\\n\\n');\n }\n\n /**\n * Read a previously generated extract for a given tier.\n * Returns the body (stripped of YAML frontmatter), or null if not found.\n */\n readPreviousExtract(tier: number): string | null {\n const extractPath = path.join(this.vaultDir, 'digest', `extract-${tier}.md`);\n let content: string;\n try {\n content = fs.readFileSync(extractPath, 'utf-8');\n } catch {\n return null;\n }\n\n return stripFrontmatter(content).body;\n }\n\n /**\n * Write a digest extract to the vault with YAML frontmatter.\n * Uses atomic write pattern (temp file + rename).\n */\n writeExtract(\n tier: number,\n body: string,\n cycleId: string,\n model: string,\n substrateCount: number,\n ): void {\n const digestDir = path.join(this.vaultDir, 'digest');\n fs.mkdirSync(digestDir, { recursive: true });\n\n const frontmatter: Record<string, unknown> = {\n type: EXTRACT_TYPE,\n tier,\n generated: new Date().toISOString(),\n cycle_id: cycleId,\n substrate_count: substrateCount,\n model,\n };\n\n const fmYaml = YAML.stringify(frontmatter, {\n defaultStringType: 'QUOTE_DOUBLE',\n defaultKeyType: 'PLAIN',\n }).trim();\n const file = `---\\n${fmYaml}\\n---\\n\\n${body}\\n`;\n\n const fullPath = path.join(digestDir, `extract-${tier}.md`);\n const tmpPath = `${fullPath}.tmp`;\n fs.writeFileSync(tmpPath, file, 'utf-8');\n fs.renameSync(tmpPath, fullPath);\n }\n\n /**\n * Append a digest cycle result as a JSON line to trace.jsonl.\n */\n appendTrace(record: DigestCycleResult): void {\n const digestDir = path.join(this.vaultDir, 'digest');\n fs.mkdirSync(digestDir, { recursive: true });\n const tracePath = path.join(digestDir, 'trace.jsonl');\n fs.appendFileSync(tracePath, JSON.stringify(record) + '\\n', 'utf-8');\n this.lastCycleTimestampCache = record.timestamp;\n }\n\n /**\n * Read the last cycle timestamp from trace.jsonl.\n * Cached in memory after first read — subsequent calls are O(1).\n */\n getLastCycleTimestamp(): string | null {\n if (this.lastCycleTimestampCache !== undefined) return this.lastCycleTimestampCache;\n\n const tracePath = path.join(this.vaultDir, 'digest', 'trace.jsonl');\n let content: string;\n try {\n content = fs.readFileSync(tracePath, 'utf-8').trim();\n } catch {\n this.lastCycleTimestampCache = null;\n return null;\n }\n\n if (!content) {\n this.lastCycleTimestampCache = null;\n return null;\n }\n\n const lines = content.split('\\n');\n const lastLine = lines[lines.length - 1];\n try {\n const record = JSON.parse(lastLine) as DigestCycleResult;\n this.lastCycleTimestampCache = record.timestamp;\n return record.timestamp;\n } catch {\n this.lastCycleTimestampCache = null;\n return null;\n }\n }\n\n /**\n * Run a full digest cycle: discover substrate, generate extracts for each tier.\n * Returns the cycle result, or null if no substrate was found.\n */\n async runCycle(opts?: DigestCycleOptions): Promise<DigestCycleResult | null> {\n if (this.cycleInProgress) {\n this.log('debug', 'Cycle already in progress — skipping');\n return null;\n }\n this.cycleInProgress = true;\n\n try {\n return await this.runCycleInternal(opts);\n } finally {\n this.cycleInProgress = false;\n }\n }\n\n private async runCycleInternal(opts?: DigestCycleOptions): Promise<DigestCycleResult | null> {\n // Ensure model is loaded with correct settings every cycle.\n // LM Studio's idle TTL can evict our instance between cycles — without\n // re-running ensureLoaded, the auto-reloaded instance would use LM Studio's\n // UI defaults (wrong KV cache setting). This is fast (~26ms) when the\n // instance is still alive (just a getLoadedInstances check).\n if (this.llm.ensureLoaded) {\n const { context_window: contextWindow, gpu_kv_cache: gpuKvCache } = this.config.digest.intelligence;\n this.log('debug', 'Verifying digest model', { contextWindow, gpuKvCache });\n await this.llm.ensureLoaded(contextWindow, gpuKvCache);\n }\n\n const startTime = Date.now();\n const fullReprocess = opts?.fullReprocess ?? false;\n const lastTimestamp = fullReprocess ? null : this.getLastCycleTimestamp();\n const substrate = this.discoverSubstrate(lastTimestamp);\n\n this.log('debug', 'Discovering substrate', { lastTimestamp: lastTimestamp ?? 'full reprocess', substrateCount: substrate.length });\n if (substrate.length === 0) {\n this.log('debug', 'No substrate found — skipping cycle');\n return null;\n }\n\n this.log('info', `Starting digest cycle`, { substrateCount: substrate.length, fullReprocess });\n const cycleId = crypto.randomUUID();\n const allEligible = this.getEligibleTiers();\n const eligibleTiers = opts?.tiers\n ? allEligible.filter((t) => opts.tiers!.includes(t))\n : allEligible;\n this.log('debug', `Eligible tiers: [${eligibleTiers.join(', ')}]`);\n const tiersGenerated: number[] = [];\n let totalTokensUsed = 0;\n let model = '';\n\n // Categorize substrate by type for the result\n const typeToKey: Record<string, keyof DigestCycleResult['substrate']> = {\n session: 'sessions',\n spore: 'spores',\n plan: 'plans',\n artifact: 'artifacts',\n 'team-member': 'team',\n };\n const substrateIndex: DigestCycleResult['substrate'] = {\n sessions: [],\n spores: [],\n plans: [],\n artifacts: [],\n team: [],\n };\n for (const note of substrate) {\n const key = typeToKey[note.type];\n if (key) {\n substrateIndex[key].push(note.id);\n }\n }\n\n // Record the cycle timestamp NOW, before tier processing. This ensures the\n // timestamp advances even if LLM calls fail, preventing the same substrate\n // from being rediscovered on every subsequent timer fire.\n const cycleTimestamp = new Date().toISOString();\n\n const systemPrompt = loadPrompt('digest-system');\n\n for (const tier of eligibleTiers) {\n const tierPrompt = loadPrompt(`digest-${tier}`);\n const previousExtract = opts?.cleanSlate ? null : this.readPreviousExtract(tier);\n\n // Calculate token budget for substrate:\n // (context_window * safety_margin) - output - system_prompt - tier_prompt - previous_extract\n const contextWindow = this.config.digest.intelligence.context_window;\n const systemPromptTokens = estimateTokens(systemPrompt);\n const tierPromptTokens = estimateTokens(tierPrompt);\n const previousExtractTokens = previousExtract\n ? estimateTokens(previousExtract) + PREVIOUS_EXTRACT_OVERHEAD_TOKENS\n : 0;\n const availableTokens = Math.floor(contextWindow * CONTEXT_SAFETY_MARGIN);\n const substrateBudget = availableTokens - tier - systemPromptTokens - tierPromptTokens - previousExtractTokens;\n\n if (substrateBudget <= 0) continue;\n\n const formattedSubstrate = this.formatSubstrate(substrate, substrateBudget);\n\n // Build user prompt (system prompt sent separately via LlmRequestOptions)\n const promptParts = [tierPrompt];\n\n if (previousExtract) {\n promptParts.push('', '## Previous Synthesis', '', previousExtract);\n }\n\n promptParts.push('', '## New Substrate', '', formattedSubstrate);\n promptParts.push(\n '',\n '---',\n 'Produce your updated synthesis now. Stay within the token budget specified above.',\n );\n\n const userPrompt = promptParts.join('\\n');\n const promptTokens = estimateTokens(systemPrompt + userPrompt);\n this.log('debug', `Tier ${tier}: sending LLM request`, { promptTokens, maxTokens: tier, substrateBudget });\n\n try {\n const tierStart = Date.now();\n const digestConfig = this.config.digest.intelligence;\n const opts: LlmRequestOptions = {\n maxTokens: tier,\n timeoutMs: DIGEST_LLM_REQUEST_TIMEOUT_MS,\n contextLength: contextWindow,\n reasoning: LLM_REASONING_MODE,\n systemPrompt,\n keepAlive: digestConfig.keep_alive ?? undefined,\n };\n const response = await this.llm.summarize(userPrompt, opts);\n const tierDuration = Date.now() - tierStart;\n\n // Strip reasoning tokens if present (some models output chain-of-thought)\n const extractText = stripReasoningTokens(response.text);\n model = response.model;\n const responseTokens = estimateTokens(extractText);\n totalTokensUsed += promptTokens + responseTokens;\n\n this.log('info', `Tier ${tier}: completed`, { durationMs: tierDuration, responseTokens, model: response.model });\n this.writeExtract(tier, extractText, cycleId, response.model, substrate.length);\n tiersGenerated.push(tier);\n } catch (err) {\n this.log('warn', `Tier ${tier}: failed`, { error: (err as Error).message });\n }\n }\n\n const result: DigestCycleResult = {\n cycleId,\n timestamp: cycleTimestamp,\n substrate: substrateIndex,\n tiersGenerated,\n model,\n durationMs: Date.now() - startTime,\n tokensUsed: totalTokensUsed,\n };\n\n this.appendTrace(result);\n return result;\n }\n}\n\n// --- Metabolism (Adaptive Timer) ---\n\nexport type MetabolismState = 'active' | 'cooling' | 'dormant';\n\n/** Milliseconds per second for config conversion. */\nconst MS_PER_SECOND = 1000;\n\nexport class Metabolism {\n state: MetabolismState = 'active';\n currentIntervalMs: number;\n\n private cooldownStep = 0;\n private lastSubstrateTime: number;\n private timer: ReturnType<typeof setTimeout> | null = null;\n private activeIntervalMs: number;\n private cooldownIntervalsMs: number[];\n private dormancyThresholdMs: number;\n\n constructor(config: MycoConfig['digest']['metabolism']) {\n this.activeIntervalMs = config.active_interval * MS_PER_SECOND;\n this.cooldownIntervalsMs = config.cooldown_intervals.map((s) => s * MS_PER_SECOND);\n this.dormancyThresholdMs = config.dormancy_threshold * MS_PER_SECOND;\n this.currentIntervalMs = this.activeIntervalMs;\n this.lastSubstrateTime = Date.now();\n }\n\n /** Reset to active state when new substrate is found. */\n onSubstrateFound(): void {\n this.state = 'active';\n this.cooldownStep = 0;\n this.currentIntervalMs = this.activeIntervalMs;\n this.lastSubstrateTime = Date.now();\n }\n\n /** Advance cooldown when a cycle finds no new substrate. */\n onEmptyCycle(): void {\n if (this.state === 'dormant') return;\n\n this.state = 'cooling';\n if (this.cooldownStep < this.cooldownIntervalsMs.length) {\n this.currentIntervalMs = this.cooldownIntervalsMs[this.cooldownStep];\n this.cooldownStep++;\n }\n\n this.checkDormancy();\n }\n\n /** Enter dormant state if enough time has elapsed since last substrate. */\n checkDormancy(): void {\n const elapsed = Date.now() - this.lastSubstrateTime;\n if (elapsed >= this.dormancyThresholdMs) {\n this.state = 'dormant';\n // Keep the last cooldown interval as the dormant polling rate\n }\n }\n\n /** Return to active from any state, resetting timers and rescheduling immediately. */\n activate(): void {\n this.onSubstrateFound();\n // Reschedule with the new active interval — without this, the old\n // (possibly dormant) timer continues ticking at the wrong rate\n if (this.callback) {\n this.reschedule();\n }\n }\n\n /** Set lastSubstrateTime explicitly (for testing). */\n markLastSubstrate(time: number): void {\n this.lastSubstrateTime = time;\n }\n\n /** Begin scheduling digest cycles with adaptive intervals. */\n start(callback: () => Promise<void>): void {\n this.callback = callback;\n this.reschedule();\n }\n\n /** Stop the timer. */\n stop(): void {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n }\n\n private callback: (() => Promise<void>) | null = null;\n\n private reschedule(): void {\n this.stop();\n if (!this.callback) return;\n const cb = this.callback;\n const schedule = (): void => {\n this.timer = setTimeout(async () => {\n await cb();\n schedule();\n }, this.currentIntervalMs);\n this.timer.unref();\n };\n schedule();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAQA,kBAAiB;AAHjB,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,YAAY;AA2DnB,IAAM,mCAAmC;AAKzC,IAAM,wBAAwB;AAG9B,IAAM,eAAe;AAId,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,0BAAqD;AAAA,EACrD,kBAAkB;AAAA,EAE1B,YAAY,cAAkC;AAC5C,SAAK,WAAW,aAAa;AAC7B,SAAK,QAAQ,aAAa;AAC1B,SAAK,MAAM,aAAa;AACxB,SAAK,SAAS,aAAa;AAC3B,SAAK,MAAM,aAAa,QAAQ,MAAM;AAAA,IAAC;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkB,oBAAkD;AAClE,UAAM,WAAW,KAAK,OAAO,OAAO,UAAU;AAE9C,UAAM,QAAQ,qBACV,KAAK,MAAM,MAAM,EAAE,cAAc,oBAAoB,OAAO,SAAS,CAAC,IACtE,KAAK,MAAM,MAAM,EAAE,OAAO,SAAS,CAAC;AAIxC,UAAM,WAAW,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,YAAY;AAG5D,aAAS,KAAK,CAAC,GAAG,MAAM;AACtB,YAAM,UAAU,8BAA8B,EAAE,IAAI,KAAK;AACzD,YAAM,UAAU,8BAA8B,EAAE,IAAI,KAAK;AACzD,UAAI,YAAY,QAAS,QAAO,UAAU;AAE1C,aAAO,EAAE,QAAQ,cAAc,EAAE,OAAO;AAAA,IAC1C,CAAC;AAED,WAAO,SAAS,MAAM,GAAG,QAAQ;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAA6B;AAC3B,UAAM,gBAAgB,KAAK,OAAO,OAAO,aAAa;AACtD,WAAO,KAAK,OAAO,OAAO,MAAM,OAAO,CAAC,SAAS;AAC/C,YAAM,aAAa,wBAAwB,IAAI;AAC/C,aAAO,eAAe,UAAa,cAAc;AAAA,IACnD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,OAAsB,aAA6B;AACjE,UAAM,aAAa,cAAc;AACjC,UAAM,QAAkB,CAAC;AACzB,QAAI,YAAY;AAEhB,eAAW,QAAQ,OAAO;AACxB,YAAM,QAAQ,QAAQ,KAAK,IAAI,KAAK,KAAK,EAAE,YAAO,KAAK,KAAK;AAAA,EAAM,KAAK,OAAO;AAC9E,UAAI,YAAY,MAAM,SAAS,cAAc,MAAM,SAAS,EAAG;AAC/D,YAAM,KAAK,KAAK;AAChB,mBAAa,MAAM;AAAA,IACrB;AAEA,WAAO,MAAM,KAAK,MAAM;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB,MAA6B;AAC/C,UAAM,cAAc,KAAK,KAAK,KAAK,UAAU,UAAU,WAAW,IAAI,KAAK;AAC3E,QAAI;AACJ,QAAI;AACF,gBAAU,GAAG,aAAa,aAAa,OAAO;AAAA,IAChD,QAAQ;AACN,aAAO;AAAA,IACT;AAEA,WAAO,iBAAiB,OAAO,EAAE;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aACE,MACA,MACA,SACA,OACA,gBACM;AACN,UAAM,YAAY,KAAK,KAAK,KAAK,UAAU,QAAQ;AACnD,OAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAE3C,UAAM,cAAuC;AAAA,MAC3C,MAAM;AAAA,MACN;AAAA,MACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC,UAAU;AAAA,MACV,iBAAiB;AAAA,MACjB;AAAA,IACF;AAEA,UAAM,SAAS,YAAAA,QAAK,UAAU,aAAa;AAAA,MACzC,mBAAmB;AAAA,MACnB,gBAAgB;AAAA,IAClB,CAAC,EAAE,KAAK;AACR,UAAM,OAAO;AAAA,EAAQ,MAAM;AAAA;AAAA;AAAA,EAAY,IAAI;AAAA;AAE3C,UAAM,WAAW,KAAK,KAAK,WAAW,WAAW,IAAI,KAAK;AAC1D,UAAM,UAAU,GAAG,QAAQ;AAC3B,OAAG,cAAc,SAAS,MAAM,OAAO;AACvC,OAAG,WAAW,SAAS,QAAQ;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,QAAiC;AAC3C,UAAM,YAAY,KAAK,KAAK,KAAK,UAAU,QAAQ;AACnD,OAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAC3C,UAAM,YAAY,KAAK,KAAK,WAAW,aAAa;AACpD,OAAG,eAAe,WAAW,KAAK,UAAU,MAAM,IAAI,MAAM,OAAO;AACnE,SAAK,0BAA0B,OAAO;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,wBAAuC;AACrC,QAAI,KAAK,4BAA4B,OAAW,QAAO,KAAK;AAE5D,UAAM,YAAY,KAAK,KAAK,KAAK,UAAU,UAAU,aAAa;AAClE,QAAI;AACJ,QAAI;AACF,gBAAU,GAAG,aAAa,WAAW,OAAO,EAAE,KAAK;AAAA,IACrD,QAAQ;AACN,WAAK,0BAA0B;AAC/B,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,SAAS;AACZ,WAAK,0BAA0B;AAC/B,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,UAAM,WAAW,MAAM,MAAM,SAAS,CAAC;AACvC,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,WAAK,0BAA0B,OAAO;AACtC,aAAO,OAAO;AAAA,IAChB,QAAQ;AACN,WAAK,0BAA0B;AAC/B,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,SAAS,MAA8D;AAC3E,QAAI,KAAK,iBAAiB;AACxB,WAAK,IAAI,SAAS,2CAAsC;AACxD,aAAO;AAAA,IACT;AACA,SAAK,kBAAkB;AAEvB,QAAI;AACF,aAAO,MAAM,KAAK,iBAAiB,IAAI;AAAA,IACzC,UAAE;AACA,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,MAAc,iBAAiB,MAA8D;AAM3F,QAAI,KAAK,IAAI,cAAc;AACzB,YAAM,EAAE,gBAAgB,eAAe,cAAc,WAAW,IAAI,KAAK,OAAO,OAAO;AACvF,WAAK,IAAI,SAAS,0BAA0B,EAAE,eAAe,WAAW,CAAC;AACzE,YAAM,KAAK,IAAI,aAAa,eAAe,UAAU;AAAA,IACvD;AAEA,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,gBAAgB,MAAM,iBAAiB;AAC7C,UAAM,gBAAgB,gBAAgB,OAAO,KAAK,sBAAsB;AACxE,UAAM,YAAY,KAAK,kBAAkB,aAAa;AAEtD,SAAK,IAAI,SAAS,yBAAyB,EAAE,eAAe,iBAAiB,kBAAkB,gBAAgB,UAAU,OAAO,CAAC;AACjI,QAAI,UAAU,WAAW,GAAG;AAC1B,WAAK,IAAI,SAAS,0CAAqC;AACvD,aAAO;AAAA,IACT;AAEA,SAAK,IAAI,QAAQ,yBAAyB,EAAE,gBAAgB,UAAU,QAAQ,cAAc,CAAC;AAC7F,UAAM,UAAU,OAAO,WAAW;AAClC,UAAM,cAAc,KAAK,iBAAiB;AAC1C,UAAM,gBAAgB,MAAM,QACxB,YAAY,OAAO,CAAC,MAAM,KAAK,MAAO,SAAS,CAAC,CAAC,IACjD;AACJ,SAAK,IAAI,SAAS,oBAAoB,cAAc,KAAK,IAAI,CAAC,GAAG;AACjE,UAAM,iBAA2B,CAAC;AAClC,QAAI,kBAAkB;AACtB,QAAI,QAAQ;AAGZ,UAAM,YAAkE;AAAA,MACtE,SAAS;AAAA,MACT,OAAO;AAAA,MACP,MAAM;AAAA,MACN,UAAU;AAAA,MACV,eAAe;AAAA,IACjB;AACA,UAAM,iBAAiD;AAAA,MACrD,UAAU,CAAC;AAAA,MACX,QAAQ,CAAC;AAAA,MACT,OAAO,CAAC;AAAA,MACR,WAAW,CAAC;AAAA,MACZ,MAAM,CAAC;AAAA,IACT;AACA,eAAW,QAAQ,WAAW;AAC5B,YAAM,MAAM,UAAU,KAAK,IAAI;AAC/B,UAAI,KAAK;AACP,uBAAe,GAAG,EAAE,KAAK,KAAK,EAAE;AAAA,MAClC;AAAA,IACF;AAKA,UAAM,kBAAiB,oBAAI,KAAK,GAAE,YAAY;AAE9C,UAAM,eAAe,WAAW,eAAe;AAE/C,eAAW,QAAQ,eAAe;AAChC,YAAM,aAAa,WAAW,UAAU,IAAI,EAAE;AAC9C,YAAM,kBAAkB,MAAM,aAAa,OAAO,KAAK,oBAAoB,IAAI;AAI/E,YAAM,gBAAgB,KAAK,OAAO,OAAO,aAAa;AACtD,YAAM,qBAAqB,eAAe,YAAY;AACtD,YAAM,mBAAmB,eAAe,UAAU;AAClD,YAAM,wBAAwB,kBAC1B,eAAe,eAAe,IAAI,mCAClC;AACJ,YAAM,kBAAkB,KAAK,MAAM,gBAAgB,qBAAqB;AACxE,YAAM,kBAAkB,kBAAkB,OAAO,qBAAqB,mBAAmB;AAEzF,UAAI,mBAAmB,EAAG;AAE1B,YAAM,qBAAqB,KAAK,gBAAgB,WAAW,eAAe;AAG1E,YAAM,cAAc,CAAC,UAAU;AAE/B,UAAI,iBAAiB;AACnB,oBAAY,KAAK,IAAI,yBAAyB,IAAI,eAAe;AAAA,MACnE;AAEA,kBAAY,KAAK,IAAI,oBAAoB,IAAI,kBAAkB;AAC/D,kBAAY;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,aAAa,YAAY,KAAK,IAAI;AACxC,YAAM,eAAe,eAAe,eAAe,UAAU;AAC7D,WAAK,IAAI,SAAS,QAAQ,IAAI,yBAAyB,EAAE,cAAc,WAAW,MAAM,gBAAgB,CAAC;AAEzG,UAAI;AACF,cAAM,YAAY,KAAK,IAAI;AAC3B,cAAM,eAAe,KAAK,OAAO,OAAO;AACxC,cAAMC,QAA0B;AAAA,UAC9B,WAAW;AAAA,UACX,WAAW;AAAA,UACX,eAAe;AAAA,UACf,WAAW;AAAA,UACX;AAAA,UACA,WAAW,aAAa,cAAc;AAAA,QACxC;AACA,cAAM,WAAW,MAAM,KAAK,IAAI,UAAU,YAAYA,KAAI;AAC1D,cAAM,eAAe,KAAK,IAAI,IAAI;AAGlC,cAAM,cAAc,qBAAqB,SAAS,IAAI;AACtD,gBAAQ,SAAS;AACjB,cAAM,iBAAiB,eAAe,WAAW;AACjD,2BAAmB,eAAe;AAElC,aAAK,IAAI,QAAQ,QAAQ,IAAI,eAAe,EAAE,YAAY,cAAc,gBAAgB,OAAO,SAAS,MAAM,CAAC;AAC/G,aAAK,aAAa,MAAM,aAAa,SAAS,SAAS,OAAO,UAAU,MAAM;AAC9E,uBAAe,KAAK,IAAI;AAAA,MAC1B,SAAS,KAAK;AACZ,aAAK,IAAI,QAAQ,QAAQ,IAAI,YAAY,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,MAC5E;AAAA,IACF;AAEA,UAAM,SAA4B;AAAA,MAChC;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,YAAY,KAAK,IAAI,IAAI;AAAA,MACzB,YAAY;AAAA,IACd;AAEA,SAAK,YAAY,MAAM;AACvB,WAAO;AAAA,EACT;AACF;AAOA,IAAM,gBAAgB;AAEf,IAAM,aAAN,MAAiB;AAAA,EACtB,QAAyB;AAAA,EACzB;AAAA,EAEQ,eAAe;AAAA,EACf;AAAA,EACA,QAA8C;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,QAA4C;AACtD,SAAK,mBAAmB,OAAO,kBAAkB;AACjD,SAAK,sBAAsB,OAAO,mBAAmB,IAAI,CAAC,MAAM,IAAI,aAAa;AACjF,SAAK,sBAAsB,OAAO,qBAAqB;AACvD,SAAK,oBAAoB,KAAK;AAC9B,SAAK,oBAAoB,KAAK,IAAI;AAAA,EACpC;AAAA;AAAA,EAGA,mBAAyB;AACvB,SAAK,QAAQ;AACb,SAAK,eAAe;AACpB,SAAK,oBAAoB,KAAK;AAC9B,SAAK,oBAAoB,KAAK,IAAI;AAAA,EACpC;AAAA;AAAA,EAGA,eAAqB;AACnB,QAAI,KAAK,UAAU,UAAW;AAE9B,SAAK,QAAQ;AACb,QAAI,KAAK,eAAe,KAAK,oBAAoB,QAAQ;AACvD,WAAK,oBAAoB,KAAK,oBAAoB,KAAK,YAAY;AACnE,WAAK;AAAA,IACP;AAEA,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA,EAGA,gBAAsB;AACpB,UAAM,UAAU,KAAK,IAAI,IAAI,KAAK;AAClC,QAAI,WAAW,KAAK,qBAAqB;AACvC,WAAK,QAAQ;AAAA,IAEf;AAAA,EACF;AAAA;AAAA,EAGA,WAAiB;AACf,SAAK,iBAAiB;AAGtB,QAAI,KAAK,UAAU;AACjB,WAAK,WAAW;AAAA,IAClB;AAAA,EACF;AAAA;AAAA,EAGA,kBAAkB,MAAoB;AACpC,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA,EAGA,MAAM,UAAqC;AACzC,SAAK,WAAW;AAChB,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA,EAGA,OAAa;AACX,QAAI,KAAK,OAAO;AACd,mBAAa,KAAK,KAAK;AACvB,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA,EAEQ,WAAyC;AAAA,EAEzC,aAAmB;AACzB,SAAK,KAAK;AACV,QAAI,CAAC,KAAK,SAAU;AACpB,UAAM,KAAK,KAAK;AAChB,UAAM,WAAW,MAAY;AAC3B,WAAK,QAAQ,WAAW,YAAY;AAClC,cAAM,GAAG;AACT,iBAAS;AAAA,MACX,GAAG,KAAK,iBAAiB;AACzB,WAAK,MAAM,MAAM;AAAA,IACnB;AACA,aAAS;AAAA,EACX;AACF;","names":["YAML","opts"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/prompts/index.ts","../src/intelligence/response.ts"],"sourcesContent":["/**\n * Prompt loader — reads .md templates from disk and interpolates variables.\n * Prompts are markdown files in this directory, not TypeScript strings.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { ARTIFACT_TYPES } from '../vault/types.js';\nimport { CANDIDATE_CONTENT_PREVIEW } from '../constants.js';\n\n/**\n * Resolve the prompts directory. With tsup code-splitting, import.meta.url\n * points to a chunk file (dist/chunk-XXXX.js), not dist/src/prompts/.\n * Walk up from the current file to find package.json, then use dist/src/prompts/.\n */\nfunction resolvePromptsDir(): string {\n let dir = path.dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 5; i++) {\n if (fs.existsSync(path.join(dir, 'package.json'))) {\n return path.join(dir, 'dist', 'src', 'prompts');\n }\n // Also check if we're already in the right place (tsc output or dev mode)\n if (fs.existsSync(path.join(dir, 'extraction.md'))) {\n return dir;\n }\n dir = path.dirname(dir);\n }\n // Final fallback: adjacent to current file (works with tsc)\n return path.dirname(fileURLToPath(import.meta.url));\n}\n\nconst PROMPTS_DIR = resolvePromptsDir();\n\nconst promptCache = new Map<string, string>();\n\nexport function loadPrompt(name: string): string {\n let cached = promptCache.get(name);\n if (!cached) {\n cached = fs.readFileSync(path.join(PROMPTS_DIR, `${name}.md`), 'utf-8').trim();\n promptCache.set(name, cached);\n }\n return cached;\n}\n\nfunction interpolate(template: string, vars: Record<string, string>): string {\n let result = template;\n for (const [key, value] of Object.entries(vars)) {\n result = result.replaceAll(`{{${key}}}`, value);\n }\n return result;\n}\n\n// --- Prompt builders ---\n\nexport function buildExtractionPrompt(\n sessionId: string,\n eventCount: number,\n toolSummary: string,\n maxTokens?: number,\n): string {\n return interpolate(loadPrompt('extraction'), {\n sessionId,\n eventCount: String(eventCount),\n toolSummary,\n maxTokens: String(maxTokens ?? 2048),\n });\n}\n\nexport function buildSummaryPrompt(\n sessionId: string,\n user: string,\n content: string,\n maxTokens?: number,\n): string {\n return interpolate(loadPrompt('summary'), {\n sessionId,\n user,\n content,\n maxTokens: String(maxTokens ?? 1024),\n });\n}\n\nexport function buildTitlePrompt(\n summary: string,\n sessionId: string,\n): string {\n return interpolate(loadPrompt('title'), {\n summary,\n sessionId,\n });\n}\n\nconst ARTIFACT_TYPE_DESCRIPTIONS = [\n '\"spec\" — Design specifications, architecture documents',\n '\"plan\" — Implementation plans, roadmaps',\n '\"rfc\" — Requests for comment, proposals',\n '\"doc\" — Documentation, guides, READMEs',\n '\"other\" — Other substantive documents',\n];\n\nexport function buildSimilarityPrompt(\n currentSummary: string,\n candidateSummary: string,\n): string {\n return interpolate(loadPrompt('session-similarity'), {\n currentSummary,\n candidateSummary,\n });\n}\n\nexport function buildClassificationPrompt(\n sessionId: string,\n candidates: Array<{ path: string; content: string }>,\n maxTokens?: number,\n): string {\n const fileList = candidates\n .map((c) => {\n const truncated = c.content.slice(0, CANDIDATE_CONTENT_PREVIEW);\n return `### ${c.path}\\n\\`\\`\\`\\n${truncated}\\n\\`\\`\\``;\n })\n .join('\\n\\n');\n\n return interpolate(loadPrompt('classification'), {\n sessionId,\n fileList,\n artifactTypes: ARTIFACT_TYPE_DESCRIPTIONS.map((d) => `- ${d}`).join('\\n'),\n validTypes: ARTIFACT_TYPES.join('|'),\n maxTokens: String(maxTokens ?? 1024),\n });\n}\n","/**\n * Clean LLM response text before parsing.\n *\n * Reasoning models (DeepSeek, Qwen, GLM, etc.) embed chain-of-thought\n * in the response using special tags. These must be stripped before\n * JSON parsing or value extraction.\n */\n\n// Patterns for reasoning model chain-of-thought tokens.\n// Order matters: most specific patterns first.\nconst REASONING_PATTERNS = [\n // <think>...</think>answer (DeepSeek, Qwen, GLM, many others)\n /<think>[\\s\\S]*?<\\/think>\\s*/gi,\n // Implicit opening: reasoning...</think>answer (GLM-4.7 observed)\n /^[\\s\\S]*?<\\/think>\\s*/i,\n // <reasoning>...</reasoning>answer\n /<reasoning>[\\s\\S]*?<\\/reasoning>\\s*/gi,\n // <|thinking|>...<|/thinking|>answer\n /<\\|thinking\\|>[\\s\\S]*?<\\|\\/thinking\\|>\\s*/gi,\n // Plain-text \"Thinking Process:\" block followed by actual content\n // (Qwen 3.5 via LM Studio without native thinking mode)\n // Matches from \"Thinking Process:\" up to the last numbered step, then the synthesis follows\n /^Thinking Process:[\\s\\S]*?(?=\\n(?:## |# |\\*\\*[A-Z]))/i,\n];\n\n/**\n * Strip reasoning/chain-of-thought tokens from LLM response text.\n * Returns the final answer without the thinking process.\n */\nexport function stripReasoningTokens(text: string): string {\n if (!text) return text;\n\n for (const pattern of REASONING_PATTERNS) {\n const stripped = text.replace(pattern, '').trim();\n if (stripped && stripped !== text.trim()) {\n return stripped;\n }\n }\n\n return text;\n}\n\n/**\n * Extract JSON from an LLM response that may contain markdown fences,\n * reasoning tokens, or other wrapper text.\n *\n * Tries in order:\n * 1. Strip reasoning tokens\n * 2. Extract from ```json ... ``` code fences\n * 3. Find bare {...} JSON object\n * 4. Parse the cleaned text directly\n */\nexport function extractJson(text: string): unknown {\n const cleaned = stripReasoningTokens(text);\n\n // Try code fence extraction\n const fenceMatch = cleaned.match(/```(?:json)?\\s*\\n?([\\s\\S]*?)\\n?```/);\n if (fenceMatch) {\n return JSON.parse(fenceMatch[1].trim());\n }\n\n // Try bare JSON object\n const objectMatch = cleaned.match(/\\{[\\s\\S]*\\}/);\n if (objectMatch) {\n return JSON.parse(objectMatch[0]);\n }\n\n // Try direct parse\n return JSON.parse(cleaned);\n}\n\n/**\n * Extract a numeric value from an LLM response that may contain\n * reasoning tokens or extra text around the number.\n */\nexport function extractNumber(text: string): number {\n const cleaned = stripReasoningTokens(text).trim();\n const match = cleaned.match(/(\\d+\\.?\\d*)/);\n if (match) return parseFloat(match[1]);\n return parseFloat(cleaned);\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { loadEnv } from './cli/shared.js';\nimport { resolveVaultDir } from './vault/resolve.js';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nloadEnv();\n\nconst USAGE = `Usage: myco <command> [args]\n\nCommands:\n init [options] Initialize a new vault\n config <get|set> [args] Get or set vault config values\n detect-providers Detect available LLM/embedding providers (JSON)\n verify Test LLM and embedding connectivity\n stats Vault health, index counts, vector count\n search <query> Combined FTS + vector search with scores\n vectors <query> Raw vector search with similarity scores\n session [id|latest] Show a session note\n logs [options] View daemon logs\n setup-llm [options] Configure LLM and embedding providers\n setup-digest [options] Configure digest and capture settings\n digest [options] Run a digest cycle (--tier N, --full)\n restart Restart the daemon\n rebuild Reindex the entire vault\n reprocess [options] Re-extract observations, regenerate summaries, re-index\n version Show plugin version\n`;\n\nasync function main(): Promise<void> {\n const [cmd, ...args] = process.argv.slice(2);\n if (!cmd || cmd === '--help' || cmd === '-h') {\n process.stdout.write(USAGE);\n return;\n }\n\n if (cmd === 'init') return (await import('./cli/init.js')).run(args);\n if (cmd === 'detect-providers') return (await import('./cli/detect-providers.js')).run(args);\n if (cmd === 'version' || cmd === '--version' || cmd === '-v') {\n const { getPluginVersion } = await import('./version.js');\n console.log(getPluginVersion());\n return;\n }\n\n const vaultDir = resolveVaultDir();\n if (!fs.existsSync(path.join(vaultDir, 'myco.yaml'))) {\n console.error(`No myco.yaml found in ${vaultDir}. Run 'myco init' first.`);\n process.exit(1);\n }\n\n switch (cmd) {\n case 'config': return (await import('./cli/config.js')).run(args, vaultDir);\n case 'verify': return (await import('./cli/verify.js')).run(args, vaultDir);\n case 'stats': return (await import('./cli/stats.js')).run(args, vaultDir);\n case 'search': return (await import('./cli/search.js')).run(args, vaultDir);\n case 'vectors': return (await import('./cli/search.js')).runVectors(args, vaultDir);\n case 'session': return (await import('./cli/session.js')).run(args, vaultDir);\n case 'setup-llm': return (await import('./cli/setup-llm.js')).run(args, vaultDir);\n case 'setup-digest': return (await import('./cli/setup-digest.js')).run(args, vaultDir);\n case 'digest': return (await import('./cli/digest.js')).run(args, vaultDir);\n case 'restart': return (await import('./cli/restart.js')).run(args, vaultDir);\n case 'rebuild': return (await import('./cli/rebuild.js')).run(args, vaultDir);\n case 'reprocess': return (await import('./cli/reprocess.js')).run(args, vaultDir);\n case 'logs': return (await import('./cli/logs.js')).run(args, vaultDir);\n default:\n console.error(`Unknown command: ${cmd}`);\n process.stdout.write(USAGE);\n process.exit(1);\n }\n}\n\nmain().catch((err) => {\n console.error(`myco: ${(err as Error).message}`);\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;;;;;AAGA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEjB,QAAQ;AAER,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBd,eAAe,OAAsB;AACnC,QAAM,CAAC,KAAK,GAAG,IAAI,IAAI,QAAQ,KAAK,MAAM,CAAC;AAC3C,MAAI,CAAC,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC5C,YAAQ,OAAO,MAAM,KAAK;AAC1B;AAAA,EACF;AAEA,MAAI,QAAQ,OAAQ,SAAQ,MAAM,OAAO,oBAAe,GAAG,IAAI,IAAI;AACnE,MAAI,QAAQ,mBAAoB,SAAQ,MAAM,OAAO,gCAA2B,GAAG,IAAI,IAAI;AAC3F,MAAI,QAAQ,aAAa,QAAQ,eAAe,QAAQ,MAAM;AAC5D,UAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,uBAAc;AACxD,YAAQ,IAAI,iBAAiB,CAAC;AAC9B;AAAA,EACF;AAEA,QAAM,WAAW,gBAAgB;AACjC,MAAI,CAAC,GAAG,WAAW,KAAK,KAAK,UAAU,WAAW,CAAC,GAAG;AACpD,YAAQ,MAAM,yBAAyB,QAAQ,0BAA0B;AACzE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,KAAK;AAAA,IACX,KAAK;AAAU,cAAQ,MAAM,OAAO,sBAAiB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC1E,KAAK;AAAU,cAAQ,MAAM,OAAO,sBAAiB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC1E,KAAK;AAAS,cAAQ,MAAM,OAAO,qBAAgB,GAAG,IAAI,MAAM,QAAQ;AAAA,IACxE,KAAK;AAAU,cAAQ,MAAM,OAAO,sBAAiB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC1E,KAAK;AAAW,cAAQ,MAAM,OAAO,sBAAiB,GAAG,WAAW,MAAM,QAAQ;AAAA,IAClF,KAAK;AAAW,cAAQ,MAAM,OAAO,uBAAkB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC5E,KAAK;AAAa,cAAQ,MAAM,OAAO,yBAAoB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAChF,KAAK;AAAgB,cAAQ,MAAM,OAAO,4BAAuB,GAAG,IAAI,MAAM,QAAQ;AAAA,IACtF,KAAK;AAAU,cAAQ,MAAM,OAAO,sBAAiB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC1E,KAAK;AAAW,cAAQ,MAAM,OAAO,uBAAkB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC5E,KAAK;AAAW,cAAQ,MAAM,OAAO,uBAAkB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAC5E,KAAK;AAAa,cAAQ,MAAM,OAAO,yBAAoB,GAAG,IAAI,MAAM,QAAQ;AAAA,IAChF,KAAK;AAAQ,cAAQ,MAAM,OAAO,oBAAe,GAAG,IAAI,MAAM,QAAQ;AAAA,IACtE;AACE,cAAQ,MAAM,oBAAoB,GAAG,EAAE;AACvC,cAAQ,OAAO,MAAM,KAAK;AAC1B,cAAQ,KAAK,CAAC;AAAA,EAClB;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,SAAU,IAAc,OAAO,EAAE;AAC/C,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}