skillwiki 0.9.11 → 0.9.13
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/cli.js +144 -11
- package/package.json +1 -1
- package/skills/.claude-plugin/plugin.json +1 -1
- package/skills/.codex-plugin/plugin.json +1 -1
- package/skills/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5455,6 +5455,12 @@ function checkCliChannels(argv, home) {
|
|
|
5455
5455
|
const devChannels = channels.filter((c) => c.isDevLink);
|
|
5456
5456
|
const prodChannels = channels.filter((c) => !c.isDevLink);
|
|
5457
5457
|
if (devChannels.length > 0 && prodChannels.length > 0) {
|
|
5458
|
+
const hasInstall2 = prodChannels.some((c) => c.name === "install");
|
|
5459
|
+
if (!hasInstall2) {
|
|
5460
|
+
const devNames2 = devChannels.map((c) => `${c.name}(dev)`);
|
|
5461
|
+
const prodNames2 = prodChannels.map((c) => c.name);
|
|
5462
|
+
return check("pass", "cli_channels", "CLI channels", `${channels.length} channels: ${[...devNames2, ...prodNames2].join(", ")} \u2014 dev source with installed production channels`);
|
|
5463
|
+
}
|
|
5458
5464
|
const devNames = devChannels.map((c) => `${c.name}(dev)`);
|
|
5459
5465
|
const prodNames = prodChannels.map((c) => c.name);
|
|
5460
5466
|
return check(
|
|
@@ -5476,6 +5482,9 @@ function checkCliChannels(argv, home) {
|
|
|
5476
5482
|
}
|
|
5477
5483
|
return check("pass", "cli_channels", "CLI channels", `${channels.length} channels: ${names.join(", ")}`);
|
|
5478
5484
|
}
|
|
5485
|
+
function isDevSourceRun(argv) {
|
|
5486
|
+
return argv.length >= 2 && argv[1].endsWith("cli.js");
|
|
5487
|
+
}
|
|
5479
5488
|
async function checkConfigFile(home) {
|
|
5480
5489
|
const cfgPath = configPath(home);
|
|
5481
5490
|
if (!existsSync11(cfgPath)) {
|
|
@@ -5582,7 +5591,7 @@ function checkNpmUpdate(home, currentVersion) {
|
|
|
5582
5591
|
}
|
|
5583
5592
|
return check("pass", "npm_update", "npm CLI version", `v${currentVersion} (${distTag}: v${latest})`);
|
|
5584
5593
|
}
|
|
5585
|
-
function checkPluginVersionDrift(home, currentVersion) {
|
|
5594
|
+
function checkPluginVersionDrift(home, currentVersion, devSourceRun) {
|
|
5586
5595
|
const plugins = findPluginInstallations(home);
|
|
5587
5596
|
if (plugins.length === 0) {
|
|
5588
5597
|
return check("pass", "plugin_version_drift", "Plugin/CLI version", "Plugin not installed \u2014 CLI only");
|
|
@@ -5598,6 +5607,10 @@ function checkPluginVersionDrift(home, currentVersion) {
|
|
|
5598
5607
|
const labels = plugins.map((plugin) => `${plugin.label} plugin`).join(", ");
|
|
5599
5608
|
return check("pass", "plugin_version_drift", "Plugin/CLI version", `${labels}, and CLI all at v${currentVersion}`);
|
|
5600
5609
|
}
|
|
5610
|
+
if (devSourceRun && drifted.every((plugin) => semverGt(currentVersion, plugin.version))) {
|
|
5611
|
+
const details2 = drifted.map((plugin) => `${plugin.label} plugin v${plugin.version}`).join(", ");
|
|
5612
|
+
return check("info", "plugin_version_drift", "Plugin/CLI version", `Dev source v${currentVersion} is ahead of installed ${details2}`);
|
|
5613
|
+
}
|
|
5601
5614
|
const details = drifted.map((plugin) => {
|
|
5602
5615
|
const updateCmd = pluginUpdateCommand(plugin, currentVersion);
|
|
5603
5616
|
return `${plugin.label} plugin v${plugin.version} \u2260 CLI v${currentVersion} \u2014 run \`${updateCmd}\``;
|
|
@@ -6170,6 +6183,10 @@ function readVaultSyncConfig(home) {
|
|
|
6170
6183
|
const content = readFileSync7(join29(home, ".skillwiki", ".env"), "utf8");
|
|
6171
6184
|
let installed = false;
|
|
6172
6185
|
let role;
|
|
6186
|
+
let serviceScope;
|
|
6187
|
+
let snapshotScript;
|
|
6188
|
+
let snapshotProfile;
|
|
6189
|
+
let snapshotWorktree;
|
|
6173
6190
|
for (const line of content.split(/\r?\n/)) {
|
|
6174
6191
|
const trimmed = line.trim();
|
|
6175
6192
|
if (trimmed.length === 0 || trimmed.startsWith("#")) continue;
|
|
@@ -6180,12 +6197,42 @@ function readVaultSyncConfig(home) {
|
|
|
6180
6197
|
if (v.length === 0) continue;
|
|
6181
6198
|
if (k === "vault_sync.installed" && v === "true") installed = true;
|
|
6182
6199
|
if (k === "vault_sync.role") role = v;
|
|
6200
|
+
if (k === "vault_sync.service_scope") serviceScope = v;
|
|
6201
|
+
if (k === "vault_sync.snapshot_script") snapshotScript = v;
|
|
6202
|
+
if (k === "vault_sync.snapshot_profile") snapshotProfile = v;
|
|
6203
|
+
if (k === "vault_sync.snapshot_worktree") snapshotWorktree = v;
|
|
6183
6204
|
}
|
|
6184
|
-
return { installed, role };
|
|
6205
|
+
return { installed, role, serviceScope, snapshotScript, snapshotProfile, snapshotWorktree };
|
|
6185
6206
|
} catch {
|
|
6186
6207
|
return { installed: false };
|
|
6187
6208
|
}
|
|
6188
6209
|
}
|
|
6210
|
+
function readKeyFromEnvFile(path, keys) {
|
|
6211
|
+
try {
|
|
6212
|
+
const content = readFileSync7(path, "utf8");
|
|
6213
|
+
for (const line of content.split(/\r?\n/)) {
|
|
6214
|
+
const trimmed = line.trim();
|
|
6215
|
+
if (trimmed.length === 0 || trimmed.startsWith("#")) continue;
|
|
6216
|
+
const eq = trimmed.indexOf("=");
|
|
6217
|
+
if (eq <= 0) continue;
|
|
6218
|
+
const key = trimmed.slice(0, eq).trim();
|
|
6219
|
+
if (!keys.includes(key)) continue;
|
|
6220
|
+
const value = trimmed.slice(eq + 1).trim();
|
|
6221
|
+
if (value.length > 0) return value;
|
|
6222
|
+
}
|
|
6223
|
+
} catch {
|
|
6224
|
+
}
|
|
6225
|
+
return void 0;
|
|
6226
|
+
}
|
|
6227
|
+
function resolveSnapshotGitWorktree(config) {
|
|
6228
|
+
if (config.snapshotWorktree) return config.snapshotWorktree;
|
|
6229
|
+
if (config.snapshotProfile) {
|
|
6230
|
+
const fromProfile = readKeyFromEnvFile(config.snapshotProfile, ["WIKI_GIT_WORKTREE", "SNAPSHOT_WORKTREE", "GIT_DIR"]);
|
|
6231
|
+
if (fromProfile) return fromProfile;
|
|
6232
|
+
}
|
|
6233
|
+
const defaultPath = "/root/wiki-git";
|
|
6234
|
+
return existsSync11(defaultPath) ? defaultPath : void 0;
|
|
6235
|
+
}
|
|
6189
6236
|
function vaultSyncChecks(input) {
|
|
6190
6237
|
const os = input.os ?? platform2();
|
|
6191
6238
|
const home = input.home;
|
|
@@ -6204,7 +6251,89 @@ function vaultSyncChecks(input) {
|
|
|
6204
6251
|
const logDir = input.logDir ?? (isMac ? join29(home, "Library", "Logs") : join29(home, ".local", "state", "vault-sync", "log"));
|
|
6205
6252
|
const shareDir = input.shareDir ?? (isMac ? join29(home, "Library", "Application Support", "vault-sync", "bin") : join29(home, ".local", "share", "vault-sync", "bin"));
|
|
6206
6253
|
const filterPath = input.filterPath ?? join29(home, ".config", "rclone", "wiki-push-filters.txt");
|
|
6207
|
-
const
|
|
6254
|
+
const packagedSnapshotPath = join29(shareDir, "wiki-snapshot.sh");
|
|
6255
|
+
const legacySnapshotPath = "/root/.hermes/scripts/wiki-snapshot-v3.sh";
|
|
6256
|
+
const snapshotPath = input.snapshotScriptPath ?? (existsSync11(packagedSnapshotPath) ? packagedSnapshotPath : legacySnapshotPath);
|
|
6257
|
+
if (input.vaultSyncRole === "snapshotter") {
|
|
6258
|
+
const c12 = existsSync11(snapshotPath) ? check("pass", "vault_sync_installed", "Vault sync installed", `Found snapshot script: ${snapshotPath}`) : check("error", "vault_sync_installed", "Vault sync installed", `Snapshot script not found at ${snapshotPath}`);
|
|
6259
|
+
const serviceScope = input.vaultSyncServiceScope ?? "user";
|
|
6260
|
+
const userTimerPath = join29(home, ".config", "systemd", "user", "wiki-snapshot.timer");
|
|
6261
|
+
const systemTimerPath = "/etc/systemd/system/wiki-snapshot.timer";
|
|
6262
|
+
let c22;
|
|
6263
|
+
if (serviceScope === "user" && existsSync11(userTimerPath)) {
|
|
6264
|
+
c22 = check("pass", "vault_sync_jobs_enabled", "Vault sync jobs enabled", `Found: ${userTimerPath}`);
|
|
6265
|
+
} else if (serviceScope === "system" && existsSync11(systemTimerPath)) {
|
|
6266
|
+
c22 = check("pass", "vault_sync_jobs_enabled", "Vault sync jobs enabled", `Found: ${systemTimerPath}`);
|
|
6267
|
+
} else if (os !== "linux") {
|
|
6268
|
+
c22 = check("warn", "vault_sync_jobs_enabled", "Vault sync jobs enabled", "Snapshotter scheduler is Linux-only and no wiki-snapshot.timer file was found");
|
|
6269
|
+
} else {
|
|
6270
|
+
try {
|
|
6271
|
+
const command = serviceScope === "system" ? "systemctl is-enabled wiki-snapshot.timer" : "systemctl --user is-enabled wiki-snapshot.timer";
|
|
6272
|
+
const out = execSync2(command, {
|
|
6273
|
+
encoding: "utf8",
|
|
6274
|
+
timeout: 2e3,
|
|
6275
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
6276
|
+
}).trim();
|
|
6277
|
+
c22 = out === "enabled" ? check("pass", "vault_sync_jobs_enabled", "Vault sync jobs enabled", `systemd: wiki-snapshot.timer enabled (${serviceScope})`) : check("error", "vault_sync_jobs_enabled", "Vault sync jobs enabled", `systemd: wiki-snapshot.timer is ${out || "not enabled"} (${serviceScope})`);
|
|
6278
|
+
} catch {
|
|
6279
|
+
c22 = check("error", "vault_sync_jobs_enabled", "Vault sync jobs enabled", `wiki-snapshot.timer check failed (${serviceScope})`);
|
|
6280
|
+
}
|
|
6281
|
+
}
|
|
6282
|
+
const c32 = check(
|
|
6283
|
+
"pass",
|
|
6284
|
+
"vault_sync_last_push_age",
|
|
6285
|
+
"Vault sync last push recency",
|
|
6286
|
+
"Snapshotter host \u2014 leaf wiki-push log not applicable"
|
|
6287
|
+
);
|
|
6288
|
+
const cFetch2 = check(
|
|
6289
|
+
"pass",
|
|
6290
|
+
"vault_sync_last_fetch_status",
|
|
6291
|
+
"Vault sync last fetch status",
|
|
6292
|
+
"Snapshotter host \u2014 leaf wiki-fetch-notify log not applicable"
|
|
6293
|
+
);
|
|
6294
|
+
const c42 = check(
|
|
6295
|
+
"pass",
|
|
6296
|
+
"vault_sync_filter_present",
|
|
6297
|
+
"Vault sync filter file present",
|
|
6298
|
+
"Snapshotter host \u2014 leaf wiki-push filter not applicable"
|
|
6299
|
+
);
|
|
6300
|
+
let c52;
|
|
6301
|
+
try {
|
|
6302
|
+
if (!existsSync11(snapshotPath)) {
|
|
6303
|
+
c52 = check(
|
|
6304
|
+
"error",
|
|
6305
|
+
"vault_sync_snapshot_guard",
|
|
6306
|
+
"Snapshot script guard",
|
|
6307
|
+
`Snapshot script not found at ${snapshotPath}`
|
|
6308
|
+
);
|
|
6309
|
+
} else {
|
|
6310
|
+
const content = readFileSync7(snapshotPath, "utf8");
|
|
6311
|
+
if (!content.includes("--max-delete")) {
|
|
6312
|
+
c52 = check(
|
|
6313
|
+
"error",
|
|
6314
|
+
"vault_sync_snapshot_guard",
|
|
6315
|
+
"Snapshot script guard",
|
|
6316
|
+
`${snapshotPath} is missing --max-delete guard \u2014 dangerous without it`
|
|
6317
|
+
);
|
|
6318
|
+
} else {
|
|
6319
|
+
c52 = check(
|
|
6320
|
+
"pass",
|
|
6321
|
+
"vault_sync_snapshot_guard",
|
|
6322
|
+
"Snapshot script guard",
|
|
6323
|
+
`--max-delete present in ${snapshotPath}`
|
|
6324
|
+
);
|
|
6325
|
+
}
|
|
6326
|
+
}
|
|
6327
|
+
} catch {
|
|
6328
|
+
c52 = check(
|
|
6329
|
+
"error",
|
|
6330
|
+
"vault_sync_snapshot_guard",
|
|
6331
|
+
"Snapshot script guard",
|
|
6332
|
+
`Cannot read ${snapshotPath}`
|
|
6333
|
+
);
|
|
6334
|
+
}
|
|
6335
|
+
return [c12, c22, c32, cFetch2, c42, c52];
|
|
6336
|
+
}
|
|
6208
6337
|
const pushScriptPath = join29(shareDir, "wiki-push.sh");
|
|
6209
6338
|
const c1 = existsSync11(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`);
|
|
6210
6339
|
let c2;
|
|
@@ -6270,7 +6399,7 @@ function vaultSyncChecks(input) {
|
|
|
6270
6399
|
"Log file is empty"
|
|
6271
6400
|
);
|
|
6272
6401
|
} else {
|
|
6273
|
-
const lastLine = lines[lines.length - 1];
|
|
6402
|
+
const lastLine = [...lines].reverse().find((line) => /FAIL|OK push/.test(line)) ?? lines[lines.length - 1];
|
|
6274
6403
|
if (/FAIL/.test(lastLine)) {
|
|
6275
6404
|
c3 = check(
|
|
6276
6405
|
"error",
|
|
@@ -6549,6 +6678,7 @@ async function vaultMetrics(resolvedPath) {
|
|
|
6549
6678
|
}
|
|
6550
6679
|
async function runDoctor(input) {
|
|
6551
6680
|
const checks = [];
|
|
6681
|
+
const devSourceRun = isDevSourceRun(input.argv);
|
|
6552
6682
|
const vsConfig = readVaultSyncConfig(input.home);
|
|
6553
6683
|
checks.push(checkNodeVersion());
|
|
6554
6684
|
checks.push(checkCliChannels(input.argv, input.home));
|
|
@@ -6562,20 +6692,21 @@ async function runDoctor(input) {
|
|
|
6562
6692
|
checks.push(check("error", "wiki_path_set", "WIKI_PATH configured", "No vault configured. Run `skillwiki init` or pass --vault."));
|
|
6563
6693
|
}
|
|
6564
6694
|
const resolvedPath = resolved.ok ? resolved.data.path : void 0;
|
|
6695
|
+
const gitCheckPath = vsConfig.role === "snapshotter" ? resolveSnapshotGitWorktree(vsConfig) ?? resolvedPath : resolvedPath;
|
|
6565
6696
|
checks.push(checkWikiPathExists(resolvedPath));
|
|
6566
6697
|
checks.push(checkVaultStructure(resolvedPath));
|
|
6567
6698
|
checks.push(checkObsidianTemplates(resolvedPath));
|
|
6568
|
-
checks.push(checkVaultGitRemote(
|
|
6699
|
+
checks.push(checkVaultGitRemote(gitCheckPath));
|
|
6569
6700
|
checks.push(await checkFleetIdentity({
|
|
6570
6701
|
vaultPath: resolvedPath,
|
|
6571
6702
|
home: input.home,
|
|
6572
6703
|
cwd: input.cwd,
|
|
6573
6704
|
envValue: input.envValue
|
|
6574
6705
|
}));
|
|
6575
|
-
checks.push(checkSyncLastPush(
|
|
6576
|
-
checks.push(checkVaultGitDirty(
|
|
6577
|
-
checks.push(checkVaultGitAhead(
|
|
6578
|
-
checks.push(checkVaultGitBehind(
|
|
6706
|
+
checks.push(checkSyncLastPush(gitCheckPath));
|
|
6707
|
+
checks.push(checkVaultGitDirty(gitCheckPath));
|
|
6708
|
+
checks.push(checkVaultGitAhead(gitCheckPath));
|
|
6709
|
+
checks.push(checkVaultGitBehind(gitCheckPath));
|
|
6579
6710
|
checks.push(checkVaultGitPullFailures(input.home));
|
|
6580
6711
|
checks.push(checkDotStoreClean(resolvedPath));
|
|
6581
6712
|
checks.push(checkS3MountPerf(resolvedPath));
|
|
@@ -6587,11 +6718,13 @@ async function runDoctor(input) {
|
|
|
6587
6718
|
checks.push(checkSkillsInstalled(input.home, input.cwd));
|
|
6588
6719
|
checks.push(checkDuplicateSkills(input.home));
|
|
6589
6720
|
checks.push(checkNpmUpdate(input.home, input.currentVersion));
|
|
6590
|
-
checks.push(checkPluginVersionDrift(input.home, input.currentVersion));
|
|
6721
|
+
checks.push(checkPluginVersionDrift(input.home, input.currentVersion, devSourceRun));
|
|
6591
6722
|
checks.push(...vaultSyncChecks({
|
|
6592
6723
|
home: input.home,
|
|
6593
6724
|
vaultSyncInstalled: vsConfig.installed,
|
|
6594
|
-
vaultSyncRole: vsConfig.role
|
|
6725
|
+
vaultSyncRole: vsConfig.role,
|
|
6726
|
+
vaultSyncServiceScope: vsConfig.serviceScope,
|
|
6727
|
+
snapshotScriptPath: vsConfig.snapshotScript
|
|
6595
6728
|
}));
|
|
6596
6729
|
checks.push(...await vaultMetrics(resolvedPath));
|
|
6597
6730
|
const summary = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillwiki",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.13",
|
|
4
4
|
"skills": "./",
|
|
5
5
|
"description": "Project-aware Karpathy-style knowledge base for Claude Code: 18 prompt-only skills (wiki-*, proj-*, using-skillwiki) backed by the deterministic `skillwiki` CLI.",
|
|
6
6
|
"author": {
|