skillwiki 0.4.4 → 0.5.1

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
@@ -10,7 +10,7 @@ import {
10
10
  // src/cli.ts
11
11
  import { readFileSync as readFileSync10 } from "fs";
12
12
  import { join as join38 } from "path";
13
- import { Command } from "commander";
13
+ import { Command as Command2 } from "commander";
14
14
 
15
15
  // ../shared/src/exit-codes.ts
16
16
  var ExitCode = {
@@ -2442,6 +2442,147 @@ async function runRawBodyDedup(vault) {
2442
2442
  };
2443
2443
  }
2444
2444
 
2445
+ // src/utils/cli-surface.ts
2446
+ import { Command } from "commander";
2447
+ function buildCliSurface() {
2448
+ const program2 = new Command();
2449
+ program2.name("skillwiki");
2450
+ program2.option("--human", "render terminal-readable output instead of JSON");
2451
+ program2.command("hash");
2452
+ program2.command("fetch-guard");
2453
+ program2.command("validate").option("--apply").option("--vault <dir>").option("--wiki <name>");
2454
+ program2.command("graph");
2455
+ program2.command("canvas");
2456
+ program2.command("overlap").option("--wiki <name>");
2457
+ program2.command("query").option("--limit <n>").option("--wiki <name>");
2458
+ program2.command("orphans").option("--wiki <name>");
2459
+ program2.command("audit");
2460
+ program2.command("install").option("--target <dir>").option("--dry-run").option("--skills-root <dir>").option("--symlink");
2461
+ program2.command("path").option("--vault <dir>").option("--target <dir>").option("--wiki <name>").option("--init-time").option("--explain");
2462
+ program2.command("lang").option("--lang <code>").option("--explain");
2463
+ program2.command("init").option("--target <dir>").requiredOption("--domain <text>").option("--taxonomy <csv>").option("--lang <code>").option("--force").option("--no-env").option("--profile <name>");
2464
+ program2.command("links").option("--wiki <name>");
2465
+ program2.command("tag-audit").option("--wiki <name>");
2466
+ program2.command("index-check").option("--wiki <name>");
2467
+ program2.command("index-link-format").option("--wiki <name>");
2468
+ program2.command("topic-map-check").option("--threshold <n>").option("--wiki <name>");
2469
+ program2.command("stale").option("--archive").option("--days <n>").option("--force-scan").option("--wiki <name>");
2470
+ program2.command("claim").option("--project <slug>").option("--slug <slug>").option("--wiki <name>");
2471
+ program2.command("pagesize").option("--lines <n>").option("--wiki <name>");
2472
+ program2.command("log-rotate").option("--threshold <n>").option("--apply").option("--wiki <name>");
2473
+ program2.command("lint").option("--days <n>").option("--lines <n>").option("--log-threshold <n>").option("--fix").option("--wiki <name>");
2474
+ program2.command("config");
2475
+ program2.command("doctor");
2476
+ program2.command("status").option("--wiki <name>");
2477
+ program2.command("archive").option("--wiki <name>");
2478
+ program2.command("drift").option("--apply").option("--new <date>").option("--wiki <name>");
2479
+ program2.command("dedup").option("--apply").option("--wiki <name>");
2480
+ program2.command("migrate-citations").option("--dry-run").option("--wiki <name>");
2481
+ program2.command("frontmatter-fix").option("--dry-run").option("--wiki <name>");
2482
+ program2.command("update").option("--tag <tag>");
2483
+ program2.command("self-update").option("--check");
2484
+ program2.command("transcripts").option("--since <date>").option("--wiki <name>");
2485
+ program2.command("project-index").option("--apply").option("--wiki <name>");
2486
+ program2.command("compound");
2487
+ program2.command("tag-sync").option("--dry-run").option("--wiki <name>");
2488
+ program2.command("sync");
2489
+ program2.command("backup");
2490
+ program2.command("seed").option("--wiki <name>");
2491
+ program2.command("observe").requiredOption("--text <text>").option("--kind <kind>").option("--project <slug>").option("--wiki <name>");
2492
+ program2.command("ingest").requiredOption("--vault <path>").requiredOption("--type <type>").requiredOption("--title <title>").option("--tags <csv>").option("--provenance <provenance>").option("--dry-run");
2493
+ const graphCmd = program2.commands.find((c) => c.name() === "graph");
2494
+ graphCmd.command("build").option("--out <path>").option("--wiki <name>");
2495
+ const canvasCmd2 = program2.commands.find((c) => c.name() === "canvas");
2496
+ canvasCmd2.command("generate").option("--graph-path <path>").option("--wiki <name>");
2497
+ const configCmd2 = program2.commands.find((c) => c.name() === "config");
2498
+ configCmd2.command("get");
2499
+ configCmd2.command("set");
2500
+ configCmd2.command("list").option("--profiles");
2501
+ configCmd2.command("path");
2502
+ const compoundCmd2 = program2.commands.find((c) => c.name() === "compound");
2503
+ compoundCmd2.command("promote").requiredOption("--project <slug>").option("--dry-run").option("--wiki <name>");
2504
+ compoundCmd2.command("list").requiredOption("--project <slug>").option("--wiki <name>");
2505
+ compoundCmd2.command("delete").requiredOption("--project <slug>").option("--wiki <name>");
2506
+ const syncCmd2 = program2.commands.find((c) => c.name() === "sync");
2507
+ syncCmd2.command("status").option("--wiki <name>");
2508
+ syncCmd2.command("push").option("--wiki <name>");
2509
+ syncCmd2.command("pull").option("--wiki <name>");
2510
+ const backupCmd2 = program2.commands.find((c) => c.name() === "backup");
2511
+ backupCmd2.command("sync").option("--dry-run").option("--bucket <name>").option("--endpoint <url>").option("--region <region>").option("--prune").option("--wiki <name>");
2512
+ backupCmd2.command("restore").option("--bucket <name>").option("--endpoint <url>").option("--region <region>").option("--target <dir>").option("--wiki <name>");
2513
+ const surface = /* @__PURE__ */ new Map();
2514
+ const rootFlags = new Set(program2.options.map((o) => o.long ?? o.short).filter((f) => f != null));
2515
+ function walk2(cmd, prefix, parentFlags) {
2516
+ const key = prefix ? `${prefix}.${cmd.name()}` : cmd.name();
2517
+ const flags = /* @__PURE__ */ new Set([...parentFlags, ...cmd.options.map((o) => o.long ?? o.short).filter((f) => f != null)]);
2518
+ surface.set(key, flags);
2519
+ for (const sub of cmd.commands) {
2520
+ walk2(sub, key, flags);
2521
+ }
2522
+ }
2523
+ for (const cmd of program2.commands) {
2524
+ walk2(cmd, "", rootFlags);
2525
+ }
2526
+ return surface;
2527
+ }
2528
+ var CLI_REF_RE = /`skillwiki\s+([a-z][a-z0-9-]*(?:\s+[a-z][a-z0-9-]*)?)((?:\s+--[a-z][a-z0-9-]*(?:\s+(?!--)\S+)?)*)`/g;
2529
+ function validateCliRefs(text, page, surface) {
2530
+ const violations = [];
2531
+ const allKeys = new Set(surface.keys());
2532
+ const parentKeys = /* @__PURE__ */ new Set();
2533
+ for (const key of allKeys) {
2534
+ const dotIdx = key.indexOf(".");
2535
+ if (dotIdx >= 0) parentKeys.add(key.slice(0, dotIdx));
2536
+ }
2537
+ for (const match of text.matchAll(CLI_REF_RE)) {
2538
+ const fullMatch = match[0];
2539
+ const cmdPart = match[1];
2540
+ const flagTokens = [...fullMatch.matchAll(/--([a-z][a-z0-9-]*)/g)].map((m) => `--${m[1]}`);
2541
+ const words = cmdPart.split(/\s+/);
2542
+ let resolvedKey;
2543
+ if (words.length >= 2) {
2544
+ const twoWordKey = `${words[0]}.${words[1]}`;
2545
+ if (allKeys.has(twoWordKey)) {
2546
+ resolvedKey = twoWordKey;
2547
+ }
2548
+ }
2549
+ if (!resolvedKey) {
2550
+ if (words.length >= 2) {
2551
+ const oneWordKey2 = words[0];
2552
+ const parentHasSubcommands = [...allKeys].some((k) => k.startsWith(oneWordKey2 + "."));
2553
+ if (parentHasSubcommands) {
2554
+ violations.push({ page, ref: fullMatch.replace(/^`|`$/g, ""), reason: "unknown_command" });
2555
+ continue;
2556
+ }
2557
+ }
2558
+ const oneWordKey = words[0];
2559
+ if (allKeys.has(oneWordKey)) {
2560
+ resolvedKey = oneWordKey;
2561
+ }
2562
+ }
2563
+ if (!resolvedKey) {
2564
+ violations.push({ page, ref: fullMatch.replace(/^`|`$/g, ""), reason: "unknown_command" });
2565
+ continue;
2566
+ }
2567
+ const validFlags = surface.get(resolvedKey);
2568
+ const dotIdx = resolvedKey.indexOf(".");
2569
+ let allValidFlags = validFlags;
2570
+ if (dotIdx >= 0) {
2571
+ const parentKey = resolvedKey.slice(0, dotIdx);
2572
+ const parentFlags = surface.get(parentKey);
2573
+ if (parentFlags) {
2574
+ allValidFlags = /* @__PURE__ */ new Set([...validFlags, ...parentFlags]);
2575
+ }
2576
+ }
2577
+ for (const flag of flagTokens) {
2578
+ if (!allValidFlags.has(flag)) {
2579
+ violations.push({ page, ref: fullMatch.replace(/^`|`$/g, ""), reason: "unknown_flag" });
2580
+ }
2581
+ }
2582
+ }
2583
+ return violations;
2584
+ }
2585
+
2445
2586
  // src/commands/lint.ts
2446
2587
  var STRUCT_MIN_BODY_LINES = 60;
2447
2588
  var STRUCT_MIN_SECTIONS = 3;
@@ -2475,7 +2616,7 @@ function extractSourceEntries(rawFm) {
2475
2616
  }
2476
2617
  var ERROR_ORDER = ["broken_wikilinks", "invalid_frontmatter", "raw_dedup", "broken_sources", "tag_not_in_taxonomy"];
2477
2618
  var WARNING_ORDER = ["raw_body_duplicate", "raw_subdirectory_duplicate", "index_incomplete", "index_link_format", "stale_page", "page_too_large", "log_rotate_needed", "orphans", "compound_refs", "legacy_citation_style", "orphaned_citations", "duplicate_frontmatter", "work_item_health", "orphaned_project_pages", "missing_overview"];
2478
- var INFO_ORDER = ["bridges", "page_structure", "topic_map_recommended", "frontmatter_wikilink", "wikilink_citation", "missing_tldr", "missing_diagram"];
2619
+ var INFO_ORDER = ["bridges", "page_structure", "topic_map_recommended", "frontmatter_wikilink", "wikilink_citation", "missing_tldr", "missing_diagram", "cli_refs"];
2479
2620
  async function runLint(input) {
2480
2621
  const buckets = {};
2481
2622
  const fixed = [];
@@ -2600,7 +2741,7 @@ async function runLint(input) {
2600
2741
  const hasOverview = /^## Overview/m.test(body);
2601
2742
  if (!hasOverview) noOverview.push(page.relPath);
2602
2743
  const bodyFirst15 = body.split("\n").slice(0, 15).join("\n");
2603
- if (!/^##\s+TL;\s*DR/m.test(bodyFirst15)) missingTldrFlags.push(page.relPath);
2744
+ if (!/^>\s*\*\*TL;DR:?\*\*/m.test(bodyFirst15) && !/^##\s+TL;\s*DR/m.test(bodyFirst15)) missingTldrFlags.push(page.relPath);
2604
2745
  const fmData = extractFrontmatter(text);
2605
2746
  const pageTags = fmData.ok && Array.isArray(fmData.data.tags) ? fmData.data.tags : [];
2606
2747
  if (pageTags.includes("architecture") && !body.includes("```mermaid")) {
@@ -2688,6 +2829,17 @@ async function runLint(input) {
2688
2829
  }
2689
2830
  }
2690
2831
  if (orphanedProjectPages.length > 0) buckets.orphaned_project_pages = orphanedProjectPages;
2832
+ const cliRefFlags = [];
2833
+ const cliSurface = buildCliSurface();
2834
+ const allScanPages = [...scan.data.typedKnowledge, ...scan.data.raw, ...scan.data.workItems, ...scan.data.compound];
2835
+ for (const page of allScanPages) {
2836
+ const text = await readPage(page);
2837
+ const violations = validateCliRefs(text, page.relPath, cliSurface);
2838
+ for (const v of violations) {
2839
+ cliRefFlags.push(`${v.page}: ${v.ref} (${v.reason})`);
2840
+ }
2841
+ }
2842
+ if (cliRefFlags.length > 0) buckets.cli_refs = cliRefFlags;
2691
2843
  if (input.fix && legacyPages.length > 0) {
2692
2844
  const FENCE_RE2 = /```[\s\S]*?```/g;
2693
2845
  const INLINE_MARKER = /\^\[raw\/[^\]]+\]/g;
@@ -2834,16 +2986,26 @@ ${trimmedBody}`;
2834
2986
  }
2835
2987
  const body = split.data.body;
2836
2988
  const rawFm = split.data.rawFrontmatter;
2837
- const trimmedBody = body.replace(/^\n+/, "");
2989
+ const lines = body.split("\n");
2990
+ let insertIndex = 0;
2991
+ for (let i = 0; i < lines.length; i++) {
2992
+ if (/^# /.test(lines[i])) {
2993
+ insertIndex = i + 1;
2994
+ while (insertIndex < lines.length && lines[insertIndex].trim() === "") {
2995
+ insertIndex++;
2996
+ }
2997
+ break;
2998
+ }
2999
+ }
3000
+ if (insertIndex === 0) {
3001
+ lines.splice(0, 0, "", "> **TL;DR:** ");
3002
+ } else {
3003
+ lines.splice(insertIndex, 0, "> **TL;DR:** ");
3004
+ }
3005
+ const trimmedFm = rawFm.endsWith("\n") ? rawFm : rawFm + "\n";
2838
3006
  const newContent = `---
2839
- ${rawFm}
2840
- ---
2841
-
2842
- ## TL;DR
2843
-
2844
- - Pending summary.
2845
-
2846
- ${trimmedBody}`;
3007
+ ${trimmedFm}---
3008
+ ${lines.join("\n")}`;
2847
3009
  await writeFile8(absPath, newContent, "utf8");
2848
3010
  fixed.push(relPath);
2849
3011
  } catch {
@@ -6172,7 +6334,7 @@ async function postCommit(vault, exitCode) {
6172
6334
 
6173
6335
  // src/cli.ts
6174
6336
  var pkg = JSON.parse(readFileSync10(new URL("../package.json", import.meta.url), "utf8"));
6175
- var program = new Command();
6337
+ var program = new Command2();
6176
6338
  program.name("skillwiki").description("Deterministic helpers for CodeWiki skills").version(pkg.version);
6177
6339
  program.option("--human", "render terminal-readable output instead of JSON");
6178
6340
  async function emit(r, vault) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.4.4",
3
+ "version": "0.5.1",
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.4.4",
3
+ "version": "0.5.1",
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.4.4",
3
+ "version": "0.5.1",
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.4.4",
3
+ "version": "0.5.1",
4
4
  "private": true,
5
5
  "files": [
6
6
  "wiki-*",
@@ -16,7 +16,7 @@ Standard four reads. If cwd is inside `projects/{slug}/`, also read project READ
16
16
  1. Identify type: entity / concept / comparison / query / summary.
17
17
  2. Set `provenance:`. Default `research`. If in project context: `project` with `provenance_projects: ["[[slug]]"]`.
18
18
  3. Compose the page with citations pre-attached. Reuse existing `raw/` sources where possible. Every page MUST include:
19
- - `## TL;DR` as the first section after frontmatter — a 1–3 bullet summary of the page's key takeaway.
19
+ - `> **TL;DR:**` blockquote as the first content after the title heading — a one-sentence summary of the page's key takeaway (under 200 chars). See SCHEMA.md `## TL;DR Convention`.
20
20
  - For pages tagged `architecture` or explaining workflows/systems: include a Mermaid diagram (`graph TB` or `sequenceDiagram`) in the body. Follow Obsidian-compatible Mermaid rules (see SCHEMA.md `## Mermaid Diagrams`).
21
21
  4. `skillwiki validate <page>`. If non-zero, STOP.
22
22
  5. Apply writes: page → `index.md` → `log.md`.
@@ -21,7 +21,7 @@ Run `skillwiki lang` at the start. Generate page-body prose, narrative sections,
21
21
  2. **Fetch.** Use `web_fetch` (or read local file) under Layer 2 controls (the CLI Layer 2 fetcher applies in tests; in skill runtime use `web_fetch` directly and treat any error as STOP).
22
22
  3. **Hash.** Write the raw file (frontmatter + body). Run `skillwiki hash <raw-file>` and embed the result in raw frontmatter `sha256:`.
23
23
  4. **Generate page(s).** Compose typed-knowledge page(s) with citations pre-attached (`^[raw/...]` markers). Every page MUST include:
24
- - `## TL;DR` as the first section after frontmatter — a 1–3 bullet summary of the page's key takeaway.
24
+ - `> **TL;DR:**` blockquote as the first content after the title heading — a one-sentence summary of the page's key takeaway (under 200 chars). See SCHEMA.md `## TL;DR Convention`.
25
25
  - For pages tagged `architecture` or explaining workflows/systems: include a Mermaid diagram (`graph TB` or `sequenceDiagram`) in the body. Follow Obsidian-compatible Mermaid rules (see SCHEMA.md `## Mermaid Diagrams`).
26
26
  5. **Validate.** For each generated page: run `skillwiki validate <page>`. If exit ≠ 0, STOP — do not write index/log.
27
27
  6. **Apply writes in order.** raw → page(s) → `index.md` → `log.md`.