clawvault 2.2.0 → 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.
- package/bin/clawvault.js +6 -0
- package/bin/register-core-commands.js +14 -4
- package/bin/register-task-commands.js +257 -0
- package/dist/{chunk-DHBDH4DN.js → chunk-FDJIZKCW.js} +8 -1
- package/dist/chunk-MDIH26GC.js +183 -0
- package/dist/chunk-NGVAEFT2.js +352 -0
- package/dist/{chunk-IFGDPIFI.js → chunk-OTQW3OMC.js} +89 -10
- package/dist/{chunk-6RIHODNR.js → chunk-SOTWYGH7.js} +6 -6
- package/dist/{chunk-KNDVXXKC.js → chunk-W463YRED.js} +1 -1
- package/dist/commands/archive.js +1 -1
- package/dist/commands/backlog.d.ts +53 -0
- package/dist/commands/backlog.js +119 -0
- package/dist/commands/blocked.d.ts +25 -0
- package/dist/commands/blocked.js +43 -0
- package/dist/commands/canvas.d.ts +20 -0
- package/dist/commands/canvas.js +309 -0
- package/dist/commands/context.js +4 -4
- package/dist/commands/doctor.js +3 -3
- package/dist/commands/graph.js +2 -2
- package/dist/commands/link.js +3 -3
- package/dist/commands/migrate-observations.js +2 -2
- package/dist/commands/observe.js +3 -3
- package/dist/commands/rebuild.js +2 -2
- package/dist/commands/recover.js +2 -2
- package/dist/commands/reflect.js +1 -1
- package/dist/commands/replay.js +3 -3
- package/dist/commands/setup.js +2 -2
- package/dist/commands/sleep.js +7 -7
- package/dist/commands/status.js +3 -3
- package/dist/commands/task.d.ts +71 -0
- package/dist/commands/task.js +189 -0
- package/dist/commands/wake.js +7 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.js +41 -41
- package/dist/lib/canvas-layout.d.ts +115 -0
- package/dist/lib/canvas-layout.js +34 -0
- package/dist/lib/task-utils.d.ts +159 -0
- package/dist/lib/task-utils.js +46 -0
- package/package.json +2 -2
- package/dist/{chunk-WZI3OAE5.js → chunk-5WR6RRPX.js} +3 -3
- package/dist/{chunk-L6NB43WV.js → chunk-6BBTI7NV.js} +3 -3
- package/dist/{chunk-73P7XCQM.js → chunk-DPS7NYIU.js} +3 -3
- package/dist/{chunk-MILVYUPK.js → chunk-IWYZAXKJ.js} +3 -3
- package/dist/{chunk-H7JW4L7H.js → chunk-OZ7RIXTO.js} +3 -3
- package/dist/{chunk-LB6P4CD5.js → chunk-PTSEIWXZ.js} +6 -6
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createBacklogItem,
|
|
3
|
+
listBacklogItems,
|
|
4
|
+
promoteBacklogItem
|
|
5
|
+
} from "../chunk-NGVAEFT2.js";
|
|
6
|
+
|
|
7
|
+
// src/commands/backlog.ts
|
|
8
|
+
function backlogAdd(vaultPath, title, options = {}) {
|
|
9
|
+
return createBacklogItem(vaultPath, title, {
|
|
10
|
+
source: options.source,
|
|
11
|
+
project: options.project,
|
|
12
|
+
content: options.content,
|
|
13
|
+
tags: options.tags
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function backlogList(vaultPath, options = {}) {
|
|
17
|
+
const filters = {};
|
|
18
|
+
if (options.project) filters.project = options.project;
|
|
19
|
+
return listBacklogItems(vaultPath, filters);
|
|
20
|
+
}
|
|
21
|
+
function backlogPromote(vaultPath, slug, options = {}) {
|
|
22
|
+
return promoteBacklogItem(vaultPath, slug, {
|
|
23
|
+
owner: options.owner,
|
|
24
|
+
priority: options.priority,
|
|
25
|
+
due: options.due
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function formatBacklogList(items) {
|
|
29
|
+
if (items.length === 0) {
|
|
30
|
+
return "No backlog items found.\n";
|
|
31
|
+
}
|
|
32
|
+
const headers = ["SOURCE", "PROJECT", "CREATED", "TITLE"];
|
|
33
|
+
const widths = [12, 16, 12, 40];
|
|
34
|
+
let output = headers.map((h, i) => h.padEnd(widths[i])).join(" ") + "\n";
|
|
35
|
+
for (const item of items) {
|
|
36
|
+
const source = item.frontmatter.source || "-";
|
|
37
|
+
const project = item.frontmatter.project || "-";
|
|
38
|
+
const created = item.frontmatter.created.split("T")[0];
|
|
39
|
+
const title = item.title.length > widths[3] ? item.title.slice(0, widths[3] - 3) + "..." : item.title;
|
|
40
|
+
const row = [
|
|
41
|
+
source.padEnd(widths[0]),
|
|
42
|
+
project.padEnd(widths[1]),
|
|
43
|
+
created.padEnd(widths[2]),
|
|
44
|
+
title
|
|
45
|
+
];
|
|
46
|
+
output += row.join(" ") + "\n";
|
|
47
|
+
}
|
|
48
|
+
return output;
|
|
49
|
+
}
|
|
50
|
+
function formatBacklogDetails(item) {
|
|
51
|
+
let output = "";
|
|
52
|
+
output += `# ${item.title}
|
|
53
|
+
`;
|
|
54
|
+
output += "-".repeat(40) + "\n";
|
|
55
|
+
if (item.frontmatter.source) {
|
|
56
|
+
output += `Source: ${item.frontmatter.source}
|
|
57
|
+
`;
|
|
58
|
+
}
|
|
59
|
+
if (item.frontmatter.project) {
|
|
60
|
+
output += `Project: ${item.frontmatter.project}
|
|
61
|
+
`;
|
|
62
|
+
}
|
|
63
|
+
if (item.frontmatter.tags && item.frontmatter.tags.length > 0) {
|
|
64
|
+
output += `Tags: ${item.frontmatter.tags.join(", ")}
|
|
65
|
+
`;
|
|
66
|
+
}
|
|
67
|
+
output += `Created: ${item.frontmatter.created}
|
|
68
|
+
`;
|
|
69
|
+
output += `File: ${item.path}
|
|
70
|
+
`;
|
|
71
|
+
output += "-".repeat(40) + "\n";
|
|
72
|
+
const contentWithoutTitle = item.content.replace(/^#\s+.+\n/, "").trim();
|
|
73
|
+
if (contentWithoutTitle) {
|
|
74
|
+
output += "\n" + contentWithoutTitle + "\n";
|
|
75
|
+
}
|
|
76
|
+
return output;
|
|
77
|
+
}
|
|
78
|
+
async function backlogCommand(vaultPath, action, args) {
|
|
79
|
+
const options = args.options || {};
|
|
80
|
+
switch (action) {
|
|
81
|
+
case "add": {
|
|
82
|
+
if (!args.title) {
|
|
83
|
+
throw new Error("Title is required for backlog add");
|
|
84
|
+
}
|
|
85
|
+
const item = backlogAdd(vaultPath, args.title, options);
|
|
86
|
+
console.log(`\u2713 Added to backlog: ${item.slug}`);
|
|
87
|
+
console.log(` Path: ${item.path}`);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case "list": {
|
|
91
|
+
const items = backlogList(vaultPath, options);
|
|
92
|
+
if (options.json) {
|
|
93
|
+
console.log(JSON.stringify(items, null, 2));
|
|
94
|
+
} else {
|
|
95
|
+
console.log(formatBacklogList(items));
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case "promote": {
|
|
100
|
+
if (!args.slug) {
|
|
101
|
+
throw new Error("Backlog item slug is required for promote");
|
|
102
|
+
}
|
|
103
|
+
const task = backlogPromote(vaultPath, args.slug, options);
|
|
104
|
+
console.log(`\u2713 Promoted to task: ${task.slug}`);
|
|
105
|
+
console.log(` Path: ${task.path}`);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
default:
|
|
109
|
+
throw new Error(`Unknown backlog action: ${action}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export {
|
|
113
|
+
backlogAdd,
|
|
114
|
+
backlogCommand,
|
|
115
|
+
backlogList,
|
|
116
|
+
backlogPromote,
|
|
117
|
+
formatBacklogDetails,
|
|
118
|
+
formatBacklogList
|
|
119
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Task } from '../lib/task-utils.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Blocked command for ClawVault
|
|
5
|
+
* Quick view of blocked tasks
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface BlockedOptions {
|
|
9
|
+
project?: string;
|
|
10
|
+
json?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get blocked tasks
|
|
14
|
+
*/
|
|
15
|
+
declare function blockedList(vaultPath: string, options?: BlockedOptions): Task[];
|
|
16
|
+
/**
|
|
17
|
+
* Format blocked tasks for terminal display
|
|
18
|
+
*/
|
|
19
|
+
declare function formatBlockedList(tasks: Task[]): string;
|
|
20
|
+
/**
|
|
21
|
+
* Blocked command handler for CLI
|
|
22
|
+
*/
|
|
23
|
+
declare function blockedCommand(vaultPath: string, options?: BlockedOptions): Promise<void>;
|
|
24
|
+
|
|
25
|
+
export { type BlockedOptions, blockedCommand, blockedList, formatBlockedList };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getBlockedTasks
|
|
3
|
+
} from "../chunk-NGVAEFT2.js";
|
|
4
|
+
|
|
5
|
+
// src/commands/blocked.ts
|
|
6
|
+
function blockedList(vaultPath, options = {}) {
|
|
7
|
+
return getBlockedTasks(vaultPath, options.project);
|
|
8
|
+
}
|
|
9
|
+
function formatBlockedList(tasks) {
|
|
10
|
+
if (tasks.length === 0) {
|
|
11
|
+
return "No blocked tasks.\n";
|
|
12
|
+
}
|
|
13
|
+
let output = `BLOCKED TASKS (${tasks.length})
|
|
14
|
+
|
|
15
|
+
`;
|
|
16
|
+
for (const task of tasks) {
|
|
17
|
+
const owner = task.frontmatter.owner || "unassigned";
|
|
18
|
+
const project = task.frontmatter.project || "no project";
|
|
19
|
+
const blockedBy = task.frontmatter.blocked_by || "unknown";
|
|
20
|
+
const updatedDate = task.frontmatter.updated.split("T")[0];
|
|
21
|
+
output += `\u25A0 ${task.title} (${owner}, ${project})
|
|
22
|
+
`;
|
|
23
|
+
output += ` Blocked by: ${blockedBy}
|
|
24
|
+
`;
|
|
25
|
+
output += ` Since: ${updatedDate}
|
|
26
|
+
`;
|
|
27
|
+
output += "\n";
|
|
28
|
+
}
|
|
29
|
+
return output;
|
|
30
|
+
}
|
|
31
|
+
async function blockedCommand(vaultPath, options = {}) {
|
|
32
|
+
const tasks = blockedList(vaultPath, options);
|
|
33
|
+
if (options.json) {
|
|
34
|
+
console.log(JSON.stringify(tasks, null, 2));
|
|
35
|
+
} else {
|
|
36
|
+
console.log(formatBlockedList(tasks));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
blockedCommand,
|
|
41
|
+
blockedList,
|
|
42
|
+
formatBlockedList
|
|
43
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Canvas } from '../lib/canvas-layout.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Canvas command for ClawVault
|
|
5
|
+
* Generates an Obsidian JSON Canvas dashboard
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface CanvasOptions {
|
|
9
|
+
output?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Generate the canvas dashboard
|
|
13
|
+
*/
|
|
14
|
+
declare function generateCanvas(vaultPath: string): Canvas;
|
|
15
|
+
/**
|
|
16
|
+
* Canvas command handler for CLI
|
|
17
|
+
*/
|
|
18
|
+
declare function canvasCommand(vaultPath: string, options?: CanvasOptions): Promise<void>;
|
|
19
|
+
|
|
20
|
+
export { type CanvasOptions, canvasCommand, generateCanvas };
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CANVAS_COLORS,
|
|
3
|
+
LAYOUT,
|
|
4
|
+
createEdge,
|
|
5
|
+
createFileNode,
|
|
6
|
+
createGroupNode,
|
|
7
|
+
createGroupWithNodes,
|
|
8
|
+
createTextNode,
|
|
9
|
+
flattenGroups,
|
|
10
|
+
getPriorityColor,
|
|
11
|
+
positionGroupsVertically,
|
|
12
|
+
truncateText
|
|
13
|
+
} from "../chunk-MDIH26GC.js";
|
|
14
|
+
import {
|
|
15
|
+
getActiveTasks,
|
|
16
|
+
getBlockedTasks,
|
|
17
|
+
getRecentlyCompletedTasks,
|
|
18
|
+
listBacklogItems,
|
|
19
|
+
listTasks
|
|
20
|
+
} from "../chunk-NGVAEFT2.js";
|
|
21
|
+
import {
|
|
22
|
+
loadMemoryGraphIndex
|
|
23
|
+
} from "../chunk-ZZA73MFY.js";
|
|
24
|
+
import {
|
|
25
|
+
getReflectionsRoot,
|
|
26
|
+
listObservationFiles
|
|
27
|
+
} from "../chunk-Z2XBWN7A.js";
|
|
28
|
+
|
|
29
|
+
// src/commands/canvas.ts
|
|
30
|
+
import * as fs from "fs";
|
|
31
|
+
import * as path from "path";
|
|
32
|
+
function generateCanvas(vaultPath) {
|
|
33
|
+
const resolvedPath = path.resolve(vaultPath);
|
|
34
|
+
const nodes = [];
|
|
35
|
+
const edges = [];
|
|
36
|
+
const activeTasks = getActiveTasks(resolvedPath);
|
|
37
|
+
const blockedTasks = getBlockedTasks(resolvedPath);
|
|
38
|
+
const backlogItems = listBacklogItems(resolvedPath);
|
|
39
|
+
const recentlyDone = getRecentlyCompletedTasks(resolvedPath, 10);
|
|
40
|
+
const graphIndex = loadMemoryGraphIndex(resolvedPath);
|
|
41
|
+
const leftGroups = [];
|
|
42
|
+
const knowledgeGraphGroup = buildKnowledgeGraphGroup(resolvedPath, graphIndex?.graph);
|
|
43
|
+
leftGroups.push(knowledgeGraphGroup);
|
|
44
|
+
const vaultStatsGroup = buildVaultStatsGroup(resolvedPath, graphIndex?.graph);
|
|
45
|
+
leftGroups.push(vaultStatsGroup);
|
|
46
|
+
const rightGroups = [];
|
|
47
|
+
if (activeTasks.length > 0) {
|
|
48
|
+
const activeTasksGroup = buildActiveTasksGroup(activeTasks);
|
|
49
|
+
rightGroups.push(activeTasksGroup);
|
|
50
|
+
}
|
|
51
|
+
if (blockedTasks.length > 0) {
|
|
52
|
+
const blockedTasksGroup = buildBlockedTasksGroup(blockedTasks);
|
|
53
|
+
rightGroups.push(blockedTasksGroup);
|
|
54
|
+
}
|
|
55
|
+
if (backlogItems.length > 0) {
|
|
56
|
+
const backlogGroup = buildBacklogGroup(backlogItems);
|
|
57
|
+
rightGroups.push(backlogGroup);
|
|
58
|
+
}
|
|
59
|
+
if (recentlyDone.length > 0) {
|
|
60
|
+
const recentlyDoneGroup = buildRecentlyDoneGroup(recentlyDone);
|
|
61
|
+
rightGroups.push(recentlyDoneGroup);
|
|
62
|
+
}
|
|
63
|
+
const positionedLeft = positionGroupsVertically(leftGroups, 0);
|
|
64
|
+
const positionedRight = positionGroupsVertically(rightGroups, 0);
|
|
65
|
+
nodes.push(...flattenGroups(positionedLeft));
|
|
66
|
+
nodes.push(...flattenGroups(positionedRight));
|
|
67
|
+
const maxLeftHeight = positionedLeft.length > 0 ? positionedLeft[positionedLeft.length - 1].group.y + positionedLeft[positionedLeft.length - 1].group.height : 0;
|
|
68
|
+
const maxRightHeight = positionedRight.length > 0 ? positionedRight[positionedRight.length - 1].group.y + positionedRight[positionedRight.length - 1].group.height : 0;
|
|
69
|
+
const bottomY = Math.max(maxLeftHeight, maxRightHeight) + LAYOUT.GROUP_SPACING;
|
|
70
|
+
const dataFlowResult = buildDataFlowDiagram(bottomY);
|
|
71
|
+
nodes.push(...dataFlowResult.nodes);
|
|
72
|
+
edges.push(...dataFlowResult.edges);
|
|
73
|
+
const taskSlugs = new Set(listTasks(resolvedPath).map((t) => t.slug));
|
|
74
|
+
for (const task of blockedTasks) {
|
|
75
|
+
if (task.frontmatter.blocked_by) {
|
|
76
|
+
const blockerSlug = task.frontmatter.blocked_by.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-");
|
|
77
|
+
if (taskSlugs.has(blockerSlug)) {
|
|
78
|
+
const taskNode = nodes.find((n) => n.type === "file" && n.file === `tasks/${task.slug}.md`);
|
|
79
|
+
const blockerNode = nodes.find((n) => n.type === "file" && n.file === `tasks/${blockerSlug}.md`);
|
|
80
|
+
if (taskNode && blockerNode) {
|
|
81
|
+
edges.push(createEdge(taskNode.id, "left", blockerNode.id, "right", "blocked by", CANVAS_COLORS.RED));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { nodes, edges };
|
|
87
|
+
}
|
|
88
|
+
function buildKnowledgeGraphGroup(vaultPath, graph) {
|
|
89
|
+
const childNodes = [];
|
|
90
|
+
let statsText = "**Knowledge Graph**\n\n";
|
|
91
|
+
if (graph) {
|
|
92
|
+
statsText += `Nodes: ${graph.stats.nodeCount}
|
|
93
|
+
`;
|
|
94
|
+
statsText += `Edges: ${graph.stats.edgeCount}
|
|
95
|
+
`;
|
|
96
|
+
statsText += `Files: ${Object.keys(graph.stats.nodeTypeCounts).filter((t) => t !== "tag" && t !== "unresolved").reduce((sum, t) => sum + (graph.stats.nodeTypeCounts[t] || 0), 0)}
|
|
97
|
+
`;
|
|
98
|
+
} else {
|
|
99
|
+
statsText += "Graph not available\n";
|
|
100
|
+
}
|
|
101
|
+
childNodes.push(createTextNode(0, 0, LAYOUT.DEFAULT_NODE_WIDTH, LAYOUT.DEFAULT_NODE_HEIGHT, statsText));
|
|
102
|
+
if (graph && graph.nodes.length > 0) {
|
|
103
|
+
const topEntities = graph.nodes.filter((n) => n.type !== "tag" && n.type !== "unresolved").sort((a, b) => b.degree - a.degree).slice(0, 10);
|
|
104
|
+
if (topEntities.length > 0) {
|
|
105
|
+
const entitiesText = "**Top Entities**\n\n" + topEntities.map((e) => `- ${e.title} (${e.degree})`).join("\n");
|
|
106
|
+
childNodes.push(createTextNode(0, 0, LAYOUT.DEFAULT_NODE_WIDTH, LAYOUT.DEFAULT_NODE_HEIGHT + 40, entitiesText));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const decisionsDir = path.join(vaultPath, "decisions");
|
|
110
|
+
if (fs.existsSync(decisionsDir)) {
|
|
111
|
+
const decisionFiles = fs.readdirSync(decisionsDir).filter((f) => f.endsWith(".md")).slice(0, 5);
|
|
112
|
+
if (decisionFiles.length > 0) {
|
|
113
|
+
const decisionsText = "**Recent Decisions**\n\n" + decisionFiles.map((f) => `- ${f.replace(".md", "")}`).join("\n");
|
|
114
|
+
childNodes.push(createTextNode(0, 0, LAYOUT.DEFAULT_NODE_WIDTH, LAYOUT.DEFAULT_NODE_HEIGHT, decisionsText));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return createGroupWithNodes(
|
|
118
|
+
LAYOUT.LEFT_COLUMN_X,
|
|
119
|
+
0,
|
|
120
|
+
LAYOUT.LEFT_COLUMN_WIDTH,
|
|
121
|
+
"\u{1F9E0} Knowledge Graph",
|
|
122
|
+
childNodes,
|
|
123
|
+
CANVAS_COLORS.PURPLE
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
function buildVaultStatsGroup(vaultPath, graph) {
|
|
127
|
+
const childNodes = [];
|
|
128
|
+
let categoryText = "**Categories**\n\n";
|
|
129
|
+
if (graph) {
|
|
130
|
+
const typeCounts = graph.stats.nodeTypeCounts;
|
|
131
|
+
const categories = Object.entries(typeCounts).filter(([type]) => type !== "tag" && type !== "unresolved").sort((a, b) => b[1] - a[1]);
|
|
132
|
+
for (const [type, count] of categories) {
|
|
133
|
+
categoryText += `- ${type}: ${count}
|
|
134
|
+
`;
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
categoryText += "Stats not available\n";
|
|
138
|
+
}
|
|
139
|
+
childNodes.push(createTextNode(0, 0, LAYOUT.DEFAULT_NODE_WIDTH, LAYOUT.DEFAULT_NODE_HEIGHT + 20, categoryText));
|
|
140
|
+
const observationFiles = listObservationFiles(vaultPath, { includeLegacy: true, includeArchive: false });
|
|
141
|
+
const recentObsCount = observationFiles.length;
|
|
142
|
+
let obsText = "**Observations**\n\n";
|
|
143
|
+
obsText += `Total days: ${recentObsCount}
|
|
144
|
+
`;
|
|
145
|
+
if (recentObsCount > 0) {
|
|
146
|
+
const latestDate = observationFiles[observationFiles.length - 1]?.date || "N/A";
|
|
147
|
+
obsText += `Latest: ${latestDate}
|
|
148
|
+
`;
|
|
149
|
+
}
|
|
150
|
+
childNodes.push(createTextNode(0, 0, LAYOUT.DEFAULT_NODE_WIDTH, LAYOUT.SMALL_NODE_HEIGHT + 20, obsText));
|
|
151
|
+
const reflectionsRoot = getReflectionsRoot(vaultPath);
|
|
152
|
+
if (fs.existsSync(reflectionsRoot)) {
|
|
153
|
+
const reflectionFiles = fs.readdirSync(reflectionsRoot, { recursive: true }).filter((f) => typeof f === "string" && f.endsWith(".md")).sort().reverse();
|
|
154
|
+
if (reflectionFiles.length > 0) {
|
|
155
|
+
const latestReflection = reflectionFiles[0];
|
|
156
|
+
const reflectionPath = path.join(reflectionsRoot, latestReflection);
|
|
157
|
+
try {
|
|
158
|
+
const content = fs.readFileSync(reflectionPath, "utf-8");
|
|
159
|
+
const openLoopsMatch = content.match(/## Open Loops\n([\s\S]*?)(?=\n##|$)/);
|
|
160
|
+
if (openLoopsMatch) {
|
|
161
|
+
const openLoops = openLoopsMatch[1].trim().split("\n").filter((l) => l.startsWith("-")).slice(0, 5);
|
|
162
|
+
if (openLoops.length > 0) {
|
|
163
|
+
const loopsText = "**Open Loops**\n\n" + openLoops.join("\n");
|
|
164
|
+
childNodes.push(createTextNode(0, 0, LAYOUT.DEFAULT_NODE_WIDTH, LAYOUT.DEFAULT_NODE_HEIGHT, loopsText));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
} catch {
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return createGroupWithNodes(
|
|
172
|
+
LAYOUT.LEFT_COLUMN_X,
|
|
173
|
+
0,
|
|
174
|
+
LAYOUT.LEFT_COLUMN_WIDTH,
|
|
175
|
+
"\u{1F4CA} Vault Stats",
|
|
176
|
+
childNodes,
|
|
177
|
+
CANVAS_COLORS.CYAN
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
function buildActiveTasksGroup(tasks) {
|
|
181
|
+
const childNodes = [];
|
|
182
|
+
for (const task of tasks.slice(0, 10)) {
|
|
183
|
+
const color = getPriorityColor(task.frontmatter.priority);
|
|
184
|
+
const relativePath = `tasks/${task.slug}.md`;
|
|
185
|
+
childNodes.push(createFileNode(0, 0, LAYOUT.DEFAULT_NODE_WIDTH, LAYOUT.FILE_NODE_HEIGHT, relativePath, color));
|
|
186
|
+
}
|
|
187
|
+
if (tasks.length > 10) {
|
|
188
|
+
childNodes.push(createTextNode(0, 0, LAYOUT.DEFAULT_NODE_WIDTH, LAYOUT.SMALL_NODE_HEIGHT, `... and ${tasks.length - 10} more`));
|
|
189
|
+
}
|
|
190
|
+
return createGroupWithNodes(
|
|
191
|
+
LAYOUT.RIGHT_COLUMN_X,
|
|
192
|
+
0,
|
|
193
|
+
LAYOUT.RIGHT_COLUMN_WIDTH,
|
|
194
|
+
"\u25CF Active Tasks",
|
|
195
|
+
childNodes
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
function buildBlockedTasksGroup(tasks) {
|
|
199
|
+
const childNodes = [];
|
|
200
|
+
for (const task of tasks.slice(0, 10)) {
|
|
201
|
+
const blockerInfo = task.frontmatter.blocked_by || "unknown";
|
|
202
|
+
const since = task.frontmatter.updated.split("T")[0];
|
|
203
|
+
const text = `**${truncateText(task.title, 30)}**
|
|
204
|
+
Blocked by: ${blockerInfo}
|
|
205
|
+
Since: ${since}`;
|
|
206
|
+
childNodes.push(createTextNode(0, 0, LAYOUT.DEFAULT_NODE_WIDTH, LAYOUT.DEFAULT_NODE_HEIGHT, text, CANVAS_COLORS.RED));
|
|
207
|
+
}
|
|
208
|
+
return createGroupWithNodes(
|
|
209
|
+
LAYOUT.RIGHT_COLUMN_X,
|
|
210
|
+
0,
|
|
211
|
+
LAYOUT.RIGHT_COLUMN_WIDTH,
|
|
212
|
+
"\u25A0 Blocked",
|
|
213
|
+
childNodes,
|
|
214
|
+
CANVAS_COLORS.RED
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
function buildBacklogGroup(items) {
|
|
218
|
+
const childNodes = [];
|
|
219
|
+
if (items.length > 5) {
|
|
220
|
+
const byProject = /* @__PURE__ */ new Map();
|
|
221
|
+
for (const item of items) {
|
|
222
|
+
const project = item.frontmatter.project || "No Project";
|
|
223
|
+
const existing = byProject.get(project) || [];
|
|
224
|
+
existing.push(item);
|
|
225
|
+
byProject.set(project, existing);
|
|
226
|
+
}
|
|
227
|
+
for (const [project, projectItems] of byProject) {
|
|
228
|
+
const itemsList = projectItems.slice(0, 5).map((i) => `- ${truncateText(i.title, 35)}`).join("\n");
|
|
229
|
+
const moreText = projectItems.length > 5 ? `
|
|
230
|
+
... +${projectItems.length - 5} more` : "";
|
|
231
|
+
const text = `**${project}**
|
|
232
|
+
|
|
233
|
+
${itemsList}${moreText}`;
|
|
234
|
+
childNodes.push(createTextNode(0, 0, LAYOUT.DEFAULT_NODE_WIDTH, LAYOUT.DEFAULT_NODE_HEIGHT + 20, text));
|
|
235
|
+
}
|
|
236
|
+
} else {
|
|
237
|
+
for (const item of items) {
|
|
238
|
+
const relativePath = `backlog/${item.slug}.md`;
|
|
239
|
+
childNodes.push(createFileNode(0, 0, LAYOUT.DEFAULT_NODE_WIDTH, LAYOUT.FILE_NODE_HEIGHT, relativePath));
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return createGroupWithNodes(
|
|
243
|
+
LAYOUT.RIGHT_COLUMN_X,
|
|
244
|
+
0,
|
|
245
|
+
LAYOUT.RIGHT_COLUMN_WIDTH,
|
|
246
|
+
"\u{1F4CB} Backlog",
|
|
247
|
+
childNodes
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
function buildRecentlyDoneGroup(tasks) {
|
|
251
|
+
const childNodes = [];
|
|
252
|
+
for (const task of tasks.slice(0, 10)) {
|
|
253
|
+
const relativePath = `tasks/${task.slug}.md`;
|
|
254
|
+
childNodes.push(createFileNode(0, 0, LAYOUT.DEFAULT_NODE_WIDTH, LAYOUT.FILE_NODE_HEIGHT, relativePath, CANVAS_COLORS.GREEN));
|
|
255
|
+
}
|
|
256
|
+
return createGroupWithNodes(
|
|
257
|
+
LAYOUT.RIGHT_COLUMN_X,
|
|
258
|
+
0,
|
|
259
|
+
LAYOUT.RIGHT_COLUMN_WIDTH,
|
|
260
|
+
"\u2713 Recently Done",
|
|
261
|
+
childNodes,
|
|
262
|
+
CANVAS_COLORS.GREEN
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
function buildDataFlowDiagram(startY) {
|
|
266
|
+
const nodes = [];
|
|
267
|
+
const edges = [];
|
|
268
|
+
const flowSteps = ["Session", "Observe", "Score", "Route", "Reflect", "Promote"];
|
|
269
|
+
const nodeWidth = 100;
|
|
270
|
+
const nodeHeight = 40;
|
|
271
|
+
const spacing = 30;
|
|
272
|
+
const totalWidth = flowSteps.length * nodeWidth + (flowSteps.length - 1) * spacing;
|
|
273
|
+
const startX = LAYOUT.LEFT_COLUMN_X + (LAYOUT.LEFT_COLUMN_WIDTH + LAYOUT.RIGHT_COLUMN_WIDTH + 50 - totalWidth) / 2;
|
|
274
|
+
const groupWidth = totalWidth + LAYOUT.GROUP_PADDING * 2;
|
|
275
|
+
const groupHeight = nodeHeight + LAYOUT.GROUP_HEADER_HEIGHT + LAYOUT.GROUP_PADDING * 2;
|
|
276
|
+
const group = createGroupNode(startX - LAYOUT.GROUP_PADDING, startY, groupWidth, groupHeight, "Data Flow", CANVAS_COLORS.CYAN);
|
|
277
|
+
nodes.push(group);
|
|
278
|
+
const stepNodes = [];
|
|
279
|
+
let currentX = startX;
|
|
280
|
+
for (const step of flowSteps) {
|
|
281
|
+
const node = createTextNode(
|
|
282
|
+
currentX,
|
|
283
|
+
startY + LAYOUT.GROUP_HEADER_HEIGHT + LAYOUT.GROUP_PADDING,
|
|
284
|
+
nodeWidth,
|
|
285
|
+
nodeHeight,
|
|
286
|
+
`**${step}**`
|
|
287
|
+
);
|
|
288
|
+
stepNodes.push(node);
|
|
289
|
+
nodes.push(node);
|
|
290
|
+
currentX += nodeWidth + spacing;
|
|
291
|
+
}
|
|
292
|
+
for (let i = 0; i < stepNodes.length - 1; i++) {
|
|
293
|
+
edges.push(createEdge(stepNodes[i].id, "right", stepNodes[i + 1].id, "left", "\u2192"));
|
|
294
|
+
}
|
|
295
|
+
return { nodes, edges };
|
|
296
|
+
}
|
|
297
|
+
async function canvasCommand(vaultPath, options = {}) {
|
|
298
|
+
const resolvedPath = path.resolve(vaultPath);
|
|
299
|
+
const outputPath = options.output || path.join(resolvedPath, "dashboard.canvas");
|
|
300
|
+
const canvas = generateCanvas(resolvedPath);
|
|
301
|
+
fs.writeFileSync(outputPath, JSON.stringify(canvas, null, 2));
|
|
302
|
+
console.log(`\u2713 Generated canvas dashboard: ${outputPath}`);
|
|
303
|
+
console.log(` Nodes: ${canvas.nodes.length}`);
|
|
304
|
+
console.log(` Edges: ${canvas.edges.length}`);
|
|
305
|
+
}
|
|
306
|
+
export {
|
|
307
|
+
canvasCommand,
|
|
308
|
+
generateCanvas
|
|
309
|
+
};
|
package/dist/commands/context.js
CHANGED
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
contextCommand,
|
|
4
4
|
formatContextMarkdown,
|
|
5
5
|
registerContextCommand
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-SOTWYGH7.js";
|
|
7
|
+
import "../chunk-OTQW3OMC.js";
|
|
8
|
+
import "../chunk-FDJIZKCW.js";
|
|
7
9
|
import "../chunk-K6XHCUFL.js";
|
|
8
|
-
import "../chunk-Z2XBWN7A.js";
|
|
9
|
-
import "../chunk-IFGDPIFI.js";
|
|
10
|
-
import "../chunk-DHBDH4DN.js";
|
|
11
10
|
import "../chunk-ZZA73MFY.js";
|
|
11
|
+
import "../chunk-Z2XBWN7A.js";
|
|
12
12
|
export {
|
|
13
13
|
buildContext,
|
|
14
14
|
contextCommand,
|
package/dist/commands/doctor.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
scanVaultLinks
|
|
3
3
|
} from "../chunk-4VQTUVH7.js";
|
|
4
|
+
import "../chunk-J7ZWCI2C.js";
|
|
4
5
|
import {
|
|
5
6
|
formatAge
|
|
6
7
|
} from "../chunk-7ZRP733D.js";
|
|
@@ -10,11 +11,10 @@ import {
|
|
|
10
11
|
import {
|
|
11
12
|
ClawVault,
|
|
12
13
|
findVault
|
|
13
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-OTQW3OMC.js";
|
|
14
15
|
import {
|
|
15
16
|
hasQmd
|
|
16
|
-
} from "../chunk-
|
|
17
|
-
import "../chunk-J7ZWCI2C.js";
|
|
17
|
+
} from "../chunk-FDJIZKCW.js";
|
|
18
18
|
import {
|
|
19
19
|
loadMemoryGraphIndex
|
|
20
20
|
} from "../chunk-ZZA73MFY.js";
|
package/dist/commands/graph.js
CHANGED
package/dist/commands/link.js
CHANGED
|
@@ -11,12 +11,12 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
buildEntityIndex
|
|
13
13
|
} from "../chunk-J7ZWCI2C.js";
|
|
14
|
-
import {
|
|
15
|
-
buildOrUpdateMemoryGraphIndex
|
|
16
|
-
} from "../chunk-ZZA73MFY.js";
|
|
17
14
|
import {
|
|
18
15
|
resolveVaultPath
|
|
19
16
|
} from "../chunk-MXSSG3QU.js";
|
|
17
|
+
import {
|
|
18
|
+
buildOrUpdateMemoryGraphIndex
|
|
19
|
+
} from "../chunk-ZZA73MFY.js";
|
|
20
20
|
|
|
21
21
|
// src/commands/link.ts
|
|
22
22
|
import * as fs from "fs";
|
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
migrateObservations,
|
|
3
3
|
migrateObservationsCommand,
|
|
4
4
|
registerMigrateObservationsCommand
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-5WR6RRPX.js";
|
|
6
|
+
import "../chunk-MXSSG3QU.js";
|
|
6
7
|
import "../chunk-K6XHCUFL.js";
|
|
7
8
|
import "../chunk-Z2XBWN7A.js";
|
|
8
|
-
import "../chunk-MXSSG3QU.js";
|
|
9
9
|
export {
|
|
10
10
|
migrateObservations,
|
|
11
11
|
migrateObservationsCommand,
|
package/dist/commands/observe.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
observeCommand,
|
|
3
3
|
registerObserveCommand
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-P5EPF6MB.js";
|
|
4
|
+
} from "../chunk-PTSEIWXZ.js";
|
|
6
5
|
import "../chunk-HRLWZGMA.js";
|
|
6
|
+
import "../chunk-P5EPF6MB.js";
|
|
7
7
|
import "../chunk-2HM7ZI4X.js";
|
|
8
|
+
import "../chunk-MXSSG3QU.js";
|
|
8
9
|
import "../chunk-K6XHCUFL.js";
|
|
9
10
|
import "../chunk-Z2XBWN7A.js";
|
|
10
|
-
import "../chunk-MXSSG3QU.js";
|
|
11
11
|
export {
|
|
12
12
|
observeCommand,
|
|
13
13
|
registerObserveCommand
|
package/dist/commands/rebuild.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
rebuildCommand,
|
|
3
3
|
registerRebuildCommand
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-DPS7NYIU.js";
|
|
5
5
|
import "../chunk-2HM7ZI4X.js";
|
|
6
|
+
import "../chunk-MXSSG3QU.js";
|
|
6
7
|
import "../chunk-K6XHCUFL.js";
|
|
7
8
|
import "../chunk-Z2XBWN7A.js";
|
|
8
|
-
import "../chunk-MXSSG3QU.js";
|
|
9
9
|
export {
|
|
10
10
|
rebuildCommand,
|
|
11
11
|
registerRebuildCommand
|
package/dist/commands/recover.js
CHANGED
package/dist/commands/reflect.js
CHANGED
|
@@ -4,9 +4,9 @@ import {
|
|
|
4
4
|
} from "../chunk-GJEGPO7U.js";
|
|
5
5
|
import "../chunk-GQVYQCY5.js";
|
|
6
6
|
import "../chunk-MQUJNOHK.js";
|
|
7
|
+
import "../chunk-MXSSG3QU.js";
|
|
7
8
|
import "../chunk-K6XHCUFL.js";
|
|
8
9
|
import "../chunk-Z2XBWN7A.js";
|
|
9
|
-
import "../chunk-MXSSG3QU.js";
|
|
10
10
|
export {
|
|
11
11
|
reflectCommand,
|
|
12
12
|
registerReflectCommand
|
package/dist/commands/replay.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
registerReplayCommand,
|
|
3
3
|
replayCommand
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-2HM7ZI4X.js";
|
|
4
|
+
} from "../chunk-6BBTI7NV.js";
|
|
6
5
|
import "../chunk-GQVYQCY5.js";
|
|
6
|
+
import "../chunk-2HM7ZI4X.js";
|
|
7
7
|
import "../chunk-MQUJNOHK.js";
|
|
8
|
+
import "../chunk-MXSSG3QU.js";
|
|
8
9
|
import "../chunk-K6XHCUFL.js";
|
|
9
10
|
import "../chunk-Z2XBWN7A.js";
|
|
10
|
-
import "../chunk-MXSSG3QU.js";
|
|
11
11
|
export {
|
|
12
12
|
registerReplayCommand,
|
|
13
13
|
replayCommand
|