@ctxr/skill-llm-wiki 1.0.1 → 1.0.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.
@@ -0,0 +1,125 @@
1
+ ---
2
+ id: recipe-post-write-heal
3
+ type: primary
4
+ depth_role: leaf
5
+ focus: "The canonical after-every-leaf-write heal invocation"
6
+ parents:
7
+ - ../index.md
8
+ tags:
9
+ - heal
10
+ - envelope
11
+ - post-write
12
+ - consumers
13
+ activation:
14
+ keyword_matches:
15
+ - post write
16
+ - after write
17
+ - heal
18
+ - validate after write
19
+ - next command
20
+ tag_matches:
21
+ - heal
22
+ - post-write
23
+
24
+ generator: "skill-llm-wiki/v1"
25
+ ---
26
+
27
+ # Recipe: post-write heal
28
+
29
+ ## Trigger
30
+
31
+ Your consumer just wrote a leaf into a hosted wiki. Before moving on, call `heal` to classify the wiki's state and let it name the next command.
32
+
33
+ ## Commands
34
+
35
+ ```bash
36
+ skill-llm-wiki heal .development/shared/reports --json
37
+ ```
38
+
39
+ That is the entire step. Do not invoke `validate`, `fix`, or `rebuild` directly; `heal` is the router.
40
+
41
+ ## Envelope fields
42
+
43
+ ```json
44
+ {
45
+ "schema": "skill-llm-wiki/v1",
46
+ "command": "heal",
47
+ "target": "/abs/.../reports",
48
+ "verdict": "ok" | "fixable" | "needs-rebuild" | "broken" | "ambiguous",
49
+ "exit": 0,
50
+ "diagnostics": [
51
+ { "code": "IDX-01", "severity": "warning", "path": "...", "message": "..." },
52
+ { "code": "NEXT-01", "severity": "info", "path": "...", "message": "next: skill-llm-wiki fix ... --json" }
53
+ ],
54
+ "next": { "command": "skill-llm-wiki", "args": ["fix", "/abs/.../reports", "--json"] },
55
+ "timing_ms": 23
56
+ }
57
+ ```
58
+
59
+ > The `next` field is the canonical machine-readable form. The `NEXT-01`
60
+ > info diagnostic carries the same hint as a human-readable string for
61
+ > operators tailing stdout; consumers should prefer `env.next` and only
62
+ > fall back to parsing the diagnostic when running against a pre-v1
63
+ > skill that does not emit it.
64
+
65
+ | Verdict | What the consumer does |
66
+ |---|---|
67
+ | `ok` | Nothing. Move on. |
68
+ | `fixable` | Invoke `env.next.command` with `env.next.args` (typically `skill-llm-wiki fix <wiki> --json`). |
69
+ | `needs-rebuild` | Invoke `env.next.command` with `env.next.args` (typically `skill-llm-wiki rebuild <wiki> --json`). |
70
+ | `broken` | Surface every `severity: "error"` diagnostic to the user. Do not auto-mutate. |
71
+ | `ambiguous` | `validate` itself failed; inspect `HEAL-00` diagnostic for the error. |
72
+
73
+ ## Minimum consumer code
74
+
75
+ ```js
76
+ import { spawnSync } from "node:child_process";
77
+
78
+ function healAfterWrite(wikiPath) {
79
+ const r = spawnSync(
80
+ "skill-llm-wiki",
81
+ ["heal", wikiPath, "--json"],
82
+ { encoding: "utf8" },
83
+ );
84
+ const env = JSON.parse(r.stdout);
85
+ switch (env.verdict) {
86
+ case "ok":
87
+ return;
88
+ case "fixable":
89
+ case "needs-rebuild": {
90
+ if (!env.next) throw new Error("heal returned fixable/needs-rebuild without a `next` field");
91
+ const result = spawnSync(env.next.command, env.next.args, { stdio: "inherit" });
92
+ if (result.status !== 0) {
93
+ throw new Error(`follow-up ${env.next.command} exited ${result.status}`);
94
+ }
95
+ return;
96
+ }
97
+ case "broken":
98
+ reportDiagnosticsToUser(env.diagnostics);
99
+ throw new Error(`heal: wiki is broken at ${wikiPath}`);
100
+ default:
101
+ throw new Error(`heal: unexpected verdict ${env.verdict}`);
102
+ }
103
+ }
104
+ ```
105
+
106
+ ## Failure modes
107
+
108
+ - `verdict: "ambiguous"` with a `HEAL-00` diagnostic: validate threw. The wiki substrate itself may be broken (e.g. missing `.llmwiki/git/`).
109
+ - A `fixable` run whose follow-up `fix` invocation fails: re-run `heal`; it should now report `needs-rebuild` or `broken`.
110
+ - `heal` on a path that does not exist or is not a wiki returns `verdict: "broken"` with `WIKI-01` in diagnostics.
111
+
112
+ ## Why not `fix` / `rebuild` / `validate` directly?
113
+
114
+ Consumers that pick one of the three without checking the validate output end up:
115
+
116
+ - Running `fix` on a structurally-broken wiki that only `rebuild` can resolve.
117
+ - Running `rebuild` on a wiki with trivial index drift, triggering unnecessary Tier 2 sub-agent work.
118
+ - Running `validate` and then duplicating the action table consumers always get wrong.
119
+
120
+ `heal` centralises the classification so every consumer uses the same rules.
121
+
122
+ ## Do not
123
+
124
+ - Call `heal` on hot paths (per-keystroke). It runs full validate; budget for one invocation per logical leaf-write batch.
125
+ - Ignore `broken` verdicts silently. The wiki is corrupt and further writes will compound the problem.
@@ -0,0 +1,111 @@
1
+ ---
2
+ id: recipe-skill-absent
3
+ type: primary
4
+ depth_role: leaf
5
+ focus: "Detect the skill is missing and surface an upgrade path without silently degrading"
6
+ parents:
7
+ - ../index.md
8
+ tags:
9
+ - skill-absent
10
+ - preflight
11
+ - install-hint
12
+ - consumers
13
+ activation:
14
+ keyword_matches:
15
+ - skill missing
16
+ - skill not installed
17
+ - install hint
18
+ - preflight skill
19
+ - hard dependency
20
+ tag_matches:
21
+ - skill-absent
22
+ - preflight
23
+
24
+ generator: "skill-llm-wiki/v1"
25
+ ---
26
+
27
+ # Recipe: skill-absent detection
28
+
29
+ ## Trigger
30
+
31
+ Your consumer treats `@ctxr/skill-llm-wiki` as a hard dependency and must refuse to run when the skill is missing, rather than silently degrading to raw-markdown writes.
32
+
33
+ ## Commands
34
+
35
+ ```bash
36
+ skill-llm-wiki contract --json
37
+ ```
38
+
39
+ This is the canonical probe. It is exempt from the runtime-dep preflight inside the skill itself, so even a partially-broken install still answers the probe as long as the binary is on PATH.
40
+
41
+ ## Decision tree
42
+
43
+ `skill-llm-wiki contract --json` emits the **contract JSON** (schema `skill-llm-wiki/contract/v1`), not the operational envelope (`skill-llm-wiki/v1`). It has no `verdict` or `diagnostics` fields; gate on `format_version` directly.
44
+
45
+ 1. `skill-llm-wiki contract --json` exits `0` with a parseable contract JSON containing `format_version >= <your required>`: proceed.
46
+ 2. `skill-llm-wiki contract --json` exits `0` with `format_version` below your required value: the skill is present but too old. Surface an upgrade message.
47
+ 3. `skill-llm-wiki contract --json` exits non-zero: the skill is installed but broken (e.g. runtime deps corrupted). Surface a reinstall message.
48
+ 4. The binary is not on PATH (spawnSync returns ENOENT or no output): the skill is not installed. Surface an install message.
49
+
50
+ ## Minimum consumer code
51
+
52
+ ```js
53
+ import { spawnSync } from "node:child_process";
54
+
55
+ const REQUIRED_FORMAT_VERSION = 1;
56
+
57
+ export function probeSkill() {
58
+ const r = spawnSync("skill-llm-wiki", ["contract", "--json"], {
59
+ encoding: "utf8",
60
+ });
61
+ if (r.error && r.error.code === "ENOENT") {
62
+ return { ok: false, state: "absent" };
63
+ }
64
+ if (r.status !== 0) {
65
+ return { ok: false, state: "broken", stderr: r.stderr };
66
+ }
67
+ try {
68
+ const env = JSON.parse(r.stdout);
69
+ if ((env.format_version ?? 0) < REQUIRED_FORMAT_VERSION) {
70
+ return { ok: false, state: "too-old", current: env.format_version };
71
+ }
72
+ return { ok: true, ...env };
73
+ } catch {
74
+ return { ok: false, state: "unparseable" };
75
+ }
76
+ }
77
+
78
+ export function enforceSkillPresent() {
79
+ const p = probeSkill();
80
+ if (p.ok) return p;
81
+ const hint =
82
+ p.state === "absent"
83
+ ? "@ctxr/skill-llm-wiki is not installed.\n" +
84
+ "Install with: npx @ctxr/kit install @ctxr/skill-llm-wiki"
85
+ : p.state === "too-old"
86
+ ? `@ctxr/skill-llm-wiki format_version ${p.current} is below the required ${REQUIRED_FORMAT_VERSION}.\n` +
87
+ "Upgrade with: npm i -g @ctxr/skill-llm-wiki@latest"
88
+ : `@ctxr/skill-llm-wiki is installed but not answering the contract probe.\n${p.stderr ?? ""}`;
89
+ throw new Error(hint);
90
+ }
91
+ ```
92
+
93
+ ## Do not
94
+
95
+ - Silently fall back to raw markdown writes when the skill is missing. Every downstream tool that expects the wiki format will break.
96
+ - Inline the install command guess. Read the contract JSON's `package_version` and compare to your own requirement; publish your install hint alongside your agent.
97
+ - Cache the probe result across sessions. A user can uninstall the skill at any time; the probe is cheap (~100ms) and should run once per invocation.
98
+
99
+ ## Recovery
100
+
101
+ Once the consumer reports the skill is missing, recovery for the user is:
102
+
103
+ ```bash
104
+ # Via @ctxr/kit (preferred, manages SKILL.md path + update flow):
105
+ npx @ctxr/kit install @ctxr/skill-llm-wiki
106
+
107
+ # Or plain npm for CI / scripted environments:
108
+ npm i -g @ctxr/skill-llm-wiki
109
+ ```
110
+
111
+ The consumer's preflight should re-run `probeSkill()` after the install.
@@ -0,0 +1,110 @@
1
+ ---
2
+ id: recipe-subject-wiki
3
+ type: primary
4
+ depth_role: leaf
5
+ focus: "Init a subject topic wiki (runbooks, adrs) with nested categories"
6
+ parents:
7
+ - ../index.md
8
+ tags:
9
+ - subject
10
+ - init
11
+ - hosted
12
+ - consumers
13
+ activation:
14
+ keyword_matches:
15
+ - subject wiki
16
+ - runbooks wiki
17
+ - adr wiki
18
+ - nested categories
19
+ tag_matches:
20
+ - subject
21
+ - init
22
+
23
+ generator: "skill-llm-wiki/v1"
24
+ ---
25
+
26
+ # Recipe: subject wiki
27
+
28
+ ## Trigger
29
+
30
+ Your consumer wants to manage a topic whose entries group by subject (runbooks, architecture decisions, playbooks). The wiki grows by adding subcategories, not dates.
31
+
32
+ ## Commands
33
+
34
+ ```bash
35
+ skill-llm-wiki init .development/shared/runbooks \
36
+ --kind subject --template runbooks --json
37
+
38
+ # After init, build (one-time):
39
+ skill-llm-wiki build .development/shared/runbooks \
40
+ --layout-mode hosted --target .development/shared/runbooks --json
41
+ ```
42
+
43
+ Available subject templates:
44
+
45
+ | Template | Best for |
46
+ |---|---|
47
+ | `runbooks` | operational runbooks, playbooks, incident response |
48
+ | `adrs` | architecture decision records (zero-padded sequential prefix) |
49
+
50
+ If you omit `--template`, `--kind subject` falls back to `runbooks`.
51
+
52
+ ## Category promotion rule
53
+
54
+ Both shipped templates encode the same invariant in their `global_invariants`: create a subject subfolder on the first write, and grow the hierarchy whenever two or more leaves share a defensible grouping. Never pile leaves at the topic root after a threshold — do it on write.
55
+
56
+ Your consumer should:
57
+
58
+ 1. Pick the subject subfolder before writing the leaf.
59
+ 2. Write the leaf at the deepest valid category path.
60
+ 3. Run `heal` (see [post-write-heal.md](post-write-heal.md)) so `validate` catches drift from the invariant.
61
+
62
+ ## Envelope fields
63
+
64
+ Same `init` envelope as the dated recipe:
65
+
66
+ ```json
67
+ {
68
+ "schema": "skill-llm-wiki/v1",
69
+ "command": "init",
70
+ "verdict": "initialised",
71
+ "target": "/abs/.../runbooks",
72
+ "artifacts": { "created": ["/abs/.../.llmwiki.layout.yaml"] },
73
+ "diagnostics": [{ "code": "NEXT-01", "severity": "info", "message": "..." }],
74
+ "next": {
75
+ "command": "skill-llm-wiki",
76
+ "args": ["build", "/abs/.../runbooks", "--layout-mode", "hosted", "--target", "/abs/.../runbooks", "--json"]
77
+ }
78
+ }
79
+ ```
80
+
81
+ Consumers read `env.next.command` + `env.next.args` to get the build invocation; the `NEXT-01` diagnostic carries the same hint as prose for humans tailing stdout.
82
+
83
+ ## Minimum consumer code
84
+
85
+ ```js
86
+ import { spawnSync } from "node:child_process";
87
+
88
+ function initSubject(topicPath, template = "runbooks") {
89
+ const r = spawnSync(
90
+ "skill-llm-wiki",
91
+ ["init", topicPath, "--kind", "subject", "--template", template, "--json"],
92
+ { encoding: "utf8" },
93
+ );
94
+ if (r.status !== 0) throw new Error(`init failed: ${r.stderr}`);
95
+ const env = JSON.parse(r.stdout);
96
+ // Prefer the structured `next` field over parsing NEXT-01.
97
+ return { contractPath: env.artifacts.created[0], next: env.next };
98
+ }
99
+ ```
100
+
101
+ ## Failure modes
102
+
103
+ - `verdict: "ambiguous"` with `INIT-05`: `--kind subject` does not match a dated template (`reports`, `sessions`, `regressions`, `plans`).
104
+ - `verdict: "ambiguous"` with `INIT-07`: contract already exists; use `--force` or `rebuild`.
105
+ - `verdict: "ambiguous"` with `INIT-08`: the topic path (or the contract path inside it) is a symbolic link. `init` refuses to follow symlinks for security. Resolve it explicitly or remove it before retrying.
106
+
107
+ ## Do not
108
+
109
+ - Put runbooks in a flat list at the topic root. After three siblings, every new leaf should land under a named subcategory.
110
+ - Use a date prefix or date subfolder. Subject wikis are explicitly not dated; that is why they use this template.
@@ -0,0 +1,149 @@
1
+ ---
2
+ id: recipe-testing
3
+ type: primary
4
+ depth_role: leaf
5
+ focus: "Use the shipped testkit in consumer test suites"
6
+ parents:
7
+ - ../index.md
8
+ tags:
9
+ - testing
10
+ - testkit
11
+ - fixtures
12
+ - consumers
13
+ activation:
14
+ keyword_matches:
15
+ - test harness
16
+ - consumer tests
17
+ - testkit
18
+ - stub skill
19
+ - wiki fixture
20
+ tag_matches:
21
+ - testing
22
+ - testkit
23
+
24
+ generator: "skill-llm-wiki/v1"
25
+ ---
26
+
27
+ # Recipe: testing with the shipped testkit
28
+
29
+ ## Trigger
30
+
31
+ Your consumer has tests that interact with `skill-llm-wiki` (e.g. your installer refuses without the skill present, your wiki-write workflow post-heal classifies verdicts). Use the shipped testkit instead of hand-rolling fixtures.
32
+
33
+ ## Commands to locate the testkit
34
+
35
+ ```bash
36
+ skill-llm-wiki where --json | jq -r '.testkit_dir'
37
+ ```
38
+
39
+ The returned absolute path contains:
40
+
41
+ - `stub-skill.mjs` — seed a presence-only skill under `.claude/skills/` or `.agents/skills/`.
42
+ - `make-wiki-fixture.mjs` — build a minimal hosted-mode wiki at a temp path using the shipped templates.
43
+ - `assert-frontmatter.mjs` — parse a leaf's frontmatter and assert expected fields.
44
+ - `cli-run.mjs` — spawn the CLI, capture stdout/stderr/status, auto-parse the envelope.
45
+
46
+ > **About `<testkit_dir>` in the code below:** the literal string
47
+ > `<testkit_dir>` is a placeholder. Resolve it at test-load time via
48
+ > the `where` probe, and convert the filesystem path to a `file://`
49
+ > URL before passing it to dynamic `import()` — Node ESM requires
50
+ > this on Windows (where `TESTKIT` looks like `C:\...`) and it is
51
+ > harmless on POSIX. Example:
52
+ >
53
+ > ```js
54
+ > import { spawnSync } from "node:child_process";
55
+ > import { pathToFileURL } from "node:url";
56
+ > const WHERE = JSON.parse(
57
+ > spawnSync("skill-llm-wiki", ["where", "--json"], { encoding: "utf8" }).stdout,
58
+ > );
59
+ > const TESTKIT = WHERE.testkit_dir;
60
+ > const { stubSkill } = await import(
61
+ > pathToFileURL(`${TESTKIT}/stub-skill.mjs`).href,
62
+ > );
63
+ > ```
64
+ >
65
+ > Do not copy the `<testkit_dir>/stub-skill.mjs` string verbatim
66
+ > into your imports — it will not resolve.
67
+
68
+ ## Consumer test code
69
+
70
+ ### Presence stub (replaces hand-rolled `wikiSkillStub`)
71
+
72
+ ```js
73
+ import { test } from "node:test";
74
+ import { mkdtempSync } from "node:fs";
75
+ import { tmpdir } from "node:os";
76
+ import { join } from "node:path";
77
+ import { stubSkill } from "<testkit_dir>/stub-skill.mjs";
78
+
79
+ test("installer refuses when skill is absent", async () => {
80
+ const home = mkdtempSync(join(tmpdir(), "test-"));
81
+ // Do NOT call stubSkill — simulate the absent case.
82
+ const r = await runInstaller({ env: { HOME: home } });
83
+ assert.equal(r.status, 1);
84
+ assert.match(r.stderr, /skill-llm-wiki is not installed/);
85
+ });
86
+
87
+ test("installer proceeds when stub is present", async () => {
88
+ const home = mkdtempSync(join(tmpdir(), "test-"));
89
+ await stubSkill({ home });
90
+ const r = await runInstaller({ env: { HOME: home } });
91
+ assert.equal(r.status, 0);
92
+ });
93
+ ```
94
+
95
+ ### Fixture wiki (for exercising write workflows)
96
+
97
+ ```js
98
+ import { makeWikiFixture } from "<testkit_dir>/make-wiki-fixture.mjs";
99
+
100
+ test("my consumer writes a report leaf in the right shape", async () => {
101
+ const wiki = await makeWikiFixture({
102
+ path: join(tmpdir(), `reports-${Date.now()}`),
103
+ kind: "dated",
104
+ template: "reports",
105
+ seedLeaves: ["2026/04/18/example.md"],
106
+ });
107
+ // Now drive your consumer write code against `wiki.path`.
108
+ await writeMyLeaf(wiki.path, "2026/04/18/new-report.md", "content");
109
+ assert.ok(existsSync(join(wiki.path, "2026/04/18/new-report.md")));
110
+ });
111
+ ```
112
+
113
+ ### CLI run (for end-to-end verdict-handling tests)
114
+
115
+ ```js
116
+ import { runCli } from "<testkit_dir>/cli-run.mjs";
117
+
118
+ test("heal on a fresh wiki returns verdict=ok", async () => {
119
+ const wiki = await makeWikiFixture({ path: tmpWiki(), kind: "dated" });
120
+ const r = runCli(["heal", wiki.path, "--json"]);
121
+ assert.equal(r.envelope.verdict, "ok");
122
+ });
123
+ ```
124
+
125
+ ### Frontmatter assertions
126
+
127
+ ```js
128
+ import { assertFrontmatterShape } from "<testkit_dir>/assert-frontmatter.mjs";
129
+
130
+ test("my consumer writes the expected frontmatter", async () => {
131
+ await writeMyLeaf(wiki.path, "2026/04/18/leaf.md", "content");
132
+ assertFrontmatterShape(join(wiki.path, "2026/04/18/leaf.md"), {
133
+ type: "primary",
134
+ depth_role: "leaf",
135
+ focus: "leaf",
136
+ });
137
+ });
138
+ ```
139
+
140
+ ## Failure modes
141
+
142
+ - `testkit_dir` is `null`: you are running against an old skill version without the testkit. Gate on `format_version >= 1` in CI.
143
+ - `stubSkill` fails with "unknown layout": pass one of `"claude-skills"` or `"agents-skills"`.
144
+ - `makeWikiFixture` fails on the template lookup: pass a name matching one of the shipped templates (see [dated-wiki.md](dated-wiki.md) / [subject-wiki.md](subject-wiki.md)).
145
+
146
+ ## Do not
147
+
148
+ - Import from `scripts/lib/` in your tests. Those are internal; only `scripts/testkit/` is part of the consumer contract.
149
+ - Hand-roll parallel stub helpers once this testkit exists. Drift between your stub and the skill's canonical shape is a real bug source.
package/guide/index.md CHANGED
@@ -74,6 +74,13 @@ entries:
74
74
  file: "ux/index.md"
