clawvault 3.1.0 → 3.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 (289) hide show
  1. package/README.md +422 -141
  2. package/bin/clawvault.js +10 -2
  3. package/bin/command-registration.test.js +3 -1
  4. package/bin/command-runtime.js +9 -1
  5. package/bin/register-core-commands.js +23 -28
  6. package/bin/register-maintenance-commands.js +39 -3
  7. package/bin/register-query-commands.js +58 -29
  8. package/bin/register-tailscale-commands.js +106 -0
  9. package/bin/register-task-commands.js +18 -1
  10. package/bin/register-task-commands.test.js +16 -0
  11. package/bin/register-vault-operations-commands.js +29 -1
  12. package/bin/register-workgraph-commands.js +1368 -0
  13. package/dashboard/lib/graph-diff.js +104 -0
  14. package/dashboard/lib/graph-diff.test.js +75 -0
  15. package/dashboard/lib/vault-parser.js +556 -0
  16. package/dashboard/lib/vault-parser.test.js +254 -0
  17. package/dashboard/public/app.js +796 -0
  18. package/dashboard/public/index.html +52 -0
  19. package/dashboard/public/styles.css +221 -0
  20. package/dashboard/server.js +374 -0
  21. package/dist/{chunk-F2JEUD4J.js → chunk-23YDQ3QU.js} +6 -8
  22. package/dist/{chunk-C7OK5WKP.js → chunk-2JQ3O2YL.js} +4 -4
  23. package/dist/{chunk-VR5NE7PZ.js → chunk-2RAZ4ZFE.js} +1 -1
  24. package/dist/chunk-2ZDO52B4.js +52 -0
  25. package/dist/{chunk-ZZA73MFY.js → chunk-33DOSHTA.js} +176 -36
  26. package/dist/chunk-33VSQP4J.js +37 -0
  27. package/dist/chunk-4BQTQMJP.js +93 -0
  28. package/dist/{chunk-GUKMRGM7.js → chunk-4OXMU5S2.js} +1 -1
  29. package/dist/{chunk-62YTUT6J.js → chunk-4PY655YM.js} +15 -3
  30. package/dist/chunk-6FH3IULF.js +352 -0
  31. package/dist/{chunk-3NSBOUT3.js → chunk-77Q5CSPJ.js} +404 -80
  32. package/dist/{chunk-4VQTUVH7.js → chunk-7YZWHM36.js} +52 -26
  33. package/dist/chunk-BSJ6RIT7.js +447 -0
  34. package/dist/chunk-BUEW6IIK.js +364 -0
  35. package/dist/{chunk-LI4O6NVK.js → chunk-CLJTREDS.js} +74 -14
  36. package/dist/chunk-EK6S23ZB.js +469 -0
  37. package/dist/{chunk-LNJA2UGL.js → chunk-ESFLMDRB.js} +9 -86
  38. package/dist/{chunk-H34S76MB.js → chunk-ESVS6K2B.js} +6 -6
  39. package/dist/{chunk-WAZ3NLWL.js → chunk-F55HGNU4.js} +0 -47
  40. package/dist/{chunk-QK3UCXWL.js → chunk-FHFUXL6G.js} +2 -2
  41. package/dist/{chunk-H62BP7RI.js → chunk-GAOWA7GR.js} +212 -46
  42. package/dist/chunk-GGA32J2R.js +784 -0
  43. package/dist/chunk-GNJL4YGR.js +79 -0
  44. package/dist/chunk-IVRIKYFE.js +520 -0
  45. package/dist/chunk-MDIH26GC.js +183 -0
  46. package/dist/{chunk-LYHGEHXG.js → chunk-MFAWT5O5.js} +0 -1
  47. package/dist/chunk-MM6QGW3P.js +207 -0
  48. package/dist/{chunk-P5EPF6MB.js → chunk-MW5C6ZQA.js} +110 -13
  49. package/dist/chunk-NCKFNBHJ.js +257 -0
  50. package/dist/{chunk-QBLMXKF2.js → chunk-OIWVQYQF.js} +1 -1
  51. package/dist/{chunk-42MXU7A6.js → chunk-P62WHA27.js} +58 -47
  52. package/dist/chunk-PBACDKKP.js +66 -0
  53. package/dist/{chunk-VGLOTGAS.js → chunk-QSHD36LH.js} +2 -2
  54. package/dist/{chunk-OZ7RIXTO.js → chunk-QSRRMEYM.js} +2 -2
  55. package/dist/chunk-QVEERJSP.js +152 -0
  56. package/dist/{chunk-N2AXRYLC.js → chunk-QWQ3TIKS.js} +1 -1
  57. package/dist/{chunk-3DHXQHYG.js → chunk-R2MIW5G7.js} +1 -1
  58. package/dist/{chunk-SJSFRIYS.js → chunk-SLXOR3CC.js} +2 -2
  59. package/dist/chunk-SS4B7P7V.js +99 -0
  60. package/dist/{chunk-JY6FYXIT.js → chunk-STCQGCEQ.js} +6 -11
  61. package/dist/chunk-TIGW564L.js +628 -0
  62. package/dist/chunk-U4O6C46S.js +154 -0
  63. package/dist/{chunk-ITPEXLHA.js → chunk-URXDAUVH.js} +24 -5
  64. package/dist/chunk-VSL7KY3M.js +189 -0
  65. package/dist/{chunk-U55BGUAU.js → chunk-W4SPAEE7.js} +6 -6
  66. package/dist/chunk-WMGIIABP.js +15 -0
  67. package/dist/{chunk-33UGEQRT.js → chunk-X3SPPUFG.js} +151 -64
  68. package/dist/chunk-Y6VJKXGL.js +373 -0
  69. package/dist/{chunk-3WRJEKN4.js → chunk-ZN54U2OZ.js} +123 -10
  70. package/dist/cli/index.js +34 -24
  71. package/dist/commands/archive.js +3 -3
  72. package/dist/commands/backlog.js +3 -3
  73. package/dist/commands/blocked.js +3 -3
  74. package/dist/commands/canvas.d.ts +15 -0
  75. package/dist/commands/canvas.js +200 -0
  76. package/dist/commands/checkpoint.js +2 -2
  77. package/dist/commands/compat.js +2 -2
  78. package/dist/commands/context.js +8 -6
  79. package/dist/commands/doctor.d.ts +11 -7
  80. package/dist/commands/doctor.js +18 -16
  81. package/dist/commands/embed.js +5 -6
  82. package/dist/commands/entities.js +2 -2
  83. package/dist/commands/graph.js +4 -4
  84. package/dist/commands/inject.d.ts +1 -1
  85. package/dist/commands/inject.js +5 -6
  86. package/dist/commands/kanban.js +4 -4
  87. package/dist/commands/link.js +5 -5
  88. package/dist/commands/migrate-observations.js +4 -4
  89. package/dist/commands/observe.d.ts +0 -1
  90. package/dist/commands/observe.js +14 -13
  91. package/dist/commands/project.js +5 -5
  92. package/dist/commands/rebuild-embeddings.d.ts +21 -0
  93. package/dist/commands/rebuild-embeddings.js +91 -0
  94. package/dist/commands/rebuild.js +12 -11
  95. package/dist/commands/recover.js +3 -3
  96. package/dist/commands/reflect.js +6 -7
  97. package/dist/commands/repair-session.js +1 -1
  98. package/dist/commands/replay.js +14 -14
  99. package/dist/commands/session-recap.js +1 -1
  100. package/dist/commands/setup.d.ts +2 -89
  101. package/dist/commands/setup.js +3 -21
  102. package/dist/commands/shell-init.js +1 -1
  103. package/dist/commands/sleep.d.ts +1 -1
  104. package/dist/commands/sleep.js +20 -19
  105. package/dist/commands/status.d.ts +2 -0
  106. package/dist/commands/status.js +57 -35
  107. package/dist/commands/sync-bd.d.ts +10 -0
  108. package/dist/commands/sync-bd.js +10 -0
  109. package/dist/commands/tailscale.d.ts +52 -0
  110. package/dist/commands/tailscale.js +26 -0
  111. package/dist/commands/task.js +4 -4
  112. package/dist/commands/template.js +2 -2
  113. package/dist/commands/wake.d.ts +1 -1
  114. package/dist/commands/wake.js +11 -10
  115. package/dist/commands/workgraph.d.ts +124 -0
  116. package/dist/commands/workgraph.js +38 -0
  117. package/dist/index.d.ts +341 -191
  118. package/dist/index.js +446 -116
  119. package/dist/{inject-Bzi5E-By.d.ts → inject-DYUrDqQO.d.ts} +3 -3
  120. package/dist/ledger-B7g7jhqG.d.ts +44 -0
  121. package/dist/lib/auto-linker.js +2 -2
  122. package/dist/lib/canvas-layout.d.ts +115 -0
  123. package/dist/lib/canvas-layout.js +35 -0
  124. package/dist/lib/config.d.ts +27 -3
  125. package/dist/lib/config.js +4 -2
  126. package/dist/lib/entity-index.js +1 -1
  127. package/dist/lib/project-utils.js +4 -4
  128. package/dist/lib/session-repair.js +1 -1
  129. package/dist/lib/session-utils.js +1 -1
  130. package/dist/lib/tailscale.d.ts +225 -0
  131. package/dist/lib/tailscale.js +50 -0
  132. package/dist/lib/task-utils.js +3 -3
  133. package/dist/lib/template-engine.js +1 -1
  134. package/dist/lib/webdav.d.ts +109 -0
  135. package/dist/lib/webdav.js +35 -0
  136. package/dist/onnxruntime_binding-5QEF3SUC.node +0 -0
  137. package/dist/onnxruntime_binding-BKPKNEGC.node +0 -0
  138. package/dist/onnxruntime_binding-FMOXGIUT.node +0 -0
  139. package/dist/onnxruntime_binding-OI2KMXC5.node +0 -0
  140. package/dist/onnxruntime_binding-UX44MLAZ.node +0 -0
  141. package/dist/onnxruntime_binding-Y2W7N7WY.node +0 -0
  142. package/dist/openclaw-plugin.d.ts +8 -0
  143. package/dist/openclaw-plugin.js +14 -0
  144. package/dist/registry-BR4326o0.d.ts +30 -0
  145. package/dist/store-CA-6sKCJ.d.ts +34 -0
  146. package/dist/thread-B9LhXNU0.d.ts +41 -0
  147. package/dist/transformers.node-A2ZRORSQ.js +46775 -0
  148. package/dist/{types-Y2_Um2Ls.d.ts → types-BbWJoC1c.d.ts} +1 -44
  149. package/dist/workgraph/index.d.ts +5 -0
  150. package/dist/workgraph/index.js +23 -0
  151. package/dist/workgraph/ledger.d.ts +2 -0
  152. package/dist/workgraph/ledger.js +25 -0
  153. package/dist/workgraph/registry.d.ts +2 -0
  154. package/dist/workgraph/registry.js +19 -0
  155. package/dist/workgraph/store.d.ts +2 -0
  156. package/dist/workgraph/store.js +25 -0
  157. package/dist/workgraph/thread.d.ts +2 -0
  158. package/dist/workgraph/thread.js +25 -0
  159. package/dist/workgraph/types.d.ts +54 -0
  160. package/dist/workgraph/types.js +7 -0
  161. package/hooks/clawvault/HOOK.md +113 -0
  162. package/hooks/clawvault/handler.js +1561 -0
  163. package/hooks/clawvault/handler.test.js +510 -0
  164. package/hooks/clawvault/openclaw.plugin.json +72 -0
  165. package/openclaw.plugin.json +65 -38
  166. package/package.json +25 -22
  167. package/dist/chunk-3RG5ZIWI.js +0 -10
  168. package/dist/chunk-3ZIH425O.js +0 -871
  169. package/dist/chunk-6U6MK36V.js +0 -205
  170. package/dist/chunk-CMB7UL7C.js +0 -327
  171. package/dist/chunk-D2H45LON.js +0 -1074
  172. package/dist/chunk-E7MFQB6D.js +0 -163
  173. package/dist/chunk-GQSLDZTS.js +0 -560
  174. package/dist/chunk-MFM6K7PU.js +0 -374
  175. package/dist/chunk-MXSSG3QU.js +0 -42
  176. package/dist/chunk-OCGVIN3L.js +0 -88
  177. package/dist/chunk-PAH27GSN.js +0 -108
  178. package/dist/chunk-YCUNCH2I.js +0 -78
  179. package/dist/cli/index.cjs +0 -8584
  180. package/dist/cli/index.d.cts +0 -5
  181. package/dist/commands/archive.cjs +0 -287
  182. package/dist/commands/archive.d.cts +0 -11
  183. package/dist/commands/backlog.cjs +0 -721
  184. package/dist/commands/backlog.d.cts +0 -53
  185. package/dist/commands/blocked.cjs +0 -204
  186. package/dist/commands/blocked.d.cts +0 -26
  187. package/dist/commands/checkpoint.cjs +0 -244
  188. package/dist/commands/checkpoint.d.cts +0 -41
  189. package/dist/commands/compat.cjs +0 -294
  190. package/dist/commands/compat.d.cts +0 -28
  191. package/dist/commands/context.cjs +0 -2990
  192. package/dist/commands/context.d.cts +0 -2
  193. package/dist/commands/doctor.cjs +0 -2986
  194. package/dist/commands/doctor.d.cts +0 -21
  195. package/dist/commands/embed.cjs +0 -232
  196. package/dist/commands/embed.d.cts +0 -17
  197. package/dist/commands/entities.cjs +0 -141
  198. package/dist/commands/entities.d.cts +0 -7
  199. package/dist/commands/graph.cjs +0 -501
  200. package/dist/commands/graph.d.cts +0 -21
  201. package/dist/commands/inject.cjs +0 -1636
  202. package/dist/commands/inject.d.cts +0 -2
  203. package/dist/commands/kanban.cjs +0 -884
  204. package/dist/commands/kanban.d.cts +0 -63
  205. package/dist/commands/link.cjs +0 -965
  206. package/dist/commands/link.d.cts +0 -11
  207. package/dist/commands/migrate-observations.cjs +0 -362
  208. package/dist/commands/migrate-observations.d.cts +0 -19
  209. package/dist/commands/observe.cjs +0 -4099
  210. package/dist/commands/observe.d.cts +0 -23
  211. package/dist/commands/project.cjs +0 -1341
  212. package/dist/commands/project.d.cts +0 -85
  213. package/dist/commands/rebuild.cjs +0 -3136
  214. package/dist/commands/rebuild.d.cts +0 -11
  215. package/dist/commands/recover.cjs +0 -361
  216. package/dist/commands/recover.d.cts +0 -38
  217. package/dist/commands/reflect.cjs +0 -1008
  218. package/dist/commands/reflect.d.cts +0 -11
  219. package/dist/commands/repair-session.cjs +0 -457
  220. package/dist/commands/repair-session.d.cts +0 -38
  221. package/dist/commands/replay.cjs +0 -4103
  222. package/dist/commands/replay.d.cts +0 -16
  223. package/dist/commands/session-recap.cjs +0 -353
  224. package/dist/commands/session-recap.d.cts +0 -27
  225. package/dist/commands/setup.cjs +0 -1278
  226. package/dist/commands/setup.d.cts +0 -99
  227. package/dist/commands/shell-init.cjs +0 -75
  228. package/dist/commands/shell-init.d.cts +0 -7
  229. package/dist/commands/sleep.cjs +0 -6029
  230. package/dist/commands/sleep.d.cts +0 -36
  231. package/dist/commands/status.cjs +0 -2737
  232. package/dist/commands/status.d.cts +0 -52
  233. package/dist/commands/task.cjs +0 -1236
  234. package/dist/commands/task.d.cts +0 -97
  235. package/dist/commands/template.cjs +0 -457
  236. package/dist/commands/template.d.cts +0 -36
  237. package/dist/commands/wake.cjs +0 -2627
  238. package/dist/commands/wake.d.cts +0 -22
  239. package/dist/context-BUGaWpyL.d.cts +0 -46
  240. package/dist/index.cjs +0 -12373
  241. package/dist/index.d.cts +0 -854
  242. package/dist/inject-Bzi5E-By.d.cts +0 -137
  243. package/dist/lib/auto-linker.cjs +0 -176
  244. package/dist/lib/auto-linker.d.cts +0 -26
  245. package/dist/lib/config.cjs +0 -78
  246. package/dist/lib/config.d.cts +0 -11
  247. package/dist/lib/entity-index.cjs +0 -84
  248. package/dist/lib/entity-index.d.cts +0 -26
  249. package/dist/lib/project-utils.cjs +0 -864
  250. package/dist/lib/project-utils.d.cts +0 -97
  251. package/dist/lib/session-repair.cjs +0 -239
  252. package/dist/lib/session-repair.d.cts +0 -110
  253. package/dist/lib/session-utils.cjs +0 -209
  254. package/dist/lib/session-utils.d.cts +0 -63
  255. package/dist/lib/task-utils.cjs +0 -1137
  256. package/dist/lib/task-utils.d.cts +0 -208
  257. package/dist/lib/template-engine.cjs +0 -47
  258. package/dist/lib/template-engine.d.cts +0 -11
  259. package/dist/plugin/index.cjs +0 -1907
  260. package/dist/plugin/index.d.cts +0 -36
  261. package/dist/plugin/index.d.ts +0 -36
  262. package/dist/plugin/index.js +0 -572
  263. package/dist/plugin/inject.cjs +0 -356
  264. package/dist/plugin/inject.d.cts +0 -54
  265. package/dist/plugin/inject.d.ts +0 -54
  266. package/dist/plugin/inject.js +0 -17
  267. package/dist/plugin/observe.cjs +0 -631
  268. package/dist/plugin/observe.d.cts +0 -39
  269. package/dist/plugin/observe.d.ts +0 -39
  270. package/dist/plugin/observe.js +0 -18
  271. package/dist/plugin/templates.cjs +0 -593
  272. package/dist/plugin/templates.d.cts +0 -52
  273. package/dist/plugin/templates.d.ts +0 -52
  274. package/dist/plugin/templates.js +0 -25
  275. package/dist/plugin/types.cjs +0 -18
  276. package/dist/plugin/types.d.cts +0 -209
  277. package/dist/plugin/types.d.ts +0 -209
  278. package/dist/plugin/types.js +0 -0
  279. package/dist/plugin/vault.cjs +0 -927
  280. package/dist/plugin/vault.d.cts +0 -68
  281. package/dist/plugin/vault.d.ts +0 -68
  282. package/dist/plugin/vault.js +0 -22
  283. package/dist/types-Y2_Um2Ls.d.cts +0 -205
  284. package/templates/memory-event.md +0 -67
  285. package/templates/party.md +0 -63
  286. package/templates/primitive-registry.yaml +0 -551
  287. package/templates/run.md +0 -68
  288. package/templates/trigger.md +0 -68
  289. package/templates/workspace.md +0 -50
