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
@@ -1,884 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/commands/kanban.ts
31
- var kanban_exports = {};
32
- __export(kanban_exports, {
33
- buildKanbanLanes: () => buildKanbanLanes,
34
- extractCardSlug: () => extractCardSlug,
35
- formatKanbanCard: () => formatKanbanCard,
36
- generateKanbanMarkdown: () => generateKanbanMarkdown,
37
- importKanbanBoard: () => importKanbanBoard,
38
- kanbanCommand: () => kanbanCommand,
39
- parseKanbanMarkdown: () => parseKanbanMarkdown,
40
- syncKanbanBoard: () => syncKanbanBoard
41
- });
42
- module.exports = __toCommonJS(kanban_exports);
43
- var fs3 = __toESM(require("fs"), 1);
44
- var path3 = __toESM(require("path"), 1);
45
- var import_gray_matter3 = __toESM(require("gray-matter"), 1);
46
-
47
- // src/lib/task-utils.ts
48
- var fs2 = __toESM(require("fs"), 1);
49
- var path2 = __toESM(require("path"), 1);
50
- var import_gray_matter2 = __toESM(require("gray-matter"), 1);
51
-
52
- // src/lib/transition-ledger.ts
53
- var fs = __toESM(require("fs"), 1);
54
- var path = __toESM(require("path"), 1);
55
- var REGRESSION_PAIRS = [
56
- ["done", "open"],
57
- ["done", "blocked"],
58
- ["in-progress", "blocked"]
59
- ];
60
- function isRegression(from, to) {
61
- return REGRESSION_PAIRS.some(([f, t]) => f === from && t === to);
62
- }
63
- function getLedgerDir(vaultPath) {
64
- return path.join(path.resolve(vaultPath), "ledger", "transitions");
65
- }
66
- function getTodayLedgerPath(vaultPath) {
67
- const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
68
- return path.join(getLedgerDir(vaultPath), `${date}.jsonl`);
69
- }
70
- var RETRYABLE_APPEND_CODES = /* @__PURE__ */ new Set(["ENOENT", "EAGAIN", "EBUSY"]);
71
- var MAX_APPEND_RETRIES = 2;
72
- function asErrno(error) {
73
- if (!error || typeof error !== "object") {
74
- return null;
75
- }
76
- return error;
77
- }
78
- function formatLedgerWriteError(filePath, error) {
79
- const errno = asErrno(error);
80
- const message = error instanceof Error ? error.message : String(error);
81
- if (errno?.code === "ENOSPC") {
82
- return new Error(`Failed to write transition ledger at ${filePath}: no space left on device.`);
83
- }
84
- if (errno?.code === "EACCES" || errno?.code === "EPERM") {
85
- return new Error(`Failed to write transition ledger at ${filePath}: permission denied.`);
86
- }
87
- return new Error(`Failed to write transition ledger at ${filePath}: ${message}`);
88
- }
89
- function appendTransition(vaultPath, event) {
90
- const ledgerDir = getLedgerDir(vaultPath);
91
- try {
92
- fs.mkdirSync(ledgerDir, { recursive: true });
93
- } catch (error) {
94
- throw formatLedgerWriteError(ledgerDir, error);
95
- }
96
- const filePath = getTodayLedgerPath(vaultPath);
97
- const payload = JSON.stringify(event) + "\n";
98
- for (let attempt = 0; attempt <= MAX_APPEND_RETRIES; attempt += 1) {
99
- try {
100
- fs.appendFileSync(filePath, payload);
101
- return;
102
- } catch (error) {
103
- const errno = asErrno(error);
104
- const code = errno?.code;
105
- if (code === "ENOENT") {
106
- try {
107
- fs.mkdirSync(ledgerDir, { recursive: true });
108
- } catch (mkdirError) {
109
- throw formatLedgerWriteError(filePath, mkdirError);
110
- }
111
- }
112
- if (code && RETRYABLE_APPEND_CODES.has(code) && attempt < MAX_APPEND_RETRIES) {
113
- continue;
114
- }
115
- throw formatLedgerWriteError(filePath, error);
116
- }
117
- }
118
- }
119
- function buildTransitionEvent(taskId, fromStatus, toStatus, options = {}) {
120
- const agentId = process.env.OPENCLAW_AGENT_ID || "manual";
121
- const costTokensRaw = process.env.OPENCLAW_TOKEN_ESTIMATE;
122
- const costTokens = costTokensRaw ? parseInt(costTokensRaw, 10) : null;
123
- return {
124
- task_id: taskId,
125
- agent_id: agentId,
126
- from_status: fromStatus,
127
- to_status: toStatus,
128
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
129
- confidence: options.confidence ?? (agentId === "manual" ? 1 : 1),
130
- cost_tokens: costTokens !== null && !isNaN(costTokens) ? costTokens : null,
131
- reason: options.reason || null
132
- };
133
- }
134
- function readAllTransitions(vaultPath) {
135
- const ledgerDir = getLedgerDir(vaultPath);
136
- if (!fs.existsSync(ledgerDir)) return [];
137
- let files = [];
138
- try {
139
- files = fs.readdirSync(ledgerDir).filter((f) => f.endsWith(".jsonl")).sort();
140
- } catch {
141
- return [];
142
- }
143
- const events = [];
144
- for (const file of files) {
145
- let lines = [];
146
- try {
147
- lines = fs.readFileSync(path.join(ledgerDir, file), "utf-8").split("\n").filter((l) => l.trim());
148
- } catch {
149
- continue;
150
- }
151
- for (const line of lines) {
152
- try {
153
- events.push(JSON.parse(line));
154
- } catch {
155
- }
156
- }
157
- }
158
- return events;
159
- }
160
- function countBlockedTransitions(vaultPath, taskId) {
161
- const events = readAllTransitions(vaultPath);
162
- return events.filter((e) => e.task_id === taskId && e.to_status === "blocked").length;
163
- }
164
-
165
- // src/lib/primitive-templates.ts
166
- var import_gray_matter = __toESM(require("gray-matter"), 1);
167
-
168
- // src/lib/task-utils.ts
169
- function getTasksDir(vaultPath) {
170
- return path2.join(path2.resolve(vaultPath), "tasks");
171
- }
172
- function getTaskPath(vaultPath, slug) {
173
- return path2.join(getTasksDir(vaultPath), `${slug}.md`);
174
- }
175
- function extractTitle(content) {
176
- const match = content.match(/^#\s+(.+)$/m);
177
- return match ? match[1].trim() : "";
178
- }
179
- function parseDueDate(value) {
180
- if (!value) return null;
181
- const timestamp = Date.parse(value);
182
- if (Number.isNaN(timestamp)) return null;
183
- return timestamp;
184
- }
185
- function startOfToday() {
186
- const now = /* @__PURE__ */ new Date();
187
- return new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
188
- }
189
- var VALID_TASK_STATUSES = /* @__PURE__ */ new Set([
190
- "open",
191
- "in-progress",
192
- "blocked",
193
- "done"
194
- ]);
195
- function isTaskStatus(value) {
196
- return typeof value === "string" && VALID_TASK_STATUSES.has(value);
197
- }
198
- function persistTaskFrontmatter(task, frontmatter) {
199
- fs2.writeFileSync(task.path, import_gray_matter2.default.stringify(task.content, frontmatter));
200
- }
201
- function resolveStatusTransition(previousStatus, nextStatus) {
202
- if (!isTaskStatus(previousStatus) || !isTaskStatus(nextStatus)) {
203
- return null;
204
- }
205
- if (previousStatus === nextStatus) {
206
- return null;
207
- }
208
- return { fromStatus: previousStatus, toStatus: nextStatus };
209
- }
210
- function logStatusTransition({
211
- vaultPath,
212
- task,
213
- fromStatus,
214
- toStatus,
215
- frontmatter,
216
- options
217
- }) {
218
- const normalizedReason = typeof options.reason === "string" ? options.reason.trim() : "";
219
- const reason = normalizedReason || (isRegression(fromStatus, toStatus) ? `regression: ${fromStatus} -> ${toStatus}` : void 0);
220
- const event = buildTransitionEvent(task.slug, fromStatus, toStatus, {
221
- confidence: options.confidence,
222
- reason
223
- });
224
- try {
225
- appendTransition(vaultPath, event);
226
- } catch {
227
- return frontmatter;
228
- }
229
- if (toStatus !== "blocked" || frontmatter.escalation) {
230
- return frontmatter;
231
- }
232
- let blockedCount = 0;
233
- try {
234
- blockedCount = countBlockedTransitions(vaultPath, task.slug);
235
- } catch {
236
- return frontmatter;
237
- }
238
- if (blockedCount < 3) {
239
- return frontmatter;
240
- }
241
- const escalatedFrontmatter = {
242
- ...frontmatter,
243
- escalation: true
244
- };
245
- try {
246
- persistTaskFrontmatter(task, escalatedFrontmatter);
247
- return escalatedFrontmatter;
248
- } catch {
249
- return frontmatter;
250
- }
251
- }
252
- function readTask(vaultPath, slug) {
253
- const taskPath = getTaskPath(vaultPath, slug);
254
- if (!fs2.existsSync(taskPath)) {
255
- return null;
256
- }
257
- try {
258
- const raw = fs2.readFileSync(taskPath, "utf-8");
259
- const { data, content } = (0, import_gray_matter2.default)(raw);
260
- const title = extractTitle(content) || slug;
261
- return {
262
- slug,
263
- title,
264
- content,
265
- frontmatter: data,
266
- path: taskPath
267
- };
268
- } catch {
269
- return null;
270
- }
271
- }
272
- function listTasks(vaultPath, filters) {
273
- const tasksDir = getTasksDir(vaultPath);
274
- if (!fs2.existsSync(tasksDir)) {
275
- return [];
276
- }
277
- const tasks = [];
278
- const entries = fs2.readdirSync(tasksDir, { withFileTypes: true });
279
- const today = startOfToday();
280
- for (const entry of entries) {
281
- if (!entry.isFile() || !entry.name.endsWith(".md")) {
282
- continue;
283
- }
284
- const slug = entry.name.replace(/\.md$/, "");
285
- const task = readTask(vaultPath, slug);
286
- if (!task) continue;
287
- if (filters) {
288
- if (filters.status && task.frontmatter.status !== filters.status) continue;
289
- if (filters.owner && task.frontmatter.owner !== filters.owner) continue;
290
- if (filters.project && task.frontmatter.project !== filters.project) continue;
291
- if (filters.priority && task.frontmatter.priority !== filters.priority) continue;
292
- if (filters.due && !task.frontmatter.due) continue;
293
- if (filters.tag) {
294
- const tags = task.frontmatter.tags || [];
295
- const hasTag = tags.some((tag) => tag.toLowerCase() === filters.tag?.toLowerCase());
296
- if (!hasTag) continue;
297
- }
298
- if (filters.overdue) {
299
- const dueTime = parseDueDate(task.frontmatter.due);
300
- if (task.frontmatter.status === "done" || dueTime === null || dueTime >= today) continue;
301
- }
302
- }
303
- tasks.push(task);
304
- }
305
- const priorityOrder = {
306
- critical: 0,
307
- high: 1,
308
- medium: 2,
309
- low: 3
310
- };
311
- if (filters?.due || filters?.overdue) {
312
- return tasks.sort((a, b) => {
313
- const aDue = parseDueDate(a.frontmatter.due);
314
- const bDue = parseDueDate(b.frontmatter.due);
315
- if (aDue !== null && bDue !== null && aDue !== bDue) {
316
- return aDue - bDue;
317
- }
318
- if (aDue !== null && bDue === null) return -1;
319
- if (aDue === null && bDue !== null) return 1;
320
- return new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime();
321
- });
322
- }
323
- return tasks.sort((a, b) => {
324
- const aPriority = priorityOrder[a.frontmatter.priority || "low"];
325
- const bPriority = priorityOrder[b.frontmatter.priority || "low"];
326
- if (aPriority !== bPriority) {
327
- return aPriority - bPriority;
328
- }
329
- return new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime();
330
- });
331
- }
332
- function updateTask(vaultPath, slug, updates, options = {}) {
333
- const task = readTask(vaultPath, slug);
334
- if (!task) {
335
- throw new Error(`Task not found: ${slug}`);
336
- }
337
- if (updates.status !== void 0 && !isTaskStatus(updates.status)) {
338
- throw new Error(`Invalid task status: ${String(updates.status)}`);
339
- }
340
- const previousStatus = task.frontmatter.status;
341
- const now = (/* @__PURE__ */ new Date()).toISOString();
342
- let newFrontmatter = {
343
- ...task.frontmatter,
344
- updated: now
345
- };
346
- if (updates.status !== void 0) {
347
- newFrontmatter.status = updates.status;
348
- if (updates.status === "done" && !newFrontmatter.completed) {
349
- newFrontmatter.completed = now;
350
- }
351
- if (updates.status !== "done") {
352
- delete newFrontmatter.completed;
353
- }
354
- }
355
- if (updates.source !== void 0) {
356
- if (updates.source === null || updates.source.trim() === "") {
357
- delete newFrontmatter.source;
358
- } else {
359
- newFrontmatter.source = updates.source;
360
- }
361
- }
362
- if (updates.owner !== void 0) {
363
- if (updates.owner === null || updates.owner.trim() === "") {
364
- delete newFrontmatter.owner;
365
- } else {
366
- newFrontmatter.owner = updates.owner;
367
- }
368
- }
369
- if (updates.project !== void 0) {
370
- if (updates.project === null || updates.project.trim() === "") {
371
- delete newFrontmatter.project;
372
- } else {
373
- newFrontmatter.project = updates.project;
374
- }
375
- }
376
- if (updates.priority !== void 0) {
377
- if (updates.priority === null) {
378
- delete newFrontmatter.priority;
379
- } else {
380
- newFrontmatter.priority = updates.priority;
381
- }
382
- }
383
- if (updates.due !== void 0) {
384
- if (updates.due === null || updates.due.trim() === "") {
385
- delete newFrontmatter.due;
386
- } else {
387
- newFrontmatter.due = updates.due;
388
- }
389
- }
390
- if (updates.tags !== void 0) {
391
- if (updates.tags === null) {
392
- delete newFrontmatter.tags;
393
- } else {
394
- const normalizedTags = updates.tags.map((tag) => tag.trim()).filter(Boolean);
395
- if (normalizedTags.length === 0) {
396
- delete newFrontmatter.tags;
397
- } else {
398
- newFrontmatter.tags = normalizedTags;
399
- }
400
- }
401
- }
402
- if (updates.completed !== void 0) {
403
- if (updates.completed === null || updates.completed.trim() === "") {
404
- delete newFrontmatter.completed;
405
- } else {
406
- newFrontmatter.completed = updates.completed;
407
- }
408
- }
409
- if (updates.escalation !== void 0) {
410
- if (updates.escalation === null) {
411
- delete newFrontmatter.escalation;
412
- } else {
413
- newFrontmatter.escalation = updates.escalation;
414
- }
415
- }
416
- if (updates.confidence !== void 0) {
417
- if (updates.confidence === null) {
418
- delete newFrontmatter.confidence;
419
- } else {
420
- newFrontmatter.confidence = updates.confidence;
421
- }
422
- }
423
- if (updates.reason !== void 0) {
424
- if (updates.reason === null || updates.reason.trim() === "") {
425
- delete newFrontmatter.reason;
426
- } else {
427
- newFrontmatter.reason = updates.reason;
428
- }
429
- }
430
- if (updates.description !== void 0) {
431
- if (updates.description === null || updates.description.trim() === "") {
432
- delete newFrontmatter.description;
433
- } else {
434
- newFrontmatter.description = updates.description;
435
- }
436
- }
437
- if (updates.estimate !== void 0) {
438
- if (updates.estimate === null || updates.estimate.trim() === "") {
439
- delete newFrontmatter.estimate;
440
- } else {
441
- newFrontmatter.estimate = updates.estimate;
442
- }
443
- }
444
- if (updates.parent !== void 0) {
445
- if (updates.parent === null || updates.parent.trim() === "") {
446
- delete newFrontmatter.parent;
447
- } else {
448
- newFrontmatter.parent = updates.parent;
449
- }
450
- }
451
- if (updates.depends_on !== void 0) {
452
- if (updates.depends_on === null) {
453
- delete newFrontmatter.depends_on;
454
- } else {
455
- const normalizedDeps = updates.depends_on.map((dep) => dep.trim()).filter(Boolean);
456
- if (normalizedDeps.length === 0) {
457
- delete newFrontmatter.depends_on;
458
- } else {
459
- newFrontmatter.depends_on = normalizedDeps;
460
- }
461
- }
462
- }
463
- if (updates.blocked_by !== void 0) {
464
- if (updates.blocked_by === null || updates.blocked_by.trim() === "") {
465
- delete newFrontmatter.blocked_by;
466
- } else {
467
- newFrontmatter.blocked_by = updates.blocked_by;
468
- }
469
- } else if (updates.status !== void 0 && updates.status !== "blocked") {
470
- delete newFrontmatter.blocked_by;
471
- }
472
- persistTaskFrontmatter(task, newFrontmatter);
473
- const transition = options.skipTransition ? null : resolveStatusTransition(previousStatus, newFrontmatter.status);
474
- if (transition) {
475
- const confidence = options.confidence ?? (typeof updates.confidence === "number" ? updates.confidence : void 0);
476
- const reason = options.reason ?? updates.reason ?? null;
477
- newFrontmatter = logStatusTransition({
478
- vaultPath,
479
- task,
480
- fromStatus: transition.fromStatus,
481
- toStatus: transition.toStatus,
482
- frontmatter: newFrontmatter,
483
- options: {
484
- confidence,
485
- reason
486
- }
487
- });
488
- }
489
- return {
490
- ...task,
491
- frontmatter: newFrontmatter
492
- };
493
- }
494
-
495
- // src/commands/kanban.ts
496
- var STATUS_LANES = [
497
- { status: "open", name: "Open" },
498
- { status: "in-progress", name: "In Progress" },
499
- { status: "blocked", name: "Blocked" },
500
- { status: "done", name: "Done" }
501
- ];
502
- var PRIORITY_LANES = [
503
- { priority: "critical", name: "\u{1F525} Critical" },
504
- { priority: "high", name: "\u{1F534} High" },
505
- { priority: "medium", name: "\u{1F7E1} Medium" },
506
- { priority: "low", name: "\u{1F7E2} Low" },
507
- { priority: null, name: "\u26AA Unset" }
508
- ];
509
- var PRIORITY_EMOJI = {
510
- critical: "\u{1F525}",
511
- high: "\u{1F534}",
512
- medium: "\u{1F7E1}",
513
- low: "\u{1F7E2}"
514
- };
515
- function normalizeGroupBy(value) {
516
- const normalized = String(value || "status").trim().toLowerCase();
517
- if (normalized === "status" || normalized === "priority" || normalized === "project" || normalized === "owner") {
518
- return normalized;
519
- }
520
- throw new Error(`Unsupported kanban group field: ${normalized}`);
521
- }
522
- function resolveBoardPath(vaultPath, output) {
523
- const resolvedVaultPath = path3.resolve(vaultPath);
524
- if (!output) {
525
- return path3.join(resolvedVaultPath, "Board.md");
526
- }
527
- if (path3.isAbsolute(output)) {
528
- return output;
529
- }
530
- return path3.join(resolvedVaultPath, output);
531
- }
532
- function toHashTag(value) {
533
- return value.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9/_-]/g, "");
534
- }
535
- function toMention(value) {
536
- return value.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9._-]/g, "");
537
- }
538
- function dateOnly(value) {
539
- return value.includes("T") ? value.split("T")[0] : value;
540
- }
541
- function dueTimestamp(task) {
542
- if (!task.frontmatter.due) return Number.POSITIVE_INFINITY;
543
- const timestamp = Date.parse(task.frontmatter.due);
544
- return Number.isNaN(timestamp) ? Number.POSITIVE_INFINITY : timestamp;
545
- }
546
- function sortTasksForCards(tasks) {
547
- return [...tasks].sort((left, right) => {
548
- const dueDiff = dueTimestamp(left) - dueTimestamp(right);
549
- if (dueDiff !== 0) return dueDiff;
550
- return new Date(right.frontmatter.created).getTime() - new Date(left.frontmatter.created).getTime();
551
- });
552
- }
553
- function statusLaneName(status) {
554
- const lane = STATUS_LANES.find((entry) => entry.status === status);
555
- return lane ? lane.name : "Open";
556
- }
557
- function priorityLaneName(priority) {
558
- const lane = PRIORITY_LANES.find((entry) => entry.priority === (priority ?? null));
559
- return lane ? lane.name : "\u26AA Unset";
560
- }
561
- function laneNameForTask(task, groupBy) {
562
- switch (groupBy) {
563
- case "status":
564
- return statusLaneName(task.frontmatter.status);
565
- case "priority":
566
- return priorityLaneName(task.frontmatter.priority);
567
- case "project":
568
- return task.frontmatter.project?.trim() || "No Project";
569
- case "owner":
570
- return task.frontmatter.owner?.trim() || "Unassigned";
571
- default:
572
- return statusLaneName(task.frontmatter.status);
573
- }
574
- }
575
- function defaultLaneOrder(groupBy, tasks) {
576
- if (groupBy === "status") {
577
- return STATUS_LANES.map((entry) => entry.name);
578
- }
579
- if (groupBy === "priority") {
580
- return PRIORITY_LANES.map((entry) => entry.name);
581
- }
582
- const fallback = groupBy === "project" ? "No Project" : "Unassigned";
583
- const values = /* @__PURE__ */ new Set();
584
- for (const task of tasks) {
585
- values.add(laneNameForTask(task, groupBy));
586
- }
587
- if (values.size === 0) {
588
- return [fallback];
589
- }
590
- const sorted = Array.from(values).sort((left, right) => left.localeCompare(right));
591
- if (sorted.includes(fallback)) {
592
- return [...sorted.filter((value) => value !== fallback), fallback];
593
- }
594
- return sorted;
595
- }
596
- function formatKanbanCard(task) {
597
- const checkbox = task.frontmatter.status === "done" ? "x" : " ";
598
- const parts = [];
599
- if (task.frontmatter.priority) {
600
- parts.push(PRIORITY_EMOJI[task.frontmatter.priority]);
601
- }
602
- parts.push(`[[${task.slug}|${task.title}]]`);
603
- if (task.frontmatter.project) {
604
- const projectTag = toHashTag(task.frontmatter.project);
605
- if (projectTag) parts.push(`#${projectTag}`);
606
- }
607
- if (task.frontmatter.owner) {
608
- const mention = toMention(task.frontmatter.owner);
609
- if (mention) parts.push(`@${mention}`);
610
- }
611
- if (task.frontmatter.tags && task.frontmatter.tags.length > 0) {
612
- for (const tag of task.frontmatter.tags) {
613
- const normalizedTag = toHashTag(tag);
614
- if (normalizedTag) parts.push(`#${normalizedTag}`);
615
- }
616
- }
617
- if (task.frontmatter.due) {
618
- parts.push(`\u{1F4C5} ${dateOnly(task.frontmatter.due)}`);
619
- }
620
- if (task.frontmatter.status === "blocked" || task.frontmatter.blocked_by) {
621
- parts.push("\u26D4");
622
- }
623
- return `- [${checkbox}] ${parts.join(" ")}`;
624
- }
625
- function buildKanbanLanes(tasks, groupBy) {
626
- const laneOrder = defaultLaneOrder(groupBy, tasks);
627
- const lanes = /* @__PURE__ */ new Map();
628
- for (const laneName of laneOrder) {
629
- lanes.set(laneName, []);
630
- }
631
- for (const task of sortTasksForCards(tasks)) {
632
- const laneName = laneNameForTask(task, groupBy);
633
- if (!lanes.has(laneName)) {
634
- lanes.set(laneName, []);
635
- }
636
- lanes.get(laneName)?.push(formatKanbanCard(task));
637
- }
638
- return Array.from(lanes.entries()).map(([name, cards]) => ({ name, cards }));
639
- }
640
- function generateKanbanMarkdown(tasks, options = {}) {
641
- const groupBy = normalizeGroupBy(options.groupBy);
642
- const syncedAt = (options.now || /* @__PURE__ */ new Date()).toISOString();
643
- const lanes = buildKanbanLanes(tasks, groupBy);
644
- const sections = lanes.map((lane) => {
645
- const cardsBlock = lane.cards.length > 0 ? lane.cards.join("\n") : "";
646
- return `## ${lane.name}
647
-
648
- ${cardsBlock}`.trimEnd();
649
- }).join("\n\n");
650
- return [
651
- "---",
652
- "kanban-plugin: basic",
653
- `clawvault-group-by: ${groupBy}`,
654
- `clawvault-last-sync: '${syncedAt}'`,
655
- "---",
656
- "",
657
- sections,
658
- "",
659
- "%% kanban:settings",
660
- '{"kanban-plugin":"basic","list-collapse":["Done"],"show-checkboxes":true}',
661
- "%%",
662
- ""
663
- ].join("\n");
664
- }
665
- function syncKanbanBoard(vaultPath, options = {}) {
666
- const groupBy = normalizeGroupBy(options.groupBy);
667
- const outputPath = resolveBoardPath(vaultPath, options.output);
668
- let tasks = listTasks(vaultPath);
669
- if (options.filterProject) {
670
- tasks = tasks.filter((task) => task.frontmatter.project === options.filterProject);
671
- }
672
- if (options.filterOwner) {
673
- tasks = tasks.filter((task) => task.frontmatter.owner === options.filterOwner);
674
- }
675
- if (!options.includeDone) {
676
- tasks = tasks.filter((task) => task.frontmatter.status !== "done");
677
- }
678
- const markdown = generateKanbanMarkdown(tasks, {
679
- groupBy,
680
- now: options.now
681
- });
682
- fs3.writeFileSync(outputPath, markdown);
683
- return {
684
- outputPath,
685
- groupBy,
686
- markdown,
687
- lanes: buildKanbanLanes(tasks, groupBy),
688
- taskCount: tasks.length
689
- };
690
- }
691
- function normalizeLaneKey(laneName) {
692
- return laneName.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").replace(/\s+/g, " ").trim();
693
- }
694
- function statusFromLaneName(laneName) {
695
- const key = normalizeLaneKey(laneName);
696
- if (key.includes("in progress") || key.includes("in-progress") || key === "active") return "in-progress";
697
- if (key.includes("blocked")) return "blocked";
698
- if (key.includes("done") || key.includes("complete")) return "done";
699
- if (key.includes("open")) return "open";
700
- return null;
701
- }
702
- function priorityFromLaneName(laneName) {
703
- const key = normalizeLaneKey(laneName);
704
- if (key.includes("critical")) return "critical";
705
- if (key.includes("high")) return "high";
706
- if (key.includes("medium")) return "medium";
707
- if (key.includes("low")) return "low";
708
- if (key.includes("unset") || key.includes("none") || key.includes("no priority")) return null;
709
- return void 0;
710
- }
711
- function isProjectFallbackLane(laneName) {
712
- const key = normalizeLaneKey(laneName);
713
- return key === "no project" || key === "none";
714
- }
715
- function isOwnerFallbackLane(laneName) {
716
- const key = normalizeLaneKey(laneName);
717
- return key === "unassigned" || key === "none";
718
- }
719
- function extractCardSlug(line) {
720
- const wikiMatch = line.match(/\[\[([^\]]+)\]\]/);
721
- if (!wikiMatch) return null;
722
- let target = wikiMatch[1].split("|")[0].trim();
723
- if (!target) return null;
724
- target = target.split("#")[0].trim();
725
- const filePart = target.split("/").pop() || target;
726
- const slug = filePart.replace(/\.md$/i, "").trim();
727
- return slug || null;
728
- }
729
- function parseKanbanMarkdown(markdown) {
730
- const parsed = (0, import_gray_matter3.default)(markdown);
731
- const groupBy = normalizeGroupBy(
732
- typeof parsed.data["clawvault-group-by"] === "string" ? parsed.data["clawvault-group-by"] : void 0
733
- );
734
- const lanes = [];
735
- const laneByName = /* @__PURE__ */ new Map();
736
- let currentLane = null;
737
- const lines = parsed.content.split(/\r?\n/);
738
- for (const line of lines) {
739
- const headerMatch = line.match(/^##\s+(.+?)\s*$/);
740
- if (headerMatch) {
741
- const laneName = headerMatch[1].trim();
742
- if (!laneByName.has(laneName)) {
743
- const lane = { name: laneName, slugs: [] };
744
- laneByName.set(laneName, lane);
745
- lanes.push(lane);
746
- }
747
- currentLane = laneByName.get(laneName) || null;
748
- continue;
749
- }
750
- if (!currentLane || !/^\s*-\s*\[[ xX]\]\s+/.test(line)) {
751
- continue;
752
- }
753
- const slug = extractCardSlug(line);
754
- if (slug) {
755
- currentLane.slugs.push(slug);
756
- }
757
- }
758
- return { groupBy, lanes };
759
- }
760
- function hasUpdates(updates) {
761
- return Object.keys(updates).length > 0;
762
- }
763
- function importKanbanBoard(vaultPath, options = {}) {
764
- const outputPath = resolveBoardPath(vaultPath, options.output);
765
- if (!fs3.existsSync(outputPath)) {
766
- throw new Error(`Kanban board not found: ${outputPath}`);
767
- }
768
- const markdown = fs3.readFileSync(outputPath, "utf-8");
769
- const parsed = parseKanbanMarkdown(markdown);
770
- const changes = [];
771
- const missingSlugs = [];
772
- const seenSlugs = /* @__PURE__ */ new Set();
773
- for (const lane of parsed.lanes) {
774
- for (const slug of lane.slugs) {
775
- if (seenSlugs.has(slug)) continue;
776
- seenSlugs.add(slug);
777
- const task = readTask(vaultPath, slug);
778
- if (!task) {
779
- missingSlugs.push(slug);
780
- continue;
781
- }
782
- const updates = {};
783
- if (parsed.groupBy === "status") {
784
- const desiredStatus = statusFromLaneName(lane.name);
785
- if (desiredStatus && task.frontmatter.status !== desiredStatus) {
786
- updates.status = desiredStatus;
787
- changes.push({
788
- slug,
789
- field: "status",
790
- from: task.frontmatter.status,
791
- to: desiredStatus
792
- });
793
- }
794
- } else if (parsed.groupBy === "priority") {
795
- const desiredPriority = priorityFromLaneName(lane.name);
796
- if (desiredPriority !== void 0) {
797
- const currentPriority = task.frontmatter.priority ?? null;
798
- if (currentPriority !== desiredPriority) {
799
- updates.priority = desiredPriority;
800
- changes.push({
801
- slug,
802
- field: "priority",
803
- from: currentPriority,
804
- to: desiredPriority
805
- });
806
- }
807
- }
808
- } else if (parsed.groupBy === "project") {
809
- const desiredProject = isProjectFallbackLane(lane.name) ? null : lane.name.trim();
810
- const currentProject = task.frontmatter.project ?? null;
811
- if (currentProject !== desiredProject) {
812
- updates.project = desiredProject;
813
- changes.push({
814
- slug,
815
- field: "project",
816
- from: currentProject,
817
- to: desiredProject
818
- });
819
- }
820
- } else if (parsed.groupBy === "owner") {
821
- const desiredOwner = isOwnerFallbackLane(lane.name) ? null : lane.name.trim();
822
- const currentOwner = task.frontmatter.owner ?? null;
823
- if (currentOwner !== desiredOwner) {
824
- updates.owner = desiredOwner;
825
- changes.push({
826
- slug,
827
- field: "owner",
828
- from: currentOwner,
829
- to: desiredOwner
830
- });
831
- }
832
- }
833
- if (hasUpdates(updates)) {
834
- updateTask(vaultPath, slug, updates);
835
- }
836
- }
837
- }
838
- return {
839
- outputPath,
840
- groupBy: parsed.groupBy,
841
- changes,
842
- missingSlugs
843
- };
844
- }
845
- async function kanbanCommand(vaultPath, action, options = {}) {
846
- if (action === "sync") {
847
- const result = syncKanbanBoard(vaultPath, options);
848
- console.log(`\u2713 Synced kanban board: ${result.outputPath}`);
849
- console.log(` Grouped by: ${result.groupBy}`);
850
- console.log(` Tasks included: ${result.taskCount}`);
851
- return;
852
- }
853
- if (action === "import") {
854
- const result = importKanbanBoard(vaultPath, options);
855
- console.log(`\u2713 Imported kanban board: ${result.outputPath}`);
856
- console.log(` Grouped by: ${result.groupBy}`);
857
- if (result.changes.length === 0) {
858
- console.log(" No task updates required.");
859
- } else {
860
- console.log(` Updated ${result.changes.length} task field(s):`);
861
- for (const change of result.changes) {
862
- const from = change.from ?? "(unset)";
863
- const to = change.to ?? "(unset)";
864
- console.log(` - ${change.slug}: ${change.field} ${from} -> ${to}`);
865
- }
866
- }
867
- if (result.missingSlugs.length > 0) {
868
- console.log(` Missing tasks (${result.missingSlugs.length}): ${result.missingSlugs.join(", ")}`);
869
- }
870
- return;
871
- }
872
- throw new Error(`Unknown kanban action: ${action}`);
873
- }
874
- // Annotate the CommonJS export names for ESM import in node:
875
- 0 && (module.exports = {
876
- buildKanbanLanes,
877
- extractCardSlug,
878
- formatKanbanCard,
879
- generateKanbanMarkdown,
880
- importKanbanBoard,
881
- kanbanCommand,
882
- parseKanbanMarkdown,
883
- syncKanbanBoard
884
- });