clawvault 2.6.1 → 2.6.4
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/README.md +352 -20
- package/bin/clawvault.js +8 -2
- package/bin/command-runtime.js +9 -1
- package/bin/register-maintenance-commands.js +19 -0
- package/bin/register-query-commands.js +58 -6
- package/bin/register-workgraph-commands.js +451 -0
- package/dist/{chunk-VXEOHTSL.js → chunk-2JQ3O2YL.js} +1 -1
- package/dist/{chunk-VR5NE7PZ.js → chunk-2RAZ4ZFE.js} +1 -1
- package/dist/chunk-2ZDO52B4.js +52 -0
- package/dist/chunk-4BQTQMJP.js +93 -0
- package/dist/{chunk-MAKNAHAW.js → chunk-5PJ4STIC.js} +98 -8
- package/dist/{chunk-IEVLHNLU.js → chunk-627Q3QWK.js} +3 -3
- package/dist/{chunk-R6SXNSFD.js → chunk-6NYYDNNG.js} +3 -3
- package/dist/chunk-ECRZL5XR.js +50 -0
- package/dist/chunk-GNJL4YGR.js +79 -0
- package/dist/{chunk-OZ7RIXTO.js → chunk-IIOU45CK.js} +1 -1
- package/dist/chunk-L4HSSQ6T.js +152 -0
- package/dist/{chunk-XAVB4GB4.js → chunk-LIGHWOH6.js} +1 -1
- package/dist/{chunk-PBEE567J.js → chunk-LUBZXECN.js} +2 -2
- package/dist/{chunk-UEOUADMO.js → chunk-MFL6EEPF.js} +204 -35
- package/dist/chunk-MM6QGW3P.js +207 -0
- package/dist/{chunk-T76H47ZS.js → chunk-MNPUYCHQ.js} +1 -1
- package/dist/{chunk-TLGBDTYT.js → chunk-MPOSMDMU.js} +6 -6
- package/dist/{chunk-RVYA52PY.js → chunk-NJYJL5AA.js} +1 -1
- package/dist/{chunk-Q2J5YTUF.js → chunk-OQGYFZ4A.js} +669 -33
- package/dist/{chunk-ME37YNW3.js → chunk-P7SY3D4E.js} +3 -3
- package/dist/chunk-RHISK3SZ.js +189 -0
- package/dist/{chunk-3BTHWPMB.js → chunk-S5OJEGFG.js} +2 -2
- package/dist/{chunk-MGDEINGP.js → chunk-SS4B7P7V.js} +1 -1
- package/dist/chunk-U4O6C46S.js +154 -0
- package/dist/{chunk-ITPEXLHA.js → chunk-URXDAUVH.js} +24 -5
- package/dist/chunk-WIOLLGAD.js +190 -0
- package/dist/chunk-WMGIIABP.js +15 -0
- package/dist/{chunk-QVMXF7FY.js → chunk-X3SPPUFG.js} +50 -0
- package/dist/{chunk-THRJVD4L.js → chunk-Y6VJKXGL.js} +1 -1
- package/dist/{chunk-KL4NAOMO.js → chunk-YDWHS4LJ.js} +49 -9
- package/dist/{chunk-4VRIMU4O.js → chunk-YNIPYN4F.js} +4 -4
- package/dist/{chunk-HIHOUSXS.js → chunk-YXQCA6B7.js} +105 -1
- package/dist/cli/index.js +18 -16
- package/dist/commands/archive.js +3 -2
- package/dist/commands/backlog.js +1 -0
- package/dist/commands/blocked.js +1 -0
- package/dist/commands/canvas.js +1 -0
- package/dist/commands/checkpoint.js +1 -0
- package/dist/commands/compat.js +2 -1
- package/dist/commands/context.js +5 -3
- package/dist/commands/doctor.d.ts +10 -1
- package/dist/commands/doctor.js +11 -8
- package/dist/commands/embed.js +5 -3
- package/dist/commands/entities.js +2 -1
- package/dist/commands/graph.js +3 -2
- package/dist/commands/inject.d.ts +1 -1
- package/dist/commands/inject.js +4 -3
- package/dist/commands/kanban.js +1 -0
- package/dist/commands/link.js +2 -1
- package/dist/commands/migrate-observations.js +3 -2
- package/dist/commands/observe.js +8 -6
- package/dist/commands/project.js +1 -0
- package/dist/commands/rebuild-embeddings.d.ts +21 -0
- package/dist/commands/rebuild-embeddings.js +91 -0
- package/dist/commands/rebuild.js +6 -4
- package/dist/commands/recover.js +1 -0
- package/dist/commands/reflect.js +5 -4
- package/dist/commands/repair-session.js +1 -0
- package/dist/commands/replay.js +7 -6
- package/dist/commands/session-recap.js +1 -0
- package/dist/commands/setup.js +3 -2
- package/dist/commands/shell-init.js +2 -0
- package/dist/commands/sleep.d.ts +1 -1
- package/dist/commands/sleep.js +8 -6
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.js +35 -24
- package/dist/commands/sync-bd.js +3 -2
- package/dist/commands/tailscale.js +3 -2
- package/dist/commands/task.js +1 -0
- package/dist/commands/template.js +1 -0
- package/dist/commands/wake.d.ts +1 -1
- package/dist/commands/wake.js +4 -2
- package/dist/index.d.ts +333 -10
- package/dist/index.js +320 -33
- package/dist/{inject-x65KXWPk.d.ts → inject-DYUrDqQO.d.ts} +2 -2
- package/dist/ledger-B7g7jhqG.d.ts +44 -0
- package/dist/lib/auto-linker.js +1 -0
- package/dist/lib/canvas-layout.js +1 -0
- package/dist/lib/config.d.ts +27 -3
- package/dist/lib/config.js +4 -1
- package/dist/lib/entity-index.js +1 -0
- package/dist/lib/project-utils.js +1 -0
- package/dist/lib/session-repair.js +1 -0
- package/dist/lib/session-utils.js +1 -0
- package/dist/lib/tailscale.js +1 -0
- package/dist/lib/task-utils.js +1 -0
- package/dist/lib/template-engine.js +1 -0
- package/dist/lib/webdav.js +1 -0
- package/dist/onnxruntime_binding-5QEF3SUC.node +0 -0
- package/dist/onnxruntime_binding-BKPKNEGC.node +0 -0
- package/dist/onnxruntime_binding-FMOXGIUT.node +0 -0
- package/dist/onnxruntime_binding-OI2KMXC5.node +0 -0
- package/dist/onnxruntime_binding-UX44MLAZ.node +0 -0
- package/dist/onnxruntime_binding-Y2W7N7WY.node +0 -0
- package/dist/registry-BR4326o0.d.ts +30 -0
- package/dist/store-CA-6sKCJ.d.ts +34 -0
- package/dist/thread-B9LhXNU0.d.ts +41 -0
- package/dist/transformers.node-A2ZRORSQ.js +46775 -0
- package/dist/{types-C74wgGL1.d.ts → types-BbWJoC1c.d.ts} +1 -1
- package/dist/workgraph/index.d.ts +5 -0
- package/dist/workgraph/index.js +23 -0
- package/dist/workgraph/ledger.d.ts +2 -0
- package/dist/workgraph/ledger.js +25 -0
- package/dist/workgraph/registry.d.ts +2 -0
- package/dist/workgraph/registry.js +19 -0
- package/dist/workgraph/store.d.ts +2 -0
- package/dist/workgraph/store.js +25 -0
- package/dist/workgraph/thread.d.ts +2 -0
- package/dist/workgraph/thread.js +25 -0
- package/dist/workgraph/types.d.ts +54 -0
- package/dist/workgraph/types.js +7 -0
- package/hooks/clawvault/HOOK.md +34 -4
- package/hooks/clawvault/handler.js +751 -8
- package/hooks/clawvault/handler.test.js +247 -0
- package/hooks/clawvault/openclaw.plugin.json +72 -0
- package/openclaw.plugin.json +84 -0
- package/package.json +8 -4
- package/dist/chunk-4QYGFWRM.js +0 -88
- package/dist/chunk-MXSSG3QU.js +0 -42
|
@@ -6,20 +6,26 @@ import {
|
|
|
6
6
|
} from "./chunk-4VQTUVH7.js";
|
|
7
7
|
import {
|
|
8
8
|
getObserverStaleness
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-627Q3QWK.js";
|
|
10
10
|
import {
|
|
11
11
|
ClawVault,
|
|
12
12
|
findVault
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-YDWHS4LJ.js";
|
|
14
14
|
import {
|
|
15
|
+
listQmdCollections,
|
|
16
|
+
loadVaultQmdConfig
|
|
17
|
+
} from "./chunk-WIOLLGAD.js";
|
|
18
|
+
import {
|
|
19
|
+
QMD_INSTALL_COMMAND,
|
|
20
|
+
QMD_INSTALL_URL,
|
|
15
21
|
hasQmd
|
|
16
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-5PJ4STIC.js";
|
|
17
23
|
import {
|
|
18
24
|
loadMemoryGraphIndex
|
|
19
25
|
} from "./chunk-ZZA73MFY.js";
|
|
20
26
|
import {
|
|
21
27
|
checkOpenClawCompatibility
|
|
22
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-X3SPPUFG.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
|
}
|
|
@@ -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));
|
|
@@ -93,13 +223,15 @@ async function doctor(vaultPath) {
|
|
|
93
223
|
const checks = [];
|
|
94
224
|
let warnings = 0;
|
|
95
225
|
let errors = 0;
|
|
226
|
+
const migrationIssues = [];
|
|
96
227
|
const compatReport = checkOpenClawCompatibility();
|
|
97
228
|
if (compatReport.errors > 0) {
|
|
98
229
|
checks.push({
|
|
99
230
|
label: "OpenClaw compatibility",
|
|
100
231
|
status: "error",
|
|
101
232
|
detail: `${compatReport.errors} error(s), ${compatReport.warnings} warning(s)`,
|
|
102
|
-
hint: "Run `clawvault compat` for full compatibility diagnostics."
|
|
233
|
+
hint: "Run `clawvault compat` for full compatibility diagnostics.",
|
|
234
|
+
category: "system"
|
|
103
235
|
});
|
|
104
236
|
errors++;
|
|
105
237
|
} else if (compatReport.warnings > 0) {
|
|
@@ -107,22 +239,29 @@ async function doctor(vaultPath) {
|
|
|
107
239
|
label: "OpenClaw compatibility",
|
|
108
240
|
status: "warn",
|
|
109
241
|
detail: `${compatReport.warnings} warning(s)`,
|
|
110
|
-
hint: "Run `clawvault compat` for full compatibility diagnostics."
|
|
242
|
+
hint: "Run `clawvault compat` for full compatibility diagnostics.",
|
|
243
|
+
category: "system"
|
|
111
244
|
});
|
|
112
245
|
warnings++;
|
|
113
246
|
} else {
|
|
114
247
|
checks.push({
|
|
115
248
|
label: "OpenClaw compatibility",
|
|
116
|
-
status: "ok"
|
|
249
|
+
status: "ok",
|
|
250
|
+
category: "system"
|
|
117
251
|
});
|
|
118
252
|
}
|
|
119
253
|
if (hasQmd()) {
|
|
120
|
-
checks.push({ label: "qmd installed", status: "ok" });
|
|
254
|
+
checks.push({ label: "qmd installed", status: "ok", category: "system" });
|
|
121
255
|
} else {
|
|
122
256
|
checks.push({
|
|
123
257
|
label: "qmd installed",
|
|
124
258
|
status: "error",
|
|
125
|
-
|
|
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"
|
|
126
265
|
});
|
|
127
266
|
errors++;
|
|
128
267
|
}
|
|
@@ -131,44 +270,57 @@ async function doctor(vaultPath) {
|
|
|
131
270
|
checks.push({
|
|
132
271
|
label: "CLAWVAULT_PATH in shell config",
|
|
133
272
|
status: "ok",
|
|
134
|
-
detail: shellConfigs.map((p) => path.basename(p)).join(", ")
|
|
273
|
+
detail: shellConfigs.map((p) => path.basename(p)).join(", "),
|
|
274
|
+
category: "system"
|
|
135
275
|
});
|
|
136
276
|
} else {
|
|
137
277
|
checks.push({
|
|
138
278
|
label: "CLAWVAULT_PATH in shell config",
|
|
139
279
|
status: "warn",
|
|
140
|
-
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"
|
|
141
282
|
});
|
|
142
283
|
warnings++;
|
|
143
284
|
}
|
|
144
285
|
if (!hasQmd()) {
|
|
145
|
-
return { vaultPath, checks, warnings, errors };
|
|
286
|
+
return { vaultPath, checks, warnings, errors, migrationIssues };
|
|
146
287
|
}
|
|
147
288
|
let vault;
|
|
148
289
|
try {
|
|
149
290
|
vault = await resolveVault(vaultPath);
|
|
150
|
-
checks.push({ label: "vault found", status: "ok", detail: vault.getPath() });
|
|
291
|
+
checks.push({ label: "vault found", status: "ok", detail: vault.getPath(), category: "system" });
|
|
151
292
|
} catch (err) {
|
|
152
293
|
checks.push({
|
|
153
294
|
label: "vault found",
|
|
154
295
|
status: "error",
|
|
155
|
-
detail: err?.message || "Unable to locate vault"
|
|
296
|
+
detail: err?.message || "Unable to locate vault",
|
|
297
|
+
category: "system"
|
|
156
298
|
});
|
|
157
299
|
errors++;
|
|
158
|
-
return { vaultPath, checks, warnings, errors };
|
|
300
|
+
return { vaultPath, checks, warnings, errors, migrationIssues };
|
|
159
301
|
}
|
|
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;
|
|
160
311
|
const stats = await vault.stats();
|
|
161
312
|
const documents = await vault.list();
|
|
162
313
|
const handoffs = await vault.list("handoffs");
|
|
163
314
|
const inbox = await vault.list("inbox");
|
|
164
315
|
const qmdCollection = vault.getQmdCollection();
|
|
165
316
|
if (qmdCollection) {
|
|
166
|
-
checks.push({ label: "qmd collection configured", status: "ok", detail: qmdCollection });
|
|
317
|
+
checks.push({ label: "qmd collection configured", status: "ok", detail: qmdCollection, category: "system" });
|
|
167
318
|
} else {
|
|
168
319
|
checks.push({
|
|
169
320
|
label: "qmd collection configured",
|
|
170
321
|
status: "warn",
|
|
171
|
-
hint: "Set qmd collection in .clawvault.json"
|
|
322
|
+
hint: "Set qmd collection in .clawvault.json or run `clawvault migrate`.",
|
|
323
|
+
category: "system"
|
|
172
324
|
});
|
|
173
325
|
warnings++;
|
|
174
326
|
}
|
|
@@ -180,7 +332,8 @@ async function doctor(vaultPath) {
|
|
|
180
332
|
label: "memory graph index",
|
|
181
333
|
status: "warn",
|
|
182
334
|
detail: "No graph index found",
|
|
183
|
-
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"
|
|
184
337
|
});
|
|
185
338
|
warnings++;
|
|
186
339
|
} else {
|
|
@@ -192,14 +345,16 @@ async function doctor(vaultPath) {
|
|
|
192
345
|
label: "memory graph index",
|
|
193
346
|
status: "warn",
|
|
194
347
|
detail: `Stale graph index (generated ${generatedAge} ago)`,
|
|
195
|
-
hint: "Run `clawvault graph --refresh` to resync index."
|
|
348
|
+
hint: "Run `clawvault graph --refresh` to resync index.",
|
|
349
|
+
category: "health"
|
|
196
350
|
});
|
|
197
351
|
warnings++;
|
|
198
352
|
} else {
|
|
199
353
|
checks.push({
|
|
200
354
|
label: "memory graph index",
|
|
201
355
|
status: "ok",
|
|
202
|
-
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"
|
|
203
358
|
});
|
|
204
359
|
}
|
|
205
360
|
}
|
|
@@ -208,7 +363,8 @@ async function doctor(vaultPath) {
|
|
|
208
363
|
checks.push({
|
|
209
364
|
label: "recent handoff",
|
|
210
365
|
status: "warn",
|
|
211
|
-
hint: "Run `clawvault sleep` at the end of sessions."
|
|
366
|
+
hint: "Run `clawvault sleep` at the end of sessions.",
|
|
367
|
+
category: "health"
|
|
212
368
|
});
|
|
213
369
|
warnings++;
|
|
214
370
|
} else {
|
|
@@ -220,14 +376,16 @@ async function doctor(vaultPath) {
|
|
|
220
376
|
label: "recent handoff",
|
|
221
377
|
status: "warn",
|
|
222
378
|
detail: `Last handoff ${ageLabel} ago`,
|
|
223
|
-
hint: "Run `clawvault sleep` before long pauses."
|
|
379
|
+
hint: "Run `clawvault sleep` before long pauses.",
|
|
380
|
+
category: "health"
|
|
224
381
|
});
|
|
225
382
|
warnings++;
|
|
226
383
|
} else {
|
|
227
384
|
checks.push({
|
|
228
385
|
label: "recent handoff",
|
|
229
386
|
status: "ok",
|
|
230
|
-
detail: `Last handoff ${ageLabel} ago
|
|
387
|
+
detail: `Last handoff ${ageLabel} ago`,
|
|
388
|
+
category: "health"
|
|
231
389
|
});
|
|
232
390
|
}
|
|
233
391
|
}
|
|
@@ -237,7 +395,8 @@ async function doctor(vaultPath) {
|
|
|
237
395
|
checks.push({
|
|
238
396
|
label: "checkpoint freshness",
|
|
239
397
|
status: "warn",
|
|
240
|
-
detail: checkpointInfo.error
|
|
398
|
+
detail: checkpointInfo.error,
|
|
399
|
+
category: "health"
|
|
241
400
|
});
|
|
242
401
|
warnings++;
|
|
243
402
|
} else if (!checkpointInfo.timestamp) {
|
|
@@ -247,7 +406,8 @@ async function doctor(vaultPath) {
|
|
|
247
406
|
label: "checkpoint freshness",
|
|
248
407
|
status,
|
|
249
408
|
detail: activeUse ? "No checkpoint found" : "No checkpoint found (vault appears inactive)",
|
|
250
|
-
hint: activeUse ? "Run `clawvault checkpoint` during heavy work." : void 0
|
|
409
|
+
hint: activeUse ? "Run `clawvault checkpoint` during heavy work." : void 0,
|
|
410
|
+
category: "health"
|
|
251
411
|
});
|
|
252
412
|
} else {
|
|
253
413
|
const checkpointDate = new Date(checkpointInfo.timestamp);
|
|
@@ -258,14 +418,16 @@ async function doctor(vaultPath) {
|
|
|
258
418
|
label: "checkpoint freshness",
|
|
259
419
|
status: "warn",
|
|
260
420
|
detail: `Last checkpoint ${ageLabel} ago`,
|
|
261
|
-
hint: "Checkpoint at least once per active day."
|
|
421
|
+
hint: "Checkpoint at least once per active day.",
|
|
422
|
+
category: "health"
|
|
262
423
|
});
|
|
263
424
|
warnings++;
|
|
264
425
|
} else {
|
|
265
426
|
checks.push({
|
|
266
427
|
label: "checkpoint freshness",
|
|
267
428
|
status: "ok",
|
|
268
|
-
detail: `Last checkpoint ${ageLabel} ago
|
|
429
|
+
detail: `Last checkpoint ${ageLabel} ago`,
|
|
430
|
+
category: "health"
|
|
269
431
|
});
|
|
270
432
|
}
|
|
271
433
|
}
|
|
@@ -275,13 +437,15 @@ async function doctor(vaultPath) {
|
|
|
275
437
|
label: "observer freshness",
|
|
276
438
|
status: "warn",
|
|
277
439
|
detail: `${observerStaleness.staleCount} stale session cursor(s); oldest ${formatAge(observerStaleness.oldestMs)} ago`,
|
|
278
|
-
hint: "Run `clawvault observe --cron` and verify cron/hook scheduling."
|
|
440
|
+
hint: "Run `clawvault observe --cron` and verify cron/hook scheduling.",
|
|
441
|
+
category: "health"
|
|
279
442
|
});
|
|
280
443
|
warnings++;
|
|
281
444
|
} else {
|
|
282
445
|
checks.push({
|
|
283
446
|
label: "observer freshness",
|
|
284
|
-
status: "ok"
|
|
447
|
+
status: "ok",
|
|
448
|
+
category: "health"
|
|
285
449
|
});
|
|
286
450
|
}
|
|
287
451
|
const linkScan = scanVaultLinks(vault.getPath());
|
|
@@ -290,14 +454,16 @@ async function doctor(vaultPath) {
|
|
|
290
454
|
label: "orphan links",
|
|
291
455
|
status: "warn",
|
|
292
456
|
detail: `${linkScan.orphans.length} orphan link(s)`,
|
|
293
|
-
hint: "Run `clawvault link --orphans` to review."
|
|
457
|
+
hint: "Run `clawvault link --orphans` to review.",
|
|
458
|
+
category: "health"
|
|
294
459
|
});
|
|
295
460
|
warnings++;
|
|
296
461
|
} else {
|
|
297
462
|
checks.push({
|
|
298
463
|
label: "orphan links",
|
|
299
464
|
status: "ok",
|
|
300
|
-
detail: `${linkScan.orphans.length} orphan link(s)
|
|
465
|
+
detail: `${linkScan.orphans.length} orphan link(s)`,
|
|
466
|
+
category: "health"
|
|
301
467
|
});
|
|
302
468
|
}
|
|
303
469
|
if (inbox.length > 5) {
|
|
@@ -305,14 +471,16 @@ async function doctor(vaultPath) {
|
|
|
305
471
|
label: "inbox backlog",
|
|
306
472
|
status: "warn",
|
|
307
473
|
detail: `${inbox.length} inbox item(s) pending`,
|
|
308
|
-
hint: "Process inbox items to keep memory tidy."
|
|
474
|
+
hint: "Process inbox items to keep memory tidy.",
|
|
475
|
+
category: "health"
|
|
309
476
|
});
|
|
310
477
|
warnings++;
|
|
311
478
|
} else {
|
|
312
479
|
checks.push({
|
|
313
480
|
label: "inbox backlog",
|
|
314
481
|
status: "ok",
|
|
315
|
-
detail: `${inbox.length} inbox item(s) pending
|
|
482
|
+
detail: `${inbox.length} inbox item(s) pending`,
|
|
483
|
+
category: "health"
|
|
316
484
|
});
|
|
317
485
|
}
|
|
318
486
|
if (stats.documents < 5) {
|
|
@@ -320,11 +488,12 @@ async function doctor(vaultPath) {
|
|
|
320
488
|
label: "vault activity",
|
|
321
489
|
status: "warn",
|
|
322
490
|
detail: `${stats.documents} total documents`,
|
|
323
|
-
hint: "Start capturing decisions, lessons, and projects."
|
|
491
|
+
hint: "Start capturing decisions, lessons, and projects.",
|
|
492
|
+
category: "health"
|
|
324
493
|
});
|
|
325
494
|
warnings++;
|
|
326
495
|
}
|
|
327
|
-
return { vaultPath: vault.getPath(), checks, warnings, errors };
|
|
496
|
+
return { vaultPath: vault.getPath(), checks, warnings, errors, migrationIssues };
|
|
328
497
|
}
|
|
329
498
|
|
|
330
499
|
export {
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__export
|
|
3
|
+
} from "./chunk-2ZDO52B4.js";
|
|
4
|
+
|
|
5
|
+
// src/workgraph/registry.ts
|
|
6
|
+
var registry_exports = {};
|
|
7
|
+
__export(registry_exports, {
|
|
8
|
+
defineType: () => defineType,
|
|
9
|
+
extendType: () => extendType,
|
|
10
|
+
getType: () => getType,
|
|
11
|
+
listTypes: () => listTypes,
|
|
12
|
+
loadRegistry: () => loadRegistry,
|
|
13
|
+
registryPath: () => registryPath,
|
|
14
|
+
saveRegistry: () => saveRegistry
|
|
15
|
+
});
|
|
16
|
+
import fs from "fs";
|
|
17
|
+
import path from "path";
|
|
18
|
+
var REGISTRY_FILE = ".clawvault/registry.json";
|
|
19
|
+
var CURRENT_VERSION = 1;
|
|
20
|
+
var BUILT_IN_TYPES = [
|
|
21
|
+
{
|
|
22
|
+
name: "thread",
|
|
23
|
+
description: "A unit of coordinated work. The core workgraph node.",
|
|
24
|
+
directory: "threads",
|
|
25
|
+
builtIn: true,
|
|
26
|
+
createdAt: "2026-01-01T00:00:00.000Z",
|
|
27
|
+
createdBy: "system",
|
|
28
|
+
fields: {
|
|
29
|
+
title: { type: "string", required: true, description: "What this thread is about" },
|
|
30
|
+
goal: { type: "string", required: true, description: "What success looks like" },
|
|
31
|
+
status: { type: "string", required: true, default: "open", description: "open | active | blocked | done | cancelled" },
|
|
32
|
+
owner: { type: "string", description: "Agent that claimed this thread" },
|
|
33
|
+
priority: { type: "string", default: "medium", description: "urgent | high | medium | low" },
|
|
34
|
+
deps: { type: "list", default: [], description: "Wiki-link refs to threads this depends on" },
|
|
35
|
+
parent: { type: "ref", description: "Parent thread (if decomposed from a larger thread)" },
|
|
36
|
+
context_refs: { type: "list", default: [], description: "Wiki-link refs to vault docs that inform this work" },
|
|
37
|
+
tags: { type: "list", default: [], description: "Freeform tags" },
|
|
38
|
+
created: { type: "date", required: true },
|
|
39
|
+
updated: { type: "date", required: true }
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "space",
|
|
44
|
+
description: "A workspace boundary that groups related threads and sets context.",
|
|
45
|
+
directory: "spaces",
|
|
46
|
+
builtIn: true,
|
|
47
|
+
createdAt: "2026-01-01T00:00:00.000Z",
|
|
48
|
+
createdBy: "system",
|
|
49
|
+
fields: {
|
|
50
|
+
title: { type: "string", required: true, description: "Space name" },
|
|
51
|
+
description: { type: "string", description: "What this space is for" },
|
|
52
|
+
members: { type: "list", default: [], description: "Agent names that participate" },
|
|
53
|
+
thread_refs: { type: "list", default: [], description: "Wiki-link refs to threads in this space" },
|
|
54
|
+
tags: { type: "list", default: [], description: "Freeform tags" },
|
|
55
|
+
created: { type: "date", required: true },
|
|
56
|
+
updated: { type: "date", required: true }
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "decision",
|
|
61
|
+
description: "A recorded decision with reasoning and context.",
|
|
62
|
+
directory: "decisions",
|
|
63
|
+
builtIn: true,
|
|
64
|
+
createdAt: "2026-01-01T00:00:00.000Z",
|
|
65
|
+
createdBy: "system",
|
|
66
|
+
fields: {
|
|
67
|
+
title: { type: "string", required: true },
|
|
68
|
+
date: { type: "date", required: true },
|
|
69
|
+
status: { type: "string", default: "active", description: "active | superseded | reverted" },
|
|
70
|
+
context_refs: { type: "list", default: [], description: "What informed this decision" },
|
|
71
|
+
tags: { type: "list", default: [] }
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "lesson",
|
|
76
|
+
description: "A captured insight or pattern learned from experience.",
|
|
77
|
+
directory: "lessons",
|
|
78
|
+
builtIn: true,
|
|
79
|
+
createdAt: "2026-01-01T00:00:00.000Z",
|
|
80
|
+
createdBy: "system",
|
|
81
|
+
fields: {
|
|
82
|
+
title: { type: "string", required: true },
|
|
83
|
+
date: { type: "date", required: true },
|
|
84
|
+
confidence: { type: "string", default: "medium", description: "high | medium | low" },
|
|
85
|
+
context_refs: { type: "list", default: [] },
|
|
86
|
+
tags: { type: "list", default: [] }
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: "fact",
|
|
91
|
+
description: "A structured piece of knowledge with optional temporal validity.",
|
|
92
|
+
directory: "facts",
|
|
93
|
+
builtIn: true,
|
|
94
|
+
createdAt: "2026-01-01T00:00:00.000Z",
|
|
95
|
+
createdBy: "system",
|
|
96
|
+
fields: {
|
|
97
|
+
subject: { type: "string", required: true },
|
|
98
|
+
predicate: { type: "string", required: true },
|
|
99
|
+
object: { type: "string", required: true },
|
|
100
|
+
confidence: { type: "number", default: 1 },
|
|
101
|
+
valid_from: { type: "date" },
|
|
102
|
+
valid_until: { type: "date" },
|
|
103
|
+
source: { type: "ref", description: "Where this fact came from" }
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "agent",
|
|
108
|
+
description: "A registered participant in the workgraph.",
|
|
109
|
+
directory: "agents",
|
|
110
|
+
builtIn: true,
|
|
111
|
+
createdAt: "2026-01-01T00:00:00.000Z",
|
|
112
|
+
createdBy: "system",
|
|
113
|
+
fields: {
|
|
114
|
+
name: { type: "string", required: true },
|
|
115
|
+
role: { type: "string", description: "What this agent specializes in" },
|
|
116
|
+
capabilities: { type: "list", default: [], description: "What this agent can do" },
|
|
117
|
+
active_threads: { type: "list", default: [], description: "Threads currently claimed" },
|
|
118
|
+
last_seen: { type: "date" }
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
];
|
|
122
|
+
function registryPath(vaultPath) {
|
|
123
|
+
return path.join(vaultPath, REGISTRY_FILE);
|
|
124
|
+
}
|
|
125
|
+
function loadRegistry(vaultPath) {
|
|
126
|
+
const rPath = registryPath(vaultPath);
|
|
127
|
+
if (fs.existsSync(rPath)) {
|
|
128
|
+
const raw = fs.readFileSync(rPath, "utf-8");
|
|
129
|
+
const registry = JSON.parse(raw);
|
|
130
|
+
return ensureBuiltIns(registry);
|
|
131
|
+
}
|
|
132
|
+
return seedRegistry();
|
|
133
|
+
}
|
|
134
|
+
function saveRegistry(vaultPath, registry) {
|
|
135
|
+
const rPath = registryPath(vaultPath);
|
|
136
|
+
const dir = path.dirname(rPath);
|
|
137
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
138
|
+
fs.writeFileSync(rPath, JSON.stringify(registry, null, 2) + "\n", "utf-8");
|
|
139
|
+
}
|
|
140
|
+
function defineType(vaultPath, name, description, fields, actor, directory) {
|
|
141
|
+
const registry = loadRegistry(vaultPath);
|
|
142
|
+
const safeName = name.toLowerCase().replace(/[^a-z0-9_-]/g, "-");
|
|
143
|
+
if (registry.types[safeName]?.builtIn) {
|
|
144
|
+
throw new Error(`Cannot redefine built-in type "${safeName}". You can extend it with new fields instead.`);
|
|
145
|
+
}
|
|
146
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
147
|
+
const typeDef = {
|
|
148
|
+
name: safeName,
|
|
149
|
+
description,
|
|
150
|
+
fields: {
|
|
151
|
+
title: { type: "string", required: true },
|
|
152
|
+
created: { type: "date", required: true },
|
|
153
|
+
updated: { type: "date", required: true },
|
|
154
|
+
tags: { type: "list", default: [] },
|
|
155
|
+
...fields
|
|
156
|
+
},
|
|
157
|
+
directory: directory ?? `${safeName}s`,
|
|
158
|
+
builtIn: false,
|
|
159
|
+
createdAt: now,
|
|
160
|
+
createdBy: actor
|
|
161
|
+
};
|
|
162
|
+
registry.types[safeName] = typeDef;
|
|
163
|
+
saveRegistry(vaultPath, registry);
|
|
164
|
+
return typeDef;
|
|
165
|
+
}
|
|
166
|
+
function getType(vaultPath, name) {
|
|
167
|
+
const registry = loadRegistry(vaultPath);
|
|
168
|
+
return registry.types[name];
|
|
169
|
+
}
|
|
170
|
+
function listTypes(vaultPath) {
|
|
171
|
+
const registry = loadRegistry(vaultPath);
|
|
172
|
+
return Object.values(registry.types);
|
|
173
|
+
}
|
|
174
|
+
function extendType(vaultPath, name, newFields, actor) {
|
|
175
|
+
const registry = loadRegistry(vaultPath);
|
|
176
|
+
const existing = registry.types[name];
|
|
177
|
+
if (!existing) throw new Error(`Type "${name}" not found in registry.`);
|
|
178
|
+
existing.fields = { ...existing.fields, ...newFields };
|
|
179
|
+
saveRegistry(vaultPath, registry);
|
|
180
|
+
return existing;
|
|
181
|
+
}
|
|
182
|
+
function seedRegistry() {
|
|
183
|
+
const types = {};
|
|
184
|
+
for (const t of BUILT_IN_TYPES) {
|
|
185
|
+
types[t.name] = t;
|
|
186
|
+
}
|
|
187
|
+
return { version: CURRENT_VERSION, types };
|
|
188
|
+
}
|
|
189
|
+
function ensureBuiltIns(registry) {
|
|
190
|
+
for (const t of BUILT_IN_TYPES) {
|
|
191
|
+
if (!registry.types[t.name]) {
|
|
192
|
+
registry.types[t.name] = t;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return registry;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export {
|
|
199
|
+
registryPath,
|
|
200
|
+
loadRegistry,
|
|
201
|
+
saveRegistry,
|
|
202
|
+
defineType,
|
|
203
|
+
getType,
|
|
204
|
+
listTypes,
|
|
205
|
+
extendType,
|
|
206
|
+
registry_exports
|
|
207
|
+
};
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
registerTailscaleCommands
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-Y6VJKXGL.js";
|
|
4
4
|
import {
|
|
5
5
|
registerObserveCommand
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-P7SY3D4E.js";
|
|
7
7
|
import {
|
|
8
8
|
registerReflectCommand
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-S5OJEGFG.js";
|
|
10
10
|
import {
|
|
11
11
|
registerContextCommand
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-LIGHWOH6.js";
|
|
13
13
|
import {
|
|
14
14
|
registerEmbedCommand
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-ECRZL5XR.js";
|
|
16
16
|
import {
|
|
17
17
|
registerInjectCommand
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-YNIPYN4F.js";
|
|
19
19
|
|
|
20
20
|
// src/cli/index.ts
|
|
21
21
|
function registerCliCommands(program) {
|