75
75
  type: index
76
76
  focus: User-facing intent resolution and preflight failure messaging.
77
+ - id: consumers
78
+ file: "consumers/index.md"
79
+ type: index
80
+ focus: "Integrating another skill or agent as a consumer of skill-llm-wiki."
81
+ tags:
82
+ - consumers
83
+ - integration
77
84
  children:
78
85
  - "basics/index.md"
79
86
  - "correctness/index.md"
@@ -83,6 +90,7 @@ children:
83
90
  - "operations/index.md"
84
91
  - "substrate/index.md"
85
92
  - "ux/index.md"
93
+ - "consumers/index.md"
86
94
  ---
87
95
  <!-- BEGIN AUTO-GENERATED NAVIGATION -->
88
96
 
@@ -110,6 +118,7 @@ children:
110
118
  | [operations/index.md](operations/index.md) | 📁 index | per-operation phase pipelines for Build, Extend, Validate, Rebuild, Fix, and Join |
111
119
  | [substrate/index.md](substrate/index.md) | 📁 index | Decision machinery — rewrite operators and the tiered AI ladder driving them. |
112
120
  | [ux/index.md](ux/index.md) | 📁 index | User-facing intent resolution and preflight failure messaging. |
121
+ | [consumers/index.md](consumers/index.md) | 📁 index | Integrating another skill or agent as a consumer of skill-llm-wiki. |
113
122
 
