skillwiki 0.10.100 → 0.10.103
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/dist/{chunk-3QT3OFAL.js → chunk-2BPOEEMW.js} +321 -192
- package/dist/{chunk-B4QTKCEK.js → chunk-PVIOU7BN.js} +7 -2
- package/dist/cli.js +579 -289
- package/dist/{managed-write-preflight-32523BPV.js → managed-write-preflight-ATDFVLJV.js} +1 -1
- package/dist/skillwiki-mcp.js +2 -2
- package/package.json +1 -1
- package/skills/.claude-plugin/plugin.json +2 -2
- package/skills/.codex-plugin/plugin.json +3 -3
- package/skills/.cursor-plugin/plugin.json +2 -2
- package/skills/README.md +2 -2
- package/skills/package.json +2 -2
- package/skills/skills/skillwiki-connect/SKILL.md +75 -0
- package/skills/skills/skillwiki-mcp/SKILL.md +4 -4
- package/skills/skills/using-skillwiki/SKILL.md +5 -3
- package/skills/skills/using-skillwiki/activation.md +1 -0
- package/skills/skillwiki-connect/SKILL.md +75 -0
- package/skills/skillwiki-mcp/SKILL.md +4 -4
- package/skills/using-skillwiki/SKILL.md +5 -3
- package/skills/using-skillwiki/activation.md +1 -0
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
snapshotterAliasForLocalHost,
|
|
41
41
|
toUndirectedWeighted,
|
|
42
42
|
writeDotenv
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-PVIOU7BN.js";
|
|
44
44
|
import {
|
|
45
45
|
atomicWriteText,
|
|
46
46
|
prepareTypedPage
|
|
@@ -1018,6 +1018,10 @@ import { join as join5 } from "path";
|
|
|
1018
1018
|
function validateKey(key) {
|
|
1019
1019
|
return CONFIG_KEYS.includes(key) || isValidWikiProfileKey(key) || isVaultSyncKey(key);
|
|
1020
1020
|
}
|
|
1021
|
+
function displayConfigValue(key, value) {
|
|
1022
|
+
if (key === "SKILLWIKI_MCP_TOKEN") return value.length > 0 ? "TOKEN_SET" : "";
|
|
1023
|
+
return value;
|
|
1024
|
+
}
|
|
1021
1025
|
function configPath(home) {
|
|
1022
1026
|
return join5(home, ".skillwiki", ".env");
|
|
1023
1027
|
}
|
|
@@ -1056,7 +1060,10 @@ async function runConfigSet(input) {
|
|
|
1056
1060
|
}
|
|
1057
1061
|
async function runConfigList(input) {
|
|
1058
1062
|
const map = await parseDotenvFile(configPath(input.home));
|
|
1059
|
-
const entries = Object.entries(map).map(([key, value]) => ({
|
|
1063
|
+
const entries = Object.entries(map).map(([key, value]) => ({
|
|
1064
|
+
key,
|
|
1065
|
+
value: displayConfigValue(key, value ?? "")
|
|
1066
|
+
}));
|
|
1060
1067
|
let profiles;
|
|
1061
1068
|
if (input.profiles) {
|
|
1062
1069
|
const defaultProfile = map["WIKI_DEFAULT"];
|
|
@@ -1078,23 +1085,66 @@ async function runConfigPath(input) {
|
|
|
1078
1085
|
return { exitCode: ExitCode.OK, result: ok({ path: filePath, exists: existsSync2(filePath), humanHint: filePath }) };
|
|
1079
1086
|
}
|
|
1080
1087
|
|
|
1088
|
+
// src/utils/mcp-auth-env.ts
|
|
1089
|
+
import { join as join6 } from "path";
|
|
1090
|
+
var MCP_URL_ENV = "SKILLWIKI_MCP_URL";
|
|
1091
|
+
var MCP_TOKEN_ENV = "SKILLWIKI_MCP_TOKEN";
|
|
1092
|
+
var MCP_HOST_ID_ENV = "SKILLWIKI_HOST_ID";
|
|
1093
|
+
function nonEmptyEnvValue(value) {
|
|
1094
|
+
if (typeof value !== "string") return void 0;
|
|
1095
|
+
const trimmed = value.trim();
|
|
1096
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
1097
|
+
}
|
|
1098
|
+
function mcpAuthFromEnv(env) {
|
|
1099
|
+
return {
|
|
1100
|
+
url: nonEmptyEnvValue(env[MCP_URL_ENV]),
|
|
1101
|
+
token: nonEmptyEnvValue(env[MCP_TOKEN_ENV]),
|
|
1102
|
+
hostId: nonEmptyEnvValue(env[MCP_HOST_ID_ENV])
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1105
|
+
async function resolveMcpAuthEnv(input) {
|
|
1106
|
+
const processAuth = mcpAuthFromEnv(input.env ?? process.env);
|
|
1107
|
+
const dotenv = await parseDotenvFile(join6(input.home, ".skillwiki", ".env"));
|
|
1108
|
+
const fileAuth = mcpAuthFromEnv(dotenv);
|
|
1109
|
+
return {
|
|
1110
|
+
url: processAuth.url ?? fileAuth.url,
|
|
1111
|
+
token: processAuth.token ?? fileAuth.token,
|
|
1112
|
+
hostId: processAuth.hostId ?? fileAuth.hostId
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
async function mergeMcpAuthIntoEnv(home, env) {
|
|
1116
|
+
const auth = await resolveMcpAuthEnv({ home, env });
|
|
1117
|
+
const merged = { ...env };
|
|
1118
|
+
if (auth.url && !nonEmptyEnvValue(env[MCP_URL_ENV])) merged[MCP_URL_ENV] = auth.url;
|
|
1119
|
+
if (auth.token && !nonEmptyEnvValue(env[MCP_TOKEN_ENV])) merged[MCP_TOKEN_ENV] = auth.token;
|
|
1120
|
+
if (auth.hostId && !nonEmptyEnvValue(env[MCP_HOST_ID_ENV])) merged[MCP_HOST_ID_ENV] = auth.hostId;
|
|
1121
|
+
return merged;
|
|
1122
|
+
}
|
|
1123
|
+
function redactMcpSecret(text, secret) {
|
|
1124
|
+
if (!secret || secret.length === 0 || !text.includes(secret)) return text;
|
|
1125
|
+
return text.split(secret).join("[REDACTED]");
|
|
1126
|
+
}
|
|
1127
|
+
function isMcpOnlyLeaf(input) {
|
|
1128
|
+
return !input.resolvedPath && Boolean(input.token) && !input.vaultSyncInstalled;
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1081
1131
|
// src/doctor/runner.ts
|
|
1082
1132
|
import { existsSync as existsSync18 } from "fs";
|
|
1083
1133
|
|
|
1084
1134
|
// src/doctor/probes/environment.ts
|
|
1085
1135
|
import { existsSync as existsSync4, lstatSync, readlinkSync } from "fs";
|
|
1086
|
-
import { resolve as resolve2, join as
|
|
1136
|
+
import { resolve as resolve2, join as join8 } from "path";
|
|
1087
1137
|
import { execSync } from "child_process";
|
|
1088
1138
|
|
|
1089
1139
|
// src/utils/plugin-registry.ts
|
|
1090
1140
|
import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync2 } from "fs";
|
|
1091
|
-
import { join as
|
|
1092
|
-
var REGISTRY_PATH =
|
|
1093
|
-
var CODEX_CONFIG_PATH =
|
|
1141
|
+
import { join as join7 } from "path";
|
|
1142
|
+
var REGISTRY_PATH = join7(".claude", "plugins", "installed_plugins.json");
|
|
1143
|
+
var CODEX_CONFIG_PATH = join7(".codex", "config.toml");
|
|
1094
1144
|
var PLUGIN_KEY = "skillwiki@llm-wiki";
|
|
1095
1145
|
function readInstalledPlugins(home) {
|
|
1096
1146
|
try {
|
|
1097
|
-
const raw = readFileSync2(
|
|
1147
|
+
const raw = readFileSync2(join7(home, REGISTRY_PATH), "utf8");
|
|
1098
1148
|
return JSON.parse(raw);
|
|
1099
1149
|
} catch {
|
|
1100
1150
|
return null;
|
|
@@ -1130,7 +1180,7 @@ function findPluginInstallations(home, key = PLUGIN_KEY) {
|
|
|
1130
1180
|
return installs;
|
|
1131
1181
|
}
|
|
1132
1182
|
function findGrokPlugin(home, key, pluginName, marketplace) {
|
|
1133
|
-
const pluginsRoot =
|
|
1183
|
+
const pluginsRoot = join7(home, ".grok", "installed-plugins");
|
|
1134
1184
|
if (!existsSync3(pluginsRoot)) return null;
|
|
1135
1185
|
let entries;
|
|
1136
1186
|
try {
|
|
@@ -1141,10 +1191,10 @@ function findGrokPlugin(home, key, pluginName, marketplace) {
|
|
|
1141
1191
|
let best = null;
|
|
1142
1192
|
for (const entry of entries) {
|
|
1143
1193
|
if (!entry.isDirectory()) continue;
|
|
1144
|
-
const installPath =
|
|
1194
|
+
const installPath = join7(pluginsRoot, entry.name);
|
|
1145
1195
|
let manifest;
|
|
1146
1196
|
try {
|
|
1147
|
-
manifest = JSON.parse(readFileSync2(
|
|
1197
|
+
manifest = JSON.parse(readFileSync2(join7(installPath, ".claude-plugin", "plugin.json"), "utf8"));
|
|
1148
1198
|
} catch {
|
|
1149
1199
|
continue;
|
|
1150
1200
|
}
|
|
@@ -1168,7 +1218,7 @@ function findGrokPlugin(home, key, pluginName, marketplace) {
|
|
|
1168
1218
|
function findCodexPlugin(home, key, pluginName, marketplace) {
|
|
1169
1219
|
const config = readCodexPluginConfig(home, key, marketplace);
|
|
1170
1220
|
if (!config?.enabled) return null;
|
|
1171
|
-
const cacheRoot =
|
|
1221
|
+
const cacheRoot = join7(home, ".codex", "plugins", "cache", marketplace, pluginName);
|
|
1172
1222
|
if (!existsSync3(cacheRoot)) return null;
|
|
1173
1223
|
let versions;
|
|
1174
1224
|
try {
|
|
@@ -1184,7 +1234,7 @@ function findCodexPlugin(home, key, pluginName, marketplace) {
|
|
|
1184
1234
|
key,
|
|
1185
1235
|
pluginName,
|
|
1186
1236
|
marketplace,
|
|
1187
|
-
installPath:
|
|
1237
|
+
installPath: join7(cacheRoot, version),
|
|
1188
1238
|
version,
|
|
1189
1239
|
sourceType: config.sourceType,
|
|
1190
1240
|
source: config.source
|
|
@@ -1201,7 +1251,7 @@ function parsePluginKey(key) {
|
|
|
1201
1251
|
function readCodexPluginConfig(home, key, marketplace) {
|
|
1202
1252
|
let raw;
|
|
1203
1253
|
try {
|
|
1204
|
-
raw = readFileSync2(
|
|
1254
|
+
raw = readFileSync2(join7(home, CODEX_CONFIG_PATH), "utf8");
|
|
1205
1255
|
} catch {
|
|
1206
1256
|
return null;
|
|
1207
1257
|
}
|
|
@@ -1243,9 +1293,14 @@ function parseTomlScalar(rawValue) {
|
|
|
1243
1293
|
}
|
|
1244
1294
|
|
|
1245
1295
|
// src/doctor/probes/helpers.ts
|
|
1296
|
+
var MCP_ONLY_LEAF_SKIP = "MCP-only leaf \u2014 check skipped";
|
|
1246
1297
|
function check(status, id, label, detail) {
|
|
1247
1298
|
return { id, label, status, detail };
|
|
1248
1299
|
}
|
|
1300
|
+
function mcpOnlyOr(mcpOnlyLeaf, id, label, fallback) {
|
|
1301
|
+
if (mcpOnlyLeaf) return check("info", id, label, MCP_ONLY_LEAF_SKIP);
|
|
1302
|
+
return fallback;
|
|
1303
|
+
}
|
|
1249
1304
|
|
|
1250
1305
|
// src/doctor/probes/environment.ts
|
|
1251
1306
|
function checkNodeVersion() {
|
|
@@ -1273,12 +1328,12 @@ function detectCliChannels(argv, home) {
|
|
|
1273
1328
|
}
|
|
1274
1329
|
const plugin = findPlugin(home);
|
|
1275
1330
|
if (plugin) {
|
|
1276
|
-
const pluginBin =
|
|
1331
|
+
const pluginBin = join8(plugin.installPath, "bin", "skillwiki");
|
|
1277
1332
|
if (existsSync4(pluginBin)) {
|
|
1278
1333
|
channels.push({ name: "plugin", path: pluginBin, isDevLink: false });
|
|
1279
1334
|
}
|
|
1280
1335
|
}
|
|
1281
|
-
const installBin =
|
|
1336
|
+
const installBin = join8(home, ".claude", "skills", "bin", "skillwiki");
|
|
1282
1337
|
if (existsSync4(installBin)) {
|
|
1283
1338
|
channels.push({ name: "install", path: installBin, isDevLink: false });
|
|
1284
1339
|
}
|
|
@@ -1370,7 +1425,7 @@ async function checkProfiles(home) {
|
|
|
1370
1425
|
}
|
|
1371
1426
|
async function checkProjectLocalOverride(cwd) {
|
|
1372
1427
|
const dir = cwd ?? process.cwd();
|
|
1373
|
-
const envPath =
|
|
1428
|
+
const envPath = join8(dir, ".skillwiki", ".env");
|
|
1374
1429
|
if (existsSync4(envPath)) {
|
|
1375
1430
|
return check("pass", "project_local", "Project-local config", `Found: ${envPath}`);
|
|
1376
1431
|
}
|
|
@@ -1380,6 +1435,14 @@ function checkWikiPathSet(ctx) {
|
|
|
1380
1435
|
if (ctx.resolvedPath) {
|
|
1381
1436
|
return check("pass", "wiki_path_set", "WIKI_PATH configured", `Resolved via ${ctx.wikiPathSource ?? "unknown"}: ${ctx.resolvedPath}`);
|
|
1382
1437
|
}
|
|
1438
|
+
if (ctx.mcpOnlyLeaf) {
|
|
1439
|
+
return check(
|
|
1440
|
+
"info",
|
|
1441
|
+
"wiki_path_set",
|
|
1442
|
+
"WIKI_PATH configured",
|
|
1443
|
+
"MCP-only leaf \u2014 no local vault; HTTP MCP handshake is the success gate"
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1383
1446
|
return check("error", "wiki_path_set", "WIKI_PATH configured", "No vault configured. Run `skillwiki init` or pass --vault.");
|
|
1384
1447
|
}
|
|
1385
1448
|
var environmentProbe = {
|
|
@@ -1398,41 +1461,56 @@ var environmentProbe = {
|
|
|
1398
1461
|
|
|
1399
1462
|
// src/doctor/probes/vault-structure.ts
|
|
1400
1463
|
import { existsSync as existsSync5, statSync as statSync2 } from "fs";
|
|
1401
|
-
import { join as
|
|
1402
|
-
function checkWikiPathExists(resolvedPath) {
|
|
1464
|
+
import { join as join9 } from "path";
|
|
1465
|
+
function checkWikiPathExists(resolvedPath, mcpOnlyLeaf) {
|
|
1403
1466
|
if (resolvedPath === void 0) {
|
|
1404
|
-
return
|
|
1467
|
+
return mcpOnlyOr(
|
|
1468
|
+
mcpOnlyLeaf,
|
|
1469
|
+
"wiki_path_exists",
|
|
1470
|
+
"Vault directory exists",
|
|
1471
|
+
check("error", "wiki_path_exists", "Vault directory exists", "Cannot check \u2014 WIKI_PATH not resolved")
|
|
1472
|
+
);
|
|
1405
1473
|
}
|
|
1406
1474
|
if (existsSync5(resolvedPath) && statSync2(resolvedPath).isDirectory()) {
|
|
1407
1475
|
return check("pass", "wiki_path_exists", "Vault directory exists", resolvedPath);
|
|
1408
1476
|
}
|
|
1409
1477
|
return check("error", "wiki_path_exists", "Vault directory exists", `${resolvedPath} does not exist or is not a directory`);
|
|
1410
1478
|
}
|
|
1411
|
-
function checkVaultStructure(resolvedPath) {
|
|
1479
|
+
function checkVaultStructure(resolvedPath, mcpOnlyLeaf) {
|
|
1412
1480
|
if (resolvedPath === void 0) {
|
|
1413
|
-
return
|
|
1481
|
+
return mcpOnlyOr(
|
|
1482
|
+
mcpOnlyLeaf,
|
|
1483
|
+
"vault_structure",
|
|
1484
|
+
"Vault structure valid",
|
|
1485
|
+
check("error", "vault_structure", "Vault structure valid", "Cannot check \u2014 WIKI_PATH not resolved")
|
|
1486
|
+
);
|
|
1414
1487
|
}
|
|
1415
1488
|
if (!existsSync5(resolvedPath)) {
|
|
1416
1489
|
return check("error", "vault_structure", "Vault structure valid", "Cannot check \u2014 vault directory does not exist");
|
|
1417
1490
|
}
|
|
1418
1491
|
const missing = [];
|
|
1419
|
-
if (!existsSync5(
|
|
1492
|
+
if (!existsSync5(join9(resolvedPath, "SCHEMA.md"))) missing.push("SCHEMA.md");
|
|
1420
1493
|
for (const dir of ["raw", "entities", "concepts", "meta"]) {
|
|
1421
|
-
if (!existsSync5(
|
|
1494
|
+
if (!existsSync5(join9(resolvedPath, dir))) missing.push(dir + "/");
|
|
1422
1495
|
}
|
|
1423
1496
|
if (missing.length === 0) {
|
|
1424
1497
|
return check("pass", "vault_structure", "Vault structure valid", "All required files and directories present");
|
|
1425
1498
|
}
|
|
1426
1499
|
return check("warn", "vault_structure", "Vault structure valid", `Missing: ${missing.join(", ")} \u2014 run \`skillwiki init\` to add CodeWiki structure`);
|
|
1427
1500
|
}
|
|
1428
|
-
function checkObsidianTemplates(resolvedPath) {
|
|
1501
|
+
function checkObsidianTemplates(resolvedPath, mcpOnlyLeaf) {
|
|
1429
1502
|
if (resolvedPath === void 0) {
|
|
1430
|
-
return
|
|
1503
|
+
return mcpOnlyOr(
|
|
1504
|
+
mcpOnlyLeaf,
|
|
1505
|
+
"obsidian_templates",
|
|
1506
|
+
"Obsidian templates",
|
|
1507
|
+
check("error", "obsidian_templates", "Obsidian templates", "Cannot check \u2014 WIKI_PATH not resolved")
|
|
1508
|
+
);
|
|
1431
1509
|
}
|
|
1432
1510
|
const missing = [];
|
|
1433
|
-
if (!existsSync5(
|
|
1434
|
-
if (!existsSync5(
|
|
1435
|
-
if (!existsSync5(
|
|
1511
|
+
if (!existsSync5(join9(resolvedPath, "_Templates"))) missing.push("_Templates/");
|
|
1512
|
+
if (!existsSync5(join9(resolvedPath, ".obsidian", "templates.json"))) missing.push(".obsidian/templates.json");
|
|
1513
|
+
if (!existsSync5(join9(resolvedPath, ".obsidian", "app.json"))) missing.push(".obsidian/app.json");
|
|
1436
1514
|
if (missing.length === 0) {
|
|
1437
1515
|
return check("pass", "obsidian_templates", "Obsidian templates", "Template folder and config present");
|
|
1438
1516
|
}
|
|
@@ -1442,23 +1520,28 @@ var vaultStructureProbe = {
|
|
|
1442
1520
|
id: "vault_structure",
|
|
1443
1521
|
run(ctx) {
|
|
1444
1522
|
return [
|
|
1445
|
-
checkWikiPathExists(ctx.resolvedPath),
|
|
1446
|
-
checkVaultStructure(ctx.resolvedPath),
|
|
1447
|
-
checkObsidianTemplates(ctx.resolvedPath)
|
|
1523
|
+
checkWikiPathExists(ctx.resolvedPath, ctx.mcpOnlyLeaf),
|
|
1524
|
+
checkVaultStructure(ctx.resolvedPath, ctx.mcpOnlyLeaf),
|
|
1525
|
+
checkObsidianTemplates(ctx.resolvedPath, ctx.mcpOnlyLeaf)
|
|
1448
1526
|
];
|
|
1449
1527
|
}
|
|
1450
1528
|
};
|
|
1451
1529
|
|
|
1452
1530
|
// src/doctor/probes/git-fleet.ts
|
|
1453
1531
|
import { existsSync as existsSync6, readFileSync as readFileSync3 } from "fs";
|
|
1454
|
-
import { join as
|
|
1532
|
+
import { join as join10 } from "path";
|
|
1455
1533
|
import { execSync as execSync2 } from "child_process";
|
|
1456
1534
|
import { platform } from "os";
|
|
1457
|
-
function checkVaultGitRemote(resolvedPath) {
|
|
1535
|
+
function checkVaultGitRemote(resolvedPath, mcpOnlyLeaf = false) {
|
|
1458
1536
|
if (resolvedPath === void 0) {
|
|
1459
|
-
return
|
|
1537
|
+
return mcpOnlyOr(
|
|
1538
|
+
mcpOnlyLeaf,
|
|
1539
|
+
"vault_git_remote",
|
|
1540
|
+
"Vault git remote",
|
|
1541
|
+
check("error", "vault_git_remote", "Vault git remote", "Cannot check \u2014 WIKI_PATH not resolved")
|
|
1542
|
+
);
|
|
1460
1543
|
}
|
|
1461
|
-
if (!existsSync6(
|
|
1544
|
+
if (!existsSync6(join10(resolvedPath, ".git"))) {
|
|
1462
1545
|
return check("warn", "vault_git_remote", "Vault git remote", "Vault is not a git repository \u2014 sync features unavailable");
|
|
1463
1546
|
}
|
|
1464
1547
|
try {
|
|
@@ -1497,11 +1580,16 @@ async function checkFleetIdentity(input) {
|
|
|
1497
1580
|
const detail = load.warnings.length > 0 ? load.warnings.join("; ") : "Fleet identity is unresolved";
|
|
1498
1581
|
return check("warn", "fleet_identity", "Fleet identity", detail);
|
|
1499
1582
|
}
|
|
1500
|
-
function checkSyncLastPush(resolvedPath) {
|
|
1583
|
+
function checkSyncLastPush(resolvedPath, mcpOnlyLeaf = false) {
|
|
1501
1584
|
if (resolvedPath === void 0) {
|
|
1502
|
-
return
|
|
1585
|
+
return mcpOnlyOr(
|
|
1586
|
+
mcpOnlyLeaf,
|
|
1587
|
+
"sync_last_push",
|
|
1588
|
+
"Vault sync recency",
|
|
1589
|
+
check("error", "sync_last_push", "Vault sync recency", "Cannot check \u2014 WIKI_PATH not resolved")
|
|
1590
|
+
);
|
|
1503
1591
|
}
|
|
1504
|
-
if (!existsSync6(
|
|
1592
|
+
if (!existsSync6(join10(resolvedPath, ".git"))) {
|
|
1505
1593
|
return check("pass", "sync_last_push", "Vault sync recency", "No git repo \u2014 sync check skipped");
|
|
1506
1594
|
}
|
|
1507
1595
|
let timestamp;
|
|
@@ -1550,7 +1638,7 @@ function checkVaultGitDirty(resolvedPath) {
|
|
|
1550
1638
|
if (resolvedPath === void 0) {
|
|
1551
1639
|
return check("pass", "vault_git_dirty", "Vault git dirty state", "No vault path \u2014 check skipped");
|
|
1552
1640
|
}
|
|
1553
|
-
if (!existsSync6(
|
|
1641
|
+
if (!existsSync6(join10(resolvedPath, ".git"))) {
|
|
1554
1642
|
return check("pass", "vault_git_dirty", "Vault git dirty state", "No git repo \u2014 check skipped");
|
|
1555
1643
|
}
|
|
1556
1644
|
try {
|
|
@@ -1597,7 +1685,7 @@ function remoteMainHash(resolvedPath) {
|
|
|
1597
1685
|
}
|
|
1598
1686
|
function checkStaleRemoteMain(resolvedPath) {
|
|
1599
1687
|
if (resolvedPath === void 0) return void 0;
|
|
1600
|
-
if (!existsSync6(
|
|
1688
|
+
if (!existsSync6(join10(resolvedPath, ".git"))) return void 0;
|
|
1601
1689
|
const localOrigin = gitRefHash(resolvedPath, "origin/main");
|
|
1602
1690
|
if (!localOrigin) return void 0;
|
|
1603
1691
|
const remoteMain = remoteMainHash(resolvedPath);
|
|
@@ -1613,7 +1701,7 @@ function checkVaultGitComparison(resolvedPath, id, label, range, nonZeroSuffix,
|
|
|
1613
1701
|
if (resolvedPath === void 0) {
|
|
1614
1702
|
return check("pass", id, label, "No vault path \u2014 check skipped");
|
|
1615
1703
|
}
|
|
1616
|
-
if (!existsSync6(
|
|
1704
|
+
if (!existsSync6(join10(resolvedPath, ".git"))) {
|
|
1617
1705
|
return check("pass", id, label, "No git repo \u2014 check skipped");
|
|
1618
1706
|
}
|
|
1619
1707
|
if (!hasOriginMain(resolvedPath)) {
|
|
@@ -1658,11 +1746,11 @@ function checkVaultGitBehind(resolvedPath) {
|
|
|
1658
1746
|
}
|
|
1659
1747
|
function pullLogPaths(home) {
|
|
1660
1748
|
const paths = platform() === "darwin" ? [
|
|
1661
|
-
|
|
1662
|
-
|
|
1749
|
+
join10(home, "Library", "Logs", "wiki-pull.log"),
|
|
1750
|
+
join10(home, ".local", "state", "vault-sync", "log", "wiki-pull.log")
|
|
1663
1751
|
] : [
|
|
1664
|
-
|
|
1665
|
-
|
|
1752
|
+
join10(home, ".local", "state", "vault-sync", "log", "wiki-pull.log"),
|
|
1753
|
+
join10(home, "Library", "Logs", "wiki-pull.log")
|
|
1666
1754
|
];
|
|
1667
1755
|
return [...new Set(paths)];
|
|
1668
1756
|
}
|
|
@@ -1693,11 +1781,16 @@ function checkVaultGitPullFailures(home) {
|
|
|
1693
1781
|
return check("warn", "vault_git_pull_failures", "Vault pull failures", `Could not read ${path}`);
|
|
1694
1782
|
}
|
|
1695
1783
|
}
|
|
1696
|
-
function checkVaultLocalGit(resolvedPath) {
|
|
1784
|
+
function checkVaultLocalGit(resolvedPath, mcpOnlyLeaf = false) {
|
|
1697
1785
|
if (resolvedPath === void 0) {
|
|
1698
|
-
return
|
|
1786
|
+
return mcpOnlyOr(
|
|
1787
|
+
mcpOnlyLeaf,
|
|
1788
|
+
"vault_local_git",
|
|
1789
|
+
"Vault local git",
|
|
1790
|
+
check("warn", "vault_local_git", "Vault local git", "Cannot check \u2014 WIKI_PATH not resolved")
|
|
1791
|
+
);
|
|
1699
1792
|
}
|
|
1700
|
-
if (!existsSync6(
|
|
1793
|
+
if (!existsSync6(join10(resolvedPath, ".git"))) {
|
|
1701
1794
|
return check("warn", "vault_local_git", "Vault local git", "Not a git repository - sync features unavailable");
|
|
1702
1795
|
}
|
|
1703
1796
|
try {
|
|
@@ -1716,7 +1809,7 @@ function checkVaultGithubRemote(resolvedPath, exec) {
|
|
|
1716
1809
|
if (resolvedPath === void 0) {
|
|
1717
1810
|
return check("pass", "vault_github_remote", "Vault GitHub remote", "No vault path \u2014 check skipped");
|
|
1718
1811
|
}
|
|
1719
|
-
if (!existsSync6(
|
|
1812
|
+
if (!existsSync6(join10(resolvedPath, ".git"))) {
|
|
1720
1813
|
return check("pass", "vault_github_remote", "Vault GitHub remote", "No git repo \u2014 check skipped");
|
|
1721
1814
|
}
|
|
1722
1815
|
const state = probeGithubReachability(resolvedPath, exec);
|
|
@@ -1760,7 +1853,7 @@ function checkVaultPromotionLag(resolvedPath) {
|
|
|
1760
1853
|
if (resolvedPath === void 0) {
|
|
1761
1854
|
return check("pass", "vault_promotion_lag", "Vault promotion lag", "No vault path \u2014 check skipped");
|
|
1762
1855
|
}
|
|
1763
|
-
if (!existsSync6(
|
|
1856
|
+
if (!existsSync6(join10(resolvedPath, ".git"))) {
|
|
1764
1857
|
return check("pass", "vault_promotion_lag", "Vault promotion lag", "No git repo \u2014 check skipped");
|
|
1765
1858
|
}
|
|
1766
1859
|
try {
|
|
@@ -1787,7 +1880,7 @@ var gitFleetProbe = {
|
|
|
1787
1880
|
id: "git_fleet",
|
|
1788
1881
|
async run(ctx) {
|
|
1789
1882
|
return [
|
|
1790
|
-
checkVaultGitRemote(ctx.gitCheckPath),
|
|
1883
|
+
checkVaultGitRemote(ctx.gitCheckPath, ctx.mcpOnlyLeaf),
|
|
1791
1884
|
await checkFleetIdentity({
|
|
1792
1885
|
vaultPath: ctx.resolvedPath,
|
|
1793
1886
|
home: ctx.input.home,
|
|
@@ -1795,12 +1888,12 @@ var gitFleetProbe = {
|
|
|
1795
1888
|
envValue: ctx.input.envValue,
|
|
1796
1889
|
fleetLoad: ctx.fleetLoad
|
|
1797
1890
|
}),
|
|
1798
|
-
checkSyncLastPush(ctx.gitCheckPath),
|
|
1891
|
+
checkSyncLastPush(ctx.gitCheckPath, ctx.mcpOnlyLeaf),
|
|
1799
1892
|
checkVaultGitDirty(ctx.gitCheckPath),
|
|
1800
1893
|
checkVaultGitAhead(ctx.gitCheckPath),
|
|
1801
1894
|
checkVaultGitBehind(ctx.gitCheckPath),
|
|
1802
1895
|
checkVaultGitPullFailures(ctx.input.home),
|
|
1803
|
-
checkVaultLocalGit(ctx.gitCheckPath),
|
|
1896
|
+
checkVaultLocalGit(ctx.gitCheckPath, ctx.mcpOnlyLeaf),
|
|
1804
1897
|
checkVaultGithubRemote(ctx.gitCheckPath, ctx.input.execProbe),
|
|
1805
1898
|
checkVaultS3Remote(ctx.input.home, ctx.input.execProbe, ctx.input.env ?? process.env),
|
|
1806
1899
|
checkVaultSnapshotterReachable(ctx.fleetLoad, ctx.input.checkSnapshotter, ctx.input.execProbe),
|
|
@@ -1811,11 +1904,11 @@ var gitFleetProbe = {
|
|
|
1811
1904
|
|
|
1812
1905
|
// src/doctor/probes/hygiene.ts
|
|
1813
1906
|
import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync5 } from "fs";
|
|
1814
|
-
import { join as
|
|
1907
|
+
import { join as join12 } from "path";
|
|
1815
1908
|
|
|
1816
1909
|
// src/utils/conflict-markers.ts
|
|
1817
1910
|
import { existsSync as existsSync7, readdirSync as readdirSync2, readFileSync as readFileSync4 } from "fs";
|
|
1818
|
-
import { join as
|
|
1911
|
+
import { join as join11 } from "path";
|
|
1819
1912
|
function scanConflictMarkerBlocksInText(relPath, text) {
|
|
1820
1913
|
const findings = [];
|
|
1821
1914
|
const lines = text.split(/\r?\n/);
|
|
@@ -1866,7 +1959,7 @@ function walkMarkdownFiles(root, dir, rel, out) {
|
|
|
1866
1959
|
for (const entry of entries) {
|
|
1867
1960
|
if (entry.isDirectory()) {
|
|
1868
1961
|
if (PRUNE_DIRS.has(entry.name)) continue;
|
|
1869
|
-
walkMarkdownFiles(root,
|
|
1962
|
+
walkMarkdownFiles(root, join11(dir, entry.name), rel ? `${rel}/${entry.name}` : entry.name, out);
|
|
1870
1963
|
} else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
1871
1964
|
out.push(rel ? `${rel}/${entry.name}` : entry.name);
|
|
1872
1965
|
}
|
|
@@ -1880,7 +1973,7 @@ function scanVaultConflictMarkers(vaultRoot) {
|
|
|
1880
1973
|
for (const rel of relPaths) {
|
|
1881
1974
|
let text;
|
|
1882
1975
|
try {
|
|
1883
|
-
text = readFileSync4(
|
|
1976
|
+
text = readFileSync4(join11(vaultRoot, rel), "utf8");
|
|
1884
1977
|
} catch {
|
|
1885
1978
|
continue;
|
|
1886
1979
|
}
|
|
@@ -1890,11 +1983,16 @@ function scanVaultConflictMarkers(vaultRoot) {
|
|
|
1890
1983
|
}
|
|
1891
1984
|
|
|
1892
1985
|
// src/doctor/probes/hygiene.ts
|
|
1893
|
-
function checkDotStoreClean(resolvedPath) {
|
|
1986
|
+
function checkDotStoreClean(resolvedPath, mcpOnlyLeaf = false) {
|
|
1894
1987
|
if (resolvedPath === void 0) {
|
|
1895
|
-
return
|
|
1988
|
+
return mcpOnlyOr(
|
|
1989
|
+
mcpOnlyLeaf,
|
|
1990
|
+
"dsstore_clean",
|
|
1991
|
+
"No .DS_Store in raw/",
|
|
1992
|
+
check("error", "dsstore_clean", "No .DS_Store in raw/", "Cannot check \u2014 WIKI_PATH not resolved")
|
|
1993
|
+
);
|
|
1896
1994
|
}
|
|
1897
|
-
const rawDir =
|
|
1995
|
+
const rawDir = join12(resolvedPath, "raw");
|
|
1898
1996
|
if (!existsSync8(rawDir)) {
|
|
1899
1997
|
return check("pass", "dsstore_clean", "No .DS_Store in raw/", "raw/ directory not found \u2014 check skipped");
|
|
1900
1998
|
}
|
|
@@ -1910,7 +2008,7 @@ function checkDotStoreClean(resolvedPath) {
|
|
|
1910
2008
|
if (entry.name === ".DS_Store") {
|
|
1911
2009
|
found.push(rel ? `${rel}/.DS_Store` : ".DS_Store");
|
|
1912
2010
|
} else if (entry.isDirectory()) {
|
|
1913
|
-
walk(
|
|
2011
|
+
walk(join12(dir, entry.name), rel ? `${rel}/${entry.name}` : entry.name);
|
|
1914
2012
|
}
|
|
1915
2013
|
}
|
|
1916
2014
|
})(rawDir, "");
|
|
@@ -1939,7 +2037,7 @@ function checkVaultConflictMarkers(resolvedPath) {
|
|
|
1939
2037
|
}
|
|
1940
2038
|
function githubSyncedGitRoot(gitRoot) {
|
|
1941
2039
|
if (gitRoot === void 0) return { ok: false, reason: "No vault path \u2014 check skipped" };
|
|
1942
|
-
if (!existsSync8(
|
|
2040
|
+
if (!existsSync8(join12(gitRoot, ".git"))) return { ok: false, reason: "Not a git repository \u2014 check skipped" };
|
|
1943
2041
|
if (!git(gitRoot, ["remote"])) return { ok: false, reason: "No git remote \u2014 not GitHub-synced, check skipped" };
|
|
1944
2042
|
return { ok: true, gitRoot };
|
|
1945
2043
|
}
|
|
@@ -1949,7 +2047,7 @@ function checkVaultGitignoreHygiene(synced) {
|
|
|
1949
2047
|
}
|
|
1950
2048
|
let content = "";
|
|
1951
2049
|
try {
|
|
1952
|
-
content = readFileSync5(
|
|
2050
|
+
content = readFileSync5(join12(synced.gitRoot, ".gitignore"), "utf8");
|
|
1953
2051
|
} catch {
|
|
1954
2052
|
content = "";
|
|
1955
2053
|
}
|
|
@@ -1987,7 +2085,7 @@ var hygieneProbe = {
|
|
|
1987
2085
|
run(ctx) {
|
|
1988
2086
|
const synced = githubSyncedGitRoot(ctx.gitCheckPath);
|
|
1989
2087
|
return [
|
|
1990
|
-
checkDotStoreClean(ctx.readOnlyScanRoot),
|
|
2088
|
+
checkDotStoreClean(ctx.readOnlyScanRoot, ctx.mcpOnlyLeaf),
|
|
1991
2089
|
checkVaultConflictMarkers(ctx.readOnlyScanRoot),
|
|
1992
2090
|
checkVaultGitignoreHygiene(synced),
|
|
1993
2091
|
checkTrackedHygieneScratch(synced)
|
|
@@ -1997,14 +2095,14 @@ var hygieneProbe = {
|
|
|
1997
2095
|
|
|
1998
2096
|
// src/doctor/probes/s3-mount-health.ts
|
|
1999
2097
|
import { existsSync as existsSync10 } from "fs";
|
|
2000
|
-
import { join as
|
|
2098
|
+
import { join as join14 } from "path";
|
|
2001
2099
|
import { execSync as execSync4 } from "child_process";
|
|
2002
2100
|
|
|
2003
2101
|
// src/utils/s3-mount-health.ts
|
|
2004
2102
|
import { execSync as execSync3 } from "child_process";
|
|
2005
2103
|
import { platform as platform2 } from "os";
|
|
2006
2104
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2, readFileSync as readFile6 } from "fs";
|
|
2007
|
-
import { join as
|
|
2105
|
+
import { join as join13 } from "path";
|
|
2008
2106
|
var OS = platform2();
|
|
2009
2107
|
function findRcloneMountPid() {
|
|
2010
2108
|
try {
|
|
@@ -2162,7 +2260,7 @@ function detectFuseMount(vaultPath) {
|
|
|
2162
2260
|
return null;
|
|
2163
2261
|
}
|
|
2164
2262
|
function writeTest(dir) {
|
|
2165
|
-
const testFile =
|
|
2263
|
+
const testFile = join13(dir, `.doctor-write-test-${process.pid}.tmp`);
|
|
2166
2264
|
const payload = `skillwiki doctor write test \u2014 ${Date.now()} \u2014 ${Math.random().toString(36).slice(2)}`;
|
|
2167
2265
|
const start = Date.now();
|
|
2168
2266
|
try {
|
|
@@ -2243,7 +2341,7 @@ function checkS3MountPerf(resolvedPath) {
|
|
|
2243
2341
|
return check("pass", "s3_mount_perf", "S3 mount performance", "local disk");
|
|
2244
2342
|
}
|
|
2245
2343
|
const mountPoint = fuse.mountPoint;
|
|
2246
|
-
const conceptsDir =
|
|
2344
|
+
const conceptsDir = join14(resolvedPath, "concepts");
|
|
2247
2345
|
if (!existsSync10(conceptsDir)) {
|
|
2248
2346
|
return check("pass", "s3_mount_perf", "S3 mount performance", `S3 FUSE mount (${mountPoint}), no concepts/ to benchmark`);
|
|
2249
2347
|
}
|
|
@@ -2394,7 +2492,10 @@ function checkRcloneFlagAudit(resolvedPath) {
|
|
|
2394
2492
|
}
|
|
2395
2493
|
return check("pass", "rclone_flags", "rclone VFS flags", `PID ${pid}: all critical flags at safe values`);
|
|
2396
2494
|
}
|
|
2397
|
-
function checkRcloneVersion(resolvedPath, vaultSyncInstalled, pushEnabled = true) {
|
|
2495
|
+
function checkRcloneVersion(resolvedPath, vaultSyncInstalled, pushEnabled = true, mcpOnlyLeaf = false) {
|
|
2496
|
+
if (mcpOnlyLeaf) {
|
|
2497
|
+
return check("pass", "rclone_version", "rclone version", "MCP-only leaf \u2014 rclone not required");
|
|
2498
|
+
}
|
|
2398
2499
|
const fuse = resolvedPath ? detectFuseMount(resolvedPath) : null;
|
|
2399
2500
|
if (pushEnabled === false && !fuse) {
|
|
2400
2501
|
return check("pass", "rclone_version", "rclone version", "push not required \u2014 check skipped");
|
|
@@ -2429,7 +2530,7 @@ function checkWriteTest(resolvedPath) {
|
|
|
2429
2530
|
if (!fuse) {
|
|
2430
2531
|
return check("pass", "s3_write_test", "S3 write test", "local disk \u2014 check skipped");
|
|
2431
2532
|
}
|
|
2432
|
-
const conceptsDir =
|
|
2533
|
+
const conceptsDir = join14(resolvedPath, "concepts");
|
|
2433
2534
|
if (!existsSync10(conceptsDir)) {
|
|
2434
2535
|
return check("pass", "s3_write_test", "S3 write test", "no concepts/ dir to test \u2014 check skipped");
|
|
2435
2536
|
}
|
|
@@ -2521,7 +2622,7 @@ var s3MountHealthProbe = {
|
|
|
2521
2622
|
checkS3MountPerf(ctx.resolvedPath),
|
|
2522
2623
|
checkS3MountFreshness(ctx.resolvedPath),
|
|
2523
2624
|
checkRcloneFlagAudit(ctx.resolvedPath),
|
|
2524
|
-
checkRcloneVersion(ctx.resolvedPath, ctx.vsConfig.installed, ctx.vsConfig.pushEnabled !== false),
|
|
2625
|
+
checkRcloneVersion(ctx.resolvedPath, ctx.vsConfig.installed, ctx.vsConfig.pushEnabled !== false, ctx.mcpOnlyLeaf),
|
|
2525
2626
|
checkWriteTest(ctx.resolvedPath),
|
|
2526
2627
|
checkVfsCacheHealth(ctx.resolvedPath)
|
|
2527
2628
|
];
|
|
@@ -2530,7 +2631,7 @@ var s3MountHealthProbe = {
|
|
|
2530
2631
|
|
|
2531
2632
|
// src/doctor/probes/skills-plugins.ts
|
|
2532
2633
|
import { existsSync as existsSync11, readdirSync as readdirSync4, readFileSync as readFileSync7 } from "fs";
|
|
2533
|
-
import { join as
|
|
2634
|
+
import { join as join15 } from "path";
|
|
2534
2635
|
function findSkillMd(dir) {
|
|
2535
2636
|
const results = [];
|
|
2536
2637
|
let entries;
|
|
@@ -2541,9 +2642,9 @@ function findSkillMd(dir) {
|
|
|
2541
2642
|
}
|
|
2542
2643
|
for (const entry of entries) {
|
|
2543
2644
|
if (entry.isFile() && entry.name === "SKILL.md") {
|
|
2544
|
-
results.push(
|
|
2645
|
+
results.push(join15(dir, entry.name));
|
|
2545
2646
|
} else if (entry.isDirectory()) {
|
|
2546
|
-
results.push(...findSkillMd(
|
|
2647
|
+
results.push(...findSkillMd(join15(dir, entry.name)));
|
|
2547
2648
|
}
|
|
2548
2649
|
}
|
|
2549
2650
|
return results;
|
|
@@ -2557,18 +2658,18 @@ function findSkillNames(dir) {
|
|
|
2557
2658
|
return results;
|
|
2558
2659
|
}
|
|
2559
2660
|
for (const entry of entries) {
|
|
2560
|
-
if (entry.isDirectory() && existsSync11(
|
|
2661
|
+
if (entry.isDirectory() && existsSync11(join15(dir, entry.name, "SKILL.md"))) {
|
|
2561
2662
|
results.push(entry.name);
|
|
2562
2663
|
}
|
|
2563
2664
|
}
|
|
2564
2665
|
return results;
|
|
2565
2666
|
}
|
|
2566
2667
|
function findInstalledSkillMd(dir) {
|
|
2567
|
-
const directSkills = findSkillNames(dir).map((name) =>
|
|
2668
|
+
const directSkills = findSkillNames(dir).map((name) => join15(dir, name, "SKILL.md"));
|
|
2568
2669
|
return directSkills.length > 0 ? directSkills : findSkillMd(dir);
|
|
2569
2670
|
}
|
|
2570
2671
|
function checkSkillsInstalled(home, cwd) {
|
|
2571
|
-
const srcDir = cwd ?
|
|
2672
|
+
const srcDir = cwd ? join15(cwd, "packages", "skills") : void 0;
|
|
2572
2673
|
if (srcDir && existsSync11(srcDir)) {
|
|
2573
2674
|
const found = findInstalledSkillMd(srcDir);
|
|
2574
2675
|
if (found.length > 0) {
|
|
@@ -2582,7 +2683,7 @@ function checkSkillsInstalled(home, cwd) {
|
|
|
2582
2683
|
return check("pass", "skills_installed", "Skills installed", `${found.length} SKILL.md file(s) found (plugin v${plugin.version})`);
|
|
2583
2684
|
}
|
|
2584
2685
|
}
|
|
2585
|
-
const skillsDir =
|
|
2686
|
+
const skillsDir = join15(home, ".claude", "skills");
|
|
2586
2687
|
if (existsSync11(skillsDir)) {
|
|
2587
2688
|
const found = findInstalledSkillMd(skillsDir);
|
|
2588
2689
|
if (found.length > 0) {
|
|
@@ -2593,10 +2694,10 @@ function checkSkillsInstalled(home, cwd) {
|
|
|
2593
2694
|
}
|
|
2594
2695
|
function checkDuplicateSkills(home) {
|
|
2595
2696
|
const plugin = findPlugin(home);
|
|
2596
|
-
const skillsDir =
|
|
2697
|
+
const skillsDir = join15(home, ".claude", "skills");
|
|
2597
2698
|
const agentSkillDirs = [
|
|
2598
|
-
{ label: "~/.codex/skills/", path:
|
|
2599
|
-
{ label: "~/.agents/skills/", path:
|
|
2699
|
+
{ label: "~/.codex/skills/", path: join15(home, ".codex", "skills") },
|
|
2700
|
+
{ label: "~/.agents/skills/", path: join15(home, ".agents", "skills") }
|
|
2600
2701
|
];
|
|
2601
2702
|
if (!plugin) {
|
|
2602
2703
|
return check("pass", "skills_duplicate", "Skills not duplicated", "Single install channel");
|
|
@@ -2629,10 +2730,10 @@ var STALE_GROK_ACTIVATION_REFERENCE = "Read @skillwiki.md";
|
|
|
2629
2730
|
var ACTIVATION_FIX_HINT = "run `npm run install:activation` from the llm-wiki repo";
|
|
2630
2731
|
function findGrokActivationTemplate(home, cwd) {
|
|
2631
2732
|
if (cwd) {
|
|
2632
|
-
const src =
|
|
2733
|
+
const src = join15(cwd, "packages", "skills", "using-skillwiki", "activation.md");
|
|
2633
2734
|
if (existsSync11(src)) return src;
|
|
2634
2735
|
}
|
|
2635
|
-
const pluginsRoot =
|
|
2736
|
+
const pluginsRoot = join15(home, ".grok", "installed-plugins");
|
|
2636
2737
|
if (!existsSync11(pluginsRoot)) return void 0;
|
|
2637
2738
|
let entries;
|
|
2638
2739
|
try {
|
|
@@ -2642,21 +2743,21 @@ function findGrokActivationTemplate(home, cwd) {
|
|
|
2642
2743
|
}
|
|
2643
2744
|
for (const entry of entries) {
|
|
2644
2745
|
if (!entry.isDirectory()) continue;
|
|
2645
|
-
const root =
|
|
2746
|
+
const root = join15(pluginsRoot, entry.name);
|
|
2646
2747
|
for (const rel of ["using-skillwiki/activation.md", "skills/using-skillwiki/activation.md"]) {
|
|
2647
|
-
const candidate =
|
|
2748
|
+
const candidate = join15(root, rel);
|
|
2648
2749
|
if (existsSync11(candidate)) return candidate;
|
|
2649
2750
|
}
|
|
2650
2751
|
}
|
|
2651
2752
|
return void 0;
|
|
2652
2753
|
}
|
|
2653
2754
|
function checkGrokActivation(home, cwd) {
|
|
2654
|
-
const grokDir =
|
|
2755
|
+
const grokDir = join15(home, ".grok");
|
|
2655
2756
|
if (!existsSync11(grokDir)) {
|
|
2656
2757
|
return check("pass", "activation_grok", "Grok activation", "Not a Grok host");
|
|
2657
2758
|
}
|
|
2658
|
-
const activationPath =
|
|
2659
|
-
const agentsPath =
|
|
2759
|
+
const activationPath = join15(grokDir, "skillwiki.md");
|
|
2760
|
+
const agentsPath = join15(grokDir, "AGENTS.md");
|
|
2660
2761
|
const hasActivation = existsSync11(activationPath);
|
|
2661
2762
|
const issues = [];
|
|
2662
2763
|
if (!hasActivation) {
|
|
@@ -2771,7 +2872,7 @@ var skillsPluginsProbe = {
|
|
|
2771
2872
|
|
|
2772
2873
|
// src/doctor/probes/vault-sync.ts
|
|
2773
2874
|
import { existsSync as existsSync12, readFileSync as readFileSync8 } from "fs";
|
|
2774
|
-
import { join as
|
|
2875
|
+
import { join as join16 } from "path";
|
|
2775
2876
|
import { execSync as execSync5 } from "child_process";
|
|
2776
2877
|
import { platform as platform3 } from "os";
|
|
2777
2878
|
function readPushResultState(stateFile) {
|
|
@@ -2800,7 +2901,7 @@ function readPushResultState(stateFile) {
|
|
|
2800
2901
|
}
|
|
2801
2902
|
function readVaultSyncConfig(home) {
|
|
2802
2903
|
try {
|
|
2803
|
-
const content = readFileSync8(
|
|
2904
|
+
const content = readFileSync8(join16(home, ".skillwiki", ".env"), "utf8");
|
|
2804
2905
|
let installed = false;
|
|
2805
2906
|
let role;
|
|
2806
2907
|
let serviceScope;
|
|
@@ -3103,7 +3204,7 @@ function snapshotterHealthChecks(scope, logDir, env) {
|
|
|
3103
3204
|
let completionOutcome = "unknown";
|
|
3104
3205
|
const logRecords = fixture ? fixture.log_records : (() => {
|
|
3105
3206
|
try {
|
|
3106
|
-
const content = readFileSync8(
|
|
3207
|
+
const content = readFileSync8(join16(logDir, "wiki-snapshot.log"), "utf8");
|
|
3107
3208
|
return content.split(/\r?\n/).filter(Boolean);
|
|
3108
3209
|
} catch {
|
|
3109
3210
|
return [];
|
|
@@ -3281,11 +3382,11 @@ function vaultSyncChecks(input) {
|
|
|
3281
3382
|
];
|
|
3282
3383
|
}
|
|
3283
3384
|
const isMac = os === "darwin";
|
|
3284
|
-
const logDir = input.logDir ?? (isMac ?
|
|
3285
|
-
const cacheDir = input.cacheDir ?? (isMac ?
|
|
3286
|
-
const shareDir = input.shareDir ?? (isMac ?
|
|
3287
|
-
const filterPath = input.filterPath ??
|
|
3288
|
-
const packagedSnapshotPath =
|
|
3385
|
+
const logDir = input.logDir ?? (isMac ? join16(home, "Library", "Logs") : join16(home, ".local", "state", "vault-sync", "log"));
|
|
3386
|
+
const cacheDir = input.cacheDir ?? (isMac ? join16(home, "Library", "Caches", "vault-sync") : join16(home, ".cache", "vault-sync"));
|
|
3387
|
+
const shareDir = input.shareDir ?? (isMac ? join16(home, "Library", "Application Support", "vault-sync", "bin") : join16(home, ".local", "share", "vault-sync", "bin"));
|
|
3388
|
+
const filterPath = input.filterPath ?? join16(home, ".config", "rclone", "wiki-push-filters.txt");
|
|
3389
|
+
const packagedSnapshotPath = join16(shareDir, "wiki-snapshot.sh");
|
|
3289
3390
|
const legacySnapshotPath = "/root/.hermes/scripts/wiki-snapshot-v3.sh";
|
|
3290
3391
|
const snapshotPath = input.snapshotScriptPath ?? (existsSync12(packagedSnapshotPath) ? packagedSnapshotPath : legacySnapshotPath);
|
|
3291
3392
|
if (input.vaultSyncRole === "snapshotter") {
|
|
@@ -3342,9 +3443,9 @@ function vaultSyncChecks(input) {
|
|
|
3342
3443
|
return [c12, ...healthChecks, cFetch2, c42, c52];
|
|
3343
3444
|
}
|
|
3344
3445
|
const env = input.env ?? process.env;
|
|
3345
|
-
const fetchLogFile =
|
|
3446
|
+
const fetchLogFile = join16(logDir, "wiki-fetch.log");
|
|
3346
3447
|
if (input.pushEnabled === false) {
|
|
3347
|
-
const fetchHelperPath =
|
|
3448
|
+
const fetchHelperPath = join16(shareDir, "wiki-fetch-notify.sh");
|
|
3348
3449
|
const c12 = existsSync12(fetchHelperPath) ? check("pass", "vault_sync_installed", "Vault sync installed", `Found: ${fetchHelperPath}`) : check(
|
|
3349
3450
|
"error",
|
|
3350
3451
|
"vault_sync_installed",
|
|
@@ -3379,7 +3480,7 @@ function vaultSyncChecks(input) {
|
|
|
3379
3480
|
);
|
|
3380
3481
|
return [c12, c22, c32, cPushResult2, cFetch2, c42, c52];
|
|
3381
3482
|
}
|
|
3382
|
-
const pushScriptPath =
|
|
3483
|
+
const pushScriptPath = join16(shareDir, "wiki-push.sh");
|
|
3383
3484
|
const c1 = existsSync12(pushScriptPath) ? check("pass", "vault_sync_installed", "Vault sync installed", `Found: ${pushScriptPath}`) : check("error", "vault_sync_installed", "Vault sync installed", `Script not found at ${pushScriptPath} \u2014 run vault-sync-install`);
|
|
3384
3485
|
let c2;
|
|
3385
3486
|
try {
|
|
@@ -3431,9 +3532,9 @@ function vaultSyncChecks(input) {
|
|
|
3431
3532
|
"Scheduler check failed \u2014 run vault-sync-install"
|
|
3432
3533
|
);
|
|
3433
3534
|
}
|
|
3434
|
-
const stateFile =
|
|
3535
|
+
const stateFile = join16(cacheDir, "wiki-push-result.state");
|
|
3435
3536
|
const pushState = readPushResultState(stateFile);
|
|
3436
|
-
const logFile =
|
|
3537
|
+
const logFile = join16(logDir, "wiki-push.log");
|
|
3437
3538
|
let c3;
|
|
3438
3539
|
if (pushState.exists && !pushState.malformed && pushState.result === "refused") {
|
|
3439
3540
|
const reasonSuffix = pushState.reason ? `: ${pushState.reason}` : "";
|
|
@@ -3583,7 +3684,7 @@ function checkVaultSyncPullHelper(home, env) {
|
|
|
3583
3684
|
);
|
|
3584
3685
|
}
|
|
3585
3686
|
function isGitDir(path) {
|
|
3586
|
-
return Boolean(path && existsSync12(
|
|
3687
|
+
return Boolean(path && existsSync12(join16(path, ".git")));
|
|
3587
3688
|
}
|
|
3588
3689
|
function checkVaultSyncReviewRequiredJournals(ctx) {
|
|
3589
3690
|
const live = ctx.resolvedPath;
|
|
@@ -3660,7 +3761,11 @@ var vaultSyncProbe = {
|
|
|
3660
3761
|
snapshotScriptPath: ctx.vsConfig.snapshotScript,
|
|
3661
3762
|
env: ctx.input.env ?? process.env
|
|
3662
3763
|
}));
|
|
3663
|
-
|
|
3764
|
+
if (!ctx.vsConfig.installed) {
|
|
3765
|
+
checks.push(check("pass", "vault_sync_pull_helper", "Vault-sync pull helper", "vault-sync not installed \u2014 check skipped"));
|
|
3766
|
+
} else {
|
|
3767
|
+
checks.push(checkVaultSyncPullHelper(ctx.input.home, ctx.input.env ?? process.env));
|
|
3768
|
+
}
|
|
3664
3769
|
checks.push(checkVaultSyncReviewRequiredJournals(ctx));
|
|
3665
3770
|
checks.push(checkSnapshotWorktreeUnmerged(ctx));
|
|
3666
3771
|
return checks;
|
|
@@ -3674,10 +3779,10 @@ import { platform as platform4 } from "os";
|
|
|
3674
3779
|
|
|
3675
3780
|
// src/utils/satellite-run-health.ts
|
|
3676
3781
|
import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
|
|
3677
|
-
import { join as
|
|
3782
|
+
import { join as join17 } from "path";
|
|
3678
3783
|
var SATELLITE_STALE_MS = 26 * 60 * 60 * 1e3;
|
|
3679
3784
|
function satelliteLatestRunPath(vault) {
|
|
3680
|
-
return
|
|
3785
|
+
return join17(vault, ".skillwiki", "agent-memory-trends", "latest-run.json");
|
|
3681
3786
|
}
|
|
3682
3787
|
function isFailedRunStatus(status) {
|
|
3683
3788
|
return status === "fail" || status === "failure";
|
|
@@ -3689,7 +3794,9 @@ function parseLatestRunFile(text) {
|
|
|
3689
3794
|
if (!status) return null;
|
|
3690
3795
|
const finishedAt = typeof parsed.finished_at === "string" && parsed.finished_at.length > 0 ? parsed.finished_at : void 0;
|
|
3691
3796
|
const failureClass = parsed.failure_class != null && String(parsed.failure_class).length > 0 ? String(parsed.failure_class) : void 0;
|
|
3692
|
-
|
|
3797
|
+
const runDate = typeof parsed.run_date === "string" && parsed.run_date.length > 0 ? parsed.run_date : void 0;
|
|
3798
|
+
const selectedCandidateCount = typeof parsed.selected_candidate_count === "number" && Number.isInteger(parsed.selected_candidate_count) && parsed.selected_candidate_count >= 0 ? parsed.selected_candidate_count : void 0;
|
|
3799
|
+
return { status, runDate, selectedCandidateCount, finishedAt, failureClass };
|
|
3693
3800
|
} catch {
|
|
3694
3801
|
return null;
|
|
3695
3802
|
}
|
|
@@ -3697,17 +3804,21 @@ function parseLatestRunFile(text) {
|
|
|
3697
3804
|
function readSatelliteLatestRunFromText(text) {
|
|
3698
3805
|
return parseLatestRunFile(text);
|
|
3699
3806
|
}
|
|
3700
|
-
function
|
|
3701
|
-
|
|
3702
|
-
if (!existsSync13(latestPath)) return null;
|
|
3807
|
+
function readSatelliteLatestRunAt(path) {
|
|
3808
|
+
if (!existsSync13(path)) return null;
|
|
3703
3809
|
try {
|
|
3704
|
-
return parseLatestRunFile(readFileSync9(
|
|
3810
|
+
return parseLatestRunFile(readFileSync9(path, "utf8"));
|
|
3705
3811
|
} catch {
|
|
3706
3812
|
return null;
|
|
3707
3813
|
}
|
|
3708
3814
|
}
|
|
3709
3815
|
function evaluateSatelliteRunHealth(vault, now) {
|
|
3710
|
-
|
|
3816
|
+
return evaluateSatelliteRunHealthAt(satelliteLatestRunPath(vault), now);
|
|
3817
|
+
}
|
|
3818
|
+
function evaluateSatelliteRunHealthAt(path, now) {
|
|
3819
|
+
return evaluateSatelliteRunHealthState(readSatelliteLatestRunAt(path), now);
|
|
3820
|
+
}
|
|
3821
|
+
function evaluateSatelliteRunHealthState(run, now) {
|
|
3711
3822
|
if (!run) {
|
|
3712
3823
|
return { failed: false, stale: false };
|
|
3713
3824
|
}
|
|
@@ -3813,7 +3924,7 @@ var satelliteProbe = {
|
|
|
3813
3924
|
|
|
3814
3925
|
// src/doctor/probes/metrics.ts
|
|
3815
3926
|
import { readFileSync as readFileSync10 } from "fs";
|
|
3816
|
-
import { join as
|
|
3927
|
+
import { join as join18 } from "path";
|
|
3817
3928
|
var METRIC_TYPES = ["entities", "concepts", "comparisons", "queries", "meta"];
|
|
3818
3929
|
function doctorReadOnlyScanRoot(resolvedPath) {
|
|
3819
3930
|
return resolveReadOnlyVaultRoot(resolvedPath).root;
|
|
@@ -3857,7 +3968,7 @@ async function vaultMetrics(resolvedPath) {
|
|
|
3857
3968
|
}
|
|
3858
3969
|
let logLines = 0;
|
|
3859
3970
|
try {
|
|
3860
|
-
logLines = readFileSync10(
|
|
3971
|
+
logLines = readFileSync10(join18(scanRoot, "log.md"), "utf8").split("\n").length;
|
|
3861
3972
|
} catch {
|
|
3862
3973
|
}
|
|
3863
3974
|
return [
|
|
@@ -3993,18 +4104,18 @@ var fuseStalenessProbe = {
|
|
|
3993
4104
|
|
|
3994
4105
|
// src/doctor/probes/activation-marker.ts
|
|
3995
4106
|
import { existsSync as existsSync15, readFileSync as readFileSync11, readdirSync as readdirSync5 } from "fs";
|
|
3996
|
-
import { join as
|
|
4107
|
+
import { join as join19 } from "path";
|
|
3997
4108
|
var GROK_ACTIVATION_REFERENCE2 = "Read @~/.grok/skillwiki.md for SkillWiki activation context.";
|
|
3998
4109
|
var STALE_GROK_ACTIVATION_REFERENCE2 = "Read @skillwiki.md";
|
|
3999
4110
|
var ACTIVATION_FIX_HINT2 = "run `npm run install:activation` from the llm-wiki repo";
|
|
4000
4111
|
function findGrokActivationTemplate2(home, cwd) {
|
|
4001
4112
|
if (cwd) {
|
|
4002
|
-
const src =
|
|
4113
|
+
const src = join19(cwd, "packages", "skills", "using-skillwiki", "activation.md");
|
|
4003
4114
|
if (existsSync15(src)) return src;
|
|
4004
|
-
const directSrc =
|
|
4115
|
+
const directSrc = join19(cwd, "skills", "using-skillwiki", "activation.md");
|
|
4005
4116
|
if (existsSync15(directSrc)) return directSrc;
|
|
4006
4117
|
}
|
|
4007
|
-
const pluginsRoot =
|
|
4118
|
+
const pluginsRoot = join19(home, ".grok", "installed-plugins");
|
|
4008
4119
|
if (!existsSync15(pluginsRoot)) return void 0;
|
|
4009
4120
|
let entries;
|
|
4010
4121
|
try {
|
|
@@ -4014,21 +4125,21 @@ function findGrokActivationTemplate2(home, cwd) {
|
|
|
4014
4125
|
}
|
|
4015
4126
|
for (const entry of entries) {
|
|
4016
4127
|
if (!entry.isDirectory()) continue;
|
|
4017
|
-
const root =
|
|
4128
|
+
const root = join19(pluginsRoot, entry.name);
|
|
4018
4129
|
for (const rel of ["using-skillwiki/activation.md", "skills/using-skillwiki/activation.md"]) {
|
|
4019
|
-
const candidate =
|
|
4130
|
+
const candidate = join19(root, rel);
|
|
4020
4131
|
if (existsSync15(candidate)) return candidate;
|
|
4021
4132
|
}
|
|
4022
4133
|
}
|
|
4023
4134
|
return void 0;
|
|
4024
4135
|
}
|
|
4025
4136
|
function checkActivationMarker(home, cwd) {
|
|
4026
|
-
const grokDir =
|
|
4137
|
+
const grokDir = join19(home, ".grok");
|
|
4027
4138
|
if (!existsSync15(grokDir)) {
|
|
4028
4139
|
return check("pass", "activation_marker", "Activation marker", "Not a Grok host \u2014 check skipped");
|
|
4029
4140
|
}
|
|
4030
|
-
const activationPath =
|
|
4031
|
-
const agentsPath =
|
|
4141
|
+
const activationPath = join19(grokDir, "skillwiki.md");
|
|
4142
|
+
const agentsPath = join19(grokDir, "AGENTS.md");
|
|
4032
4143
|
const hasActivation = existsSync15(activationPath);
|
|
4033
4144
|
const issues = [];
|
|
4034
4145
|
if (!hasActivation) {
|
|
@@ -4085,7 +4196,7 @@ var activationMarkerProbe = {
|
|
|
4085
4196
|
|
|
4086
4197
|
// src/doctor/probes/ds-store-noise.ts
|
|
4087
4198
|
import { existsSync as existsSync16, readdirSync as readdirSync6 } from "fs";
|
|
4088
|
-
import { join as
|
|
4199
|
+
import { join as join20 } from "path";
|
|
4089
4200
|
var VAULT_TRACKED_DIRS = ["raw", "entities", "concepts", "comparisons", "queries", "meta", "_archive", "_Templates"];
|
|
4090
4201
|
function checkDsStoreNoise(resolvedPath) {
|
|
4091
4202
|
if (resolvedPath === void 0) {
|
|
@@ -4107,13 +4218,13 @@ function checkDsStoreNoise(resolvedPath) {
|
|
|
4107
4218
|
found.push(rel ? `${rel}/.DS_Store` : ".DS_Store");
|
|
4108
4219
|
} else if (entry.isDirectory()) {
|
|
4109
4220
|
if (entry.name === ".git" || entry.name === "node_modules") continue;
|
|
4110
|
-
walk(
|
|
4221
|
+
walk(join20(dir, entry.name), rel ? `${rel}/${entry.name}` : entry.name);
|
|
4111
4222
|
}
|
|
4112
4223
|
}
|
|
4113
4224
|
}
|
|
4114
4225
|
let scannedAny = false;
|
|
4115
4226
|
for (const sub of VAULT_TRACKED_DIRS) {
|
|
4116
|
-
const subDir =
|
|
4227
|
+
const subDir = join20(resolvedPath, sub);
|
|
4117
4228
|
if (existsSync16(subDir)) {
|
|
4118
4229
|
scannedAny = true;
|
|
4119
4230
|
walk(subDir, sub);
|
|
@@ -4143,17 +4254,14 @@ var dsStoreNoiseProbe = {
|
|
|
4143
4254
|
|
|
4144
4255
|
// src/doctor/probes/mcp-handshake.ts
|
|
4145
4256
|
import { existsSync as existsSync17 } from "fs";
|
|
4146
|
-
import { join as
|
|
4257
|
+
import { join as join21 } from "path";
|
|
4147
4258
|
var DEFAULT_MCP_URL = "https://wiki.karldigi.dev/mcp";
|
|
4148
|
-
var URL_ENV = "SKILLWIKI_MCP_URL";
|
|
4149
|
-
var TOKEN_ENV = "SKILLWIKI_MCP_TOKEN";
|
|
4150
4259
|
function mcpEnv(ctx) {
|
|
4151
4260
|
return ctx.input.env ?? process.env;
|
|
4152
4261
|
}
|
|
4153
4262
|
function checkMcpUrl(ctx) {
|
|
4154
|
-
const
|
|
4155
|
-
|
|
4156
|
-
if (typeof override === "string" && override.trim().length > 0) {
|
|
4263
|
+
const creds = mcpAuthFromEnv(mcpEnv(ctx));
|
|
4264
|
+
if (creds.url) {
|
|
4157
4265
|
return check("pass", "mcp_url_configured", "HTTP MCP URL", "configured via env override");
|
|
4158
4266
|
}
|
|
4159
4267
|
return check(
|
|
@@ -4164,21 +4272,20 @@ function checkMcpUrl(ctx) {
|
|
|
4164
4272
|
);
|
|
4165
4273
|
}
|
|
4166
4274
|
function checkMcpCredential(ctx) {
|
|
4167
|
-
const
|
|
4168
|
-
|
|
4169
|
-
if (typeof value === "string" && value.trim().length > 0) {
|
|
4275
|
+
const creds = mcpAuthFromEnv(mcpEnv(ctx));
|
|
4276
|
+
if (creds.token) {
|
|
4170
4277
|
return check("pass", "mcp_credential_present", "HTTP MCP auth", "present");
|
|
4171
4278
|
}
|
|
4172
4279
|
return check(
|
|
4173
4280
|
"warn",
|
|
4174
4281
|
"mcp_credential_present",
|
|
4175
4282
|
"HTTP MCP auth",
|
|
4176
|
-
"not set \u2014 set in process env or host Configure (value not shown)"
|
|
4283
|
+
"not set \u2014 set in process env, ~/.skillwiki/.env, or host Configure (value not shown)"
|
|
4177
4284
|
);
|
|
4178
4285
|
}
|
|
4179
4286
|
function checkFrozenLeafWritePath(ctx) {
|
|
4180
4287
|
const vault = ctx.resolvedPath;
|
|
4181
|
-
if (!vault || !existsSync17(
|
|
4288
|
+
if (!vault || !existsSync17(join21(vault, ".WIKI_GIT_FROZEN"))) {
|
|
4182
4289
|
return check(
|
|
4183
4290
|
"pass",
|
|
4184
4291
|
"mcp_frozen_leaf_write_path",
|
|
@@ -4210,8 +4317,7 @@ function versionLessThan(a, b) {
|
|
|
4210
4317
|
return pa.patch < pb.patch;
|
|
4211
4318
|
}
|
|
4212
4319
|
function redactSecret(detail, secret) {
|
|
4213
|
-
|
|
4214
|
-
return detail.split(secret).join("[REDACTED]");
|
|
4320
|
+
return redactMcpSecret(detail, secret);
|
|
4215
4321
|
}
|
|
4216
4322
|
function handshakeRow(status, detail, secret) {
|
|
4217
4323
|
return check(status, HANDSHAKE_ID, HANDSHAKE_LABEL, redactSecret(detail, secret));
|
|
@@ -4269,9 +4375,10 @@ async function checkMcpHandshake(ctx) {
|
|
|
4269
4375
|
return handshakeRow("pass", "not requested \u2014 check skipped");
|
|
4270
4376
|
}
|
|
4271
4377
|
const env = mcpEnv(ctx);
|
|
4272
|
-
const
|
|
4273
|
-
const
|
|
4274
|
-
|
|
4378
|
+
const creds = mcpAuthFromEnv(env);
|
|
4379
|
+
const url = creds.url ?? DEFAULT_MCP_URL;
|
|
4380
|
+
const token = creds.token ?? "";
|
|
4381
|
+
if (token.length === 0) {
|
|
4275
4382
|
return handshakeRow("error", "auth not set \u2014 handshake not attempted (value not shown)");
|
|
4276
4383
|
}
|
|
4277
4384
|
const fetchFn = ctx.input.mcpFetch ?? globalThis.fetch;
|
|
@@ -4304,7 +4411,7 @@ async function checkMcpHandshake(ctx) {
|
|
|
4304
4411
|
init.sessionId
|
|
4305
4412
|
);
|
|
4306
4413
|
const tools = toolNames(listed.result);
|
|
4307
|
-
const frozen = Boolean(ctx.resolvedPath && existsSync17(
|
|
4414
|
+
const frozen = Boolean(ctx.resolvedPath && existsSync17(join21(ctx.resolvedPath, ".WIKI_GIT_FROZEN")));
|
|
4308
4415
|
if (frozen && !tools.includes(WORKITEM_TOOL)) {
|
|
4309
4416
|
return handshakeRow(
|
|
4310
4417
|
"error",
|
|
@@ -4377,6 +4484,10 @@ var DoctorRunner = class {
|
|
|
4377
4484
|
async run(input) {
|
|
4378
4485
|
const devSourceRun = isDevSourceRun(input.argv);
|
|
4379
4486
|
const vsConfig = readVaultSyncConfig(input.home);
|
|
4487
|
+
const baseEnv = input.env ?? process.env;
|
|
4488
|
+
const mergedEnv = await mergeMcpAuthIntoEnv(input.home, baseEnv);
|
|
4489
|
+
const auth = mcpAuthFromEnv(mergedEnv);
|
|
4490
|
+
const inputWithEnv = { ...input, env: mergedEnv };
|
|
4380
4491
|
const resolved = await resolveRuntimePath({
|
|
4381
4492
|
flag: void 0,
|
|
4382
4493
|
envValue: input.envValue,
|
|
@@ -4385,9 +4496,14 @@ var DoctorRunner = class {
|
|
|
4385
4496
|
});
|
|
4386
4497
|
const resolvedPath = resolved.ok ? resolved.data.path : void 0;
|
|
4387
4498
|
const gitCheckPath = vsConfig.role === "snapshotter" ? resolveSnapshotGitWorktree(input.home) ?? resolvedPath : resolvedPath;
|
|
4499
|
+
const mcpOnlyLeaf = isMcpOnlyLeaf({
|
|
4500
|
+
resolvedPath,
|
|
4501
|
+
token: auth.token,
|
|
4502
|
+
vaultSyncInstalled: vsConfig.installed
|
|
4503
|
+
});
|
|
4388
4504
|
const fleetLoad = resolvedPath ? await loadFleetManifestAndHost({
|
|
4389
4505
|
vault: resolvedPath,
|
|
4390
|
-
env: { ...
|
|
4506
|
+
env: { ...mergedEnv, WIKI_PATH: input.envValue ?? resolvedPath },
|
|
4391
4507
|
home: input.home,
|
|
4392
4508
|
cwd: input.cwd,
|
|
4393
4509
|
osHostname: process.env.HOSTNAME,
|
|
@@ -4396,7 +4512,7 @@ var DoctorRunner = class {
|
|
|
4396
4512
|
const satelliteGate = satelliteGateFromFleetLoad(fleetLoad);
|
|
4397
4513
|
const readOnlyScanRoot = resolvedPath ? doctorReadOnlyScanRoot(resolvedPath) : void 0;
|
|
4398
4514
|
const ctx = {
|
|
4399
|
-
input,
|
|
4515
|
+
input: inputWithEnv,
|
|
4400
4516
|
devSourceRun,
|
|
4401
4517
|
vsConfig,
|
|
4402
4518
|
resolvedPath,
|
|
@@ -4404,13 +4520,18 @@ var DoctorRunner = class {
|
|
|
4404
4520
|
gitCheckPath,
|
|
4405
4521
|
fleetLoad,
|
|
4406
4522
|
readOnlyScanRoot,
|
|
4407
|
-
satelliteGate
|
|
4523
|
+
satelliteGate,
|
|
4524
|
+
mcpOnlyLeaf
|
|
4408
4525
|
};
|
|
4409
|
-
const
|
|
4526
|
+
const rawChecks = [];
|
|
4410
4527
|
for (const probe of this.probes) {
|
|
4411
4528
|
const probeChecks = await probe.run(ctx);
|
|
4412
|
-
|
|
4529
|
+
rawChecks.push(...probeChecks);
|
|
4413
4530
|
}
|
|
4531
|
+
const checks = rawChecks.map((c) => ({
|
|
4532
|
+
...c,
|
|
4533
|
+
detail: redactMcpSecret(c.detail, auth.token)
|
|
4534
|
+
}));
|
|
4414
4535
|
const summary = {
|
|
4415
4536
|
pass: checks.filter((c) => c.status === "pass").length,
|
|
4416
4537
|
info: checks.filter((c) => c.status === "info").length,
|
|
@@ -4429,7 +4550,7 @@ var DoctorRunner = class {
|
|
|
4429
4550
|
if (summary.info > 0) summaryParts.push(`${summary.info} info`);
|
|
4430
4551
|
summaryParts.push(`${summary.warn} warn`, `${summary.error} error`);
|
|
4431
4552
|
lines.push(summaryParts.join(" \xB7 "));
|
|
4432
|
-
const humanHint = lines.join("\n");
|
|
4553
|
+
const humanHint = redactMcpSecret(lines.join("\n"), auth.token);
|
|
4433
4554
|
return { exitCode, result: ok({ checks, summary, humanHint }) };
|
|
4434
4555
|
}
|
|
4435
4556
|
};
|
|
@@ -4461,7 +4582,7 @@ function readCliPackageJson(baseUrl = import.meta.url) {
|
|
|
4461
4582
|
// src/utils/vault-write-gates.ts
|
|
4462
4583
|
import { execFileSync } from "child_process";
|
|
4463
4584
|
import { existsSync as existsSync19, readdirSync as readdirSync7, readFileSync as readFileSync13, statSync as statSync3 } from "fs";
|
|
4464
|
-
import { join as
|
|
4585
|
+
import { join as join22, relative as relative2 } from "path";
|
|
4465
4586
|
var DEFAULT_DIRTY_VOLUME_THRESHOLD = 50;
|
|
4466
4587
|
var DEFAULT_CAPTURE_BUDGET = 20;
|
|
4467
4588
|
var DEFAULT_NO_DECISION_STREAK = 3;
|
|
@@ -4517,7 +4638,7 @@ function isEventLedgerPath(rel) {
|
|
|
4517
4638
|
return n === "meta/log-events" || n.startsWith("meta/log-events/");
|
|
4518
4639
|
}
|
|
4519
4640
|
function countEventLedgerFiles(vault) {
|
|
4520
|
-
return listFilesRecursive(
|
|
4641
|
+
return listFilesRecursive(join22(vault, "meta", "log-events")).length;
|
|
4521
4642
|
}
|
|
4522
4643
|
function measureDirtyVolume(vault) {
|
|
4523
4644
|
const empty = (extra = {}) => ({
|
|
@@ -4577,7 +4698,7 @@ function measureDirtyVolume(vault) {
|
|
|
4577
4698
|
if (!rel) continue;
|
|
4578
4699
|
if (code === "??") {
|
|
4579
4700
|
untracked += 1;
|
|
4580
|
-
const abs =
|
|
4701
|
+
const abs = join22(vault, rel);
|
|
4581
4702
|
if (existsSync19(abs) && statSync3(abs).isDirectory()) {
|
|
4582
4703
|
const files = listFilesRecursive(abs);
|
|
4583
4704
|
expanded += files.length;
|
|
@@ -4621,7 +4742,7 @@ function listFilesRecursive(dir) {
|
|
|
4621
4742
|
}
|
|
4622
4743
|
for (const name of entries) {
|
|
4623
4744
|
if (name === ".git") continue;
|
|
4624
|
-
const p =
|
|
4745
|
+
const p = join22(dir, name);
|
|
4625
4746
|
try {
|
|
4626
4747
|
const st = statSync3(p);
|
|
4627
4748
|
if (st.isDirectory()) out.push(...listFilesRecursive(p));
|
|
@@ -4752,7 +4873,7 @@ function listProjectDayCaptures(vault, project, day) {
|
|
|
4752
4873
|
return;
|
|
4753
4874
|
}
|
|
4754
4875
|
for (const name of entries) {
|
|
4755
|
-
const abs =
|
|
4876
|
+
const abs = join22(dir, name);
|
|
4756
4877
|
const rel = relBase ? `${relBase}/${name}` : name;
|
|
4757
4878
|
try {
|
|
4758
4879
|
const st = statSync3(abs);
|
|
@@ -4762,16 +4883,16 @@ function listProjectDayCaptures(vault, project, day) {
|
|
|
4762
4883
|
}
|
|
4763
4884
|
}
|
|
4764
4885
|
};
|
|
4765
|
-
walk(
|
|
4766
|
-
walk(
|
|
4767
|
-
walk(
|
|
4768
|
-
const workRoot =
|
|
4886
|
+
walk(join22(vault, "raw", "transcripts"), "raw/transcripts");
|
|
4887
|
+
walk(join22(vault, "projects", slug, "raw", "transcripts"), `projects/${slug}/raw/transcripts`);
|
|
4888
|
+
walk(join22(vault, "projects", slug, "requirements"), `projects/${slug}/requirements`);
|
|
4889
|
+
const workRoot = join22(vault, "projects", slug, "work");
|
|
4769
4890
|
if (existsSync19(workRoot)) {
|
|
4770
4891
|
try {
|
|
4771
4892
|
for (const name of readdirSync7(workRoot)) {
|
|
4772
4893
|
if (!name.startsWith(day)) continue;
|
|
4773
4894
|
if (!/investigate|pilot-q|research|cycle|dev-loop/.test(name)) continue;
|
|
4774
|
-
const abs =
|
|
4895
|
+
const abs = join22(workRoot, name);
|
|
4775
4896
|
if (statSync3(abs).isDirectory()) {
|
|
4776
4897
|
for (const f of listFilesRecursive(abs)) {
|
|
4777
4898
|
const rel = relative2(vault, f).replace(/\\/g, "/");
|
|
@@ -4877,7 +4998,7 @@ function runWritePreflight(input) {
|
|
|
4877
4998
|
// src/commands/observe.ts
|
|
4878
4999
|
import { mkdir as mkdir3, writeFile as writeFile2 } from "fs/promises";
|
|
4879
5000
|
import { existsSync as existsSync20, statSync as statSync4 } from "fs";
|
|
4880
|
-
import { join as
|
|
5001
|
+
import { join as join23 } from "path";
|
|
4881
5002
|
import { createHash as createHash2 } from "crypto";
|
|
4882
5003
|
var ALLOWED_KINDS = /* @__PURE__ */ new Set(["note", "bug", "task", "idea", "session-log"]);
|
|
4883
5004
|
function slugify(text) {
|
|
@@ -4926,7 +5047,7 @@ async function runObserve(input) {
|
|
|
4926
5047
|
};
|
|
4927
5048
|
}
|
|
4928
5049
|
}
|
|
4929
|
-
const transcriptsDir =
|
|
5050
|
+
const transcriptsDir = join23(input.vault, "raw", "transcripts");
|
|
4930
5051
|
try {
|
|
4931
5052
|
await mkdir3(transcriptsDir, { recursive: true });
|
|
4932
5053
|
} catch {
|
|
@@ -4938,7 +5059,7 @@ async function runObserve(input) {
|
|
|
4938
5059
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4939
5060
|
const slug = slugify(input.text);
|
|
4940
5061
|
const fileName = `${today}-observation-${slug}.md`;
|
|
4941
|
-
const filePath =
|
|
5062
|
+
const filePath = join23(transcriptsDir, fileName);
|
|
4942
5063
|
const body = `
|
|
4943
5064
|
${input.text.trim()}
|
|
4944
5065
|
`;
|
|
@@ -4980,7 +5101,7 @@ ${input.text.trim()}
|
|
|
4980
5101
|
// src/commands/memory.ts
|
|
4981
5102
|
import { createHash as createHash3 } from "crypto";
|
|
4982
5103
|
import { mkdir as mkdir4, readFile as readFile7, readdir as readdir2, stat as stat2, writeFile as writeFile3 } from "fs/promises";
|
|
4983
|
-
import { basename as basename2, extname, join as
|
|
5104
|
+
import { basename as basename2, extname, join as join24, relative as relative3, sep as sep2 } from "path";
|
|
4984
5105
|
|
|
4985
5106
|
// src/utils/memory-authority.ts
|
|
4986
5107
|
var TIER_RANK = {
|
|
@@ -5099,8 +5220,8 @@ async function runMemoryIndex(input) {
|
|
|
5099
5220
|
}
|
|
5100
5221
|
const generatedAt = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
5101
5222
|
const relCachePath = memoryCacheRelPath(input.project);
|
|
5102
|
-
const absCachePath =
|
|
5103
|
-
await mkdir4(
|
|
5223
|
+
const absCachePath = join24(input.vault, relCachePath);
|
|
5224
|
+
await mkdir4(join24(input.vault, ".skillwiki", "memory", input.project), { recursive: true });
|
|
5104
5225
|
await writeFile3(absCachePath, `${JSON.stringify({
|
|
5105
5226
|
generated_at: generatedAt,
|
|
5106
5227
|
project: input.project,
|
|
@@ -5292,7 +5413,7 @@ async function buildMemoryIndexState(pages, project) {
|
|
|
5292
5413
|
}
|
|
5293
5414
|
async function checkMemoryIndex(vault, project, current) {
|
|
5294
5415
|
const relCachePath = memoryCacheRelPath(project);
|
|
5295
|
-
const cacheText = await readIfExists(
|
|
5416
|
+
const cacheText = await readIfExists(join24(vault, relCachePath));
|
|
5296
5417
|
if (!cacheText) {
|
|
5297
5418
|
return {
|
|
5298
5419
|
ok: true,
|
|
@@ -5701,7 +5822,7 @@ async function walkImportFiles(dir, out) {
|
|
|
5701
5822
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
5702
5823
|
for (const entry of entries) {
|
|
5703
5824
|
if (entry.name === ".git" || entry.name === "node_modules") continue;
|
|
5704
|
-
const path =
|
|
5825
|
+
const path = join24(dir, entry.name);
|
|
5705
5826
|
if (entry.isDirectory()) {
|
|
5706
5827
|
await walkImportFiles(path, out);
|
|
5707
5828
|
} else if (entry.isFile() && isImportCandidate(path)) {
|
|
@@ -5768,8 +5889,8 @@ async function writeImportCapture(vault, entry, today) {
|
|
|
5768
5889
|
const content = hiddenString(entry, "__content");
|
|
5769
5890
|
const project = hiddenString(entry, "__project");
|
|
5770
5891
|
const relPath = await availableImportPath(vault, entry.proposed_path);
|
|
5771
|
-
const absPath =
|
|
5772
|
-
await mkdir4(
|
|
5892
|
+
const absPath = join24(vault, relPath);
|
|
5893
|
+
await mkdir4(join24(vault, "raw", "transcripts"), { recursive: true });
|
|
5773
5894
|
await writeFile3(absPath, renderImportCapture(entry, content, project, today), "utf8");
|
|
5774
5895
|
const validation = await runValidate({ file: absPath });
|
|
5775
5896
|
return {
|
|
@@ -5785,7 +5906,7 @@ async function availableImportPath(vault, proposed) {
|
|
|
5785
5906
|
const stem = proposed.slice(0, -ext.length);
|
|
5786
5907
|
let candidate = proposed;
|
|
5787
5908
|
let i = 2;
|
|
5788
|
-
while (await readIfExists(
|
|
5909
|
+
while (await readIfExists(join24(vault, candidate))) {
|
|
5789
5910
|
candidate = `${stem}-${i}${ext}`;
|
|
5790
5911
|
i++;
|
|
5791
5912
|
}
|
|
@@ -5970,10 +6091,10 @@ function memoryCacheRelPath(project) {
|
|
|
5970
6091
|
}
|
|
5971
6092
|
async function readMemoryCache(vault, project) {
|
|
5972
6093
|
if (project) {
|
|
5973
|
-
const projectCache = await readIfExists(
|
|
6094
|
+
const projectCache = await readIfExists(join24(vault, memoryCacheRelPath(project)));
|
|
5974
6095
|
if (projectCache) return projectCache;
|
|
5975
6096
|
}
|
|
5976
|
-
return readIfExists(
|
|
6097
|
+
return readIfExists(join24(vault, ".skillwiki", "memory-topics.json"));
|
|
5977
6098
|
}
|
|
5978
6099
|
function dedupePages(pages) {
|
|
5979
6100
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -6065,7 +6186,7 @@ function slugify2(value) {
|
|
|
6065
6186
|
|
|
6066
6187
|
// src/commands/query.ts
|
|
6067
6188
|
import { readFile as readFile9, stat as stat4 } from "fs/promises";
|
|
6068
|
-
import { join as
|
|
6189
|
+
import { join as join26 } from "path";
|
|
6069
6190
|
|
|
6070
6191
|
// src/utils/rrf.ts
|
|
6071
6192
|
var RRF_K = 60;
|
|
@@ -6081,7 +6202,7 @@ function fuseRankings(lists, k = RRF_K) {
|
|
|
6081
6202
|
|
|
6082
6203
|
// src/utils/vector-index.ts
|
|
6083
6204
|
import { mkdir as mkdir5, readFile as readFile8, stat as stat3 } from "fs/promises";
|
|
6084
|
-
import { join as
|
|
6205
|
+
import { join as join25 } from "path";
|
|
6085
6206
|
import { existsSync as existsSync21 } from "fs";
|
|
6086
6207
|
var VECTOR_INDEX_REL = ".skillwiki/vectors/index.json";
|
|
6087
6208
|
var VECTOR_INDEX_SCHEMA = "skillwiki-tfidf-index/v1";
|
|
@@ -6096,7 +6217,7 @@ function extractPageTokens(text) {
|
|
|
6096
6217
|
return tokenize(`${title} ${body}`);
|
|
6097
6218
|
}
|
|
6098
6219
|
function vectorIndexPath(vault) {
|
|
6099
|
-
return
|
|
6220
|
+
return join25(vault, ...VECTOR_INDEX_REL.split("/"));
|
|
6100
6221
|
}
|
|
6101
6222
|
function termFreq(tokens) {
|
|
6102
6223
|
const tf = /* @__PURE__ */ new Map();
|
|
@@ -6151,7 +6272,7 @@ async function buildVectorIndex(vault, now = (/* @__PURE__ */ new Date()).toISOS
|
|
|
6151
6272
|
docs
|
|
6152
6273
|
};
|
|
6153
6274
|
const dest = vectorIndexPath(vault);
|
|
6154
|
-
await mkdir5(
|
|
6275
|
+
await mkdir5(join25(vault, ".skillwiki", "vectors"), { recursive: true });
|
|
6155
6276
|
await atomicWriteText(dest, `${JSON.stringify(index)}
|
|
6156
6277
|
`);
|
|
6157
6278
|
return ok(index);
|
|
@@ -6194,7 +6315,7 @@ async function reindexPageInVectorIndex(vault, pageRelPath, now = (/* @__PURE__
|
|
|
6194
6315
|
if (!normalizedPage.endsWith(".md")) {
|
|
6195
6316
|
return err("USAGE", { message: `Page must be a .md file: ${pageRelPath}` });
|
|
6196
6317
|
}
|
|
6197
|
-
const absPath =
|
|
6318
|
+
const absPath = join25(vault, ...normalizedPage.split("/"));
|
|
6198
6319
|
let text;
|
|
6199
6320
|
try {
|
|
6200
6321
|
text = await readFile8(absPath, "utf8");
|
|
@@ -6279,7 +6400,7 @@ async function reindexPageInVectorIndex(vault, pageRelPath, now = (/* @__PURE__
|
|
|
6279
6400
|
}
|
|
6280
6401
|
}
|
|
6281
6402
|
const dest = vectorIndexPath(vault);
|
|
6282
|
-
await mkdir5(
|
|
6403
|
+
await mkdir5(join25(vault, ".skillwiki", "vectors"), { recursive: true });
|
|
6283
6404
|
await atomicWriteText(dest, `${JSON.stringify(index)}
|
|
6284
6405
|
`);
|
|
6285
6406
|
return ok({
|
|
@@ -6297,7 +6418,7 @@ async function pruneVectorIndex(vault, opts) {
|
|
|
6297
6418
|
const orphans = [];
|
|
6298
6419
|
for (const docKey of Object.keys(index.docs)) {
|
|
6299
6420
|
const normalizedKey = docKey.split(/\\|\//).join("/");
|
|
6300
|
-
const absPath =
|
|
6421
|
+
const absPath = join25(vault, ...normalizedKey.split("/"));
|
|
6301
6422
|
if (!existsSync21(absPath)) {
|
|
6302
6423
|
orphans.push(normalizedKey);
|
|
6303
6424
|
}
|
|
@@ -6344,7 +6465,7 @@ async function pruneVectorIndex(vault, opts) {
|
|
|
6344
6465
|
index.docs[docKey] = toTfIdf(termFreq(tokens), index.df, newPageCount);
|
|
6345
6466
|
} else {
|
|
6346
6467
|
try {
|
|
6347
|
-
const text = await readFile8(
|
|
6468
|
+
const text = await readFile8(join25(vault, ...docKey.split("/")), "utf8");
|
|
6348
6469
|
const tokens = extractPageTokens(text);
|
|
6349
6470
|
index.docs[docKey] = toTfIdf(termFreq(tokens), index.df, newPageCount);
|
|
6350
6471
|
} catch {
|
|
@@ -6354,7 +6475,7 @@ async function pruneVectorIndex(vault, opts) {
|
|
|
6354
6475
|
}
|
|
6355
6476
|
if (!opts?.dryRun) {
|
|
6356
6477
|
const dest = vectorIndexPath(vault);
|
|
6357
|
-
await mkdir5(
|
|
6478
|
+
await mkdir5(join25(vault, ".skillwiki", "vectors"), { recursive: true });
|
|
6358
6479
|
await atomicWriteText(dest, `${JSON.stringify(index)}
|
|
6359
6480
|
`);
|
|
6360
6481
|
}
|
|
@@ -6655,7 +6776,7 @@ function computeKeywordScore(terms, title, tags, body, relPath) {
|
|
|
6655
6776
|
return score;
|
|
6656
6777
|
}
|
|
6657
6778
|
async function loadOrBuildGraph(vault) {
|
|
6658
|
-
const graphPath =
|
|
6779
|
+
const graphPath = join26(vault, ".skillwiki", "graph.json");
|
|
6659
6780
|
let needsBuild = false;
|
|
6660
6781
|
try {
|
|
6661
6782
|
const fileStat = await stat4(graphPath);
|
|
@@ -6744,7 +6865,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
6744
6865
|
import { z } from "zod";
|
|
6745
6866
|
|
|
6746
6867
|
// src/mcp/vault-resolve.ts
|
|
6747
|
-
import { join as
|
|
6868
|
+
import { join as join27, resolve as resolve4 } from "path";
|
|
6748
6869
|
|
|
6749
6870
|
// src/mcp/allowlist.ts
|
|
6750
6871
|
import { resolve as resolve3, sep as sep3 } from "path";
|
|
@@ -6806,7 +6927,7 @@ async function resolveMcpVault(input) {
|
|
|
6806
6927
|
return ok({ vault: vaultPath, source });
|
|
6807
6928
|
}
|
|
6808
6929
|
function defaultGraphOut(vault) {
|
|
6809
|
-
return
|
|
6930
|
+
return join27(vault, ".skillwiki", "graph.json");
|
|
6810
6931
|
}
|
|
6811
6932
|
|
|
6812
6933
|
// src/mcp/result-format.ts
|
|
@@ -6823,7 +6944,7 @@ function formatToolResult(payload) {
|
|
|
6823
6944
|
// src/mcp/audit-log.ts
|
|
6824
6945
|
import { appendFileSync, mkdirSync as mkdirSync2 } from "fs";
|
|
6825
6946
|
import { homedir } from "os";
|
|
6826
|
-
import { join as
|
|
6947
|
+
import { join as join28 } from "path";
|
|
6827
6948
|
function auditEnabled() {
|
|
6828
6949
|
const v = process.env.SKILLWIKI_MCP_AUDIT;
|
|
6829
6950
|
if (v === "0" || v === "false") return false;
|
|
@@ -6835,7 +6956,7 @@ function auditSink() {
|
|
|
6835
6956
|
function auditFilePath() {
|
|
6836
6957
|
const custom = process.env.SKILLWIKI_MCP_AUDIT_FILE;
|
|
6837
6958
|
if (custom && custom.length > 0) return custom;
|
|
6838
|
-
return
|
|
6959
|
+
return join28(homedir(), ".skillwiki", "mcp-audit.jsonl");
|
|
6839
6960
|
}
|
|
6840
6961
|
function auditMcpToolCall(entry) {
|
|
6841
6962
|
if (!auditEnabled()) return;
|
|
@@ -6845,7 +6966,7 @@ function auditMcpToolCall(entry) {
|
|
|
6845
6966
|
return;
|
|
6846
6967
|
}
|
|
6847
6968
|
const path = auditFilePath();
|
|
6848
|
-
mkdirSync2(
|
|
6969
|
+
mkdirSync2(join28(path, ".."), { recursive: true });
|
|
6849
6970
|
appendFileSync(path, line, "utf8");
|
|
6850
6971
|
}
|
|
6851
6972
|
async function runMcpToolHandler(tool, input, fn) {
|
|
@@ -7120,7 +7241,7 @@ function registerMcpMutatingTools(server) {
|
|
|
7120
7241
|
|
|
7121
7242
|
// src/mcp/resources.ts
|
|
7122
7243
|
import { readFile as readFile11 } from "fs/promises";
|
|
7123
|
-
import { join as
|
|
7244
|
+
import { join as join30 } from "path";
|
|
7124
7245
|
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7125
7246
|
|
|
7126
7247
|
// src/mcp/lint-bucket.ts
|
|
@@ -7250,7 +7371,7 @@ async function fetchQueryPreview(input) {
|
|
|
7250
7371
|
|
|
7251
7372
|
// src/mcp/graph-html.ts
|
|
7252
7373
|
import { readFile as readFile10 } from "fs/promises";
|
|
7253
|
-
import { join as
|
|
7374
|
+
import { join as join29 } from "path";
|
|
7254
7375
|
import { existsSync as existsSync22 } from "fs";
|
|
7255
7376
|
var TYPE_COLORS = {
|
|
7256
7377
|
entities: "#e74c3c",
|
|
@@ -7319,7 +7440,7 @@ ${nodeSvg}
|
|
|
7319
7440
|
return { html, node_count: nodes.length, edge_count: edges.length, truncated };
|
|
7320
7441
|
}
|
|
7321
7442
|
async function fetchGraphHtmlReport(input) {
|
|
7322
|
-
const graphPath = input.graphPath ??
|
|
7443
|
+
const graphPath = input.graphPath ?? join29(input.vault, ".skillwiki", "graph.json");
|
|
7323
7444
|
const maxNodes = Math.min(Math.max(10, input.maxNodes ?? 120), 500);
|
|
7324
7445
|
if (!existsSync22(graphPath)) {
|
|
7325
7446
|
return {
|
|
@@ -7393,7 +7514,7 @@ async function fetchStaleSummary(input) {
|
|
|
7393
7514
|
|
|
7394
7515
|
// src/mcp/resources.ts
|
|
7395
7516
|
async function readVaultFile(vault, rel) {
|
|
7396
|
-
return readFile11(
|
|
7517
|
+
return readFile11(join30(vault, rel), "utf8");
|
|
7397
7518
|
}
|
|
7398
7519
|
async function tailLines(text, lines) {
|
|
7399
7520
|
const parts = text.split(/\r?\n/);
|
|
@@ -7479,7 +7600,7 @@ function registerMcpResources(server) {
|
|
|
7479
7600
|
if (!v.ok) {
|
|
7480
7601
|
return { contents: [{ uri: uri.href, mimeType: "text/plain", text: JSON.stringify(v) }] };
|
|
7481
7602
|
}
|
|
7482
|
-
const path =
|
|
7603
|
+
const path = join30(v.data.vault, ".skillwiki", "graph.json");
|
|
7483
7604
|
try {
|
|
7484
7605
|
const raw = await readFile11(path, "utf8");
|
|
7485
7606
|
const graph = JSON.parse(raw);
|
|
@@ -7830,6 +7951,12 @@ export {
|
|
|
7830
7951
|
renderProjectIndex,
|
|
7831
7952
|
runProjectIndex,
|
|
7832
7953
|
scanConflictMarkerBlocksInText,
|
|
7954
|
+
MCP_URL_ENV,
|
|
7955
|
+
MCP_TOKEN_ENV,
|
|
7956
|
+
MCP_HOST_ID_ENV,
|
|
7957
|
+
nonEmptyEnvValue,
|
|
7958
|
+
mergeMcpAuthIntoEnv,
|
|
7959
|
+
redactMcpSecret,
|
|
7833
7960
|
configPath,
|
|
7834
7961
|
runConfigGet,
|
|
7835
7962
|
runConfigSet,
|
|
@@ -7843,7 +7970,9 @@ export {
|
|
|
7843
7970
|
satelliteLatestRunPath,
|
|
7844
7971
|
isFailedRunStatus,
|
|
7845
7972
|
readSatelliteLatestRunFromText,
|
|
7846
|
-
|
|
7973
|
+
readSatelliteLatestRunAt,
|
|
7974
|
+
evaluateSatelliteRunHealthState,
|
|
7975
|
+
DEFAULT_MCP_URL,
|
|
7847
7976
|
runDoctor,
|
|
7848
7977
|
readCliPackageJson,
|
|
7849
7978
|
DEFAULT_DIRTY_VOLUME_THRESHOLD,
|