@@ -7,8 +7,6 @@ var CHECKPOINT_FILE = "last-checkpoint.json";
7
7
  var SESSION_STATE_FILE = "session-state.json";
8
8
  var DIRTY_DEATH_FLAG = "dirty-death.flag";
9
9
  var CHECKPOINT_HISTORY_DIR = "checkpoints";
10
- var CHECKPOINT_RETENTION_MAX_COUNT = 50;
11
- var CHECKPOINT_RETENTION_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
12
10
  var pendingCheckpoint = null;
13
11
  var pendingData = null;
14
12
  function ensureClawvaultDir(vaultPath) {
@@ -18,50 +16,6 @@ function ensureClawvaultDir(vaultPath) {
18
16
  }
19
17
  return dir;
20
18
  }
21
- function readCheckpointHistoryEntries(historyDir) {
22
- const entries = [];
23
- const files = fs.readdirSync(historyDir).filter((entry) => entry.endsWith(".json"));
24
- for (const fileName of files) {
25
- const filePath = path.join(historyDir, fileName);
26
- try {
27
- const parsed = JSON.parse(fs.readFileSync(filePath, "utf-8"));
28
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
29
- continue;
30
- }
31
- const timestamp = typeof parsed.timestamp === "string" ? parsed.timestamp : "";
32
- const timestampMs = Date.parse(timestamp);
33
- if (Number.isNaN(timestampMs)) {
34
- continue;
35
- }
36
- entries.push({ filePath, timestampMs });
37
- } catch {
38
- }
39
- }
40
- return entries.sort((left, right) => {
41
- if (right.timestampMs !== left.timestampMs) {
42
- return right.timestampMs - left.timestampMs;
43
- }
44
- return right.filePath.localeCompare(left.filePath);
45
- });
46
- }
47
- function pruneCheckpointHistory(historyDir, nowMs) {
48
- if (!fs.existsSync(historyDir)) {
49
- return;
50
- }
51
- const entries = readCheckpointHistoryEntries(historyDir);
52
- if (entries.length <= CHECKPOINT_RETENTION_MAX_COUNT) {
53
- return;
54
- }
55
- for (let index = CHECKPOINT_RETENTION_MAX_COUNT; index < entries.length; index += 1) {
56
- const ageMs = nowMs - entries[index].timestampMs;
57
- if (ageMs > CHECKPOINT_RETENTION_MAX_AGE_MS) {
58
- try {
59
- fs.unlinkSync(entries[index].filePath);
60
- } catch {
61
- }
62
- }
63
- }
64
- }
65
19
  function writeCheckpointToDisk(dir, data) {
66
20
  const checkpointPath = path.join(dir, CHECKPOINT_FILE);
67
21
  fs.writeFileSync(checkpointPath, JSON.stringify(data, null, 2));
@@ -70,7 +24,6 @@ function writeCheckpointToDisk(dir, data) {
70
24
  const historyFileName = `${data.timestamp.replace(/[:.]/g, "-")}.json`;
71
25
  const historyPath = path.join(historyDir, historyFileName);
72
26
  fs.writeFileSync(historyPath, JSON.stringify(data, null, 2));
73
- pruneCheckpointHistory(historyDir, Date.now());
74
27
  const flagPath = path.join(dir, DIRTY_DEATH_FLAG);
75
28
  fs.writeFileSync(flagPath, data.timestamp);
76
29
  }
@@ -3,7 +3,7 @@ var DATE_HEADING_RE = /^##\s+(\d{4}-\d{2}-\d{2})\s*$/;
3
3
  var SCORED_LINE_RE = /^(?:-\s*)?\[(decision|preference|fact|commitment|task|todo|commitment-unresolved|milestone|lesson|relationship|project)\|c=(0(?:\.\d+)?|1(?:\.0+)?)\|i=(0(?:\.\d+)?|1(?:\.0+)?)\]\s+(.+)$/i;
4
4
  var EMOJI_LINE_RE = /^(?:-\s*)?(🔴|🟡|🟢)\s+(\d{2}:\d{2})?\s*(.+)$/u;
5
5
  var DECISION_RE = /\b(decis(?:ion|ions)?|decid(?:e|ed|ing)|chose|selected|opted|went with|picked)\b/i;
6
- var PREFERENCE_RE = /\b(prefer(?:ence|s|red)?|likes?|dislikes?|default to|always use|never use|enjoys?|loves?|favou?rite|fan of|interested in|go-to|tend(?:s)? to use|passionate about|hobby|hobbies|(?:I|my|our)\s+(?:own|have|use|got|bought|drive|wear|eat|drink|cook|play|watch|read|listen)|(?:I(?:'m| am))\s+(?:a |an |into |allergic|vegetarian|vegan|gluten|lactose|trying to|learning)|usually|every (?:morning|evening|night|day|week)|routine)\b/i;
6
+ var PREFERENCE_RE = /\b(prefer(?:ence|s|red)?|likes?|dislikes?|default to|always use|never use)\b/i;
7
7
  var COMMITMENT_RE = /\b(commit(?:ment|ted)?|promised|deadline|due|scheduled|will deliver|agreed to)\b/i;
8
8
  var TODO_RE = /(?:\btodo:\s*|\bwe need to\b|\bdon't forget(?: to)?\b|\bremember to\b|\bmake sure to\b)/i;
9
9
  var COMMITMENT_TASK_RE = /\b(?:i'?ll|i will|let me|(?:i'?m\s+)?going to|plan to|should)\b/i;
@@ -33,10 +33,10 @@ function inferObservationType(content) {
33
33
  if (DECISION_RE.test(content)) return "decision";
34
34
  if (UNRESOLVED_RE.test(content)) return "commitment-unresolved";
35
35
  if (TODO_RE.test(content)) return "todo";
36
- if (PREFERENCE_RE.test(content)) return "preference";
37
36
  if (COMMITMENT_TASK_RE.test(content) || DEADLINE_RE.test(content)) return "task";
38
37
  if (COMMITMENT_RE.test(content)) return "commitment";
39
38
  if (MILESTONE_RE.test(content)) return "milestone";
39
+ if (PREFERENCE_RE.test(content)) return "preference";
40
40
  if (LESSON_RE.test(content)) return "lesson";
41
41
  if (RELATIONSHIP_RE.test(content)) return "relationship";
42
42
  if (PROJECT_RE.test(content)) return "project";
@@ -1,25 +1,31 @@
1
+ import {
2
+ scanVaultLinks
3
+ } from "./chunk-7YZWHM36.js";
1
4
  import {
2
5
  formatAge
3
6
  } from "./chunk-7ZRP733D.js";
4
7
  import {
5
- scanVaultLinks
6
- } from "./chunk-4VQTUVH7.js";
8
+ checkOpenClawCompatibility
9
+ } from "./chunk-X3SPPUFG.js";
7
10
  import {
8
11
  getObserverStaleness
9
- } from "./chunk-LNJA2UGL.js";
10
- import {
11
- checkOpenClawCompatibility
12
- } from "./chunk-33UGEQRT.js";
12
+ } from "./chunk-ESFLMDRB.js";
13
13
  import {
14
14
  ClawVault,
15
15
  findVault
16
- } from "./chunk-LI4O6NVK.js";
16
+ } from "./chunk-CLJTREDS.js";
17
17
  import {
18
+ listQmdCollections,
19
+ loadVaultQmdConfig
20
+ } from "./chunk-6FH3IULF.js";
21
+ import {
22
+ QMD_INSTALL_COMMAND,
23
+ QMD_INSTALL_URL,
18
24
  hasQmd
19
- } from "./chunk-D2H45LON.js";
25
+ } from "./chunk-EK6S23ZB.js";
20
26
  import {
21
27
  loadMemoryGraphIndex
22
- } from "./chunk-ZZA73MFY.js";
28
+ } from "./chunk-33DOSHTA.js";
23
29
 
