clawvault 2.2.1 → 2.3.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 (39) hide show
  1. package/bin/clawvault.js +6 -0
  2. package/bin/register-task-commands.js +257 -0
  3. package/dist/chunk-MDIH26GC.js +183 -0
  4. package/dist/chunk-NGVAEFT2.js +352 -0
  5. package/dist/commands/archive.js +1 -1
  6. package/dist/commands/backlog.d.ts +53 -0
  7. package/dist/commands/backlog.js +119 -0
  8. package/dist/commands/blocked.d.ts +25 -0
  9. package/dist/commands/blocked.js +43 -0
  10. package/dist/commands/canvas.d.ts +20 -0
  11. package/dist/commands/canvas.js +309 -0
  12. package/dist/commands/context.js +3 -3
  13. package/dist/commands/doctor.js +1 -1
  14. package/dist/commands/graph.js +2 -2
  15. package/dist/commands/link.js +3 -3
  16. package/dist/commands/migrate-observations.js +2 -2
  17. package/dist/commands/observe.js +3 -3
  18. package/dist/commands/rebuild.js +2 -2
  19. package/dist/commands/recover.js +2 -2
  20. package/dist/commands/reflect.js +1 -1
  21. package/dist/commands/replay.js +3 -3
  22. package/dist/commands/sleep.js +5 -5
  23. package/dist/commands/status.js +1 -1
  24. package/dist/commands/task.d.ts +71 -0
  25. package/dist/commands/task.js +189 -0
  26. package/dist/commands/wake.js +7 -7
  27. package/dist/index.js +38 -38
  28. package/dist/lib/canvas-layout.d.ts +115 -0
  29. package/dist/lib/canvas-layout.js +34 -0
  30. package/dist/lib/task-utils.d.ts +159 -0
  31. package/dist/lib/task-utils.js +46 -0
  32. package/package.json +2 -2
  33. package/dist/{chunk-WZI3OAE5.js → chunk-5WR6RRPX.js} +3 -3
  34. package/dist/{chunk-L6NB43WV.js → chunk-6BBTI7NV.js} +3 -3
  35. package/dist/{chunk-73P7XCQM.js → chunk-DPS7NYIU.js} +3 -3
  36. package/dist/{chunk-MILVYUPK.js → chunk-IWYZAXKJ.js} +3 -3
  37. package/dist/{chunk-H7JW4L7H.js → chunk-OZ7RIXTO.js} +3 -3
  38. package/dist/{chunk-LB6P4CD5.js → chunk-PTSEIWXZ.js} +6 -6
  39. package/dist/{chunk-I5X6J4FX.js → chunk-SOTWYGH7.js} +6 -6
package/bin/clawvault.js CHANGED
@@ -16,6 +16,7 @@ import { registerResilienceCommands } from './register-resilience-commands.js';
16
16
  import { registerSessionLifecycleCommands } from './register-session-lifecycle-commands.js';
17
17
  import { registerTemplateCommands } from './register-template-commands.js';
18
18
  import { registerVaultOperationsCommands } from './register-vault-operations-commands.js';