114
123
  <!-- END AUTO-GENERATED NAVIGATION -->
115
124
 
@@ -9,7 +9,7 @@ covers:
9
9
  - the CLI refuses every ambiguous invocation with a structured INT-NN code
10
10
  - Claude MUST ask the user before running the skill when intent is unclear
11
11
  - ambiguity scenarios each have a fixed resolving flag the user can pick
12
- - "--json-errors makes the ambiguity body machine-parseable for Claude to read"
12
+ - "--json (canonical) or --json-errors (legacy alias) makes the ambiguity body machine-parseable for Claude to read"
13
13
  - "--no-prompt / LLM_WIKI_NO_PROMPT=1 disables interactive fallback; failures become hard errors"
14
14
  - never silently default — the cost of a wrong guess is always higher than a clarifying question
15
15
  tags:
@@ -82,11 +82,12 @@ in the wrong place) is always higher than a one-sentence clarifying question.
82
82
  | INT-12 | Prompt required in non-interactive mode | supply the flag the prompt was asking for, or re-run in a TTY |
83
83
  | INT-13 | Unknown `--quality-mode` value | use `tiered-fast` / `claude-first` / `tier0-only` |
84
84
 
85
- ## `--json-errors` for programmatic consumption
85
+ ## `--json` for programmatic consumption
86
86
 
87
87
  When the skill is called from a script or from another Claude session, pass
88
- `--json-errors` on every invocation. The ambiguity body becomes a single JSON
89
- object on stderr:
88
+ `--json` (canonical) on every invocation; `--json-errors` is the legacy alias
89
+ and continues to work. The ambiguity body becomes a single JSON object on
90
+ stderr:
90
91
 
91
92
  ```json
92
93
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctxr/skill-llm-wiki",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Claude Code skill — build, extend, validate, rebuild, fix, and join LLM wikis from any knowledge corpus. Token-efficient retrieval via hierarchical indices, DAG parents, and deterministic rewrite operators.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -31,12 +31,16 @@
31
31
  "LICENSE",
32
32
  "CHANGELOG.md",
33
33
  "scripts/",
34
- "guide/"
34
+ "guide/",
35
+ "templates/"
35
36
  ],
36
37
  "ctxr": {
37
38
  "type": "skill",
38
39
  "target": "folder"
39
40
  },
41
+ "bin": {
42
+ "skill-llm-wiki": "scripts/cli.mjs"
43
+ },
40
44
  "scripts": {
41
45
  "test": "node --test",
42
46
  "validate": "node scripts/cli.mjs --version",