24
30
  // src/commands/doctor.ts
25
31
  import * as fs from "fs";
@@ -29,6 +35,12 @@ var CLAWVAULT_DIR = ".clawvault";
29
35
  var CHECKPOINT_FILE = "last-checkpoint.json";
30
36
  var DAY_MS = 24 * 60 * 60 * 1e3;
31
37
  var ACTIVE_USE_DAYS = 7;
38
+ var V2_COLLECTION_PATTERNS = [
39
+ /^clawvault$/i,
40
+ /^vault$/i,
41
+ /^memory$/i,
42
+ /^notes$/i
43
+ ];
32
44
  function daysSince(date, now = Date.now()) {
33
45
  return Math.max(0, Math.floor((now - date.getTime()) / DAY_MS));
34
46
  }
@@ -51,7 +63,7 @@ function getShellConfigPaths(shellPath) {
51
63
  const home = os.homedir();
52
64
  const shellName = shellPath ? path.basename(shellPath) : "bash";
53
65
  if (shellName === "zsh") {
54
- return [path.join(home, ".zshenv"), path.join(home, ".zshrc"), path.join(home, ".zprofile")];
66
+ return [path.join(home, ".zshrc"), path.join(home, ".zprofile")];
55
67
  }
56
68
  if (shellName === "fish") {
57
69
  return [path.join(home, ".config", "fish", "config.fish")];
@@ -71,6 +83,124 @@ function hasClawvaultPathConfig(paths) {
71
83
  }
72
84
  return false;
73
85
  }
86
+ function isLikelyV2CollectionName(name) {
87
+ return V2_COLLECTION_PATTERNS.some((pattern) => pattern.test(name));
88
+ }
89
+ function checkQmdCollectionExists(collections, expectedName) {
90
+ const found = collections.find((c) => c.name === expectedName);
91
+ return { exists: !!found, collection: found };
92
+ }
93
+ function checkCollectionPathMatches(collection, expectedRoot) {
94
+ if (!collection.root) return false;
95
+ const normalizedCollectionRoot = path.resolve(collection.root);
96
+ const normalizedExpectedRoot = path.resolve(expectedRoot);
97
+ return normalizedCollectionRoot === normalizedExpectedRoot;
98
+ }
99
+ function detectMigrationIssues(vaultPath, configuredCollection, configuredRoot) {
100
+ const issues = [];
101
+ if (!hasQmd()) {
102
+ return issues;
103
+ }
104
+ let collections;
105
+ try {
106
+ collections = listQmdCollections();
107
+ } catch {
108
+ return issues;
109
+ }
110
+ const vaultConfig = loadVaultQmdConfig(vaultPath);
111
+ const expectedCollection = configuredCollection || vaultConfig.qmdCollection;
112
+ const expectedRoot = configuredRoot || vaultConfig.qmdRoot;
113
+ const { exists, collection } = checkQmdCollectionExists(collections, expectedCollection);
114
+ if (!exists) {
115
+ const potentialV2Collections = collections.filter(
116
+ (c) => isLikelyV2CollectionName(c.name) && c.root && path.resolve(c.root) === path.resolve(expectedRoot)
117
+ );
118
+ if (potentialV2Collections.length > 0) {
119
+ issues.push({
120
+ type: "stale_collection_name",
121
+ description: `Found v2-style collection "${potentialV2Collections[0].name}" that should be renamed to "${expectedCollection}"`,
122
+ autoFixable: true,
123
+ details: {
124
+ oldName: potentialV2Collections[0].name,
125
+ newName: expectedCollection,
126
+ root: potentialV2Collections[0].root
127
+ }
128
+ });
129
+ } else {
130
+ issues.push({
131
+ type: "missing_qmd_collection",
132
+ description: `qmd collection "${expectedCollection}" does not exist`,
133
+ autoFixable: true,
134
+ details: {
135
+ collectionName: expectedCollection,
136
+ expectedRoot
137
+ }
138
+ });
139
+ }
140
+ } else if (collection && !checkCollectionPathMatches(collection, expectedRoot)) {
141
+ issues.push({
142
+ type: "wrong_vault_path",
143
+ description: `Collection "${expectedCollection}" points to "${collection.root}" but vault is at "${expectedRoot}"`,
144
+ autoFixable: true,
145
+ details: {
146
+ collectionName: expectedCollection,
147
+ currentRoot: collection.root,
148
+ expectedRoot
149
+ }
150
+ });
151
+ }
152
+ const orphanedCollections = collections.filter((c) => {
153
+ if (c.name === expectedCollection) return false;
154
+ if (!c.root) return false;
155
+ const collectionRoot = path.resolve(c.root);
156
+ const vaultRoot = path.resolve(expectedRoot);
157
+ return collectionRoot === vaultRoot || collectionRoot.startsWith(vaultRoot + path.sep);
158
+ });
159
+ for (const orphan of orphanedCollections) {
160
+ issues.push({
161
+ type: "orphaned_collection",
162
+ description: `Orphaned collection "${orphan.name}" points to vault path but is not the configured collection`,
163
+ autoFixable: true,
164
+ details: {
165
+ collectionName: orphan.name,
166
+ root: orphan.root
167
+ }
168
+ });
169
+ }
170
+ const configPath = path.join(vaultPath, ".clawvault.json");
171
+ if (fs.existsSync(configPath)) {
172
+ try {
173
+ const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
174
+ if (!config.qmdCollection || !config.qmdRoot) {
175
+ issues.push({
176
+ type: "missing_qmd_config",
177
+ description: "Vault config is missing qmdCollection or qmdRoot settings",
178
+ autoFixable: true,
179
+ details: {
180
+ hasQmdCollection: !!config.qmdCollection,
181
+ hasQmdRoot: !!config.qmdRoot
182
+ }
183
+ });
184
+ }
185
+ } catch {
186
+ issues.push({
187
+ type: "legacy_config_format",
188
+ description: "Unable to parse .clawvault.json - may need migration",
189
+ autoFixable: false
190
+ });
191
+ }
192
+ }
193
+ return issues;
194
+ }
195
+ function migrationIssuesToChecks(issues) {
196
+ return issues.map((issue) => ({
197
+ label: `migration: ${issue.type.replace(/_/g, " ")}`,
198
+ status: "warn",
199
+ detail: issue.description,
200
+ hint: issue.autoFixable ? "Run `clawvault migrate` to auto-fix this issue." : "Manual intervention required.",
201
+ category: "migration"
202
+ }));
203
+ }
74
204
  async function resolveVault(vaultPath) {
75
205
  if (vaultPath) {
76
206
  const vault = new ClawVault(path.resolve(vaultPath));
@@ -89,19 +219,19 @@ async function resolveVault(vaultPath) {
89
219
  }
90
220
  return found;
91
221
  }
92
- async function doctor(options) {
93
- const vaultPath = typeof options === "string" ? options : options?.vaultPath;
94
- const _fix = typeof options === "object" ? options?.fix : false;
222
+ async function doctor(vaultPath) {
95
223
  const checks = [];
96
224
  let warnings = 0;
97
225
  let errors = 0;
226
+ const migrationIssues = [];
98
227
  const compatReport = checkOpenClawCompatibility();
99
228
  if (compatReport.errors > 0) {
100
229
  checks.push({
101
230
  label: "OpenClaw compatibility",
102
231
  status: "error",
103
232
  detail: `${compatReport.errors} error(s), ${compatReport.warnings} warning(s)`,
104
- hint: "Run `clawvault compat` for full compatibility diagnostics."
233
+ hint: "Run `clawvault compat` for full compatibility diagnostics.",
234
+ category: "system"
105
235
  });
106
236
  errors++;
107
237
  } else if (compatReport.warnings > 0) {
@@ -109,22 +239,29 @@ async function doctor(options) {
109
239
  label: "OpenClaw compatibility",
110
240
  status: "warn",
111
241
  detail: `${compatReport.warnings} warning(s)`,
112
- hint: "Run `clawvault compat` for full compatibility diagnostics."
242
+ hint: "Run `clawvault compat` for full compatibility diagnostics.",
243
+ category: "system"
113
244
  });
114
245
  warnings++;
115
246
  } else {
116
247
  checks.push({
117
248
  label: "OpenClaw compatibility",
118
- status: "ok"
249
+ status: "ok",
250
+ category: "system"
119
251
  });
120
252
  }
121
253
  if (hasQmd()) {
122
- checks.push({ label: "qmd installed", status: "ok" });
254
+ checks.push({ label: "qmd installed", status: "ok", category: "system" });
123
255
  } else {
124
256
  checks.push({
125
257
  label: "qmd installed",
126
258
  status: "error",
127
- hint: "Install qmd to enable ClawVault commands."
259
+ detail: "qmd binary not found in PATH",
260
+ hint: `Install qmd to enable ClawVault search and indexing:
261
+ ${QMD_INSTALL_COMMAND}
262
+
263
+ For more information: ${QMD_INSTALL_URL}`,
264
+ category: "system"
128
265
  });
129
266
  errors++;
130
267
  }
@@ -133,45 +270,57 @@ async function doctor(options) {
133
270
  checks.push({
134
271
  label: "CLAWVAULT_PATH in shell config",
135
272
  status: "ok",
136
- detail: shellConfigs.map((p) => path.basename(p)).join(", ")
273
+ detail: shellConfigs.map((p) => path.basename(p)).join(", "),
274
+ category: "system"
137
275
  });
138
276
  } else {
139
277
  checks.push({
140
278
  label: "CLAWVAULT_PATH in shell config",
141
279
  status: "warn",
142
- hint: "Run `clawvault shell-init` and add it to your shell rc."
280
+ hint: "Run `clawvault shell-init` and add it to your shell rc.",
281
+ category: "system"
143
282
  });
144
283
  warnings++;
145
284
  }
146
285
  if (!hasQmd()) {
147
- return { vaultPath, checks, warnings, errors };
286
+ return { vaultPath, checks, warnings, errors, migrationIssues };
148
287
  }
149
288
  let vault;
150
289
  try {
151
290
  vault = await resolveVault(vaultPath);
152
- checks.push({ label: "vault found", status: "ok", detail: vault.getPath() });
291
+ checks.push({ label: "vault found", status: "ok", detail: vault.getPath(), category: "system" });
153
292
  } catch (err) {
154
293
  checks.push({
155
294
  label: "vault found",
156
295
  status: "error",
157
- detail: err?.message || "Unable to locate vault"
296
+ detail: err?.message || "Unable to locate vault",
297
+ category: "system"
158
298
  });
159
299
  errors++;
160
- return { vaultPath, checks, warnings, errors };
300
+ return { vaultPath, checks, warnings, errors, migrationIssues };
161
301
  }
162
- const qmdCollection = vault.getQmdCollection();
163
- const qmdRoot = vault.getQmdRoot();
302
+ const detectedMigrationIssues = detectMigrationIssues(
303
+ vault.getPath(),
304
+ vault.getQmdCollection(),
305
+ vault.getQmdRoot()
306
+ );
307
+ migrationIssues.push(...detectedMigrationIssues);
308
+ const migrationChecks = migrationIssuesToChecks(detectedMigrationIssues);
309
+ checks.push(...migrationChecks);
310
+ warnings += migrationChecks.length;
164
311
  const stats = await vault.stats();
165
312
  const documents = await vault.list();
166
313
  const handoffs = await vault.list("handoffs");
167
314
  const inbox = await vault.list("inbox");
315
+ const qmdCollection = vault.getQmdCollection();
168
316
  if (qmdCollection) {
169
- checks.push({ label: "qmd collection configured", status: "ok", detail: qmdCollection });
317
+ checks.push({ label: "qmd collection configured", status: "ok", detail: qmdCollection, category: "system" });
170
318
  } else {
171
319
  checks.push({
172
320
  label: "qmd collection configured",
173
321
  status: "warn",
174
- hint: "Set qmd collection in .clawvault.json"
322
+ hint: "Set qmd collection in .clawvault.json or run `clawvault migrate`.",
323
+ category: "system"
175
324
  });
176
325
  warnings++;
177
326
  }
@@ -183,7 +332,8 @@ async function doctor(options) {
183
332
  label: "memory graph index",
184
333
  status: "warn",
185
334
  detail: "No graph index found",
186
- hint: "Run `clawvault graph --refresh` to build .clawvault/graph-index.json."
335
+ hint: "Run `clawvault graph --refresh` to build .clawvault/graph-index.json.",
336
+ category: "health"
187
337
  });
188
338
  warnings++;
189
339
  } else {
@@ -195,14 +345,16 @@ async function doctor(options) {
195
345
  label: "memory graph index",
196
346
  status: "warn",
197
347
  detail: `Stale graph index (generated ${generatedAge} ago)`,
198
- hint: "Run `clawvault graph --refresh` to resync index."
348
+ hint: "Run `clawvault graph --refresh` to resync index.",
349
+ category: "health"
199
350
  });
200
351
  warnings++;
201
352
  } else {
202
353
  checks.push({
203
354
  label: "memory graph index",
204
355
  status: "ok",
205
- detail: `${graphIndex.graph.stats.nodeCount} nodes, ${graphIndex.graph.stats.edgeCount} edges`
356
+ detail: `${graphIndex.graph.stats.nodeCount} nodes, ${graphIndex.graph.stats.edgeCount} edges`,
357
+ category: "health"
206
358
  });
207
359
  }
