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
|
|
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
|
-
${
|
|
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
|
|
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.
|
|
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": {
|
package/skills/package.json
CHANGED
|
@@ -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
|
-
-
|
|
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
|
-
-
|
|
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`.
|