skillwiki 0.10.100 → 0.10.102
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-B4QTKCEK.js → chunk-7UK67FAZ.js} +3 -1
- package/dist/{chunk-3QT3OFAL.js → chunk-PIXBNB74.js} +307 -185
- package/dist/cli.js +526 -271
- package/dist/{managed-write-preflight-32523BPV.js → managed-write-preflight-NS7OQ2Y7.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-7UK67FAZ.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";
|
|
@@ -3813,7 +3918,7 @@ var satelliteProbe = {
|
|
|
3813
3918
|
|
|
3814
3919
|
// src/doctor/probes/metrics.ts
|
|
3815
3920
|
import { readFileSync as readFileSync10 } from "fs";
|
|
3816
|
-
import { join as
|
|
3921
|
+
import { join as join18 } from "path";
|
|
3817
3922
|
var METRIC_TYPES = ["entities", "concepts", "comparisons", "queries", "meta"];
|
|
3818
3923
|
function doctorReadOnlyScanRoot(resolvedPath) {
|
|
3819
3924
|
return resolveReadOnlyVaultRoot(resolvedPath).root;
|
|
@@ -3857,7 +3962,7 @@ async function vaultMetrics(resolvedPath) {
|
|
|
3857
3962
|
}
|
|
3858
3963
|
let logLines = 0;
|
|
3859
3964
|
try {
|
|
3860
|
-
logLines = readFileSync10(
|
|
3965
|
+
logLines = readFileSync10(join18(scanRoot, "log.md"), "utf8").split("\n").length;
|
|
3861
3966
|
} catch {
|
|
3862
3967
|
}
|
|
3863
3968
|
return [
|
|
@@ -3993,18 +4098,18 @@ var fuseStalenessProbe = {
|
|
|
3993
4098
|
|
|
3994
4099
|
// src/doctor/probes/activation-marker.ts
|
|
3995
4100
|
import { existsSync as existsSync15, readFileSync as readFileSync11, readdirSync as readdirSync5 } from "fs";
|
|
3996
|
-
import { join as
|
|
4101
|
+
import { join as join19 } from "path";
|
|
3997
4102
|
var GROK_ACTIVATION_REFERENCE2 = "Read @~/.grok/skillwiki.md for SkillWiki activation context.";
|
|
3998
4103
|
var STALE_GROK_ACTIVATION_REFERENCE2 = "Read @skillwiki.md";
|
|
3999
4104
|
var ACTIVATION_FIX_HINT2 = "run `npm run install:activation` from the llm-wiki repo";
|
|
4000
4105
|
function findGrokActivationTemplate2(home, cwd) {
|
|
4001
4106
|
if (cwd) {
|
|
4002
|
-
const src =
|
|
4107
|
+
const src = join19(cwd, "packages", "skills", "using-skillwiki", "activation.md");
|
|
4003
4108
|
if (existsSync15(src)) return src;
|
|
4004
|
-
const directSrc =
|
|
4109
|
+
const directSrc = join19(cwd, "skills", "using-skillwiki", "activation.md");
|
|
4005
4110
|
if (existsSync15(directSrc)) return directSrc;
|
|
4006
4111
|
}
|
|
4007
|
-
const pluginsRoot =
|
|
4112
|
+
const pluginsRoot = join19(home, ".grok", "installed-plugins");
|
|
4008
4113
|
if (!existsSync15(pluginsRoot)) return void 0;
|
|
4009
4114
|
let entries;
|
|
4010
4115
|
try {
|
|
@@ -4014,21 +4119,21 @@ function findGrokActivationTemplate2(home, cwd) {
|
|
|
4014
4119
|
}
|
|
4015
4120
|
for (const entry of entries) {
|
|
4016
4121
|
if (!entry.isDirectory()) continue;
|
|
4017
|
-
const root =
|
|
4122
|
+
const root = join19(pluginsRoot, entry.name);
|
|
4018
4123
|
for (const rel of ["using-skillwiki/activation.md", "skills/using-skillwiki/activation.md"]) {
|
|
4019
|
-
const candidate =
|
|
4124
|
+
const candidate = join19(root, rel);
|
|
4020
4125
|
if (existsSync15(candidate)) return candidate;
|
|
4021
4126
|
}
|
|
4022
4127
|
}
|
|
4023
4128
|
return void 0;
|
|
4024
4129
|
}
|
|
4025
4130
|
function checkActivationMarker(home, cwd) {
|
|
4026
|
-
const grokDir =
|
|
4131
|
+
const grokDir = join19(home, ".grok");
|
|
4027
4132
|
if (!existsSync15(grokDir)) {
|
|
4028
4133
|
return check("pass", "activation_marker", "Activation marker", "Not a Grok host \u2014 check skipped");
|
|
4029
4134
|
}
|
|
4030
|
-
const activationPath =
|
|
4031
|
-
const agentsPath =
|
|
4135
|
+
const activationPath = join19(grokDir, "skillwiki.md");
|
|
4136
|
+
const agentsPath = join19(grokDir, "AGENTS.md");
|
|
4032
4137
|
const hasActivation = existsSync15(activationPath);
|
|
4033
4138
|
const issues = [];
|
|
4034
4139
|
if (!hasActivation) {
|
|
@@ -4085,7 +4190,7 @@ var activationMarkerProbe = {
|
|
|
4085
4190
|
|
|
4086
4191
|
// src/doctor/probes/ds-store-noise.ts
|
|
4087
4192
|
import { existsSync as existsSync16, readdirSync as readdirSync6 } from "fs";
|
|
4088
|
-
import { join as
|
|
4193
|
+
import { join as join20 } from "path";
|
|
4089
4194
|
var VAULT_TRACKED_DIRS = ["raw", "entities", "concepts", "comparisons", "queries", "meta", "_archive", "_Templates"];
|
|
4090
4195
|
function checkDsStoreNoise(resolvedPath) {
|
|
4091
4196
|
if (resolvedPath === void 0) {
|
|
@@ -4107,13 +4212,13 @@ function checkDsStoreNoise(resolvedPath) {
|
|
|
4107
4212
|
found.push(rel ? `${rel}/.DS_Store` : ".DS_Store");
|
|
4108
4213
|
} else if (entry.isDirectory()) {
|
|
4109
4214
|
if (entry.name === ".git" || entry.name === "node_modules") continue;
|
|
4110
|
-
walk(
|
|
4215
|
+
walk(join20(dir, entry.name), rel ? `${rel}/${entry.name}` : entry.name);
|
|
4111
4216
|
}
|
|
4112
4217
|
}
|
|
4113
4218
|
}
|
|
4114
4219
|
let scannedAny = false;
|
|
4115
4220
|
for (const sub of VAULT_TRACKED_DIRS) {
|
|
4116
|
-
const subDir =
|
|
4221
|
+
const subDir = join20(resolvedPath, sub);
|
|
4117
4222
|
if (existsSync16(subDir)) {
|
|
4118
4223
|
scannedAny = true;
|
|
4119
4224
|
walk(subDir, sub);
|
|
@@ -4143,17 +4248,14 @@ var dsStoreNoiseProbe = {
|
|
|
4143
4248
|
|
|
4144
4249
|
// src/doctor/probes/mcp-handshake.ts
|
|
4145
4250
|
import { existsSync as existsSync17 } from "fs";
|
|
4146
|
-
import { join as
|
|
4251
|
+
import { join as join21 } from "path";
|
|
4147
4252
|
var DEFAULT_MCP_URL = "https://wiki.karldigi.dev/mcp";
|
|
4148
|
-
var URL_ENV = "SKILLWIKI_MCP_URL";
|
|
4149
|
-
var TOKEN_ENV = "SKILLWIKI_MCP_TOKEN";
|
|
4150
4253
|
function mcpEnv(ctx) {
|
|
4151
4254
|
return ctx.input.env ?? process.env;
|
|
4152
4255
|
}
|
|
4153
4256
|
function checkMcpUrl(ctx) {
|
|
4154
|
-
const
|
|
4155
|
-
|
|
4156
|
-
if (typeof override === "string" && override.trim().length > 0) {
|
|
4257
|
+
const creds = mcpAuthFromEnv(mcpEnv(ctx));
|
|
4258
|
+
if (creds.url) {
|
|
4157
4259
|
return check("pass", "mcp_url_configured", "HTTP MCP URL", "configured via env override");
|
|
4158
4260
|
}
|
|
4159
4261
|
return check(
|
|
@@ -4164,21 +4266,20 @@ function checkMcpUrl(ctx) {
|
|
|
4164
4266
|
);
|
|
4165
4267
|
}
|
|
4166
4268
|
function checkMcpCredential(ctx) {
|
|
4167
|
-
const
|
|
4168
|
-
|
|
4169
|
-
if (typeof value === "string" && value.trim().length > 0) {
|
|
4269
|
+
const creds = mcpAuthFromEnv(mcpEnv(ctx));
|
|
4270
|
+
if (creds.token) {
|
|
4170
4271
|
return check("pass", "mcp_credential_present", "HTTP MCP auth", "present");
|
|
4171
4272
|
}
|
|
4172
4273
|
return check(
|
|
4173
4274
|
"warn",
|
|
4174
4275
|
"mcp_credential_present",
|
|
4175
4276
|
"HTTP MCP auth",
|
|
4176
|
-
"not set \u2014 set in process env or host Configure (value not shown)"
|
|
4277
|
+
"not set \u2014 set in process env, ~/.skillwiki/.env, or host Configure (value not shown)"
|
|
4177
4278
|
);
|
|
4178
4279
|
}
|
|
4179
4280
|
function checkFrozenLeafWritePath(ctx) {
|
|
4180
4281
|
const vault = ctx.resolvedPath;
|
|
4181
|
-
if (!vault || !existsSync17(
|
|
4282
|
+
if (!vault || !existsSync17(join21(vault, ".WIKI_GIT_FROZEN"))) {
|
|
4182
4283
|
return check(
|
|
4183
4284
|
"pass",
|
|
4184
4285
|
"mcp_frozen_leaf_write_path",
|
|
@@ -4210,8 +4311,7 @@ function versionLessThan(a, b) {
|
|
|
4210
4311
|
return pa.patch < pb.patch;
|
|
4211
4312
|
}
|
|
4212
4313
|
function redactSecret(detail, secret) {
|
|
4213
|
-
|
|
4214
|
-
return detail.split(secret).join("[REDACTED]");
|
|
4314
|
+
return redactMcpSecret(detail, secret);
|
|
4215
4315
|
}
|
|
4216
4316
|
function handshakeRow(status, detail, secret) {
|
|
4217
4317
|
return check(status, HANDSHAKE_ID, HANDSHAKE_LABEL, redactSecret(detail, secret));
|
|
@@ -4269,9 +4369,10 @@ async function checkMcpHandshake(ctx) {
|
|
|
4269
4369
|
return handshakeRow("pass", "not requested \u2014 check skipped");
|
|
4270
4370
|
}
|
|
4271
4371
|
const env = mcpEnv(ctx);
|
|
4272
|
-
const
|
|
4273
|
-
const
|
|
4274
|
-
|
|
4372
|
+
const creds = mcpAuthFromEnv(env);
|
|
4373
|
+
const url = creds.url ?? DEFAULT_MCP_URL;
|
|
4374
|
+
const token = creds.token ?? "";
|
|
4375
|
+
if (token.length === 0) {
|
|
4275
4376
|
return handshakeRow("error", "auth not set \u2014 handshake not attempted (value not shown)");
|
|
4276
4377
|
}
|
|
4277
4378
|
const fetchFn = ctx.input.mcpFetch ?? globalThis.fetch;
|
|
@@ -4304,7 +4405,7 @@ async function checkMcpHandshake(ctx) {
|
|
|
4304
4405
|
init.sessionId
|
|
4305
4406
|
);
|
|
4306
4407
|
const tools = toolNames(listed.result);
|
|
4307
|
-
const frozen = Boolean(ctx.resolvedPath && existsSync17(
|
|
4408
|
+
const frozen = Boolean(ctx.resolvedPath && existsSync17(join21(ctx.resolvedPath, ".WIKI_GIT_FROZEN")));
|
|
4308
4409
|
if (frozen && !tools.includes(WORKITEM_TOOL)) {
|
|
4309
4410
|
return handshakeRow(
|
|
4310
4411
|
"error",
|
|
@@ -4377,6 +4478,10 @@ var DoctorRunner = class {
|
|
|
4377
4478
|
async run(input) {
|
|
4378
4479
|
const devSourceRun = isDevSourceRun(input.argv);
|
|
4379
4480
|
const vsConfig = readVaultSyncConfig(input.home);
|
|
4481
|
+
const baseEnv = input.env ?? process.env;
|
|
4482
|
+
const mergedEnv = await mergeMcpAuthIntoEnv(input.home, baseEnv);
|
|
4483
|
+
const auth = mcpAuthFromEnv(mergedEnv);
|
|
4484
|
+
const inputWithEnv = { ...input, env: mergedEnv };
|
|
4380
4485
|
const resolved = await resolveRuntimePath({
|
|
4381
4486
|
flag: void 0,
|
|
4382
4487
|
envValue: input.envValue,
|
|
@@ -4385,9 +4490,14 @@ var DoctorRunner = class {
|
|
|
4385
4490
|
});
|
|
4386
4491
|
const resolvedPath = resolved.ok ? resolved.data.path : void 0;
|
|
4387
4492
|
const gitCheckPath = vsConfig.role === "snapshotter" ? resolveSnapshotGitWorktree(input.home) ?? resolvedPath : resolvedPath;
|
|
4493
|
+
const mcpOnlyLeaf = isMcpOnlyLeaf({
|
|
4494
|
+
resolvedPath,
|
|
4495
|
+
token: auth.token,
|
|
4496
|
+
vaultSyncInstalled: vsConfig.installed
|
|
4497
|
+
});
|
|
4388
4498
|
const fleetLoad = resolvedPath ? await loadFleetManifestAndHost({
|
|
4389
4499
|
vault: resolvedPath,
|
|
4390
|
-
env: { ...
|
|
4500
|
+
env: { ...mergedEnv, WIKI_PATH: input.envValue ?? resolvedPath },
|
|
4391
4501
|
home: input.home,
|
|
4392
4502
|
cwd: input.cwd,
|
|
4393
4503
|
osHostname: process.env.HOSTNAME,
|
|
@@ -4396,7 +4506,7 @@ var DoctorRunner = class {
|
|
|
4396
4506
|
const satelliteGate = satelliteGateFromFleetLoad(fleetLoad);
|
|
4397
4507
|
const readOnlyScanRoot = resolvedPath ? doctorReadOnlyScanRoot(resolvedPath) : void 0;
|
|
4398
4508
|
const ctx = {
|
|
4399
|
-
input,
|
|
4509
|
+
input: inputWithEnv,
|
|
4400
4510
|
devSourceRun,
|
|
4401
4511
|
vsConfig,
|
|
4402
4512
|
resolvedPath,
|
|
@@ -4404,13 +4514,18 @@ var DoctorRunner = class {
|
|
|
4404
4514
|
gitCheckPath,
|
|
4405
4515
|
fleetLoad,
|
|
4406
4516
|
readOnlyScanRoot,
|
|
4407
|
-
satelliteGate
|
|
4517
|
+
satelliteGate,
|
|
4518
|
+
mcpOnlyLeaf
|
|
4408
4519
|
};
|
|
4409
|
-
const
|
|
4520
|
+
const rawChecks = [];
|
|
4410
4521
|
for (const probe of this.probes) {
|
|
4411
4522
|
const probeChecks = await probe.run(ctx);
|
|
4412
|
-
|
|
4523
|
+
rawChecks.push(...probeChecks);
|
|
4413
4524
|
}
|
|
4525
|
+
const checks = rawChecks.map((c) => ({
|
|
4526
|
+
...c,
|
|
4527
|
+
detail: redactMcpSecret(c.detail, auth.token)
|
|
4528
|
+
}));
|
|
4414
4529
|
const summary = {
|
|
4415
4530
|
pass: checks.filter((c) => c.status === "pass").length,
|
|
4416
4531
|
info: checks.filter((c) => c.status === "info").length,
|
|
@@ -4429,7 +4544,7 @@ var DoctorRunner = class {
|
|
|
4429
4544
|
if (summary.info > 0) summaryParts.push(`${summary.info} info`);
|
|
4430
4545
|
summaryParts.push(`${summary.warn} warn`, `${summary.error} error`);
|
|
4431
4546
|
lines.push(summaryParts.join(" \xB7 "));
|
|
4432
|
-
const humanHint = lines.join("\n");
|
|
4547
|
+
const humanHint = redactMcpSecret(lines.join("\n"), auth.token);
|
|
4433
4548
|
return { exitCode, result: ok({ checks, summary, humanHint }) };
|
|
4434
4549
|
}
|
|
4435
4550
|
};
|
|
@@ -4461,7 +4576,7 @@ function readCliPackageJson(baseUrl = import.meta.url) {
|
|
|
4461
4576
|
// src/utils/vault-write-gates.ts
|
|
4462
4577
|
import { execFileSync } from "child_process";
|
|
4463
4578
|
import { existsSync as existsSync19, readdirSync as readdirSync7, readFileSync as readFileSync13, statSync as statSync3 } from "fs";
|
|
4464
|
-
import { join as
|
|
4579
|
+
import { join as join22, relative as relative2 } from "path";
|
|
4465
4580
|
var DEFAULT_DIRTY_VOLUME_THRESHOLD = 50;
|
|
4466
4581
|
var DEFAULT_CAPTURE_BUDGET = 20;
|
|
4467
4582
|
var DEFAULT_NO_DECISION_STREAK = 3;
|
|
@@ -4517,7 +4632,7 @@ function isEventLedgerPath(rel) {
|
|
|
4517
4632
|
return n === "meta/log-events" || n.startsWith("meta/log-events/");
|
|
4518
4633
|
}
|
|
4519
4634
|
function countEventLedgerFiles(vault) {
|
|
4520
|
-
return listFilesRecursive(
|
|
4635
|
+
return listFilesRecursive(join22(vault, "meta", "log-events")).length;
|
|
4521
4636
|
}
|
|
4522
4637
|
function measureDirtyVolume(vault) {
|
|
4523
4638
|
const empty = (extra = {}) => ({
|
|
@@ -4577,7 +4692,7 @@ function measureDirtyVolume(vault) {
|
|
|
4577
4692
|
if (!rel) continue;
|
|
4578
4693
|
if (code === "??") {
|
|
4579
4694
|
untracked += 1;
|
|
4580
|
-
const abs =
|
|
4695
|
+
const abs = join22(vault, rel);
|
|
4581
4696
|
if (existsSync19(abs) && statSync3(abs).isDirectory()) {
|
|
4582
4697
|
const files = listFilesRecursive(abs);
|
|
4583
4698
|
expanded += files.length;
|
|
@@ -4621,7 +4736,7 @@ function listFilesRecursive(dir) {
|
|
|
4621
4736
|
}
|
|
4622
4737
|
for (const name of entries) {
|
|
4623
4738
|
if (name === ".git") continue;
|
|
4624
|
-
const p =
|
|
4739
|
+
const p = join22(dir, name);
|
|
4625
4740
|
try {
|
|
4626
4741
|
const st = statSync3(p);
|
|
4627
4742
|
if (st.isDirectory()) out.push(...listFilesRecursive(p));
|
|
@@ -4752,7 +4867,7 @@ function listProjectDayCaptures(vault, project, day) {
|
|
|
4752
4867
|
return;
|
|
4753
4868
|
}
|
|
4754
4869
|
for (const name of entries) {
|
|
4755
|
-
const abs =
|
|
4870
|
+
const abs = join22(dir, name);
|
|
4756
4871
|
const rel = relBase ? `${relBase}/${name}` : name;
|
|
4757
4872
|
try {
|
|
4758
4873
|
const st = statSync3(abs);
|
|
@@ -4762,16 +4877,16 @@ function listProjectDayCaptures(vault, project, day) {
|
|
|
4762
4877
|
}
|
|
4763
4878
|
}
|
|
4764
4879
|
};
|
|
4765
|
-
walk(
|
|
4766
|
-
walk(
|
|
4767
|
-
walk(
|
|
4768
|
-
const workRoot =
|
|
4880
|
+
walk(join22(vault, "raw", "transcripts"), "raw/transcripts");
|
|
4881
|
+
walk(join22(vault, "projects", slug, "raw", "transcripts"), `projects/${slug}/raw/transcripts`);
|
|
4882
|
+
walk(join22(vault, "projects", slug, "requirements"), `projects/${slug}/requirements`);
|
|
4883
|
+
const workRoot = join22(vault, "projects", slug, "work");
|
|
4769
4884
|
if (existsSync19(workRoot)) {
|
|
4770
4885
|
try {
|
|
4771
4886
|
for (const name of readdirSync7(workRoot)) {
|
|
4772
4887
|
if (!name.startsWith(day)) continue;
|
|
4773
4888
|
if (!/investigate|pilot-q|research|cycle|dev-loop/.test(name)) continue;
|
|
4774
|
-
const abs =
|
|
4889
|
+
const abs = join22(workRoot, name);
|
|
4775
4890
|
if (statSync3(abs).isDirectory()) {
|
|
4776
4891
|
for (const f of listFilesRecursive(abs)) {
|
|
4777
4892
|
const rel = relative2(vault, f).replace(/\\/g, "/");
|
|
@@ -4877,7 +4992,7 @@ function runWritePreflight(input) {
|
|
|
4877
4992
|
// src/commands/observe.ts
|
|
4878
4993
|
import { mkdir as mkdir3, writeFile as writeFile2 } from "fs/promises";
|
|
4879
4994
|
import { existsSync as existsSync20, statSync as statSync4 } from "fs";
|
|
4880
|
-
import { join as
|
|
4995
|
+
import { join as join23 } from "path";
|
|
4881
4996
|
import { createHash as createHash2 } from "crypto";
|
|
4882
4997
|
var ALLOWED_KINDS = /* @__PURE__ */ new Set(["note", "bug", "task", "idea", "session-log"]);
|
|
4883
4998
|
function slugify(text) {
|
|
@@ -4926,7 +5041,7 @@ async function runObserve(input) {
|
|
|
4926
5041
|
};
|
|
4927
5042
|
}
|
|
4928
5043
|
}
|
|
4929
|
-
const transcriptsDir =
|
|
5044
|
+
const transcriptsDir = join23(input.vault, "raw", "transcripts");
|
|
4930
5045
|
try {
|
|
4931
5046
|
await mkdir3(transcriptsDir, { recursive: true });
|
|
4932
5047
|
} catch {
|
|
@@ -4938,7 +5053,7 @@ async function runObserve(input) {
|
|
|
4938
5053
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
4939
5054
|
const slug = slugify(input.text);
|
|
4940
5055
|
const fileName = `${today}-observation-${slug}.md`;
|
|
4941
|
-
const filePath =
|
|
5056
|
+
const filePath = join23(transcriptsDir, fileName);
|
|
4942
5057
|
const body = `
|
|
4943
5058
|
${input.text.trim()}
|
|
4944
5059
|
`;
|
|
@@ -4980,7 +5095,7 @@ ${input.text.trim()}
|
|
|
4980
5095
|
// src/commands/memory.ts
|
|
4981
5096
|
import { createHash as createHash3 } from "crypto";
|
|
4982
5097
|
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
|
|
5098
|
+
import { basename as basename2, extname, join as join24, relative as relative3, sep as sep2 } from "path";
|
|
4984
5099
|
|
|
4985
5100
|
// src/utils/memory-authority.ts
|
|
4986
5101
|
var TIER_RANK = {
|
|
@@ -5099,8 +5214,8 @@ async function runMemoryIndex(input) {
|
|
|
5099
5214
|
}
|
|
5100
5215
|
const generatedAt = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
5101
5216
|
const relCachePath = memoryCacheRelPath(input.project);
|
|
5102
|
-
const absCachePath =
|
|
5103
|
-
await mkdir4(
|
|
5217
|
+
const absCachePath = join24(input.vault, relCachePath);
|
|
5218
|
+
await mkdir4(join24(input.vault, ".skillwiki", "memory", input.project), { recursive: true });
|
|
5104
5219
|
await writeFile3(absCachePath, `${JSON.stringify({
|
|
5105
5220
|
generated_at: generatedAt,
|
|
5106
5221
|
project: input.project,
|
|
@@ -5292,7 +5407,7 @@ async function buildMemoryIndexState(pages, project) {
|
|
|
5292
5407
|
}
|
|
5293
5408
|
async function checkMemoryIndex(vault, project, current) {
|
|
5294
5409
|
const relCachePath = memoryCacheRelPath(project);
|
|
5295
|
-
const cacheText = await readIfExists(
|
|
5410
|
+
const cacheText = await readIfExists(join24(vault, relCachePath));
|
|
5296
5411
|
if (!cacheText) {
|
|
5297
5412
|
return {
|
|
5298
5413
|
ok: true,
|
|
@@ -5701,7 +5816,7 @@ async function walkImportFiles(dir, out) {
|
|
|
5701
5816
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
5702
5817
|
for (const entry of entries) {
|
|
5703
5818
|
if (entry.name === ".git" || entry.name === "node_modules") continue;
|
|
5704
|
-
const path =
|
|
5819
|
+
const path = join24(dir, entry.name);
|
|
5705
5820
|
if (entry.isDirectory()) {
|
|
5706
5821
|
await walkImportFiles(path, out);
|
|
5707
5822
|
} else if (entry.isFile() && isImportCandidate(path)) {
|
|
@@ -5768,8 +5883,8 @@ async function writeImportCapture(vault, entry, today) {
|
|
|
5768
5883
|
const content = hiddenString(entry, "__content");
|
|
5769
5884
|
const project = hiddenString(entry, "__project");
|
|
5770
5885
|
const relPath = await availableImportPath(vault, entry.proposed_path);
|
|
5771
|
-
const absPath =
|
|
5772
|
-
await mkdir4(
|
|
5886
|
+
const absPath = join24(vault, relPath);
|
|
5887
|
+
await mkdir4(join24(vault, "raw", "transcripts"), { recursive: true });
|
|
5773
5888
|
await writeFile3(absPath, renderImportCapture(entry, content, project, today), "utf8");
|
|
5774
5889
|
const validation = await runValidate({ file: absPath });
|
|
5775
5890
|
return {
|
|
@@ -5785,7 +5900,7 @@ async function availableImportPath(vault, proposed) {
|
|
|
5785
5900
|
const stem = proposed.slice(0, -ext.length);
|
|
5786
5901
|
let candidate = proposed;
|
|
5787
5902
|
let i = 2;
|
|
5788
|
-
while (await readIfExists(
|
|
5903
|
+
while (await readIfExists(join24(vault, candidate))) {
|
|
5789
5904
|
candidate = `${stem}-${i}${ext}`;
|
|
5790
5905
|
i++;
|
|
5791
5906
|
}
|
|
@@ -5970,10 +6085,10 @@ function memoryCacheRelPath(project) {
|
|
|
5970
6085
|
}
|
|
5971
6086
|
async function readMemoryCache(vault, project) {
|
|
5972
6087
|
if (project) {
|
|
5973
|
-
const projectCache = await readIfExists(
|
|
6088
|
+
const projectCache = await readIfExists(join24(vault, memoryCacheRelPath(project)));
|
|
5974
6089
|
if (projectCache) return projectCache;
|
|
5975
6090
|
}
|
|
5976
|
-
return readIfExists(
|
|
6091
|
+
return readIfExists(join24(vault, ".skillwiki", "memory-topics.json"));
|
|
5977
6092
|
}
|
|
5978
6093
|
function dedupePages(pages) {
|
|
5979
6094
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -6065,7 +6180,7 @@ function slugify2(value) {
|
|
|
6065
6180
|
|
|
6066
6181
|
// src/commands/query.ts
|
|
6067
6182
|
import { readFile as readFile9, stat as stat4 } from "fs/promises";
|
|
6068
|
-
import { join as
|
|
6183
|
+
import { join as join26 } from "path";
|
|
6069
6184
|
|
|
6070
6185
|
// src/utils/rrf.ts
|
|
6071
6186
|
var RRF_K = 60;
|
|
@@ -6081,7 +6196,7 @@ function fuseRankings(lists, k = RRF_K) {
|
|
|
6081
6196
|
|
|
6082
6197
|
// src/utils/vector-index.ts
|
|
6083
6198
|
import { mkdir as mkdir5, readFile as readFile8, stat as stat3 } from "fs/promises";
|
|
6084
|
-
import { join as
|
|
6199
|
+
import { join as join25 } from "path";
|
|
6085
6200
|
import { existsSync as existsSync21 } from "fs";
|
|
6086
6201
|
var VECTOR_INDEX_REL = ".skillwiki/vectors/index.json";
|
|
6087
6202
|
var VECTOR_INDEX_SCHEMA = "skillwiki-tfidf-index/v1";
|
|
@@ -6096,7 +6211,7 @@ function extractPageTokens(text) {
|
|
|
6096
6211
|
return tokenize(`${title} ${body}`);
|
|
6097
6212
|
}
|
|
6098
6213
|
function vectorIndexPath(vault) {
|
|
6099
|
-
return
|
|
6214
|
+
return join25(vault, ...VECTOR_INDEX_REL.split("/"));
|
|
6100
6215
|
}
|
|
6101
6216
|
function termFreq(tokens) {
|
|
6102
6217
|
const tf = /* @__PURE__ */ new Map();
|
|
@@ -6151,7 +6266,7 @@ async function buildVectorIndex(vault, now = (/* @__PURE__ */ new Date()).toISOS
|
|
|
6151
6266
|
docs
|
|
6152
6267
|
};
|
|
6153
6268
|
const dest = vectorIndexPath(vault);
|
|
6154
|
-
await mkdir5(
|
|
6269
|
+
await mkdir5(join25(vault, ".skillwiki", "vectors"), { recursive: true });
|
|
6155
6270
|
await atomicWriteText(dest, `${JSON.stringify(index)}
|
|
6156
6271
|
`);
|
|
6157
6272
|
return ok(index);
|
|
@@ -6194,7 +6309,7 @@ async function reindexPageInVectorIndex(vault, pageRelPath, now = (/* @__PURE__
|
|
|
6194
6309
|
if (!normalizedPage.endsWith(".md")) {
|
|
6195
6310
|
return err("USAGE", { message: `Page must be a .md file: ${pageRelPath}` });
|
|
6196
6311
|
}
|
|
6197
|
-
const absPath =
|
|
6312
|
+
const absPath = join25(vault, ...normalizedPage.split("/"));
|
|
6198
6313
|
let text;
|
|
6199
6314
|
try {
|
|
6200
6315
|
text = await readFile8(absPath, "utf8");
|
|
@@ -6279,7 +6394,7 @@ async function reindexPageInVectorIndex(vault, pageRelPath, now = (/* @__PURE__
|
|
|
6279
6394
|
}
|
|
6280
6395
|
}
|
|
6281
6396
|
const dest = vectorIndexPath(vault);
|
|
6282
|
-
await mkdir5(
|
|
6397
|
+
await mkdir5(join25(vault, ".skillwiki", "vectors"), { recursive: true });
|
|
6283
6398
|
await atomicWriteText(dest, `${JSON.stringify(index)}
|
|
6284
6399
|
`);
|
|
6285
6400
|
return ok({
|
|
@@ -6297,7 +6412,7 @@ async function pruneVectorIndex(vault, opts) {
|
|
|
6297
6412
|
const orphans = [];
|
|
6298
6413
|
for (const docKey of Object.keys(index.docs)) {
|
|
6299
6414
|
const normalizedKey = docKey.split(/\\|\//).join("/");
|
|
6300
|
-
const absPath =
|
|
6415
|
+
const absPath = join25(vault, ...normalizedKey.split("/"));
|
|
6301
6416
|
if (!existsSync21(absPath)) {
|
|
6302
6417
|
orphans.push(normalizedKey);
|
|
6303
6418
|
}
|
|
@@ -6344,7 +6459,7 @@ async function pruneVectorIndex(vault, opts) {
|
|
|
6344
6459
|
index.docs[docKey] = toTfIdf(termFreq(tokens), index.df, newPageCount);
|
|
6345
6460
|
} else {
|
|
6346
6461
|
try {
|
|
6347
|
-
const text = await readFile8(
|
|
6462
|
+
const text = await readFile8(join25(vault, ...docKey.split("/")), "utf8");
|
|
6348
6463
|
const tokens = extractPageTokens(text);
|
|
6349
6464
|
index.docs[docKey] = toTfIdf(termFreq(tokens), index.df, newPageCount);
|
|
6350
6465
|
} catch {
|
|
@@ -6354,7 +6469,7 @@ async function pruneVectorIndex(vault, opts) {
|
|
|
6354
6469
|
}
|
|
6355
6470
|
if (!opts?.dryRun) {
|
|
6356
6471
|
const dest = vectorIndexPath(vault);
|
|
6357
|
-
await mkdir5(
|
|
6472
|
+
await mkdir5(join25(vault, ".skillwiki", "vectors"), { recursive: true });
|
|
6358
6473
|
await atomicWriteText(dest, `${JSON.stringify(index)}
|
|
6359
6474
|
`);
|
|
6360
6475
|
}
|
|
@@ -6655,7 +6770,7 @@ function computeKeywordScore(terms, title, tags, body, relPath) {
|
|
|
6655
6770
|
return score;
|
|
6656
6771
|
}
|
|
6657
6772
|
async function loadOrBuildGraph(vault) {
|
|
6658
|
-
const graphPath =
|
|
6773
|
+
const graphPath = join26(vault, ".skillwiki", "graph.json");
|
|
6659
6774
|
let needsBuild = false;
|
|
6660
6775
|
try {
|
|
6661
6776
|
const fileStat = await stat4(graphPath);
|
|
@@ -6744,7 +6859,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
6744
6859
|
import { z } from "zod";
|
|
6745
6860
|
|
|
6746
6861
|
// src/mcp/vault-resolve.ts
|
|
6747
|
-
import { join as
|
|
6862
|
+
import { join as join27, resolve as resolve4 } from "path";
|
|
6748
6863
|
|
|
6749
6864
|
// src/mcp/allowlist.ts
|
|
6750
6865
|
import { resolve as resolve3, sep as sep3 } from "path";
|
|
@@ -6806,7 +6921,7 @@ async function resolveMcpVault(input) {
|
|
|
6806
6921
|
return ok({ vault: vaultPath, source });
|
|
6807
6922
|
}
|
|
6808
6923
|
function defaultGraphOut(vault) {
|
|
6809
|
-
return
|
|
6924
|
+
return join27(vault, ".skillwiki", "graph.json");
|
|
6810
6925
|
}
|
|
6811
6926
|
|
|
6812
6927
|
// src/mcp/result-format.ts
|
|
@@ -6823,7 +6938,7 @@ function formatToolResult(payload) {
|
|
|
6823
6938
|
// src/mcp/audit-log.ts
|
|
6824
6939
|
import { appendFileSync, mkdirSync as mkdirSync2 } from "fs";
|
|
6825
6940
|
import { homedir } from "os";
|
|
6826
|
-
import { join as
|
|
6941
|
+
import { join as join28 } from "path";
|
|
6827
6942
|
function auditEnabled() {
|
|
6828
6943
|
const v = process.env.SKILLWIKI_MCP_AUDIT;
|
|
6829
6944
|
if (v === "0" || v === "false") return false;
|
|
@@ -6835,7 +6950,7 @@ function auditSink() {
|
|
|
6835
6950
|
function auditFilePath() {
|
|
6836
6951
|
const custom = process.env.SKILLWIKI_MCP_AUDIT_FILE;
|
|
6837
6952
|
if (custom && custom.length > 0) return custom;
|
|
6838
|
-
return
|
|
6953
|
+
return join28(homedir(), ".skillwiki", "mcp-audit.jsonl");
|
|
6839
6954
|
}
|
|
6840
6955
|
function auditMcpToolCall(entry) {
|
|
6841
6956
|
if (!auditEnabled()) return;
|
|
@@ -6845,7 +6960,7 @@ function auditMcpToolCall(entry) {
|
|
|
6845
6960
|
return;
|
|
6846
6961
|
}
|
|
6847
6962
|
const path = auditFilePath();
|
|
6848
|
-
mkdirSync2(
|
|
6963
|
+
mkdirSync2(join28(path, ".."), { recursive: true });
|
|
6849
6964
|
appendFileSync(path, line, "utf8");
|
|
6850
6965
|
}
|
|
6851
6966
|
async function runMcpToolHandler(tool, input, fn) {
|
|
@@ -7120,7 +7235,7 @@ function registerMcpMutatingTools(server) {
|
|
|
7120
7235
|
|
|
7121
7236
|
// src/mcp/resources.ts
|
|
7122
7237
|
import { readFile as readFile11 } from "fs/promises";
|
|
7123
|
-
import { join as
|
|
7238
|
+
import { join as join30 } from "path";
|
|
7124
7239
|
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7125
7240
|
|
|
7126
7241
|
// src/mcp/lint-bucket.ts
|
|
@@ -7250,7 +7365,7 @@ async function fetchQueryPreview(input) {
|
|
|
7250
7365
|
|
|
7251
7366
|
// src/mcp/graph-html.ts
|
|
7252
7367
|
import { readFile as readFile10 } from "fs/promises";
|
|
7253
|
-
import { join as
|
|
7368
|
+
import { join as join29 } from "path";
|
|
7254
7369
|
import { existsSync as existsSync22 } from "fs";
|
|
7255
7370
|
var TYPE_COLORS = {
|
|
7256
7371
|
entities: "#e74c3c",
|
|
@@ -7319,7 +7434,7 @@ ${nodeSvg}
|
|
|
7319
7434
|
return { html, node_count: nodes.length, edge_count: edges.length, truncated };
|
|
7320
7435
|
}
|
|
7321
7436
|
async function fetchGraphHtmlReport(input) {
|
|
7322
|
-
const graphPath = input.graphPath ??
|
|
7437
|
+
const graphPath = input.graphPath ?? join29(input.vault, ".skillwiki", "graph.json");
|
|
7323
7438
|
const maxNodes = Math.min(Math.max(10, input.maxNodes ?? 120), 500);
|
|
7324
7439
|
if (!existsSync22(graphPath)) {
|
|
7325
7440
|
return {
|
|
@@ -7393,7 +7508,7 @@ async function fetchStaleSummary(input) {
|
|
|
7393
7508
|
|
|
7394
7509
|
// src/mcp/resources.ts
|
|
7395
7510
|
async function readVaultFile(vault, rel) {
|
|
7396
|
-
return readFile11(
|
|
7511
|
+
return readFile11(join30(vault, rel), "utf8");
|
|
7397
7512
|
}
|
|
7398
7513
|
async function tailLines(text, lines) {
|
|
7399
7514
|
const parts = text.split(/\r?\n/);
|
|
@@ -7479,7 +7594,7 @@ function registerMcpResources(server) {
|
|
|
7479
7594
|
if (!v.ok) {
|
|
7480
7595
|
return { contents: [{ uri: uri.href, mimeType: "text/plain", text: JSON.stringify(v) }] };
|
|
7481
7596
|
}
|
|
7482
|
-
const path =
|
|
7597
|
+
const path = join30(v.data.vault, ".skillwiki", "graph.json");
|
|
7483
7598
|
try {
|
|
7484
7599
|
const raw = await readFile11(path, "utf8");
|
|
7485
7600
|
const graph = JSON.parse(raw);
|
|
@@ -7830,6 +7945,12 @@ export {
|
|
|
7830
7945
|
renderProjectIndex,
|
|
7831
7946
|
runProjectIndex,
|
|
7832
7947
|
scanConflictMarkerBlocksInText,
|
|
7948
|
+
MCP_URL_ENV,
|
|
7949
|
+
MCP_TOKEN_ENV,
|
|
7950
|
+
MCP_HOST_ID_ENV,
|
|
7951
|
+
nonEmptyEnvValue,
|
|
7952
|
+
mergeMcpAuthIntoEnv,
|
|
7953
|
+
redactMcpSecret,
|
|
7833
7954
|
configPath,
|
|
7834
7955
|
runConfigGet,
|
|
7835
7956
|
runConfigSet,
|
|
@@ -7844,6 +7965,7 @@ export {
|
|
|
7844
7965
|
isFailedRunStatus,
|
|
7845
7966
|
readSatelliteLatestRunFromText,
|
|
7846
7967
|
evaluateSatelliteRunHealth,
|
|
7968
|
+
DEFAULT_MCP_URL,
|
|
7847
7969
|
runDoctor,
|
|
7848
7970
|
readCliPackageJson,
|
|
7849
7971
|
DEFAULT_DIRTY_VOLUME_THRESHOLD,
|