208
360
  }
@@ -211,7 +363,8 @@ async function doctor(options) {
211
363
  checks.push({
212
364
  label: "recent handoff",
213
365
  status: "warn",
214
- hint: "Run `clawvault sleep` at the end of sessions."
366
+ hint: "Run `clawvault sleep` at the end of sessions.",
367
+ category: "health"
215
368
  });
216
369
  warnings++;
217
370
  } else {
@@ -223,14 +376,16 @@ async function doctor(options) {
223
376
  label: "recent handoff",
224
377
  status: "warn",
225
378
  detail: `Last handoff ${ageLabel} ago`,
226
- hint: "Run `clawvault sleep` before long pauses."
379
+ hint: "Run `clawvault sleep` before long pauses.",
380
+ category: "health"
227
381
  });
228
382
  warnings++;
229
383
  } else {
230
384
  checks.push({
231
385
  label: "recent handoff",
232
386
  status: "ok",
233
- detail: `Last handoff ${ageLabel} ago`
387
+ detail: `Last handoff ${ageLabel} ago`,
388
+ category: "health"
234
389
  });
235
390
  }
236
391
  }
@@ -240,7 +395,8 @@ async function doctor(options) {
240
395
  checks.push({
241
396
  label: "checkpoint freshness",
242
397
  status: "warn",
243
- detail: checkpointInfo.error
398
+ detail: checkpointInfo.error,
399
+ category: "health"
244
400
  });
245
401
  warnings++;
246
402
  } else if (!checkpointInfo.timestamp) {
@@ -250,7 +406,8 @@ async function doctor(options) {
250
406
  label: "checkpoint freshness",
251
407
  status,
252
408
  detail: activeUse ? "No checkpoint found" : "No checkpoint found (vault appears inactive)",
253
- hint: activeUse ? "Run `clawvault checkpoint` during heavy work." : void 0
409
+ hint: activeUse ? "Run `clawvault checkpoint` during heavy work." : void 0,
410
+ category: "health"
254
411
  });
