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 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 fm = extractFrontmatter(await readPage(raw));
2221
- if (!fm.ok) continue;
2222
- const sourceUrl = typeof fm.data.source_url === "string" ? fm.data.source_url : null;
2223
- const storedHash = typeof fm.data.sha256 === "string" ? fm.data.sha256 : null;
2224
- if (!sourceUrl || !storedHash) continue;
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
- results.push({
2240
- raw_path: raw.relPath,
2241
- source_url: sourceUrl,
2242
- stored_sha256: storedHash,
2243
- current_sha256: currentHash,
2244
- status: drifted2 ? "drifted" : "unchanged"
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 writeFile7 } from "fs/promises";
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 writeFile7(page.absPath, newText, "utf8");
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 writeFile8 } from "fs/promises";
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 writeFile8(page.absPath, newText, "utf8");
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.32",
3
+ "version": "0.2.0-beta.33",
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.2.0-beta.32",
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": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillwiki/skills",
3
- "version": "0.2.0-beta.32",
3
+ "version": "0.2.0-beta.33",
4
4
  "private": true,
5
5
  "files": [
6
6
  "wiki-*",