@zosmaai/pi-llm-wiki 0.10.9 → 0.11.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/CHANGELOG.md +6 -0
- package/README.de.md +35 -4
- package/README.es.md +260 -170
- package/README.fr.md +35 -4
- package/README.hi.md +35 -4
- package/README.ja.md +35 -4
- package/README.ko.md +35 -4
- package/README.md +41 -12
- package/README.pt.md +35 -4
- package/README.ru.md +35 -4
- package/README.zh.md +260 -170
- package/assets/demo.gif +0 -0
- package/dist/extensions/llm-wiki/lib/bootstrap.js +74 -0
- package/dist/extensions/llm-wiki/lib/embeddings.js +401 -0
- package/dist/extensions/llm-wiki/lib/guardrails.js +232 -0
- package/dist/extensions/llm-wiki/lib/indexing.js +78 -0
- package/dist/extensions/llm-wiki/lib/ingest-worker.js +410 -0
- package/dist/extensions/llm-wiki/lib/inject.js +65 -0
- package/dist/extensions/llm-wiki/lib/knowledge-document.js +442 -0
- package/dist/extensions/llm-wiki/lib/knowledge-links.js +206 -0
- package/dist/extensions/llm-wiki/lib/legacy-repair.js +443 -0
- package/dist/extensions/llm-wiki/lib/metadata.js +505 -0
- package/dist/extensions/llm-wiki/lib/model-command.js +85 -0
- package/dist/extensions/llm-wiki/lib/observation.js +283 -0
- package/dist/extensions/llm-wiki/lib/recall.js +875 -0
- package/dist/extensions/llm-wiki/lib/retro.js +158 -0
- package/dist/extensions/llm-wiki/lib/runtime.js +187 -0
- package/dist/extensions/llm-wiki/lib/source-extractors.js +426 -0
- package/dist/extensions/llm-wiki/lib/source-packet.js +229 -0
- package/dist/extensions/llm-wiki/lib/subagent.js +41 -0
- package/dist/extensions/llm-wiki/lib/task-config.js +201 -0
- package/dist/extensions/llm-wiki/lib/tools.js +1199 -0
- package/dist/extensions/llm-wiki/lib/trajectories-command.js +51 -0
- package/dist/extensions/llm-wiki/lib/trajectory.js +467 -0
- package/dist/extensions/llm-wiki/lib/utils.js +353 -0
- package/dist/extensions/llm-wiki/lib/vault-format.js +247 -0
- package/dist/extensions/llm-wiki/lib/visible-status.js +31 -0
- package/dist/extensions/llm-wiki/lib/wiki-service.js +128 -0
- package/dist/mcp/exec.js +121 -0
- package/dist/mcp/index.js +229 -0
- package/dist/mcp/operations.js +130 -0
- package/dist/package.json +1 -0
- package/docs/api.md +5 -2
- package/docs/architecture.md +5 -2
- package/docs/configuration.md +25 -0
- package/docs/superpowers/plans/2026-08-02-okf-foundation.md +1579 -0
- package/docs/superpowers/plans/2026-08-03-okf-foundation-remediation.md +3005 -0
- package/docs/superpowers/plans/2026-08-06-authoritative-event-history-phase-1-foundation-hardening.md +937 -0
- package/docs/superpowers/plans/2026-08-06-okf-foundation-release-remediation.md +1174 -0
- package/docs/superpowers/plans/2026-08-07-synthesis-language.md +98 -0
- package/docs/superpowers/specs/2026-08-02-okf-foundation-design.md +593 -0
- package/docs/superpowers/specs/2026-08-02-okf-v0.2-interoperability-design.md +542 -0
- package/docs/superpowers/specs/2026-08-07-synthesis-language-design.md +94 -0
- package/extensions/llm-wiki/index.ts +22 -36
- package/extensions/llm-wiki/lib/bootstrap.ts +87 -0
- package/extensions/llm-wiki/lib/embeddings.ts +9 -3
- package/extensions/llm-wiki/lib/guardrails.ts +26 -18
- package/extensions/llm-wiki/lib/indexing.ts +2 -1
- package/extensions/llm-wiki/lib/ingest-worker.ts +304 -28
- package/extensions/llm-wiki/lib/knowledge-document.ts +663 -0
- package/extensions/llm-wiki/lib/knowledge-links.ts +282 -0
- package/extensions/llm-wiki/lib/legacy-repair.ts +572 -0
- package/extensions/llm-wiki/lib/metadata.ts +550 -128
- package/extensions/llm-wiki/lib/model-command.ts +0 -1
- package/extensions/llm-wiki/lib/observation.ts +37 -43
- package/extensions/llm-wiki/lib/recall.ts +61 -33
- package/extensions/llm-wiki/lib/retro.ts +65 -41
- package/extensions/llm-wiki/lib/runtime.ts +0 -3
- package/extensions/llm-wiki/lib/source-extractors.ts +12 -17
- package/extensions/llm-wiki/lib/source-packet.ts +45 -32
- package/extensions/llm-wiki/lib/task-config.ts +36 -0
- package/extensions/llm-wiki/lib/tools.ts +413 -342
- package/extensions/llm-wiki/lib/trajectory.ts +15 -1
- package/extensions/llm-wiki/lib/utils.ts +127 -131
- package/extensions/llm-wiki/lib/vault-format.ts +363 -0
- package/extensions/llm-wiki/lib/wiki-service.ts +183 -0
- package/mcp/exec.ts +122 -0
- package/mcp/index.ts +60 -250
- package/mcp/operations.ts +176 -0
- package/package.json +8 -2
- package/scripts/migrate-llm-wiki.js +801 -0
- package/skills/llm-wiki/SKILL.md +12 -8
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { existsSync, readFileSync
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { basename, join } from "node:path";
|
|
3
3
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
4
|
+
import { bootstrapVault } from "./lib/bootstrap.js";
|
|
4
5
|
import { installGuardrails } from "./lib/guardrails.js";
|
|
5
6
|
import { buildAgentStartInjection, normalizeSystemPrompt } from "./lib/inject.js";
|
|
6
7
|
import { registerWikiModelCommand } from "./lib/model-command.js";
|
|
@@ -39,14 +40,8 @@ import {
|
|
|
39
40
|
registerWikiDistillSkills,
|
|
40
41
|
registerWikiRecallSkill,
|
|
41
42
|
} from "./lib/trajectory.js";
|
|
42
|
-
import {
|
|
43
|
-
|
|
44
|
-
fmtDate,
|
|
45
|
-
getVaultPaths,
|
|
46
|
-
migrateDoubledPersonalVault,
|
|
47
|
-
resolveVaultPaths,
|
|
48
|
-
writeJson,
|
|
49
|
-
} from "./lib/utils.js";
|
|
43
|
+
import { migrateDoubledPersonalVault, resolveVaultPaths } from "./lib/utils.js";
|
|
44
|
+
import { inspectWritableVault } from "./lib/vault-format.js";
|
|
50
45
|
import { applySessionStartStatus } from "./lib/visible-status.js";
|
|
51
46
|
|
|
52
47
|
/**
|
|
@@ -144,33 +139,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
144
139
|
|
|
145
140
|
const paths = resolveVaultPaths(process.cwd());
|
|
146
141
|
if (!existsSync(join(paths.dotWiki, "config.json"))) {
|
|
147
|
-
// Silently create the wiki vault — no UI prompts
|
|
148
|
-
//
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
const schema = [
|
|
162
|
-
"# LLM Wiki Schema",
|
|
163
|
-
"",
|
|
164
|
-
"## Ownership Rules",
|
|
165
|
-
"",
|
|
166
|
-
"| Path | Owner | Rule |",
|
|
167
|
-
"|------|-------|------|",
|
|
168
|
-
"| raw/** | extension | immutable after capture |",
|
|
169
|
-
"| wiki/** | model + user | editable knowledge pages |",
|
|
170
|
-
"| meta/* | extension | auto-generated |",
|
|
171
|
-
"| . | human + explicit request | operating rules |",
|
|
172
|
-
].join("\n");
|
|
173
|
-
writeFileSync(join(vaultPaths.dotWiki, "WIKI_SCHEMA.md"), schema, "utf-8");
|
|
142
|
+
// Silently create the wiki vault — no UI prompts. Topic/mode will be
|
|
143
|
+
// inferred from the user's first prompt via before_agent_start.
|
|
144
|
+
const result = bootstrapVault(paths, { topic: "pending", mode: "personal" });
|
|
145
|
+
if (!result.ok || !result.projection.ok) {
|
|
146
|
+
ctx.ui.setStatus(
|
|
147
|
+
"llm-wiki",
|
|
148
|
+
`🧠 Wiki setup blocked: ${
|
|
149
|
+
result.ok ? result.projection.diagnostics[0].message : result.diagnostics[0].message
|
|
150
|
+
}`,
|
|
151
|
+
);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
174
154
|
|
|
175
155
|
needsTopicInference = true;
|
|
176
156
|
// INTENTIONALLY NOT gated by `noticesEnabled` (issues #77, #84): one-shot
|
|
@@ -180,6 +160,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
180
160
|
return;
|
|
181
161
|
}
|
|
182
162
|
|
|
163
|
+
const writable = inspectWritableVault(paths);
|
|
164
|
+
if (!writable.ok) {
|
|
165
|
+
ctx.ui.setStatus("llm-wiki", `🧠 Wiki setup blocked: ${writable.diagnostics[0].message}`);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
183
169
|
// Surface the "wiki active" badge and the active background task model
|
|
184
170
|
// (issue #69), both gated by `llm-wiki.notices` (issue #77, regression
|
|
185
171
|
// fixed in #83, helper extracted in #84). `ensureConfig` MUST run first so
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { existsSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import type { KnowledgeDiagnostic } from "./knowledge-document.js";
|
|
4
|
+
import { type ProjectionResult, appendEvent, rebuildMetadata } from "./metadata.js";
|
|
5
|
+
import { type VaultPaths, ensureVaultStructure, fmtDate, writeJson } from "./utils.js";
|
|
6
|
+
import { inspectWritableVault, readVaultConfig } from "./vault-format.js";
|
|
7
|
+
|
|
8
|
+
export const WIKI_SCHEMA = [
|
|
9
|
+
"# LLM Wiki Schema",
|
|
10
|
+
"",
|
|
11
|
+
"## Ownership Rules",
|
|
12
|
+
"",
|
|
13
|
+
"| Path | Owner | Rule |",
|
|
14
|
+
"|------|-------|------|",
|
|
15
|
+
"| raw/** | extension | immutable after capture |",
|
|
16
|
+
"| wiki/** | model + user | editable knowledge pages |",
|
|
17
|
+
"| meta/events.jsonl | extension tools | append-only authoritative state |",
|
|
18
|
+
"| meta/* except events.jsonl | extension | generated projections |",
|
|
19
|
+
"| . | human + explicit request | operating rules |",
|
|
20
|
+
"",
|
|
21
|
+
"Back up `meta/events.jsonl` to preserve activity history. Generated logs cannot reconstruct it.",
|
|
22
|
+
"",
|
|
23
|
+
"## Source Packet Format",
|
|
24
|
+
"",
|
|
25
|
+
"```",
|
|
26
|
+
"raw/sources/SRC-YYYY-MM-DD-NNN/",
|
|
27
|
+
" manifest.json",
|
|
28
|
+
" original/",
|
|
29
|
+
" extracted.md",
|
|
30
|
+
" attachments/",
|
|
31
|
+
"```",
|
|
32
|
+
"",
|
|
33
|
+
"## Page Types",
|
|
34
|
+
"",
|
|
35
|
+
"- **source** — what this specific source says",
|
|
36
|
+
"- **entity** — people, orgs, tools, products",
|
|
37
|
+
"- **concept** — ideas, patterns, frameworks",
|
|
38
|
+
"- **synthesis** — cross-source theses and tensions",
|
|
39
|
+
"- **analysis** — durable filed answers from queries",
|
|
40
|
+
"- **requirement** — atomic requirements with status, priority, and traceability",
|
|
41
|
+
"",
|
|
42
|
+
"## Linking Style",
|
|
43
|
+
"",
|
|
44
|
+
"- New internal links: [label](/folder/page.md)",
|
|
45
|
+
"- Legacy readable links: [[folder/page]]",
|
|
46
|
+
"- Source citation: [source](/sources/SRC-YYYY-MM-DD-NNN.md)",
|
|
47
|
+
"",
|
|
48
|
+
].join("\n");
|
|
49
|
+
|
|
50
|
+
export interface BootstrapInput {
|
|
51
|
+
topic: string;
|
|
52
|
+
mode: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type BootstrapResult =
|
|
56
|
+
| { ok: true; created: boolean; projection: ProjectionResult }
|
|
57
|
+
| { ok: false; created: false; diagnostics: KnowledgeDiagnostic[] };
|
|
58
|
+
|
|
59
|
+
export function bootstrapVault(paths: VaultPaths, input: BootstrapInput): BootstrapResult {
|
|
60
|
+
const configPath = join(paths.dotWiki, "config.json");
|
|
61
|
+
const created = !existsSync(paths.dotWiki);
|
|
62
|
+
let existing: Record<string, unknown> = {};
|
|
63
|
+
|
|
64
|
+
if (!created) {
|
|
65
|
+
const writable = inspectWritableVault(paths);
|
|
66
|
+
if (!writable.ok) return { ok: false, created: false, diagnostics: writable.diagnostics };
|
|
67
|
+
const config = readVaultConfig(paths);
|
|
68
|
+
if (!config.ok) return { ok: false, created: false, diagnostics: [config.diagnostic] };
|
|
69
|
+
existing = config.config;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const config: Record<string, unknown> = {
|
|
73
|
+
...existing,
|
|
74
|
+
name: input.topic,
|
|
75
|
+
mode: input.mode,
|
|
76
|
+
topic: input.topic,
|
|
77
|
+
created: existing.created ?? fmtDate(),
|
|
78
|
+
version: existing.version ?? "1.0",
|
|
79
|
+
...(created ? { knowledge_format: "okf-0.2" } : {}),
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
ensureVaultStructure(paths);
|
|
83
|
+
writeJson(configPath, config);
|
|
84
|
+
writeFileSync(join(paths.dotWiki, "WIKI_SCHEMA.md"), WIKI_SCHEMA, "utf8");
|
|
85
|
+
appendEvent(paths, { kind: "bootstrap", topic: input.topic, mode: input.mode });
|
|
86
|
+
return { ok: true, created, projection: rebuildMetadata(paths) };
|
|
87
|
+
}
|
|
@@ -3,10 +3,12 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
3
3
|
import { request as httpRequest } from "node:http";
|
|
4
4
|
import { request as httpsRequest } from "node:https";
|
|
5
5
|
import { join } from "node:path";
|
|
6
|
+
import { parseKnowledgeDocument } from "./knowledge-document.js";
|
|
6
7
|
import type { Registry } from "./metadata.js";
|
|
7
8
|
import type { LaunchCtx, Runtime } from "./runtime.js";
|
|
8
9
|
import type { TaskConfig } from "./task-config.js";
|
|
9
|
-
import { type VaultPaths,
|
|
10
|
+
import { type VaultPaths, readJson, writeJson } from "./utils.js";
|
|
11
|
+
import { assertWritableVault } from "./vault-format.js";
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Background semantic embeddings, computed at write time (issue #66, epic #63).
|
|
@@ -166,6 +168,7 @@ export function readEmbeddingStore(paths: VaultPaths): EmbeddingStore {
|
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
export function writeEmbeddingStore(paths: VaultPaths, store: EmbeddingStore): void {
|
|
171
|
+
assertWritableVault(paths);
|
|
169
172
|
writeJson(embeddingStorePath(paths), store);
|
|
170
173
|
}
|
|
171
174
|
|
|
@@ -189,8 +192,9 @@ function readPageText(paths: VaultPaths, id: string): PageText | undefined {
|
|
|
189
192
|
const pagePath = join(paths.wiki, `${id}.md`);
|
|
190
193
|
if (!existsSync(pagePath)) return undefined;
|
|
191
194
|
const raw = readFileSync(pagePath, "utf-8");
|
|
192
|
-
const
|
|
193
|
-
|
|
195
|
+
const result = parseKnowledgeDocument(raw, `${id}.md`);
|
|
196
|
+
if (!result.ok) return undefined;
|
|
197
|
+
const text = buildEmbeddingText(id, result.document.frontmatter, result.document.body);
|
|
194
198
|
return { id, text, hash: contentHash(text) };
|
|
195
199
|
}
|
|
196
200
|
|
|
@@ -205,6 +209,7 @@ export async function embedPages(
|
|
|
205
209
|
embedder: Embedder,
|
|
206
210
|
opts: { force?: boolean } = {},
|
|
207
211
|
): Promise<EmbedStats> {
|
|
212
|
+
assertWritableVault(paths);
|
|
208
213
|
const store = readEmbeddingStore(paths);
|
|
209
214
|
const targets: PageText[] = [];
|
|
210
215
|
let skipped = 0;
|
|
@@ -251,6 +256,7 @@ export async function reindexEmbeddings(
|
|
|
251
256
|
embedder: Embedder,
|
|
252
257
|
opts: { force?: boolean } = {},
|
|
253
258
|
): Promise<ReindexStats> {
|
|
259
|
+
assertWritableVault(paths);
|
|
254
260
|
const registry = readJson<Registry>(join(paths.meta, "registry.json"), {
|
|
255
261
|
version: "1.0",
|
|
256
262
|
last_updated: "",
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { resolve, sep } from "node:path";
|
|
2
1
|
import { isToolCallEventType } from "@mariozechner/pi-coding-agent";
|
|
3
2
|
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
4
3
|
import { scheduleReindex } from "./indexing.js";
|
|
5
4
|
import { rebuildMetadataLight } from "./metadata.js";
|
|
6
5
|
import type { Runtime } from "./runtime.js";
|
|
7
|
-
import { isProtectedPath, resolveVaultPaths } from "./utils.js";
|
|
6
|
+
import { isPathWithin, isProtectedPath, resolveVaultPaths } from "./utils.js";
|
|
7
|
+
import type { VaultPaths } from "./utils.js";
|
|
8
|
+
import { inspectVaultFormat, isGeneratedOkfPath } from "./vault-format.js";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Guardrails and auto-rebuild hooks for the LLM Wiki extension.
|
|
@@ -172,26 +173,35 @@ export function extractMutationPaths(input: unknown): string[] {
|
|
|
172
173
|
|
|
173
174
|
/** True when a write or patch-shaped edit targets a page in the wiki directory. */
|
|
174
175
|
export function hasWikiMutation(input: unknown, wikiPath: string): boolean {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
176
|
+
return extractMutationPaths(input).some((path) => isPathWithin(wikiPath, path));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function mutationBlockReason(path: string, paths: VaultPaths): string | undefined {
|
|
180
|
+
const protectedPath = isProtectedPath(path, paths);
|
|
181
|
+
if (protectedPath.protected) return protectedPath.reason;
|
|
182
|
+
|
|
183
|
+
if (isPathWithin(paths.dotWiki, path)) {
|
|
184
|
+
const state = inspectVaultFormat(paths);
|
|
185
|
+
if (state.blocking) {
|
|
186
|
+
return `Wiki vault configuration is invalid: ${state.diagnostics[0].message}`;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (isGeneratedOkfPath(path, paths)) {
|
|
191
|
+
return "Generated OKF indexes and log are read-only. Use wiki_rebuild_meta or the page-producing tool that owns the source mutation.";
|
|
192
|
+
}
|
|
193
|
+
return undefined;
|
|
182
194
|
}
|
|
183
195
|
|
|
184
196
|
/** Install guardrails on the extension API. */
|
|
185
197
|
export function installGuardrails(pi: ExtensionAPI, runtime?: Runtime): void {
|
|
186
|
-
// Block direct edits to raw/ and meta
|
|
198
|
+
// Block direct edits to raw/ and meta/, plus OKF generated projections
|
|
187
199
|
pi.on("tool_call", async (event) => {
|
|
188
200
|
if (isToolCallEventType("write", event)) {
|
|
189
201
|
const path = event.input.path as string;
|
|
190
202
|
const paths = resolveVaultPaths(process.cwd());
|
|
191
|
-
const
|
|
192
|
-
if (
|
|
193
|
-
return { block: true, reason: check.reason };
|
|
194
|
-
}
|
|
203
|
+
const reason = mutationBlockReason(path, paths);
|
|
204
|
+
if (reason) return { block: true, reason };
|
|
195
205
|
}
|
|
196
206
|
|
|
197
207
|
if (isToolCallEventType("edit", event)) {
|
|
@@ -203,10 +213,8 @@ export function installGuardrails(pi: ExtensionAPI, runtime?: Runtime): void {
|
|
|
203
213
|
|
|
204
214
|
const paths = resolveVaultPaths(process.cwd());
|
|
205
215
|
for (const path of targetPaths) {
|
|
206
|
-
const
|
|
207
|
-
if (
|
|
208
|
-
return { block: true, reason: check.reason };
|
|
209
|
-
}
|
|
216
|
+
const reason = mutationBlockReason(path, paths);
|
|
217
|
+
if (reason) return { block: true, reason };
|
|
210
218
|
}
|
|
211
219
|
}
|
|
212
220
|
});
|
|
@@ -64,7 +64,8 @@ export function scheduleReindex(
|
|
|
64
64
|
// that land during embedding are not lost.
|
|
65
65
|
while (dirty.has(root)) {
|
|
66
66
|
dirty.delete(root);
|
|
67
|
-
rebuildMetadataLight(paths);
|
|
67
|
+
const projection = rebuildMetadataLight(paths);
|
|
68
|
+
if (!projection.ok) continue;
|
|
68
69
|
|
|
69
70
|
// Refresh embeddings only after metadata is consistent. Stale-aware and
|
|
70
71
|
// a no-op unless an embedder is configured.
|