255
412
  } else {
256
413
  const checkpointDate = new Date(checkpointInfo.timestamp);
@@ -261,14 +418,16 @@ async function doctor(options) {
261
418
  label: "checkpoint freshness",
262
419
  status: "warn",
263
420
  detail: `Last checkpoint ${ageLabel} ago`,
264
- hint: "Checkpoint at least once per active day."
421
+ hint: "Checkpoint at least once per active day.",
422
+ category: "health"
265
423
  });
266
424
  warnings++;
267
425
  } else {
268
426
  checks.push({
269
427
  label: "checkpoint freshness",
270
428
  status: "ok",
271
- detail: `Last checkpoint ${ageLabel} ago`
429
+ detail: `Last checkpoint ${ageLabel} ago`,
430
+ category: "health"
272
431
  });
273
432
  }
274
433
  }
@@ -278,13 +437,15 @@ async function doctor(options) {
278
437
  label: "observer freshness",
279
438
  status: "warn",
280
439
  detail: `${observerStaleness.staleCount} stale session cursor(s); oldest ${formatAge(observerStaleness.oldestMs)} ago`,
281
- hint: "Run `clawvault observe --cron` and verify cron/hook scheduling."
440
+ hint: "Run `clawvault observe --cron` and verify cron/hook scheduling.",
441
+ category: "health"
282
442
  });
