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 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 snapshotPath = input.snapshotScriptPath ?? "/root/.hermes/scripts/wiki-snapshot-v3.sh";
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(resolvedPath));
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(resolvedPath));
6576
- checks.push(checkVaultGitDirty(resolvedPath));
6577
- checks.push(checkVaultGitAhead(resolvedPath));
6578
- checks.push(checkVaultGitBehind(resolvedPath));
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.11",
3
+ "version": "0.9.13",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "skillwiki": "dist/cli.js"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.9.11",
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": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.9.11",
3
+ "version": "0.9.13",
4
4
  "description": "Project-aware Karpathy-style knowledge base for Codex with 18 prompt-only skills backed by the deterministic skillwiki CLI.",
5
5
  "author": {
6
6
  "name": "karlorz",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillwiki/skills",
3
- "version": "0.9.11",
3
+ "version": "0.9.13",
4
4
  "private": true,
5
5
  "files": [
6
6
  "wiki-*",