skillwiki 0.2.0 → 0.2.1-beta.2

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
@@ -878,6 +878,10 @@ function hasOrphanedCitations(body) {
878
878
  }
879
879
  return false;
880
880
  }
881
+ function hasWikilinkCitations(body) {
882
+ const stripped = stripFences(body);
883
+ return /\[\[raw\/[^\]]+\]\]/.test(stripped);
884
+ }
881
885
 
882
886
  // src/commands/audit.ts
883
887
  async function runAudit(input) {
@@ -1704,7 +1708,7 @@ function hasDuplicateFrontmatter(body) {
1704
1708
  }
1705
1709
  var ERROR_ORDER = ["broken_wikilinks", "invalid_frontmatter", "raw_dedup", "tag_not_in_taxonomy"];
1706
1710
  var WARNING_ORDER = ["index_incomplete", "index_link_format", "stale_page", "page_too_large", "log_rotate_needed", "orphans", "legacy_citation_style", "orphaned_citations", "duplicate_frontmatter", "missing_overview"];
1707
- var INFO_ORDER = ["bridges", "page_structure", "topic_map_recommended", "frontmatter_wikilink"];
1711
+ var INFO_ORDER = ["bridges", "page_structure", "topic_map_recommended", "frontmatter_wikilink", "wikilink_citation"];
1708
1712
  async function runLint(input) {
1709
1713
  const buckets = {};
1710
1714
  const links = await runLinks({ vault: input.vault });
@@ -1757,6 +1761,7 @@ async function runLint(input) {
1757
1761
  const dupFrontmatter = [];
1758
1762
  const noOverview = [];
1759
1763
  const fmWikilinkFlags = [];
1764
+ const wikilinkCitationFlags = [];
1760
1765
  for (const page of scan.data.typedKnowledge) {
1761
1766
  const text = await readPage(page);
1762
1767
  const split = splitFrontmatter(text);
@@ -1766,6 +1771,7 @@ async function runLint(input) {
1766
1771
  if (hasDuplicateFrontmatter(body)) dupFrontmatter.push(page.relPath);
1767
1772
  if (isLegacyCitationStyle(body)) legacyPages.push(page.relPath);
1768
1773
  if (hasOrphanedCitations(body)) orphanedPages.push(page.relPath);
1774
+ if (hasWikilinkCitations(body)) wikilinkCitationFlags.push(page.relPath);
1769
1775
  const fmLinks = rawFm.match(/\[\[([^\[\]|]+)(?:\|[^\[\]]*)?\]\]/g) ?? [];
1770
1776
  for (const link of fmLinks) {
1771
1777
  const target = link.replace(/^\[\[/, "").replace(/(?:\|[^\[\]]*)?\]\]$/, "").trim();
@@ -1794,6 +1800,7 @@ async function runLint(input) {
1794
1800
  if (dupFrontmatter.length > 0) buckets.duplicate_frontmatter = dupFrontmatter;
1795
1801
  if (noOverview.length > 0) buckets.missing_overview = noOverview;
1796
1802
  if (fmWikilinkFlags.length > 0) buckets.frontmatter_wikilink = fmWikilinkFlags;
1803
+ if (wikilinkCitationFlags.length > 0) buckets.wikilink_citation = wikilinkCitationFlags;
1797
1804
  }
1798
1805
  const errorOut = ERROR_ORDER.flatMap((k) => buckets[k] ? [{ kind: k, items: buckets[k] }] : []);
1799
1806
  const warningOut = WARNING_ORDER.flatMap((k) => buckets[k] ? [{ kind: k, items: buckets[k] }] : []);
@@ -1888,8 +1895,8 @@ async function runConfigPath(input) {
1888
1895
  }
1889
1896
 
1890
1897
  // src/commands/doctor.ts
1891
- import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3, statSync } from "fs";
1892
- import { join as join16 } from "path";
1898
+ import { existsSync as existsSync3, readdirSync, statSync } from "fs";
1899
+ import { join as join17 } from "path";
1893
1900
  import { execSync } from "child_process";
1894
1901
 
1895
1902
  // src/utils/auto-update.ts
@@ -1953,6 +1960,27 @@ function triggerAutoUpdate(home, currentVersion) {
1953
1960
  child.unref();
1954
1961
  }
1955
1962
 
1963
+ // src/utils/plugin-registry.ts
1964
+ import { readFileSync as readFileSync3 } from "fs";
1965
+ import { join as join16 } from "path";
1966
+ var REGISTRY_PATH = join16(".claude", "plugins", "installed_plugins.json");
1967
+ var PLUGIN_KEY = "skillwiki@llm-wiki";
1968
+ function readInstalledPlugins(home) {
1969
+ try {
1970
+ const raw = readFileSync3(join16(home, REGISTRY_PATH), "utf8");
1971
+ return JSON.parse(raw);
1972
+ } catch {
1973
+ return null;
1974
+ }
1975
+ }
1976
+ function findPlugin(home, key = PLUGIN_KEY) {
1977
+ const registry = readInstalledPlugins(home);
1978
+ if (!registry?.plugins) return null;
1979
+ const entries = registry.plugins[key];
1980
+ if (!entries || entries.length === 0) return null;
1981
+ return entries[0];
1982
+ }
1983
+
1956
1984
  // src/commands/doctor.ts
1957
1985
  function check(status, id, label, detail) {
1958
1986
  return { id, label, status, detail };
@@ -2008,9 +2036,9 @@ function checkVaultStructure(resolvedPath) {
2008
2036
  return check("error", "vault_structure", "Vault structure valid", "Cannot check \u2014 vault directory does not exist");
2009
2037
  }
2010
2038
  const missing = [];
2011
- if (!existsSync3(join16(resolvedPath, "SCHEMA.md"))) missing.push("SCHEMA.md");
2039
+ if (!existsSync3(join17(resolvedPath, "SCHEMA.md"))) missing.push("SCHEMA.md");
2012
2040
  for (const dir of ["raw", "entities", "concepts", "meta"]) {
2013
- if (!existsSync3(join16(resolvedPath, dir))) missing.push(dir + "/");
2041
+ if (!existsSync3(join17(resolvedPath, dir))) missing.push(dir + "/");
2014
2042
  }
2015
2043
  if (missing.length === 0) {
2016
2044
  return check("pass", "vault_structure", "Vault structure valid", "All required files and directories present");
@@ -2018,15 +2046,21 @@ function checkVaultStructure(resolvedPath) {
2018
2046
  return check("warn", "vault_structure", "Vault structure valid", `Missing: ${missing.join(", ")} \u2014 run \`skillwiki init\` to add CodeWiki structure`);
2019
2047
  }
2020
2048
  function checkSkillsInstalled(home) {
2021
- const skillsDir = join16(home, ".claude", "skills");
2022
- if (!existsSync3(skillsDir)) {
2023
- return check("warn", "skills_installed", "Skills installed", `${skillsDir} not found`);
2049
+ const plugin = findPlugin(home);
2050
+ if (plugin) {
2051
+ const found = findSkillMd(plugin.installPath);
2052
+ if (found.length > 0) {
2053
+ return check("pass", "skills_installed", "Skills installed", `${found.length} SKILL.md file(s) found (plugin v${plugin.version})`);
2054
+ }
2024
2055
  }
2025
- const found = findSkillMd(skillsDir);
2026
- if (found.length > 0) {
2027
- return check("pass", "skills_installed", "Skills installed", `${found.length} SKILL.md file(s) found`);
2056
+ const skillsDir = join17(home, ".claude", "skills");
2057
+ if (existsSync3(skillsDir)) {
2058
+ const found = findSkillMd(skillsDir);
2059
+ if (found.length > 0) {
2060
+ return check("pass", "skills_installed", "Skills installed", `${found.length} SKILL.md file(s) found (CLI install)`);
2061
+ }
2028
2062
  }
2029
- return check("warn", "skills_installed", "Skills installed", "No SKILL.md files found in ~/.claude/skills/");
2063
+ return check("warn", "skills_installed", "Skills installed", "No SKILL.md files found");
2030
2064
  }
2031
2065
  function checkNpmUpdate(home, currentVersion) {
2032
2066
  const { hasUpdate, latest } = latestFromCache(home, currentVersion);
@@ -2039,30 +2073,21 @@ function checkNpmUpdate(home, currentVersion) {
2039
2073
  return check("pass", "npm_update", "npm CLI version", `v${currentVersion} (latest: v${latest})`);
2040
2074
  }
2041
2075
  function checkPluginVersionDrift(home, currentVersion) {
2042
- const pluginJsonPath = join16(home, ".claude", "plugins", "cache", "llm-wiki", "plugin.json");
2043
- if (!existsSync3(pluginJsonPath)) {
2044
- return check("pass", "plugin_version_drift", "Plugin/CLI version", "Plugin cache not found \u2014 plugin not installed");
2076
+ const plugin = findPlugin(home);
2077
+ if (!plugin) {
2078
+ return check("pass", "plugin_version_drift", "Plugin/CLI version", "Plugin not installed \u2014 CLI only");
2045
2079
  }
2046
- try {
2047
- const content = readFileSync3(pluginJsonPath, { encoding: "utf8" });
2048
- const pluginData = JSON.parse(content);
2049
- const pluginVersion = pluginData.version;
2050
- if (!pluginVersion) {
2051
- return check("pass", "plugin_version_drift", "Plugin/CLI version", "Plugin version not found in cache");
2052
- }
2053
- if (pluginVersion === currentVersion) {
2054
- return check("pass", "plugin_version_drift", "Plugin/CLI version", `Both at v${currentVersion}`);
2055
- }
2056
- const updateCmd = semverGt(pluginVersion, currentVersion) ? "npm install -g skillwiki@beta" : "claude plugin update skillwiki@llm-wiki";
2057
- return check(
2058
- "warn",
2059
- "plugin_version_drift",
2060
- "Plugin/CLI version",
2061
- `Plugin v${pluginVersion} \u2260 CLI v${currentVersion} \u2014 run \`${updateCmd}\``
2062
- );
2063
- } catch {
2064
- return check("pass", "plugin_version_drift", "Plugin/CLI version", "Could not read plugin cache");
2080
+ const pluginVersion = plugin.version;
2081
+ if (pluginVersion === currentVersion) {
2082
+ return check("pass", "plugin_version_drift", "Plugin/CLI version", `Both at v${currentVersion}`);
2065
2083
  }
2084
+ const updateCmd = semverGt(pluginVersion, currentVersion) ? "npm install -g skillwiki@beta" : "claude plugin update skillwiki@llm-wiki";
2085
+ return check(
2086
+ "warn",
2087
+ "plugin_version_drift",
2088
+ "Plugin/CLI version",
2089
+ `Plugin v${pluginVersion} \u2260 CLI v${currentVersion} \u2014 run \`${updateCmd}\``
2090
+ );
2066
2091
  }
2067
2092
  async function checkProfiles(home) {
2068
2093
  const map = await parseDotenvFile(configPath(home));
@@ -2086,7 +2111,7 @@ async function checkProfiles(home) {
2086
2111
  }
2087
2112
  async function checkProjectLocalOverride(cwd) {
2088
2113
  const dir = cwd ?? process.cwd();
2089
- const envPath = join16(dir, ".skillwiki", ".env");
2114
+ const envPath = join17(dir, ".skillwiki", ".env");
2090
2115
  if (existsSync3(envPath)) {
2091
2116
  return check("pass", "project_local", "Project-local config", `Found: ${envPath}`);
2092
2117
  }
@@ -2102,9 +2127,9 @@ function findSkillMd(dir) {
2102
2127
  }
2103
2128
  for (const entry of entries) {
2104
2129
  if (entry.isFile() && entry.name === "SKILL.md") {
2105
- results.push(join16(dir, entry.name));
2130
+ results.push(join17(dir, entry.name));
2106
2131
  } else if (entry.isDirectory()) {
2107
- results.push(...findSkillMd(join16(dir, entry.name)));
2132
+ results.push(...findSkillMd(join17(dir, entry.name)));
2108
2133
  }
2109
2134
  }
2110
2135
  return results;
@@ -2148,7 +2173,7 @@ async function runDoctor(input) {
2148
2173
 
2149
2174
  // src/commands/archive.ts
2150
2175
  import { rename as rename3, mkdir as mkdir5, readFile as readFile13, writeFile as writeFile6 } from "fs/promises";
2151
- import { join as join17, dirname as dirname7 } from "path";
2176
+ import { join as join18, dirname as dirname7 } from "path";
2152
2177
  async function runArchive(input) {
2153
2178
  const scan = await scanVault(input.vault);
2154
2179
  if (!scan.ok) return { exitCode: ExitCode.VAULT_PATH_INVALID, result: scan };
@@ -2160,10 +2185,10 @@ async function runArchive(input) {
2160
2185
  }
2161
2186
  if (!relPath) return { exitCode: ExitCode.ARCHIVE_TARGET_NOT_FOUND, result: err("ARCHIVE_TARGET_NOT_FOUND", { page: input.page }) };
2162
2187
  if (relPath.startsWith("_archive/")) return { exitCode: ExitCode.ARCHIVE_ALREADY_ARCHIVED, result: err("ARCHIVE_ALREADY_ARCHIVED", { page: relPath }) };
2163
- const archivePath = join17("_archive", relPath);
2164
- await mkdir5(dirname7(join17(input.vault, archivePath)), { recursive: true });
2188
+ const archivePath = join18("_archive", relPath);
2189
+ await mkdir5(dirname7(join18(input.vault, archivePath)), { recursive: true });
2165
2190
  let indexUpdated = false;
2166
- const indexPath = join17(input.vault, "index.md");
2191
+ const indexPath = join18(input.vault, "index.md");
2167
2192
  try {
2168
2193
  const idx = await readFile13(indexPath, "utf8");
2169
2194
  const slug = relPath.replace(/\.md$/, "").split("/").pop();
@@ -2176,7 +2201,7 @@ async function runArchive(input) {
2176
2201
  } catch (e) {
2177
2202
  if (e?.code !== "ENOENT") throw e;
2178
2203
  }
2179
- await rename3(join17(input.vault, relPath), join17(input.vault, archivePath));
2204
+ await rename3(join18(input.vault, relPath), join18(input.vault, archivePath));
2180
2205
  return { exitCode: ExitCode.OK, result: ok({ archived_from: relPath, archived_to: archivePath, index_updated: indexUpdated, humanHint: `${relPath} -> ${archivePath}${indexUpdated ? " (index updated)" : ""}` }) };
2181
2206
  }
2182
2207
 
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.2.0",
3
+ "version": "0.2.1-beta.2",
4
+ "version": "0.2.1-beta.2",
4
5
  "type": "module",
5
6
  "bin": {
6
7
  "skillwiki": "dist/cli.js"
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.2.0",
3
+ "version": "0.2.1-beta.2",
4
+ "version": "0.2.1-beta.2",
4
5
  "skills": "./",
5
6
  "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
7
  "author": {
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@skillwiki/skills",
3
- "version": "0.2.0",
3
+ "version": "0.2.1-beta.2",
4
+ "version": "0.2.1-beta.2",
4
5
  "private": true,
5
6
  "files": [
6
7
  "wiki-*",