283
443
  warnings++;
284
444
  } else {
285
445
  checks.push({
286
446
  label: "observer freshness",
287
- status: "ok"
447
+ status: "ok",
448
+ category: "health"
288
449
  });
289
450
  }
290
451
  const linkScan = scanVaultLinks(vault.getPath());
@@ -293,14 +454,16 @@ async function doctor(options) {
293
454
  label: "orphan links",
294
455
  status: "warn",
295
456
  detail: `${linkScan.orphans.length} orphan link(s)`,
296
- hint: "Run `clawvault link --orphans` to review."
457
+ hint: "Run `clawvault link --orphans` to review.",
458
+ category: "health"
297
459
  });
298
460
  warnings++;
299
461
  } else {
300
462
  checks.push({
301
463
  label: "orphan links",
302
464
  status: "ok",
303
- detail: `${linkScan.orphans.length} orphan link(s)`
465
+ detail: `${linkScan.orphans.length} orphan link(s)`,
466
+ category: "health"
304
467
  });
305
468
  }
306
469
  if (inbox.length > 5) {
@@ -308,14 +471,16 @@ async function doctor(options) {
308
471
  label: "inbox backlog",
309
472
  status: "warn",
310
473
  detail: `${inbox.length} inbox item(s) pending`,
311
- hint: "Process inbox items to keep memory tidy."
474
+ hint: "Process inbox items to keep memory tidy.",
475
+ category: "health"
312
476
  });
313
477
  warnings++;
314
478
  } else {
315
479
  checks.push({
316
480
  label: "inbox backlog",
317
481
  status: "ok",
318
- detail: `${inbox.length} inbox item(s) pending`
482
+ detail: `${inbox.length} inbox item(s) pending`,
483
+ category: "health"
319
484
  });
320
485
  }
321
486
  if (stats.documents < 5) {
@@ -323,11 +488,12 @@ async function doctor(options) {
323
488
  label: "vault activity",
324
489
  status: "warn",
325
490
  detail: `${stats.documents} total documents`,
326
- hint: "Start capturing decisions, lessons, and projects."
491
+ hint: "Start capturing decisions, lessons, and projects.",
492
+ category: "health"
327
493
  });
328
494
  warnings++;
329
495
  }
330
- return { vaultPath: vault.getPath(), qmdCollection, qmdRoot, checks, warnings, errors };
496
+ return { vaultPath: vault.getPath(), checks, warnings, errors, migrationIssues };
331
497
  }
332
498
 
333
499
  export {