skillwiki 0.2.0-beta.32 → 0.2.0-beta.33
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 +42 -19
- package/package.json +1 -1
- package/skills/.claude-plugin/plugin.json +1 -1
- package/skills/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2176,6 +2176,7 @@ async function runArchive(input) {
|
|
|
2176
2176
|
|
|
2177
2177
|
// src/commands/drift.ts
|
|
2178
2178
|
import { createHash as createHash2 } from "crypto";
|
|
2179
|
+
import { writeFile as writeFile7 } from "fs/promises";
|
|
2179
2180
|
|
|
2180
2181
|
// src/utils/fetch.ts
|
|
2181
2182
|
async function controlledFetch(url, opts) {
|
|
@@ -2217,11 +2218,15 @@ async function runDrift(input) {
|
|
|
2217
2218
|
if (!scan.ok) return { exitCode: ExitCode.VAULT_PATH_INVALID, result: scan };
|
|
2218
2219
|
const results = [];
|
|
2219
2220
|
for (const raw of scan.data.raw) {
|
|
2220
|
-
const
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
const
|
|
2224
|
-
|
|
2221
|
+
const text = await readPage(raw);
|
|
2222
|
+
const split = splitFrontmatter(text);
|
|
2223
|
+
if (!split.ok) continue;
|
|
2224
|
+
const { rawFrontmatter, body } = split.data;
|
|
2225
|
+
const sourceUrlMatch = rawFrontmatter.match(/^source_url:\s*(.+)$/m);
|
|
2226
|
+
const storedHashMatch = rawFrontmatter.match(/^sha256:\s*([a-f0-9]+)$/m);
|
|
2227
|
+
if (!sourceUrlMatch || !storedHashMatch) continue;
|
|
2228
|
+
const sourceUrl = sourceUrlMatch[1].trim();
|
|
2229
|
+
const storedHash = storedHashMatch[1];
|
|
2225
2230
|
const resp = await doFetch(sourceUrl, FETCH_OPTS);
|
|
2226
2231
|
if (!resp.ok) {
|
|
2227
2232
|
results.push({
|
|
@@ -2236,29 +2241,47 @@ async function runDrift(input) {
|
|
|
2236
2241
|
}
|
|
2237
2242
|
const currentHash = createHash2("sha256").update(Buffer.from(resp.data.body, "utf8")).digest("hex");
|
|
2238
2243
|
const drifted2 = currentHash !== storedHash;
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2244
|
+
if (drifted2 && input.apply) {
|
|
2245
|
+
const newFm = rawFrontmatter.replace(/^sha256:\s*[a-f0-9]+$/m, `sha256: ${currentHash}`);
|
|
2246
|
+
const newText = `---
|
|
2247
|
+
${newFm}
|
|
2248
|
+
---
|
|
2249
|
+
${body}`;
|
|
2250
|
+
await writeFile7(raw.absPath, newText, "utf8");
|
|
2251
|
+
results.push({
|
|
2252
|
+
raw_path: raw.relPath,
|
|
2253
|
+
source_url: sourceUrl,
|
|
2254
|
+
stored_sha256: storedHash,
|
|
2255
|
+
current_sha256: currentHash,
|
|
2256
|
+
status: "updated"
|
|
2257
|
+
});
|
|
2258
|
+
} else {
|
|
2259
|
+
results.push({
|
|
2260
|
+
raw_path: raw.relPath,
|
|
2261
|
+
source_url: sourceUrl,
|
|
2262
|
+
stored_sha256: storedHash,
|
|
2263
|
+
current_sha256: currentHash,
|
|
2264
|
+
status: drifted2 ? "drifted" : "unchanged"
|
|
2265
|
+
});
|
|
2266
|
+
}
|
|
2246
2267
|
}
|
|
2247
2268
|
const drifted = results.filter((r) => r.status === "drifted");
|
|
2248
2269
|
const fetchFailed = results.filter((r) => r.status === "fetch_failed");
|
|
2270
|
+
const updated = results.filter((r) => r.status === "updated");
|
|
2249
2271
|
const unchanged = results.filter((r) => r.status === "unchanged").length;
|
|
2250
2272
|
const exitCode = drifted.length > 0 ? ExitCode.DRIFT_DETECTED : ExitCode.OK;
|
|
2251
2273
|
const hintLines = [`scanned: ${results.length}, unchanged: ${unchanged}`];
|
|
2252
2274
|
if (drifted.length > 0) hintLines.push(`drifted: ${drifted.length}`, ...drifted.map((d) => ` ${d.raw_path}`));
|
|
2253
2275
|
if (fetchFailed.length > 0) hintLines.push(`fetch_failed: ${fetchFailed.length}`, ...fetchFailed.map((f) => ` ${f.raw_path}: ${f.fetch_error}`));
|
|
2276
|
+
if (updated.length > 0) hintLines.push(`updated: ${updated.length}`, ...updated.map((u) => ` ${u.raw_path}`));
|
|
2254
2277
|
return {
|
|
2255
2278
|
exitCode,
|
|
2256
|
-
result: ok({ scanned: results.length, drifted, fetch_failed: fetchFailed, unchanged, humanHint: hintLines.join("\n") })
|
|
2279
|
+
result: ok({ scanned: results.length, drifted, fetch_failed: fetchFailed, updated, unchanged, humanHint: hintLines.join("\n") })
|
|
2257
2280
|
};
|
|
2258
2281
|
}
|
|
2259
2282
|
|
|
2260
2283
|
// src/commands/migrate-citations.ts
|
|
2261
|
-
import { writeFile as
|
|
2284
|
+
import { writeFile as writeFile8 } from "fs/promises";
|
|
2262
2285
|
var MARKER_RE2 = /\^\[(raw\/[^\]]+)\]/g;
|
|
2263
2286
|
function moveMarkersToParagraphEnd(body) {
|
|
2264
2287
|
const lines = body.split("\n");
|
|
@@ -2381,7 +2404,7 @@ ${migratedBody}${newFooter}`;
|
|
|
2381
2404
|
continue;
|
|
2382
2405
|
}
|
|
2383
2406
|
if (!input.dryRun) {
|
|
2384
|
-
await
|
|
2407
|
+
await writeFile8(page.absPath, newText, "utf8");
|
|
2385
2408
|
}
|
|
2386
2409
|
migrated.push(page.relPath);
|
|
2387
2410
|
}
|
|
@@ -2403,7 +2426,7 @@ ${migratedBody}${newFooter}`;
|
|
|
2403
2426
|
}
|
|
2404
2427
|
|
|
2405
2428
|
// src/commands/frontmatter-fix.ts
|
|
2406
|
-
import { writeFile as
|
|
2429
|
+
import { writeFile as writeFile9 } from "fs/promises";
|
|
2407
2430
|
function isoToday() {
|
|
2408
2431
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2409
2432
|
}
|
|
@@ -2445,7 +2468,7 @@ ${newBody}`;
|
|
|
2445
2468
|
continue;
|
|
2446
2469
|
}
|
|
2447
2470
|
if (!input.dryRun) {
|
|
2448
|
-
await
|
|
2471
|
+
await writeFile9(page.absPath, newText, "utf8");
|
|
2449
2472
|
}
|
|
2450
2473
|
fixed.push(page.relPath);
|
|
2451
2474
|
}
|
|
@@ -2663,10 +2686,10 @@ program.command("archive <page> [vault]").description("archive a typed-knowledge
|
|
|
2663
2686
|
if (!v.ok) emit({ exitCode: v.exitCode, result: v.payload });
|
|
2664
2687
|
else emit(await runArchive({ vault: v.vault, page }));
|
|
2665
2688
|
});
|
|
2666
|
-
program.command("drift [vault]").description("detect content drift in raw sources").option("--wiki <name>", "wiki profile name").action(async (vault, opts) => {
|
|
2689
|
+
program.command("drift [vault]").description("detect content drift in raw sources").option("--apply", "update sha256 in drifted sources").option("--wiki <name>", "wiki profile name").action(async (vault, opts) => {
|
|
2667
2690
|
const v = await resolveVaultArg(vault, opts.wiki);
|
|
2668
2691
|
if (!v.ok) emit({ exitCode: v.exitCode, result: v.payload });
|
|
2669
|
-
else emit(await runDrift({ vault: v.vault }));
|
|
2692
|
+
else emit(await runDrift({ vault: v.vault, apply: opts.apply }));
|
|
2670
2693
|
});
|
|
2671
2694
|
program.command("dedup [vault]").description("detect duplicate raw sources by sha256").option("--apply", "rewire citations and remove duplicate raw files", false).option("--wiki <name>", "wiki profile name").action(async (vault, opts) => {
|
|
2672
2695
|
const v = await resolveVaultArg(vault, opts.wiki);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillwiki",
|
|
3
|
-
"version": "0.2.0-beta.
|
|
3
|
+
"version": "0.2.0-beta.33",
|
|
4
4
|
"skills": "./",
|
|
5
5
|
"description": "Project-aware Karpathy-style knowledge base for Claude Code: 11 prompt-only skills (wiki-*, proj-*, using-skillwiki) backed by the deterministic `skillwiki` CLI (8 subcommands, JSON-by-default).",
|
|
6
6
|
"author": {
|