@zosmaai/pi-llm-wiki 0.11.4 → 0.11.6
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/README.de.md +8 -0
- package/README.es.md +8 -0
- package/README.fr.md +8 -0
- package/README.hi.md +8 -0
- package/README.ja.md +8 -0
- package/README.ko.md +8 -0
- package/README.md +8 -0
- package/README.pt.md +8 -0
- package/README.ru.md +8 -0
- package/README.zh.md +8 -0
- package/assets/wiki-dashboard.png +0 -0
- package/commands/wiki-ingest.md +1 -0
- package/commands/wiki-req.md +1 -0
- package/commands/wiki-retro.md +1 -0
- package/dist/extensions/llm-wiki/lib/dashboard-command.js +86 -0
- package/dist/extensions/llm-wiki/lib/dashboard.js +175 -0
- package/dist/extensions/llm-wiki/lib/guardrails.js +30 -1
- package/dist/extensions/llm-wiki/lib/host.js +21 -1
- package/dist/extensions/llm-wiki/lib/ingest-worker.js +44 -20
- package/dist/extensions/llm-wiki/lib/knowledge-document.js +20 -2
- package/dist/extensions/llm-wiki/lib/knowledge-links.js +133 -27
- package/dist/extensions/llm-wiki/lib/metadata.js +6 -6
- package/dist/extensions/llm-wiki/lib/observation.js +22 -3
- package/dist/extensions/llm-wiki/lib/retro.js +38 -4
- package/dist/extensions/llm-wiki/lib/runtime.js +2 -2
- package/dist/extensions/llm-wiki/lib/settings-command.js +377 -0
- package/dist/extensions/llm-wiki/lib/task-config.js +100 -1
- package/dist/extensions/llm-wiki/lib/tools.js +47 -8
- package/dist/mcp/index.js +2 -1
- package/dist/mcp/operations.js +21 -2
- package/docs/api.md +24 -1
- package/docs/commands.md +6 -1
- package/docs/configuration.md +11 -0
- package/docs/obsidian.md +6 -6
- package/docs/superpowers/plans/2026-08-09-qmd-retrieval-phase-1-quality-baseline-and-compatibility.md +1520 -0
- package/docs/superpowers/plans/2026-08-27-wikilink-resolver-normalization.md +735 -0
- package/docs/superpowers/plans/2026-08-29-wikilink-gate-ensure-page-retro.md +642 -0
- package/docs/superpowers/plans/2026-08-29-wikilink-write-validation.md +695 -0
- package/docs/superpowers/roadmaps/2026-08-09-qmd-retrieval-roadmap.md +448 -0
- package/docs/superpowers/specs/2026-08-08-qmd-retrieval-design.md +806 -0
- package/extensions/llm-wiki/index.ts +4 -0
- package/extensions/llm-wiki/lib/dashboard-command.ts +106 -0
- package/extensions/llm-wiki/lib/dashboard.ts +210 -0
- package/extensions/llm-wiki/lib/guardrails.ts +26 -1
- package/extensions/llm-wiki/lib/host.ts +21 -1
- package/extensions/llm-wiki/lib/ingest-worker.ts +64 -27
- package/extensions/llm-wiki/lib/knowledge-document.ts +21 -2
- package/extensions/llm-wiki/lib/knowledge-links.ts +208 -35
- package/extensions/llm-wiki/lib/metadata.ts +10 -6
- package/extensions/llm-wiki/lib/observation.ts +23 -3
- package/extensions/llm-wiki/lib/retro.ts +48 -4
- package/extensions/llm-wiki/lib/runtime.ts +2 -2
- package/extensions/llm-wiki/lib/settings-command.ts +483 -0
- package/extensions/llm-wiki/lib/task-config.ts +138 -0
- package/extensions/llm-wiki/lib/tools.ts +62 -8
- package/mcp/index.ts +12 -1
- package/mcp/operations.ts +32 -2
- package/package.json +4 -4
- package/prompts/wiki-ingest.md +1 -0
- package/prompts/wiki-req.md +1 -0
- package/prompts/wiki-retro.md +1 -0
- package/skills/llm-wiki/SKILL.md +11 -1
|
@@ -11,12 +11,16 @@ import {
|
|
|
11
11
|
serializeKnowledgeDocument,
|
|
12
12
|
writeKnowledgeDocumentFile,
|
|
13
13
|
} from "./knowledge-document.js";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
applyWikilinkGate,
|
|
16
|
+
buildResolvedBacklinks,
|
|
17
|
+
buildWikilinkIndex,
|
|
18
|
+
} from "./knowledge-links.js";
|
|
15
19
|
import { repairLegacyKnowledgeDocuments } from "./legacy-repair.js";
|
|
16
20
|
import { type Registry, appendEvent, rebuildMetadata, rebuildMetadataLight } from "./metadata.js";
|
|
17
21
|
import type { Runtime } from "./runtime.js";
|
|
18
22
|
import { captureFile, captureText, captureUrl } from "./source-packet.js";
|
|
19
|
-
import { parseModelRef } from "./task-config.js";
|
|
23
|
+
import { loadTaskConfig, parseModelRef, resolveWikilinkValidation } from "./task-config.js";
|
|
20
24
|
import {
|
|
21
25
|
type VaultPaths,
|
|
22
26
|
detectVaultFormat,
|
|
@@ -415,6 +419,7 @@ export function registerWikiIngest(pi: ExtensionAPI, runtime?: Runtime): void {
|
|
|
415
419
|
manifest: s.manifest,
|
|
416
420
|
extracted: s.extracted,
|
|
417
421
|
synthesisLanguage: runtime.config.synthesisLanguage,
|
|
422
|
+
wikilinkValidation: runtime.config.wikilinkValidation,
|
|
418
423
|
});
|
|
419
424
|
if (committed) {
|
|
420
425
|
// Background semantic embeddings (#66): embed the pages this
|
|
@@ -428,8 +433,10 @@ export function registerWikiIngest(pi: ExtensionAPI, runtime?: Runtime): void {
|
|
|
428
433
|
];
|
|
429
434
|
launchEmbedPages(runtime, launchCtx, paths, pageIds, `embed:ingest:${s.id}`);
|
|
430
435
|
}
|
|
436
|
+
const wl = committed?.wikilinkDiagnostics?.length ?? 0;
|
|
437
|
+
const wlNote = wl > 0 ? `, ${wl} wikilink issue${wl === 1 ? "" : "s"}` : "";
|
|
431
438
|
const summary = committed
|
|
432
|
-
? `LLM Wiki: ingested ${s.id} → ${committed.entitiesCreated.length} entit${committed.entitiesCreated.length === 1 ? "y" : "ies"}, ${committed.conceptsCreated.length} concept${committed.conceptsCreated.length === 1 ? "" : "s"}`
|
|
439
|
+
? `LLM Wiki: ingested ${s.id} → ${committed.entitiesCreated.length} entit${committed.entitiesCreated.length === 1 ? "y" : "ies"}, ${committed.conceptsCreated.length} concept${committed.conceptsCreated.length === 1 ? "" : "s"}${wlNote}`
|
|
433
440
|
: `LLM Wiki: ${s.id} produced no synthesis`;
|
|
434
441
|
if (ctx.hasUI) {
|
|
435
442
|
ctx.ui.notify(summary, committed ? "info" : "warning");
|
|
@@ -565,7 +572,42 @@ export function registerWikiEnsurePage(pi: ExtensionAPI, runtime?: Runtime): voi
|
|
|
565
572
|
}
|
|
566
573
|
|
|
567
574
|
const today = fmtDate();
|
|
568
|
-
|
|
575
|
+
let body = params.content ?? buildPageBody(type, params.title);
|
|
576
|
+
|
|
577
|
+
// Pre-write wikilink gate (#172): validate/normalize caller-supplied content.
|
|
578
|
+
const mode = resolveWikilinkValidation(loadTaskConfig(ctx.cwd));
|
|
579
|
+
let wikilinkIssues: string[] = [];
|
|
580
|
+
if (mode !== "off") {
|
|
581
|
+
const registry = readJson<{ pages: Record<string, unknown> }>(
|
|
582
|
+
join(paths.meta, "registry.json"),
|
|
583
|
+
{ pages: {} },
|
|
584
|
+
);
|
|
585
|
+
const gate = applyWikilinkGate(
|
|
586
|
+
body,
|
|
587
|
+
buildWikilinkIndex(Object.keys(registry.pages)),
|
|
588
|
+
`${folder}/${slug}`,
|
|
589
|
+
mode,
|
|
590
|
+
);
|
|
591
|
+
wikilinkIssues = gate.diagnostics.map((d) => d.message);
|
|
592
|
+
if (!gate.ok) {
|
|
593
|
+
return {
|
|
594
|
+
content: [
|
|
595
|
+
{
|
|
596
|
+
type: "text",
|
|
597
|
+
text: `Rejected write — unresolved/ambiguous wikilinks:\n${wikilinkIssues
|
|
598
|
+
.map((m) => `- ${m}`)
|
|
599
|
+
.join("\n")}`,
|
|
600
|
+
},
|
|
601
|
+
],
|
|
602
|
+
details: { error: "link_validation", issues: wikilinkIssues } as Record<
|
|
603
|
+
string,
|
|
604
|
+
unknown
|
|
605
|
+
>,
|
|
606
|
+
isError: true,
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
if (mode === "normalize") body = gate.body;
|
|
610
|
+
}
|
|
569
611
|
const doc = createKnowledgeDocument(
|
|
570
612
|
`${folder}/${slug}.md`,
|
|
571
613
|
{
|
|
@@ -595,9 +637,16 @@ export function registerWikiEnsurePage(pi: ExtensionAPI, runtime?: Runtime): voi
|
|
|
595
637
|
rebuildMetadataLight(paths);
|
|
596
638
|
}
|
|
597
639
|
|
|
640
|
+
const gateNote = wikilinkIssues.length
|
|
641
|
+
? `\n\n⚠️ ${wikilinkIssues.length} wikilink issue(s):\n${wikilinkIssues.map((m) => `- ${m}`).join("\n")}`
|
|
642
|
+
: "";
|
|
598
643
|
return {
|
|
599
|
-
content: [{ type: "text", text: `✅ Created ${type} page: \`${pagePath}
|
|
600
|
-
details: {
|
|
644
|
+
content: [{ type: "text", text: `✅ Created ${type} page: \`${pagePath}\`${gateNote}` }],
|
|
645
|
+
details: {
|
|
646
|
+
path: pagePath,
|
|
647
|
+
created: true,
|
|
648
|
+
wikilinkIssues,
|
|
649
|
+
} as Record<string, unknown>,
|
|
601
650
|
};
|
|
602
651
|
},
|
|
603
652
|
});
|
|
@@ -871,7 +920,7 @@ function runWikiLint(paths: VaultPaths, autoFix: boolean): string {
|
|
|
871
920
|
|
|
872
921
|
const discovery = discoverKnowledgeDocuments(paths);
|
|
873
922
|
const pages = discovery.documents;
|
|
874
|
-
const
|
|
923
|
+
const wikilinkIndex = buildWikilinkIndex(pages.map((page) => page.id));
|
|
875
924
|
const inbound = Object.fromEntries(pages.map((page) => [page.id, 0]));
|
|
876
925
|
const gapSources = new Map<string, Set<string>>();
|
|
877
926
|
const findings: string[] = [];
|
|
@@ -879,7 +928,7 @@ function runWikiLint(paths: VaultPaths, autoFix: boolean): string {
|
|
|
879
928
|
let contradictions = 0;
|
|
880
929
|
|
|
881
930
|
for (const page of pages) {
|
|
882
|
-
const resolved = buildResolvedBacklinks(page.id, page.body,
|
|
931
|
+
const resolved = buildResolvedBacklinks(page.id, page.body, wikilinkIndex);
|
|
883
932
|
for (const target of resolved.targets) inbound[target]++;
|
|
884
933
|
for (const unresolved of resolved.unresolved) {
|
|
885
934
|
const sources = gapSources.get(unresolved.target) ?? new Set<string>();
|
|
@@ -888,6 +937,11 @@ function runWikiLint(paths: VaultPaths, autoFix: boolean): string {
|
|
|
888
937
|
missingPages++;
|
|
889
938
|
findings.push(`Missing page: ${unresolved.target} (in ${page.id})`);
|
|
890
939
|
}
|
|
940
|
+
for (const d of resolved.diagnostics) {
|
|
941
|
+
if (d.code === "link_ambiguous") {
|
|
942
|
+
findings.push(d.message.replace("Ambiguous wikilink: ", "Ambiguous: "));
|
|
943
|
+
}
|
|
944
|
+
}
|
|
891
945
|
}
|
|
892
946
|
|
|
893
947
|
let orphans = 0;
|
package/mcp/index.ts
CHANGED
|
@@ -15,6 +15,10 @@ import { join } from "node:path";
|
|
|
15
15
|
import { McpServer } from "@modelcontextprotocol/server";
|
|
16
16
|
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
|
|
17
17
|
import * as z from "zod/v4";
|
|
18
|
+
import {
|
|
19
|
+
loadTaskConfig,
|
|
20
|
+
resolveWikilinkValidation,
|
|
21
|
+
} from "../extensions/llm-wiki/lib/task-config.js";
|
|
18
22
|
import { getVaultPaths, resolveVaultPaths } from "../extensions/llm-wiki/lib/utils.js";
|
|
19
23
|
import { createExecApi } from "./exec.js";
|
|
20
24
|
import {
|
|
@@ -265,7 +269,14 @@ server.registerTool(
|
|
|
265
269
|
}
|
|
266
270
|
|
|
267
271
|
const paths = getPaths();
|
|
268
|
-
const result = await retroOperation(
|
|
272
|
+
const result = await retroOperation(
|
|
273
|
+
paths,
|
|
274
|
+
slug,
|
|
275
|
+
title,
|
|
276
|
+
body,
|
|
277
|
+
category,
|
|
278
|
+
resolveWikilinkValidation(loadTaskConfig(process.cwd())),
|
|
279
|
+
);
|
|
269
280
|
|
|
270
281
|
if (!result.ok) {
|
|
271
282
|
return {
|
package/mcp/operations.ts
CHANGED
|
@@ -6,13 +6,20 @@
|
|
|
6
6
|
* registry entries, or builds page strings itself.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { join } from "node:path";
|
|
9
10
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
10
11
|
import { bootstrapVault } from "../extensions/llm-wiki/lib/bootstrap.js";
|
|
12
|
+
import {
|
|
13
|
+
type WikilinkValidationMode,
|
|
14
|
+
applyWikilinkGate,
|
|
15
|
+
buildWikilinkIndex,
|
|
16
|
+
} from "../extensions/llm-wiki/lib/knowledge-links.js";
|
|
11
17
|
import { type ProjectionResult, rebuildMetadata } from "../extensions/llm-wiki/lib/metadata.js";
|
|
12
18
|
import { type RecallResult, searchWikiLayered } from "../extensions/llm-wiki/lib/recall.js";
|
|
13
19
|
import { saveInsight } from "../extensions/llm-wiki/lib/retro.js";
|
|
14
20
|
import { captureFile, captureText, captureUrl } from "../extensions/llm-wiki/lib/source-packet.js";
|
|
15
|
-
import
|
|
21
|
+
import { resolveWikilinkValidation } from "../extensions/llm-wiki/lib/task-config.js";
|
|
22
|
+
import { type VaultPaths, readJson } from "../extensions/llm-wiki/lib/utils.js";
|
|
16
23
|
import {
|
|
17
24
|
VaultWriteError,
|
|
18
25
|
inspectVaultFormat,
|
|
@@ -134,6 +141,7 @@ export async function retroOperation(
|
|
|
134
141
|
title: string,
|
|
135
142
|
body: string,
|
|
136
143
|
category?: string,
|
|
144
|
+
wikilinkValidation?: WikilinkValidationMode,
|
|
137
145
|
): Promise<
|
|
138
146
|
| { ok: true; slug: string; sourcePagePath: string }
|
|
139
147
|
| { ok: false; diagnostics: Array<{ code: string; message: string }> }
|
|
@@ -145,8 +153,30 @@ export async function retroOperation(
|
|
|
145
153
|
diagnostics: vaultCheck.diagnostics.map((d) => ({ code: d.code, message: d.message })),
|
|
146
154
|
};
|
|
147
155
|
}
|
|
156
|
+
// Pre-write wikilink gate (#172): validate/normalize caller-supplied body.
|
|
157
|
+
const mode = resolveWikilinkValidation({ wikilinkValidation });
|
|
158
|
+
let gateBody = body;
|
|
159
|
+
if (mode !== "off") {
|
|
160
|
+
const registry = readJson<{ pages: Record<string, unknown> }>(
|
|
161
|
+
join(paths.meta, "registry.json"),
|
|
162
|
+
{ pages: {} },
|
|
163
|
+
);
|
|
164
|
+
const gate = applyWikilinkGate(
|
|
165
|
+
body,
|
|
166
|
+
buildWikilinkIndex(Object.keys(registry.pages)),
|
|
167
|
+
`sources/${slug}`,
|
|
168
|
+
mode,
|
|
169
|
+
);
|
|
170
|
+
if (!gate.ok) {
|
|
171
|
+
return {
|
|
172
|
+
ok: false,
|
|
173
|
+
diagnostics: gate.diagnostics.map((d) => ({ code: "link_validation", message: d.message })),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
if (mode === "normalize") gateBody = gate.body;
|
|
177
|
+
}
|
|
148
178
|
try {
|
|
149
|
-
const result = saveInsight(paths, slug, title,
|
|
179
|
+
const result = saveInsight(paths, slug, title, gateBody, category, { rebuild: false });
|
|
150
180
|
const projection = projectionOutcome(rebuildMetadata(paths));
|
|
151
181
|
if (!projection.ok) return projection;
|
|
152
182
|
return { ok: true, slug: result.slug, sourcePagePath: result.sourcePagePath };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zosmaai/pi-llm-wiki",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.6",
|
|
4
4
|
"description": "Self-maintaining LLM Wiki for Pi — Karpathy-pattern knowledge base with immutable source capture, automated ingestion, search, linting, and Obsidian-compatible vault. auto-updating personal & company wiki.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi",
|
|
@@ -75,17 +75,18 @@
|
|
|
75
75
|
]
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|
|
78
|
-
"@mariozechner/pi-coding-agent": "*"
|
|
79
|
-
"typebox": "*"
|
|
78
|
+
"@mariozechner/pi-coding-agent": "*"
|
|
80
79
|
},
|
|
81
80
|
"engines": {
|
|
82
81
|
"node": ">=18"
|
|
83
82
|
},
|
|
84
83
|
"dependencies": {
|
|
85
84
|
"@cfworker/json-schema": "^4.1.1",
|
|
85
|
+
"@mariozechner/pi-tui": "0.70.6",
|
|
86
86
|
"@modelcontextprotocol/server": "^2.0.0",
|
|
87
87
|
"mdast-util-from-markdown": "^2.0.3",
|
|
88
88
|
"node-html-markdown": "^2.0.0",
|
|
89
|
+
"typebox": "^1.1.34",
|
|
89
90
|
"yaml": "^2.9.0",
|
|
90
91
|
"zod": "^4.0"
|
|
91
92
|
},
|
|
@@ -98,7 +99,6 @@
|
|
|
98
99
|
"@types/mdast": "^4.0.4",
|
|
99
100
|
"@types/node": "^22",
|
|
100
101
|
"@vitest/coverage-v8": "^3.2.4",
|
|
101
|
-
"typebox": "^1.1.34",
|
|
102
102
|
"typescript": "^5.7.0",
|
|
103
103
|
"vitest": "^3.0.0"
|
|
104
104
|
},
|
package/prompts/wiki-ingest.md
CHANGED
|
@@ -33,4 +33,5 @@ $ARGUMENTS
|
|
|
33
33
|
**Rules:**
|
|
34
34
|
- Never modify files in `raw/` — source packets are immutable after capture.
|
|
35
35
|
- Never fabricate information — always cite sources with `[[sources/SRC-...]]`.
|
|
36
|
+
- Inside Markdown table cells, write aliased wikilinks as `[[target\|alias]]`, never `[[target|alias]]`.
|
|
36
37
|
- The extension auto-updates metadata — you do NOT need to manually edit `meta/` files.
|
package/prompts/wiki-req.md
CHANGED
|
@@ -53,3 +53,4 @@ Read the LLM Wiki skill at `.pi/skills/llm-wiki/SKILL.md` first to understand th
|
|
|
53
53
|
- Use status values: `draft` → `clarified` → `active` → `implemented` → `deferred` → `rejected`
|
|
54
54
|
- Use priority values: `p0` (blocking), `p1` (critical), `p2` (important), `p3` (nice-to-have)
|
|
55
55
|
- Do not create requirements in `raw/` — that layer is for external source artifacts only
|
|
56
|
+
- Inside Markdown table cells, write aliased wikilinks as `[[target\|alias]]`, never `[[target|alias]]`.
|
package/prompts/wiki-retro.md
CHANGED
|
@@ -32,3 +32,4 @@ Read the LLM Wiki skill at `.pi/skills/llm-wiki/SKILL.md` first to understand th
|
|
|
32
32
|
- One atomic insight per `wiki_retro` call. Use multiple calls for multiple insights.
|
|
33
33
|
- Don't save obvious things. Save non-obvious patterns, tradeoffs, and design decisions.
|
|
34
34
|
- Always add `[[wikilinks]]` to connect the new insight with existing wiki knowledge.
|
|
35
|
+
- Inside Markdown table cells, write aliased wikilinks as `[[target\|alias]]`, never `[[target|alias]]`.
|
package/skills/llm-wiki/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: llm-wiki
|
|
3
|
-
description: Build and maintain a persistent, interlinked Obsidian-compatible markdown wiki using Karpathy's LLM Wiki pattern. Extension-backed with auto-generated metadata, guardrails, and
|
|
3
|
+
description: Build and maintain a persistent, interlinked Obsidian-compatible markdown wiki using Karpathy's LLM Wiki pattern. Extension-backed with auto-generated metadata, guardrails, and 14 custom tools (+3 opt-in agent-trajectory tools).
|
|
4
4
|
whenToUse: Call wiki_recall at task start to find relevant wiki pages. Call wiki_retro at task end to save new insights. When agent-trajectory working-memory is enabled (opt-in, /wiki-trajectories on), also call wiki_recall_skill at task start to find reusable skills / past cases ("have I done this before?") and wiki_capture_trajectory after non-trivial tasks to record how you solved them. The extension injects a brief status line, but explicit calls with task-specific terms get better results.
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -178,6 +178,16 @@ The choice is persisted to project settings (`.pi/settings.json` under `llm-wiki
|
|
|
178
178
|
wiki_ingest(model="anthropic/claude-haiku")
|
|
179
179
|
```
|
|
180
180
|
|
|
181
|
+
### Settings Screen (`/wiki-settings`)
|
|
182
|
+
|
|
183
|
+
**Interactive settings:** run `/wiki-settings` to open a persistent settings screen. It lists every
|
|
184
|
+
`llm-wiki` setting with its current value and where it is set (project overrides global; the
|
|
185
|
+
default is shown when unset). Booleans cycle in place with Enter/Space; numbers, strings, and the
|
|
186
|
+
model edit inline in a prefilled input. Every change persists immediately to the chosen scope
|
|
187
|
+
(project or global). Setting the model to `session` clears `llm-wiki.taskModel` (back to the session model).
|
|
188
|
+
|
|
189
|
+
### Dashboard Screen (`/wiki-dashboard`) **Read-only vault health:** run `/wiki-dashboard` to open a persistent read-only screen: page counts by type + total size, last page touch + stale (30d+) count, activity by kind last 7 days (observes/retros/syntheses), pending raw-source ingest queue, zero-backlink page count (see `/wiki-lint` full scan), embedding coverage (emb/ files vs. pages). All values computed from existing on-disk state — no writes, no LLM calls. Esc closes.
|
|
190
|
+
|
|
181
191
|
### Auto-Bootstrap (One-Time)
|
|
182
192
|
|
|
183
193
|
The extension creates the wiki vault automatically on startup. On the first turn, it injects a directive asking you to infer topic and mode, then call:
|