19
+ import { registerTaskCommands } from './register-task-commands.js';
19
20
  import {
20
21
  getVault,
21
22
  resolveVaultPath,
@@ -82,5 +83,10 @@ registerVaultOperationsCommands(program, {
82
83
  path
83
84
  });
84
85
 
86
+ registerTaskCommands(program, {
87
+ chalk,
88
+ resolveVaultPath
89
+ });
90
+
85
91
  // Parse and run
86
92
  program.parse();
@@ -0,0 +1,257 @@
1
+ /**
2
+ * Task tracking command registrations for ClawVault
3
+ * Registers task, backlog, blocked, and canvas commands
4
+ */
5
+
6
+ export function registerTaskCommands(
7
+ program,
8
+ { chalk, resolveVaultPath }
9
+ ) {
10
+ // === TASK ===
11
+ const taskCmd = program
12
+ .command('task')
13
+ .description('Task management');
14
+
15
+ // task add
16
+ taskCmd
17
+ .command('add <title>')
18
+ .description('Add a new task')
19
+ .option('-v, --vault <path>', 'Vault path')
20
+ .option('--owner <owner>', 'Task owner')
21
+ .option('--project <project>', 'Project name')
22
+ .option('--priority <priority>', 'Priority (critical, high, medium, low)')
23
+ .option('--due <date>', 'Due date (YYYY-MM-DD)')
24
+ .action(async (title, options) => {
25
+ try {
26
+ const vaultPath = resolveVaultPath(options.vault);
27
+ const { taskCommand } = await import('../dist/commands/task.js');
28
+ await taskCommand(vaultPath, 'add', {
29
+ title,
30
+ options: {
31
+ owner: options.owner,
32
+ project: options.project,
33
+ priority: options.priority,
34
+ due: options.due
35
+ }
36
+ });
37
+ } catch (err) {
38
+ console.error(chalk.red(`Error: ${err.message}`));
39
+ process.exit(1);
40
+ }
41
+ });
42
+
43
+ // task list
44
+ taskCmd
45
+ .command('list')
46
+ .description('List tasks')
47
+ .option('-v, --vault <path>', 'Vault path')
48
+ .option('--owner <owner>', 'Filter by owner')
49
+ .option('--project <project>', 'Filter by project')
50
+ .option('--status <status>', 'Filter by status (open, in-progress, blocked, done)')
51
+ .option('--priority <priority>', 'Filter by priority')
52
+ .option('--json', 'Output as JSON')
53
+ .action(async (options) => {
54
+ try {
55
+ const vaultPath = resolveVaultPath(options.vault);
56
+ const { taskCommand } = await import('../dist/commands/task.js');
57
+ await taskCommand(vaultPath, 'list', {
58
+ options: {
59
+ owner: options.owner,
60
+ project: options.project,
61
+ status: options.status,
62
+ priority: options.priority,
63
+ json: options.json
64
+ }
65
+ });
66
+ } catch (err) {
67
+ console.error(chalk.red(`Error: ${err.message}`));
68
+ process.exit(1);
69
+ }
70
+ });
71
+
72
+ // task update
73
+ taskCmd
74
+ .command('update <slug>')
75
+ .description('Update a task')
76
+ .option('-v, --vault <path>', 'Vault path')
77
+ .option('--status <status>', 'New status')
78
+ .option('--owner <owner>', 'New owner')
79
+ .option('--project <project>', 'New project')
80
+ .option('--priority <priority>', 'New priority')
81
+ .option('--blocked-by <blocker>', 'What is blocking this task')
82
+ .option('--due <date>', 'New due date')
83
+ .action(async (slug, options) => {
84
+ try {
85
+ const vaultPath = resolveVaultPath(options.vault);
86
+ const { taskCommand } = await import('../dist/commands/task.js');
87
+ await taskCommand(vaultPath, 'update', {
88
+ slug,
89
+ options: {
90
+ status: options.status,
91
+ owner: options.owner,
92
+ project: options.project,
93
+ priority: options.priority,
94
+ blockedBy: options.blockedBy,
95
+ due: options.due
96
+ }
97
+ });
98
+ } catch (err) {
99
+ console.error(chalk.red(`Error: ${err.message}`));
100
+ process.exit(1);
101
+ }
102
+ });
103
+
104
+ // task done
105
+ taskCmd
106
+ .command('done <slug>')
107
+ .description('Mark a task as done')
108
+ .option('-v, --vault <path>', 'Vault path')
109
+ .action(async (slug, options) => {
110
+ try {
111
+ const vaultPath = resolveVaultPath(options.vault);
112
+ const { taskCommand } = await import('../dist/commands/task.js');
113
+ await taskCommand(vaultPath, 'done', { slug });
114
+ } catch (err) {
115
+ console.error(chalk.red(`Error: ${err.message}`));
116
+ process.exit(1);
117
+ }
118
+ });
119
+
120
+ // task show
121
+ taskCmd
122
+ .command('show <slug>')
123
+ .description('Show task details')
124
+ .option('-v, --vault <path>', 'Vault path')
125
+ .option('--json', 'Output as JSON')
126
+ .action(async (slug, options) => {
127
+ try {
128
+ const vaultPath = resolveVaultPath(options.vault);
129
+ const { taskCommand } = await import('../dist/commands/task.js');
130
+ await taskCommand(vaultPath, 'show', {
131
+ slug,
132
+ options: { json: options.json }
133
+ });
134
+ } catch (err) {
135
+ console.error(chalk.red(`Error: ${err.message}`));
136
+ process.exit(1);
137
+ }
138
+ });
139
+
140
+ // === BACKLOG ===
141
+ const backlogCmd = program
142
+ .command('backlog')
143
+ .description('Backlog management');
144
+
145
+ // backlog add (also supports "backlog <title>" shorthand)
146
+ backlogCmd
147
+ .command('add <title>')
148
+ .description('Add item to backlog')
149
+ .option('-v, --vault <path>', 'Vault path')
150
+ .option('--source <source>', 'Source of the idea')
151
+ .option('--project <project>', 'Project name')
152
+ .action(async (title, options) => {
153
+ try {
154
+ const vaultPath = resolveVaultPath(options.vault);
155
+ const { backlogCommand } = await import('../dist/commands/backlog.js');
156
+ await backlogCommand(vaultPath, 'add', {
157
+ title,
158
+ options: {
159
+ source: options.source,
160
+ project: options.project
161
+ }
162
+ });
163
+ } catch (err) {
164
+ console.error(chalk.red(`Error: ${err.message}`));
165
+ process.exit(1);
166
+ }
167
+ });
168
+
169
+ // backlog list
170
+ backlogCmd
171
+ .command('list')
172
+ .description('List backlog items')
173
+ .option('-v, --vault <path>', 'Vault path')
174
+ .option('--project <project>', 'Filter by project')
175
+ .option('--json', 'Output as JSON')
176
+ .action(async (options) => {
177
+ try {
178
+ const vaultPath = resolveVaultPath(options.vault);
179
+ const { backlogCommand } = await import('../dist/commands/backlog.js');
180
+ await backlogCommand(vaultPath, 'list', {
181
+ options: {
182
+ project: options.project,
183
+ json: options.json
184
+ }
185
+ });
186
+ } catch (err) {
187
+ console.error(chalk.red(`Error: ${err.message}`));
188
+ process.exit(1);
189
+ }
190
+ });
191
+
192
+ // backlog promote
193
+ backlogCmd
194
+ .command('promote <slug>')
195
+ .description('Promote backlog item to task')
196
+ .option('-v, --vault <path>', 'Vault path')
197
+ .option('--owner <owner>', 'Task owner')
198
+ .option('--priority <priority>', 'Task priority')
199
+ .option('--due <date>', 'Due date')
200
+ .action(async (slug, options) => {
201
+ try {
202
+ const vaultPath = resolveVaultPath(options.vault);
203
+ const { backlogCommand } = await import('../dist/commands/backlog.js');
204
+ await backlogCommand(vaultPath, 'promote', {
205
+ slug,
206
+ options: {
207
+ owner: options.owner,
208
+ priority: options.priority,
209
+ due: options.due
210
+ }
211
+ });
212
+ } catch (err) {
213
+ console.error(chalk.red(`Error: ${err.message}`));
214
+ process.exit(1);
215
+ }
216
+ });
217
+
218
+ // === BLOCKED ===
219
+ program
220
+ .command('blocked')
221
+ .description('View blocked tasks')
222
+ .option('-v, --vault <path>', 'Vault path')
223
+ .option('--project <project>', 'Filter by project')
224
+ .option('--json', 'Output as JSON')
225
+ .action(async (options) => {
226
+ try {
227
+ const vaultPath = resolveVaultPath(options.vault);
228
+ const { blockedCommand } = await import('../dist/commands/blocked.js');
229
+ await blockedCommand(vaultPath, {
230
+ project: options.project,
231
+ json: options.json
232
+ });
233
+ } catch (err) {
234
+ console.error(chalk.red(`Error: ${err.message}`));
235
+ process.exit(1);
236
+ }
237
+ });
238
+
239
+ // === CANVAS ===
240
+ program
241
+ .command('canvas')
242
+ .description('Generate Obsidian canvas dashboard')
243
+ .option('-v, --vault <path>', 'Vault path')
244
+ .option('--output <path>', 'Output file path (default: dashboard.canvas)')
245
+ .action(async (options) => {
246
+ try {
247
+ const vaultPath = resolveVaultPath(options.vault);
248
+ const { canvasCommand } = await import('../dist/commands/canvas.js');
249
+ await canvasCommand(vaultPath, {
250
+ output: options.output
251
+ });
252
+ } catch (err) {
253
+ console.error(chalk.red(`Error: ${err.message}`));
254
+ process.exit(1);
255
+ }
256
+ });
257
+ }
@@ -0,0 +1,183 @@
1
+ // src/lib/canvas-layout.ts
2
+ import * as crypto from "crypto";
3
+ var CANVAS_COLORS = {
4
+ RED: "1",
5
+ // Critical, blocked
6
+ ORANGE: "2",
7
+ // High priority
8
+ YELLOW: "3",
9
+ // Medium priority
10
+ GREEN: "4",
11
+ // Done, success
12
+ CYAN: "5",
13
+ // Stats
14
+ PURPLE: "6"
15
+ // Knowledge graph
16
+ };
17
+ var LAYOUT = {
18
+ LEFT_COLUMN_X: 0,
19
+ LEFT_COLUMN_WIDTH: 500,
20
+ RIGHT_COLUMN_X: 550,
21
+ RIGHT_COLUMN_WIDTH: 450,
22
+ GROUP_PADDING: 20,
23
+ NODE_SPACING: 15,
24
+ GROUP_SPACING: 50,
25
+ DEFAULT_NODE_WIDTH: 280,
26
+ DEFAULT_NODE_HEIGHT: 80,
27
+ FILE_NODE_HEIGHT: 60,
28
+ SMALL_NODE_HEIGHT: 50,
29
+ GROUP_HEADER_HEIGHT: 40
30
+ };
31
+ function generateId() {
32
+ return crypto.randomBytes(8).toString("hex");
33
+ }
34
+ function createTextNode(x, y, width, height, text, color) {
35
+ const node = {
36
+ id: generateId(),
37
+ type: "text",
38
+ x,
39
+ y,
40
+ width,
41
+ height,
42
+ text
43
+ };
44
+ if (color) node.color = color;
45
+ return node;
46
+ }
47
+ function createFileNode(x, y, width, height, file, color) {
48
+ const node = {
49
+ id: generateId(),
50
+ type: "file",
51
+ x,
52
+ y,
53
+ width,
54
+ height,
55
+ file
56
+ };
57
+ if (color) node.color = color;
58
+ return node;
59
+ }
60
+ function createGroupNode(x, y, width, height, label, color) {
61
+ const node = {
62
+ id: generateId(),
63
+ type: "group",
64
+ x,
65
+ y,
66
+ width,
67
+ height,
68
+ label
69
+ };
70
+ if (color) node.color = color;
71
+ return node;
72
+ }
73
+ function createEdge(fromNode, fromSide, toNode, toSide, label, color) {
74
+ const edge = {
75
+ id: generateId(),
76
+ fromNode,
77
+ fromSide,
78
+ toNode,
79
+ toSide
80
+ };
81
+ if (label) edge.label = label;
82
+ if (color) edge.color = color;
83
+ return edge;
84
+ }
85
+ function stackNodesVertically(nodes, startX, startY, spacing = LAYOUT.NODE_SPACING) {
86
+ let currentY = startY;
87
+ const positionedNodes = [];
88
+ for (const node of nodes) {
89
+ positionedNodes.push({
90
+ ...node,
91
+ x: startX,
92
+ y: currentY
93
+ });
94
+ currentY += node.height + spacing;
95
+ }
96
+ return {
97
+ nodes: positionedNodes,
98
+ totalHeight: currentY - startY - spacing
99
+ };
100
+ }
101
+ function createGroupWithNodes(groupX, groupY, groupWidth, label, childNodes, color) {
102
+ const padding = LAYOUT.GROUP_PADDING;
103
+ const headerHeight = LAYOUT.GROUP_HEADER_HEIGHT;
104
+ const stacked = stackNodesVertically(
105
+ childNodes,
106
+ groupX + padding,
107
+ groupY + headerHeight + padding
108
+ );
109
+ const groupHeight = headerHeight + padding * 2 + stacked.totalHeight + LAYOUT.NODE_SPACING;
110
+ const group = createGroupNode(groupX, groupY, groupWidth, groupHeight, label, color);
111
+ return {
112
+ group,
113
+ nodes: stacked.nodes
114
+ };
115
+ }
116
+ function getPriorityColor(priority) {
117
+ switch (priority) {
118
+ case "critical":
119
+ return CANVAS_COLORS.RED;
120
+ case "high":
121
+ return CANVAS_COLORS.ORANGE;
122
+ case "medium":
123
+ return CANVAS_COLORS.YELLOW;
124
+ default:
125
+ return void 0;
126
+ }
127
+ }
128
+ function truncateText(text, maxChars) {
129
+ if (text.length <= maxChars) return text;
130
+ return text.slice(0, maxChars - 3) + "...";
131
+ }
132
+ function formatCanvasText(lines) {
133
+ return lines.join("\n");
134
+ }
135
+ function calculateColumnHeight(groups) {
136
+ let height = 0;
137
+ for (let i = 0; i < groups.length; i++) {
138
+ height += groups[i].group.height;
139
+ if (i < groups.length - 1) {
140
+ height += LAYOUT.GROUP_SPACING;
141
+ }
142
+ }
143
+ return height;
144
+ }
145
+ function positionGroupsVertically(groups, startY = 0) {
146
+ let currentY = startY;
147
+ const positioned = [];
148
+ for (const { group, nodes } of groups) {
149
+ const yOffset = currentY - group.y;
150
+ positioned.push({
151
+ group: { ...group, y: currentY },
152
+ nodes: nodes.map((n) => ({ ...n, y: n.y + yOffset }))
153
+ });
154
+ currentY += group.height + LAYOUT.GROUP_SPACING;
155
+ }
156
+ return positioned;
157
+ }
158
+ function flattenGroups(groups) {
159
+ const nodes = [];
160
+ for (const { group, nodes: childNodes } of groups) {
161
+ nodes.push(group);
162
+ nodes.push(...childNodes);
163
+ }
164
+ return nodes;
165
+ }
166
+
167
+ export {
168
+ CANVAS_COLORS,
169
+ LAYOUT,
170
+ generateId,
171
+ createTextNode,
172
+ createFileNode,
173
+ createGroupNode,
174
+ createEdge,
175
+ stackNodesVertically,
176
+ createGroupWithNodes,
177
+ getPriorityColor,
178
+ truncateText,
179
+ formatCanvasText,
180
+ calculateColumnHeight,
181
+ positionGroupsVertically,
182
+ flattenGroups
183
+ };