skillwiki 0.2.3 → 0.2.5

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.
@@ -14,7 +14,7 @@ if (!home || !currentVersion) process.exit(0);
14
14
  var cacheFile = join(home, ".skillwiki", ".update-cache.json");
15
15
  setTimeout(() => process.exit(0), 3e4);
16
16
  try {
17
- const latest = execSync("npm view skillwiki@beta version", {
17
+ const latest = execSync("npm view skillwiki@latest version", {
18
18
  encoding: "utf8",
19
19
  timeout: 15e3
20
20
  }).trim();
@@ -25,7 +25,7 @@ try {
25
25
  currentVersion
26
26
  };
27
27
  if (semverGt(latest, currentVersion)) {
28
- execSync("npm install -g skillwiki@beta", {
28
+ execSync("npm install -g skillwiki@latest", {
29
29
  stdio: "ignore",
30
30
  timeout: 6e4
31
31
  });
package/dist/cli.js CHANGED
@@ -2239,7 +2239,7 @@ function extractSourceEntries(rawFm) {
2239
2239
  }
2240
2240
  var ERROR_ORDER = ["broken_wikilinks", "invalid_frontmatter", "raw_dedup", "broken_sources", "tag_not_in_taxonomy"];
2241
2241
  var WARNING_ORDER = ["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"];
2242
- var INFO_ORDER = ["bridges", "page_structure", "topic_map_recommended", "frontmatter_wikilink", "wikilink_citation"];
2242
+ var INFO_ORDER = ["bridges", "page_structure", "topic_map_recommended", "frontmatter_wikilink", "wikilink_citation", "missing_tldr", "missing_diagram"];
2243
2243
  async function runLint(input) {
2244
2244
  const buckets = {};
2245
2245
  const fixed = [];
@@ -2302,6 +2302,8 @@ async function runLint(input) {
2302
2302
  const fmWikilinkFlags = [];
2303
2303
  const wikilinkCitationFlags = [];
2304
2304
  const brokenSourceFlags = [];
2305
+ const missingTldrFlags = [];
2306
+ const missingDiagramFlags = [];
2305
2307
  for (const page of scan.data.typedKnowledge) {
2306
2308
  const text = await readPage(page);
2307
2309
  const split = splitFrontmatter(text);
@@ -2332,6 +2334,13 @@ async function runLint(input) {
2332
2334
  const bodyLines = body.split("\n").filter((l) => l.trim().length > 0).length;
2333
2335
  const hasOverview = /^## Overview/m.test(body);
2334
2336
  if (!hasOverview) noOverview.push(page.relPath);
2337
+ const bodyFirst15 = body.split("\n").slice(0, 15).join("\n");
2338
+ if (!/^##\s+TL;\s*DR/m.test(bodyFirst15)) missingTldrFlags.push(page.relPath);
2339
+ const fmData = extractFrontmatter(text);
2340
+ const pageTags = fmData.ok && Array.isArray(fmData.data.tags) ? fmData.data.tags : [];
2341
+ if (pageTags.includes("architecture") && !body.includes("```mermaid")) {
2342
+ missingDiagramFlags.push(page.relPath);
2343
+ }
2335
2344
  if (bodyLines < STRUCT_MIN_BODY_LINES) {
2336
2345
  const hasRelated = /^## (Related|Relationships)/m.test(body);
2337
2346
  const sectionCount = (body.match(/^## /gm) ?? []).length;
@@ -2351,6 +2360,8 @@ async function runLint(input) {
2351
2360
  if (fmWikilinkFlags.length > 0) buckets.frontmatter_wikilink = fmWikilinkFlags;
2352
2361
  if (wikilinkCitationFlags.length > 0) buckets.wikilink_citation = wikilinkCitationFlags;
2353
2362
  if (brokenSourceFlags.length > 0) buckets.broken_sources = brokenSourceFlags;
2363
+ if (missingTldrFlags.length > 0) buckets.missing_tldr = missingTldrFlags;
2364
+ if (missingDiagramFlags.length > 0) buckets.missing_diagram = missingDiagramFlags;
2354
2365
  const workItemHealth = [];
2355
2366
  const workItemDirs = /* @__PURE__ */ new Map();
2356
2367
  for (const page of scan.data.workItems) {
@@ -2540,6 +2551,39 @@ ${trimmedBody}`;
2540
2551
  if (remaining.length > 0) buckets.missing_overview = remaining;
2541
2552
  else delete buckets.missing_overview;
2542
2553
  }
2554
+ if (input.fix && missingTldrFlags.length > 0) {
2555
+ for (const relPath of missingTldrFlags) {
2556
+ try {
2557
+ const absPath = `${input.vault}/${relPath}`;
2558
+ const raw = await readFile13(absPath, "utf8");
2559
+ const split = splitFrontmatter(raw);
2560
+ if (!split.ok) {
2561
+ unresolved.push(relPath);
2562
+ continue;
2563
+ }
2564
+ const body = split.data.body;
2565
+ const rawFm = split.data.rawFrontmatter;
2566
+ const trimmedBody = body.replace(/^\n+/, "");
2567
+ const newContent = `---
2568
+ ${rawFm}
2569
+ ---
2570
+
2571
+ ## TL;DR
2572
+
2573
+ - Pending summary.
2574
+
2575
+ ${trimmedBody}`;
2576
+ await writeFile7(absPath, newContent, "utf8");
2577
+ fixed.push(relPath);
2578
+ } catch {
2579
+ unresolved.push(relPath);
2580
+ }
2581
+ }
2582
+ const fixedSet = new Set(fixed);
2583
+ const remaining = missingTldrFlags.filter((p) => !fixedSet.has(p));
2584
+ if (remaining.length > 0) buckets.missing_tldr = remaining;
2585
+ else delete buckets.missing_tldr;
2586
+ }
2543
2587
  if (input.fix && wikilinkCitationFlags.length > 0) {
2544
2588
  const WIKILINK_RE = /\[\[raw\/([^\]|]+)(?:\|[^\]]*)?\]\]/g;
2545
2589
  const FENCE_RE2 = /```[\s\S]*?```/g;
@@ -3015,7 +3059,7 @@ function checkPluginVersionDrift(home, currentVersion) {
3015
3059
  if (pluginVersion === currentVersion) {
3016
3060
  return check("pass", "plugin_version_drift", "Plugin/CLI version", `Both at v${currentVersion}`);
3017
3061
  }
3018
- const updateCmd = semverGt(pluginVersion, currentVersion) ? "npm install -g skillwiki@beta" : "claude plugin update skillwiki@llm-wiki";
3062
+ const updateCmd = semverGt(pluginVersion, currentVersion) ? "npm install -g skillwiki@latest" : "claude plugin update skillwiki@llm-wiki";
3019
3063
  return check(
3020
3064
  "warn",
3021
3065
  "plugin_version_drift",
@@ -3667,7 +3711,7 @@ async function runUpdate(input) {
3667
3711
  readFileSync6(new URL("../../package.json", import.meta.url), "utf8")
3668
3712
  );
3669
3713
  const currentVersion = pkg2.version;
3670
- const tag = input.distTag ?? "beta";
3714
+ const tag = input.distTag ?? "latest";
3671
3715
  const target = join23(input.home, ".claude", "skills");
3672
3716
  let latest;
3673
3717
  try {
@@ -3761,7 +3805,7 @@ async function runSelfUpdate(input) {
3761
3805
  } else {
3762
3806
  source = "npm";
3763
3807
  try {
3764
- availableVersion = execSync3("npm view skillwiki@beta version", {
3808
+ availableVersion = execSync3("npm view skillwiki@latest version", {
3765
3809
  encoding: "utf8",
3766
3810
  timeout: 15e3
3767
3811
  }).trim();
@@ -3831,7 +3875,7 @@ async function runSelfUpdate(input) {
3831
3875
  }
3832
3876
  let latestVersion;
3833
3877
  try {
3834
- latestVersion = execSync3("npm view skillwiki@beta version", {
3878
+ latestVersion = execSync3("npm view skillwiki@latest version", {
3835
3879
  encoding: "utf8",
3836
3880
  timeout: 15e3
3837
3881
  }).trim();
@@ -3849,12 +3893,12 @@ async function runSelfUpdate(input) {
3849
3893
  currentVersion,
3850
3894
  availableVersion: latestVersion,
3851
3895
  updateAvailable: false,
3852
- humanHint: `Already on latest beta: v${currentVersion}`
3896
+ humanHint: `Already on latest: v${currentVersion}`
3853
3897
  })
3854
3898
  };
3855
3899
  }
3856
3900
  try {
3857
- execSync3("npm install -g skillwiki@beta", {
3901
+ execSync3("npm install -g skillwiki@latest", {
3858
3902
  stdio: "pipe",
3859
3903
  timeout: 6e4
3860
3904
  });
@@ -3872,7 +3916,7 @@ async function runSelfUpdate(input) {
3872
3916
  availableVersion: latestVersion,
3873
3917
  updateAvailable: true,
3874
3918
  newVersion: latestVersion,
3875
- humanHint: `Updated skillwiki ${currentVersion} \u2192 ${latestVersion} via npm@beta`
3919
+ humanHint: `Updated skillwiki ${currentVersion} \u2192 ${latestVersion} via npm@latest`
3876
3920
  })
3877
3921
  };
3878
3922
  }
@@ -5973,11 +6017,11 @@ program.command("frontmatter-fix [vault]").description("fix common frontmatter i
5973
6017
  if (!v.ok) emit({ exitCode: v.exitCode, result: v.payload });
5974
6018
  else emit(await runFrontmatterFix({ vault: v.vault, dryRun: !!opts.dryRun }), v.vault);
5975
6019
  });
5976
- program.command("update").description("update skillwiki CLI to the latest version").option("--tag <tag>", "npm dist-tag", "beta").action(async (opts) => emit(await runUpdate({
6020
+ program.command("update").description("update skillwiki CLI to the latest version").option("--tag <tag>", "npm dist-tag", "latest").action(async (opts) => emit(await runUpdate({
5977
6021
  home: process.env.HOME ?? "",
5978
6022
  distTag: opts.tag
5979
6023
  })));
5980
- program.command("self-update").description("update skillwiki CLI from local source or npm@beta").option("--check", "check for updates without installing", false).action(async (opts) => emit(await runSelfUpdate({
6024
+ program.command("self-update").description("update skillwiki CLI from local source or npm@latest").option("--check", "check for updates without installing", false).action(async (opts) => emit(await runSelfUpdate({
5981
6025
  home: process.env.HOME ?? "",
5982
6026
  check: !!opts.check
5983
6027
  })));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
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.3",
3
+ "version": "0.2.5",
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": {
@@ -2,4 +2,4 @@
2
2
  # skillwiki CLI wrapper — delegates to npx so the CLI is available
3
3
  # automatically when this plugin is enabled (Claude Code adds bin/ to PATH).
4
4
  set -euo pipefail
5
- exec npx -y skillwiki@beta "$@"
5
+ exec npx -y skillwiki@latest "$@"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillwiki/skills",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "private": true,
5
5
  "files": [
6
6
  "wiki-*",
@@ -22,7 +22,9 @@ Standard four reads. If cwd is inside `projects/{slug}/`, also read project READ
22
22
  0. **Resolve vault and language.** Run `skillwiki path` (fail if NO_VAULT_CONFIGURED) and `skillwiki lang`.
23
23
  1. Identify type: entity / concept / comparison / query / summary.
24
24
  2. Set `provenance:`. Default `research`. If in project context: `project` with `provenance_projects: ["[[slug]]"]`.
25
- 3. Compose the page with citations pre-attached. Reuse existing `raw/` sources where possible.
25
+ 3. Compose the page with citations pre-attached. Reuse existing `raw/` sources where possible. Every page MUST include:
26
+ - `## TL;DR` as the first section after frontmatter — a 1–3 bullet summary of the page's key takeaway.
27
+ - 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
28
  4. `skillwiki validate <page>`. If non-zero, STOP.
27
29
  5. Apply writes: page → `index.md` → `log.md`.
28
30
 
@@ -27,7 +27,9 @@ Run `skillwiki lang` at the start. Generate page-body prose, narrative sections,
27
27
  1. **Guard.** For each URL: run `skillwiki fetch-guard <url>`. If exit ≠ 0, STOP and surface the error. Do not retry.
28
28
  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).
29
29
  3. **Hash.** Write the raw file (frontmatter + body). Run `skillwiki hash <raw-file>` and embed the result in raw frontmatter `sha256:`.
30
- 4. **Generate page(s).** Compose typed-knowledge page(s) with citations pre-attached (`^[raw/...]` markers).
30
+ 4. **Generate page(s).** Compose typed-knowledge page(s) with citations pre-attached (`^[raw/...]` markers). Every page MUST include:
31
+ - `## TL;DR` as the first section after frontmatter — a 1–3 bullet summary of the page's key takeaway.
32
+ - 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`).
31
33
  5. **Validate.** For each generated page: run `skillwiki validate <page>`. If exit ≠ 0, STOP — do not write index/log.
32
34
  6. **Apply writes in order.** raw → page(s) → `index.md` → `log.md`.
33
35
  7. **Confidence flag.** If only one source is cited, set `confidence: low`.
@@ -52,6 +52,17 @@ Rule: every tag on every page MUST appear in this taxonomy. Add new tags here fi
52
52
  - Citations in body: `^[raw/...]` markers at paragraph-end; every entry in `sources:` MUST appear in body and in `## Sources` footer.
53
53
  - Legacy inline `^[raw/...]` markers remain valid; `migrate-citations` converts them.
54
54
  - sha256 in `raw/` frontmatter is computed by `skillwiki hash` over body bytes after closing `---`.
55
+ - Every typed-knowledge page SHOULD include a `## TL;DR` section near the top (after frontmatter, before `## Overview`). Lint flags pages missing it as `missing_tldr` (info).
56
+
57
+ ## Mermaid Diagrams
58
+
59
+ Pages explaining architectures, workflows, or complex concepts SHOULD include inline Mermaid diagrams. Lint flags architecture-tagged pages without a ` ```mermaid ` block as `missing_diagram` (info).
60
+
61
+ Obsidian-compatible Mermaid rules:
62
+ - Prefer `graph TB` / `sequenceDiagram`.
63
+ - Use `subgraph "Title"` (avoid `subgraph ID[Label]`).
64
+ - Avoid `\n` in labels; use `<br/>` or single-line labels.
65
+ - Keep node IDs ASCII and simple (`CMUX_DB`, `OC_GW`).
55
66
 
56
67
  ## Obsidian Integration
57
68