skillwiki 0.6.2-beta.1 → 0.7.0
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 +384 -33
- 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
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-TPS5XD2J.js";
|
|
9
9
|
|
|
10
10
|
// src/cli.ts
|
|
11
|
-
import { readFileSync as
|
|
11
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
12
12
|
import { join as join41 } from "path";
|
|
13
13
|
import { Command as Command2 } from "commander";
|
|
14
14
|
|
|
@@ -3489,9 +3489,10 @@ async function runConfigPath(input) {
|
|
|
3489
3489
|
}
|
|
3490
3490
|
|
|
3491
3491
|
// src/commands/doctor.ts
|
|
3492
|
-
import { existsSync as existsSync7, lstatSync, readlinkSync, readdirSync, statSync as statSync2 } from "fs";
|
|
3492
|
+
import { existsSync as existsSync7, lstatSync, readlinkSync, readdirSync, statSync as statSync2, readFileSync as readFileSync7 } from "fs";
|
|
3493
3493
|
import { join as join24, resolve as resolve4 } from "path";
|
|
3494
3494
|
import { execSync as execSync2 } from "child_process";
|
|
3495
|
+
import { platform as platform2 } from "os";
|
|
3495
3496
|
|
|
3496
3497
|
// src/utils/auto-update.ts
|
|
3497
3498
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
|
|
@@ -4209,12 +4210,12 @@ function checkRcloneFlagAudit(resolvedPath) {
|
|
|
4209
4210
|
}
|
|
4210
4211
|
return check("pass", "rclone_flags", "rclone VFS flags", `PID ${pid}: all critical flags at safe values`);
|
|
4211
4212
|
}
|
|
4212
|
-
function checkRcloneVersion(resolvedPath) {
|
|
4213
|
-
if (!resolvedPath) {
|
|
4213
|
+
function checkRcloneVersion(resolvedPath, vaultSyncInstalled) {
|
|
4214
|
+
if (!resolvedPath && !vaultSyncInstalled) {
|
|
4214
4215
|
return check("pass", "rclone_version", "rclone version", "No vault path \u2014 check skipped");
|
|
4215
4216
|
}
|
|
4216
|
-
const fuse = detectFuseMount(resolvedPath);
|
|
4217
|
-
if (!fuse) {
|
|
4217
|
+
const fuse = resolvedPath ? detectFuseMount(resolvedPath) : null;
|
|
4218
|
+
if (!fuse && !vaultSyncInstalled) {
|
|
4218
4219
|
return check("pass", "rclone_version", "rclone version", "local disk \u2014 check skipped");
|
|
4219
4220
|
}
|
|
4220
4221
|
const ver = getRcloneVersion();
|
|
@@ -4326,6 +4327,301 @@ function checkVfsCacheHealth(resolvedPath) {
|
|
|
4326
4327
|
`${stats.files} files, ${(stats.bytesUsed / 1024 / 1024).toFixed(1)}MB \u2014 clean (0 errored, 0 pending)`
|
|
4327
4328
|
);
|
|
4328
4329
|
}
|
|
4330
|
+
function readVaultSyncConfig(home) {
|
|
4331
|
+
try {
|
|
4332
|
+
const content = readFileSync7(join24(home, ".skillwiki", ".env"), "utf8");
|
|
4333
|
+
let installed = false;
|
|
4334
|
+
let role;
|
|
4335
|
+
for (const line of content.split(/\r?\n/)) {
|
|
4336
|
+
const trimmed = line.trim();
|
|
4337
|
+
if (trimmed.length === 0 || trimmed.startsWith("#")) continue;
|
|
4338
|
+
const eq = trimmed.indexOf("=");
|
|
4339
|
+
if (eq <= 0) continue;
|
|
4340
|
+
const k = trimmed.slice(0, eq).trim();
|
|
4341
|
+
const v = trimmed.slice(eq + 1).trim();
|
|
4342
|
+
if (v.length === 0) continue;
|
|
4343
|
+
if (k === "vault_sync.installed" && v === "true") installed = true;
|
|
4344
|
+
if (k === "vault_sync.role") role = v;
|
|
4345
|
+
}
|
|
4346
|
+
return { installed, role };
|
|
4347
|
+
} catch {
|
|
4348
|
+
return { installed: false };
|
|
4349
|
+
}
|
|
4350
|
+
}
|
|
4351
|
+
function vaultSyncChecks(input) {
|
|
4352
|
+
const os = input.os ?? platform2();
|
|
4353
|
+
const home = input.home;
|
|
4354
|
+
if (!input.vaultSyncInstalled) {
|
|
4355
|
+
const skip = (id, label) => check("pass", id, label, "vault-sync not installed \u2014 check skipped");
|
|
4356
|
+
return [
|
|
4357
|
+
skip("vault_sync_installed", "Vault sync installed"),
|
|
4358
|
+
skip("vault_sync_jobs_enabled", "Vault sync jobs enabled"),
|
|
4359
|
+
skip("vault_sync_last_push_age", "Vault sync last push recency"),
|
|
4360
|
+
skip("vault_sync_last_fetch_status", "Vault sync last fetch status"),
|
|
4361
|
+
skip("vault_sync_filter_present", "Vault sync filter file present"),
|
|
4362
|
+
skip("vault_sync_snapshot_guard", "Snapshot script guard")
|
|
4363
|
+
];
|
|
4364
|
+
}
|
|
4365
|
+
const isMac = os === "darwin";
|
|
4366
|
+
const logDir = input.logDir ?? (isMac ? join24(home, "Library", "Logs") : join24(home, ".local", "state", "vault-sync", "log"));
|
|
4367
|
+
const shareDir = input.shareDir ?? (isMac ? join24(home, "Library", "Application Support", "vault-sync", "bin") : join24(home, ".local", "share", "vault-sync", "bin"));
|
|
4368
|
+
const filterPath = input.filterPath ?? join24(home, ".config", "rclone", "wiki-push-filters.txt");
|
|
4369
|
+
const snapshotPath = input.snapshotScriptPath ?? "/root/.hermes/scripts/wiki-snapshot-v3.sh";
|
|
4370
|
+
const pushScriptPath = join24(shareDir, "wiki-push.sh");
|
|
4371
|
+
const c1 = existsSync7(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`);
|
|
4372
|
+
let c2;
|
|
4373
|
+
try {
|
|
4374
|
+
if (isMac) {
|
|
4375
|
+
const uidStr = execSync2("id -u", {
|
|
4376
|
+
encoding: "utf8",
|
|
4377
|
+
timeout: 2e3,
|
|
4378
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
4379
|
+
}).trim();
|
|
4380
|
+
const uid = parseInt(uidStr, 10);
|
|
4381
|
+
execSync2(`launchctl print gui/${uid}/com.karlchow.wiki-push`, {
|
|
4382
|
+
encoding: "utf8",
|
|
4383
|
+
timeout: 2e3,
|
|
4384
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
4385
|
+
});
|
|
4386
|
+
c2 = check(
|
|
4387
|
+
"pass",
|
|
4388
|
+
"vault_sync_jobs_enabled",
|
|
4389
|
+
"Vault sync jobs enabled",
|
|
4390
|
+
"launchd: com.karlchow.wiki-push loaded"
|
|
4391
|
+
);
|
|
4392
|
+
} else {
|
|
4393
|
+
const out = execSync2("systemctl --user is-enabled wiki-push.timer", {
|
|
4394
|
+
encoding: "utf8",
|
|
4395
|
+
timeout: 2e3,
|
|
4396
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
4397
|
+
}).trim();
|
|
4398
|
+
if (out === "enabled") {
|
|
4399
|
+
c2 = check(
|
|
4400
|
+
"pass",
|
|
4401
|
+
"vault_sync_jobs_enabled",
|
|
4402
|
+
"Vault sync jobs enabled",
|
|
4403
|
+
"systemd: wiki-push.timer enabled"
|
|
4404
|
+
);
|
|
4405
|
+
} else {
|
|
4406
|
+
c2 = check(
|
|
4407
|
+
"error",
|
|
4408
|
+
"vault_sync_jobs_enabled",
|
|
4409
|
+
"Vault sync jobs enabled",
|
|
4410
|
+
`systemd: wiki-push.timer is ${out} \u2014 run vault-sync-install`
|
|
4411
|
+
);
|
|
4412
|
+
}
|
|
4413
|
+
}
|
|
4414
|
+
} catch {
|
|
4415
|
+
c2 = check(
|
|
4416
|
+
"error",
|
|
4417
|
+
"vault_sync_jobs_enabled",
|
|
4418
|
+
"Vault sync jobs enabled",
|
|
4419
|
+
"Scheduler check failed \u2014 run vault-sync-install"
|
|
4420
|
+
);
|
|
4421
|
+
}
|
|
4422
|
+
const logFile = join24(logDir, "wiki-push.log");
|
|
4423
|
+
let c3;
|
|
4424
|
+
try {
|
|
4425
|
+
const logContent = readFileSync7(logFile, "utf8");
|
|
4426
|
+
const lines = logContent.trim().split("\n").filter(Boolean);
|
|
4427
|
+
if (lines.length === 0) {
|
|
4428
|
+
c3 = check(
|
|
4429
|
+
"warn",
|
|
4430
|
+
"vault_sync_last_push_age",
|
|
4431
|
+
"Vault sync last push recency",
|
|
4432
|
+
"Log file is empty"
|
|
4433
|
+
);
|
|
4434
|
+
} else {
|
|
4435
|
+
const lastLine = lines[lines.length - 1];
|
|
4436
|
+
if (/FAIL/.test(lastLine)) {
|
|
4437
|
+
c3 = check(
|
|
4438
|
+
"error",
|
|
4439
|
+
"vault_sync_last_push_age",
|
|
4440
|
+
"Vault sync last push recency",
|
|
4441
|
+
`Last push failed: ${lastLine}`
|
|
4442
|
+
);
|
|
4443
|
+
} else if (/OK push/.test(lastLine)) {
|
|
4444
|
+
const tsMatch = lastLine.match(/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z)/);
|
|
4445
|
+
if (tsMatch) {
|
|
4446
|
+
const lastPush = new Date(tsMatch[1]).getTime();
|
|
4447
|
+
const ageSec = (Date.now() - lastPush) / 1e3;
|
|
4448
|
+
if (ageSec <= 180) {
|
|
4449
|
+
c3 = check(
|
|
4450
|
+
"pass",
|
|
4451
|
+
"vault_sync_last_push_age",
|
|
4452
|
+
"Vault sync last push recency",
|
|
4453
|
+
`Last push ${ageSec.toFixed(0)}s ago`
|
|
4454
|
+
);
|
|
4455
|
+
} else {
|
|
4456
|
+
c3 = check(
|
|
4457
|
+
"warn",
|
|
4458
|
+
"vault_sync_last_push_age",
|
|
4459
|
+
"Vault sync last push recency",
|
|
4460
|
+
`Last push ${Math.round(ageSec)}s ago (>3 min)`
|
|
4461
|
+
);
|
|
4462
|
+
}
|
|
4463
|
+
} else {
|
|
4464
|
+
c3 = check(
|
|
4465
|
+
"warn",
|
|
4466
|
+
"vault_sync_last_push_age",
|
|
4467
|
+
"Vault sync last push recency",
|
|
4468
|
+
`Unparseable push line: ${lastLine.slice(0, 80)}`
|
|
4469
|
+
);
|
|
4470
|
+
}
|
|
4471
|
+
} else {
|
|
4472
|
+
c3 = check(
|
|
4473
|
+
"warn",
|
|
4474
|
+
"vault_sync_last_push_age",
|
|
4475
|
+
"Vault sync last push recency",
|
|
4476
|
+
`Last log entry: ${lastLine.slice(0, 80)}`
|
|
4477
|
+
);
|
|
4478
|
+
}
|
|
4479
|
+
}
|
|
4480
|
+
} catch {
|
|
4481
|
+
c3 = existsSync7(logDir) ? check(
|
|
4482
|
+
"warn",
|
|
4483
|
+
"vault_sync_last_push_age",
|
|
4484
|
+
"Vault sync last push recency",
|
|
4485
|
+
`Log file not found at ${logFile}`
|
|
4486
|
+
) : check(
|
|
4487
|
+
"error",
|
|
4488
|
+
"vault_sync_last_push_age",
|
|
4489
|
+
"Vault sync last push recency",
|
|
4490
|
+
`Log directory not found at ${logDir}`
|
|
4491
|
+
);
|
|
4492
|
+
}
|
|
4493
|
+
const fetchLogFile = join24(logDir, "wiki-fetch.log");
|
|
4494
|
+
let cFetch;
|
|
4495
|
+
try {
|
|
4496
|
+
const logContent = readFileSync7(fetchLogFile, "utf8");
|
|
4497
|
+
const lines = logContent.trim().split("\n").filter(Boolean);
|
|
4498
|
+
if (lines.length === 0) {
|
|
4499
|
+
cFetch = check(
|
|
4500
|
+
"warn",
|
|
4501
|
+
"vault_sync_last_fetch_status",
|
|
4502
|
+
"Vault sync last fetch status",
|
|
4503
|
+
"Fetch log file is empty"
|
|
4504
|
+
);
|
|
4505
|
+
} else {
|
|
4506
|
+
const lastLine = lines[lines.length - 1];
|
|
4507
|
+
if (/fetch failed/i.test(lastLine)) {
|
|
4508
|
+
cFetch = check(
|
|
4509
|
+
"error",
|
|
4510
|
+
"vault_sync_last_fetch_status",
|
|
4511
|
+
"Vault sync last fetch status",
|
|
4512
|
+
`Last fetch failed: ${lastLine.slice(0, 100)}`
|
|
4513
|
+
);
|
|
4514
|
+
} else if (/OK/.test(lastLine)) {
|
|
4515
|
+
cFetch = check(
|
|
4516
|
+
"pass",
|
|
4517
|
+
"vault_sync_last_fetch_status",
|
|
4518
|
+
"Vault sync last fetch status",
|
|
4519
|
+
lastLine.slice(0, 100)
|
|
4520
|
+
);
|
|
4521
|
+
} else {
|
|
4522
|
+
cFetch = check(
|
|
4523
|
+
"warn",
|
|
4524
|
+
"vault_sync_last_fetch_status",
|
|
4525
|
+
"Vault sync last fetch status",
|
|
4526
|
+
`Last fetch log entry: ${lastLine.slice(0, 80)}`
|
|
4527
|
+
);
|
|
4528
|
+
}
|
|
4529
|
+
}
|
|
4530
|
+
} catch {
|
|
4531
|
+
cFetch = check(
|
|
4532
|
+
"warn",
|
|
4533
|
+
"vault_sync_last_fetch_status",
|
|
4534
|
+
"Vault sync last fetch status",
|
|
4535
|
+
`Fetch log not found at ${fetchLogFile}`
|
|
4536
|
+
);
|
|
4537
|
+
}
|
|
4538
|
+
let c4;
|
|
4539
|
+
try {
|
|
4540
|
+
if (!existsSync7(filterPath)) {
|
|
4541
|
+
c4 = check(
|
|
4542
|
+
"error",
|
|
4543
|
+
"vault_sync_filter_present",
|
|
4544
|
+
"Vault sync filter file present",
|
|
4545
|
+
`Filter file not found at ${filterPath}`
|
|
4546
|
+
);
|
|
4547
|
+
} else {
|
|
4548
|
+
const content = readFileSync7(filterPath, "utf8");
|
|
4549
|
+
const requiredExcludes = [
|
|
4550
|
+
"remotely-save/data.json",
|
|
4551
|
+
".skillwiki/sync.lock",
|
|
4552
|
+
".claude/settings.local.json"
|
|
4553
|
+
];
|
|
4554
|
+
const missing = requiredExcludes.filter((ex) => !content.includes(ex));
|
|
4555
|
+
if (missing.length > 0) {
|
|
4556
|
+
c4 = check(
|
|
4557
|
+
"warn",
|
|
4558
|
+
"vault_sync_filter_present",
|
|
4559
|
+
"Vault sync filter file present",
|
|
4560
|
+
`Missing required excludes: ${missing.join(", ")}`
|
|
4561
|
+
);
|
|
4562
|
+
} else {
|
|
4563
|
+
c4 = check(
|
|
4564
|
+
"pass",
|
|
4565
|
+
"vault_sync_filter_present",
|
|
4566
|
+
"Vault sync filter file present",
|
|
4567
|
+
`Found with required excludes at ${filterPath}`
|
|
4568
|
+
);
|
|
4569
|
+
}
|
|
4570
|
+
}
|
|
4571
|
+
} catch {
|
|
4572
|
+
c4 = check(
|
|
4573
|
+
"error",
|
|
4574
|
+
"vault_sync_filter_present",
|
|
4575
|
+
"Vault sync filter file present",
|
|
4576
|
+
`Cannot read filter file at ${filterPath}`
|
|
4577
|
+
);
|
|
4578
|
+
}
|
|
4579
|
+
let c5;
|
|
4580
|
+
if (input.vaultSyncRole !== "snapshotter") {
|
|
4581
|
+
c5 = check(
|
|
4582
|
+
"pass",
|
|
4583
|
+
"vault_sync_snapshot_guard",
|
|
4584
|
+
"Snapshot script guard",
|
|
4585
|
+
"Not a snapshotter host \u2014 check skipped"
|
|
4586
|
+
);
|
|
4587
|
+
} else {
|
|
4588
|
+
try {
|
|
4589
|
+
if (!existsSync7(snapshotPath)) {
|
|
4590
|
+
c5 = check(
|
|
4591
|
+
"error",
|
|
4592
|
+
"vault_sync_snapshot_guard",
|
|
4593
|
+
"Snapshot script guard",
|
|
4594
|
+
`Snapshot script not found at ${snapshotPath}`
|
|
4595
|
+
);
|
|
4596
|
+
} else {
|
|
4597
|
+
const content = readFileSync7(snapshotPath, "utf8");
|
|
4598
|
+
if (!content.includes("--max-delete")) {
|
|
4599
|
+
c5 = check(
|
|
4600
|
+
"error",
|
|
4601
|
+
"vault_sync_snapshot_guard",
|
|
4602
|
+
"Snapshot script guard",
|
|
4603
|
+
`${snapshotPath} is missing --max-delete guard \u2014 dangerous without it`
|
|
4604
|
+
);
|
|
4605
|
+
} else {
|
|
4606
|
+
c5 = check(
|
|
4607
|
+
"pass",
|
|
4608
|
+
"vault_sync_snapshot_guard",
|
|
4609
|
+
"Snapshot script guard",
|
|
4610
|
+
`--max-delete present in ${snapshotPath}`
|
|
4611
|
+
);
|
|
4612
|
+
}
|
|
4613
|
+
}
|
|
4614
|
+
} catch {
|
|
4615
|
+
c5 = check(
|
|
4616
|
+
"error",
|
|
4617
|
+
"vault_sync_snapshot_guard",
|
|
4618
|
+
"Snapshot script guard",
|
|
4619
|
+
`Cannot read ${snapshotPath}`
|
|
4620
|
+
);
|
|
4621
|
+
}
|
|
4622
|
+
}
|
|
4623
|
+
return [c1, c2, c3, cFetch, c4, c5];
|
|
4624
|
+
}
|
|
4329
4625
|
function findSkillMd(dir) {
|
|
4330
4626
|
const results = [];
|
|
4331
4627
|
let entries;
|
|
@@ -4360,6 +4656,7 @@ function findSkillNames(dir) {
|
|
|
4360
4656
|
}
|
|
4361
4657
|
async function runDoctor(input) {
|
|
4362
4658
|
const checks = [];
|
|
4659
|
+
const vsConfig = readVaultSyncConfig(input.home);
|
|
4363
4660
|
checks.push(checkNodeVersion());
|
|
4364
4661
|
checks.push(checkCliChannels(input.argv, input.home));
|
|
4365
4662
|
checks.push(await checkConfigFile(input.home));
|
|
@@ -4380,13 +4677,18 @@ async function runDoctor(input) {
|
|
|
4380
4677
|
checks.push(checkDotStoreClean(resolvedPath));
|
|
4381
4678
|
checks.push(checkS3MountPerf(resolvedPath));
|
|
4382
4679
|
checks.push(checkRcloneFlagAudit(resolvedPath));
|
|
4383
|
-
checks.push(checkRcloneVersion(resolvedPath));
|
|
4680
|
+
checks.push(checkRcloneVersion(resolvedPath, vsConfig.installed));
|
|
4384
4681
|
checks.push(checkWriteTest(resolvedPath));
|
|
4385
4682
|
checks.push(checkVfsCacheHealth(resolvedPath));
|
|
4386
4683
|
checks.push(checkSkillsInstalled(input.home, input.cwd));
|
|
4387
4684
|
checks.push(checkDuplicateSkills(input.home));
|
|
4388
4685
|
checks.push(checkNpmUpdate(input.home, input.currentVersion));
|
|
4389
4686
|
checks.push(checkPluginVersionDrift(input.home, input.currentVersion));
|
|
4687
|
+
checks.push(...vaultSyncChecks({
|
|
4688
|
+
home: input.home,
|
|
4689
|
+
vaultSyncInstalled: vsConfig.installed,
|
|
4690
|
+
vaultSyncRole: vsConfig.role
|
|
4691
|
+
}));
|
|
4390
4692
|
const summary = {
|
|
4391
4693
|
pass: checks.filter((c) => c.status === "pass").length,
|
|
4392
4694
|
info: checks.filter((c) => c.status === "info").length,
|
|
@@ -4909,7 +5211,7 @@ ${newBody}`;
|
|
|
4909
5211
|
|
|
4910
5212
|
// src/commands/update.ts
|
|
4911
5213
|
import { execSync as execSync3 } from "child_process";
|
|
4912
|
-
import { readFileSync as
|
|
5214
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
4913
5215
|
import { join as join26 } from "path";
|
|
4914
5216
|
function resolveGlobalSkillsRoot() {
|
|
4915
5217
|
try {
|
|
@@ -4939,7 +5241,7 @@ async function refreshInstalledSkills(target) {
|
|
|
4939
5241
|
}
|
|
4940
5242
|
async function runUpdate(input) {
|
|
4941
5243
|
const pkg2 = JSON.parse(
|
|
4942
|
-
|
|
5244
|
+
readFileSync8(new URL("../../package.json", import.meta.url), "utf8")
|
|
4943
5245
|
);
|
|
4944
5246
|
const currentVersion = pkg2.version;
|
|
4945
5247
|
const tag = input.distTag ?? "latest";
|
|
@@ -5013,12 +5315,12 @@ async function runUpdate(input) {
|
|
|
5013
5315
|
|
|
5014
5316
|
// src/commands/self-update.ts
|
|
5015
5317
|
import { execSync as execSync4 } from "child_process";
|
|
5016
|
-
import { existsSync as existsSync8, readFileSync as
|
|
5318
|
+
import { existsSync as existsSync8, readFileSync as readFileSync9 } from "fs";
|
|
5017
5319
|
import { join as join27 } from "path";
|
|
5018
5320
|
var DEFAULT_SOURCE_ROOT_SUFFIX = "/Desktop/code/llm-wiki";
|
|
5019
5321
|
async function runSelfUpdate(input) {
|
|
5020
5322
|
const currentVersion = JSON.parse(
|
|
5021
|
-
|
|
5323
|
+
readFileSync9(new URL("../../package.json", import.meta.url), "utf8")
|
|
5022
5324
|
).version;
|
|
5023
5325
|
const sourceRoot = input.sourceRoot ?? `${input.home}${DEFAULT_SOURCE_ROOT_SUFFIX}`;
|
|
5024
5326
|
const localPkgPath = join27(sourceRoot, "packages", "cli", "package.json");
|
|
@@ -5029,7 +5331,7 @@ async function runSelfUpdate(input) {
|
|
|
5029
5331
|
if (hasLocalSource) {
|
|
5030
5332
|
source = "local";
|
|
5031
5333
|
try {
|
|
5032
|
-
availableVersion = JSON.parse(
|
|
5334
|
+
availableVersion = JSON.parse(readFileSync9(localPkgPath, "utf8")).version ?? null;
|
|
5033
5335
|
} catch {
|
|
5034
5336
|
availableVersion = null;
|
|
5035
5337
|
}
|
|
@@ -5087,7 +5389,7 @@ async function runSelfUpdate(input) {
|
|
|
5087
5389
|
}
|
|
5088
5390
|
const newVersion = (() => {
|
|
5089
5391
|
try {
|
|
5090
|
-
return JSON.parse(
|
|
5392
|
+
return JSON.parse(readFileSync9(localPkgPath, "utf8")).version ?? "unknown";
|
|
5091
5393
|
} catch {
|
|
5092
5394
|
return "unknown";
|
|
5093
5395
|
}
|
|
@@ -6127,7 +6429,7 @@ import { existsSync as existsSync12 } from "fs";
|
|
|
6127
6429
|
import { join as join34 } from "path";
|
|
6128
6430
|
|
|
6129
6431
|
// src/utils/sync-lock.ts
|
|
6130
|
-
import { existsSync as existsSync11, mkdirSync as mkdirSync3, readFileSync as
|
|
6432
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync3, readFileSync as readFileSync10, renameSync, unlinkSync as unlinkSync4, writeFileSync as writeFileSync5 } from "fs";
|
|
6131
6433
|
import { join as join33 } from "path";
|
|
6132
6434
|
import { createHash as createHash6 } from "crypto";
|
|
6133
6435
|
function getSessionId() {
|
|
@@ -6142,7 +6444,7 @@ function readLock(vault) {
|
|
|
6142
6444
|
const path = lockPath(vault);
|
|
6143
6445
|
if (!existsSync11(path)) return null;
|
|
6144
6446
|
try {
|
|
6145
|
-
const raw =
|
|
6447
|
+
const raw = readFileSync10(path, "utf8");
|
|
6146
6448
|
return JSON.parse(raw);
|
|
6147
6449
|
} catch {
|
|
6148
6450
|
return null;
|
|
@@ -6430,6 +6732,7 @@ async function runSyncPull(input) {
|
|
|
6430
6732
|
let pulled = false;
|
|
6431
6733
|
let conflicts = 0;
|
|
6432
6734
|
let filesUpdated = 0;
|
|
6735
|
+
let autoResolved = 0;
|
|
6433
6736
|
try {
|
|
6434
6737
|
const pullOutput = gitStrict(vault, ["pull", "--rebase", "origin", "HEAD"]);
|
|
6435
6738
|
pulled = true;
|
|
@@ -6438,25 +6741,71 @@ async function runSyncPull(input) {
|
|
|
6438
6741
|
} catch (e) {
|
|
6439
6742
|
const errString = String(e);
|
|
6440
6743
|
if (errString.includes("conflict")) {
|
|
6441
|
-
|
|
6442
|
-
|
|
6744
|
+
let inConflict = true;
|
|
6745
|
+
while (inConflict) {
|
|
6746
|
+
const stoppedSha = git(vault, ["rev-parse", "--verify", "REBASE_HEAD"]);
|
|
6747
|
+
let commitMsg = "";
|
|
6748
|
+
if (stoppedSha) {
|
|
6749
|
+
commitMsg = git(vault, ["log", "--format=%s", "-1", stoppedSha]);
|
|
6750
|
+
}
|
|
6751
|
+
const isArchiveOrSnapshot = commitMsg.startsWith("archive: moved") || commitMsg.startsWith("Snapshot ");
|
|
6752
|
+
const conflictedFiles = git(vault, ["diff", "--name-only", "--diff-filter=U"]);
|
|
6753
|
+
const conflictedList = conflictedFiles ? conflictedFiles.split("\n").filter((l) => l.trim().length > 0) : [];
|
|
6754
|
+
if (conflictedList.length === 0) {
|
|
6755
|
+
try {
|
|
6756
|
+
gitStrict(vault, ["rebase", "--continue"]);
|
|
6757
|
+
inConflict = true;
|
|
6758
|
+
} catch {
|
|
6759
|
+
inConflict = false;
|
|
6760
|
+
}
|
|
6761
|
+
continue;
|
|
6762
|
+
}
|
|
6763
|
+
if (isArchiveOrSnapshot) {
|
|
6764
|
+
for (const f of conflictedList) {
|
|
6765
|
+
try {
|
|
6766
|
+
gitStrict(vault, ["checkout", "--ours", f]);
|
|
6767
|
+
gitStrict(vault, ["add", f]);
|
|
6768
|
+
} catch {
|
|
6769
|
+
}
|
|
6770
|
+
}
|
|
6771
|
+
autoResolved += conflictedList.length;
|
|
6772
|
+
try {
|
|
6773
|
+
gitStrict(vault, ["rebase", "--continue"]);
|
|
6774
|
+
} catch (continueErr) {
|
|
6775
|
+
continue;
|
|
6776
|
+
}
|
|
6777
|
+
} else {
|
|
6778
|
+
conflicts = conflictedList.length;
|
|
6779
|
+
return {
|
|
6780
|
+
exitCode: ExitCode.SYNC_PULL_FAILED,
|
|
6781
|
+
result: ok({
|
|
6782
|
+
fetched,
|
|
6783
|
+
pulled: false,
|
|
6784
|
+
files_updated: 0,
|
|
6785
|
+
conflicts,
|
|
6786
|
+
auto_resolved: 0,
|
|
6787
|
+
lint_errors: 0,
|
|
6788
|
+
lint_warnings: 0,
|
|
6789
|
+
humanHint: `pull failed with ${conflicts} conflict(s) on non-archive commit "${commitMsg}" \u2014 resolve manually`
|
|
6790
|
+
})
|
|
6791
|
+
};
|
|
6792
|
+
}
|
|
6793
|
+
}
|
|
6794
|
+
if (autoResolved > 0) {
|
|
6795
|
+
const diffOutput = git(vault, ["diff", "--stat", "HEAD@{1}..HEAD"]);
|
|
6796
|
+
if (diffOutput) {
|
|
6797
|
+
const fileMatch = diffOutput.match(/(\d+) file[s]? changed/);
|
|
6798
|
+
if (fileMatch) filesUpdated = parseInt(fileMatch[1], 10);
|
|
6799
|
+
}
|
|
6800
|
+
pulled = true;
|
|
6801
|
+
conflicts = 0;
|
|
6802
|
+
}
|
|
6803
|
+
} else {
|
|
6443
6804
|
return {
|
|
6444
6805
|
exitCode: ExitCode.SYNC_PULL_FAILED,
|
|
6445
|
-
result:
|
|
6446
|
-
fetched,
|
|
6447
|
-
pulled: false,
|
|
6448
|
-
files_updated: 0,
|
|
6449
|
-
conflicts,
|
|
6450
|
-
lint_errors: 0,
|
|
6451
|
-
lint_warnings: 0,
|
|
6452
|
-
humanHint: `pull failed with ${conflicts} conflict(s) \u2014 resolve manually`
|
|
6453
|
-
})
|
|
6806
|
+
result: err("GIT_PULL_FAILED", { message: errString })
|
|
6454
6807
|
};
|
|
6455
6808
|
}
|
|
6456
|
-
return {
|
|
6457
|
-
exitCode: ExitCode.SYNC_PULL_FAILED,
|
|
6458
|
-
result: err("GIT_PULL_FAILED", { message: errString })
|
|
6459
|
-
};
|
|
6460
6809
|
}
|
|
6461
6810
|
let lintErrors = 0;
|
|
6462
6811
|
let lintWarnings = 0;
|
|
@@ -6468,6 +6817,7 @@ async function runSyncPull(input) {
|
|
|
6468
6817
|
const hintParts = [];
|
|
6469
6818
|
if (filesUpdated > 0) hintParts.push(`updated ${filesUpdated} file(s)`);
|
|
6470
6819
|
else hintParts.push("already up to date");
|
|
6820
|
+
if (autoResolved > 0) hintParts.push(`${autoResolved} conflict(s) auto-resolved`);
|
|
6471
6821
|
if (lintErrors > 0) hintParts.push(`${lintErrors} lint error(s)`);
|
|
6472
6822
|
if (lintWarnings > 0) hintParts.push(`${lintWarnings} lint warning(s)`);
|
|
6473
6823
|
const exitCode = lintErrors > 0 ? ExitCode.LINT_HAS_ERRORS : lintWarnings > 0 ? ExitCode.LINT_HAS_WARNINGS : ExitCode.OK;
|
|
@@ -6478,6 +6828,7 @@ async function runSyncPull(input) {
|
|
|
6478
6828
|
pulled,
|
|
6479
6829
|
files_updated: filesUpdated,
|
|
6480
6830
|
conflicts,
|
|
6831
|
+
auto_resolved: autoResolved,
|
|
6481
6832
|
lint_errors: lintErrors,
|
|
6482
6833
|
lint_warnings: lintWarnings,
|
|
6483
6834
|
humanHint: hintParts.join(", ")
|
|
@@ -6598,7 +6949,7 @@ function runSyncUnlock(input) {
|
|
|
6598
6949
|
}
|
|
6599
6950
|
|
|
6600
6951
|
// src/commands/backup.ts
|
|
6601
|
-
import { statSync as statSync4, readdirSync as readdirSync2, readFileSync as
|
|
6952
|
+
import { statSync as statSync4, readdirSync as readdirSync2, readFileSync as readFileSync11, mkdirSync as mkdirSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
6602
6953
|
import { join as join35, relative as relative3, dirname as dirname11 } from "path";
|
|
6603
6954
|
import { PutObjectCommand, HeadObjectCommand, ListObjectsV2Command, GetObjectCommand, DeleteObjectsCommand } from "@aws-sdk/client-s3";
|
|
6604
6955
|
|
|
@@ -6665,7 +7016,7 @@ async function runBackupSync(input) {
|
|
|
6665
7016
|
continue;
|
|
6666
7017
|
}
|
|
6667
7018
|
try {
|
|
6668
|
-
const body =
|
|
7019
|
+
const body = readFileSync11(absPath);
|
|
6669
7020
|
await client.send(new PutObjectCommand({ Bucket: input.bucket, Key: relPath, Body: body }));
|
|
6670
7021
|
uploaded++;
|
|
6671
7022
|
} catch {
|
|
@@ -7292,7 +7643,7 @@ async function postCommit(vault, exitCode) {
|
|
|
7292
7643
|
}
|
|
7293
7644
|
|
|
7294
7645
|
// src/cli.ts
|
|
7295
|
-
var pkg = JSON.parse(
|
|
7646
|
+
var pkg = JSON.parse(readFileSync12(new URL("../package.json", import.meta.url), "utf8"));
|
|
7296
7647
|
var program = new Command2();
|
|
7297
7648
|
program.name("skillwiki").description("Deterministic helpers for CodeWiki skills").version(pkg.version);
|
|
7298
7649
|
program.option("--human", "render terminal-readable output instead of JSON");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillwiki",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
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": {
|