@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.
Files changed (82) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.de.md +35 -4
  3. package/README.es.md +260 -170
  4. package/README.fr.md +35 -4
  5. package/README.hi.md +35 -4
  6. package/README.ja.md +35 -4
  7. package/README.ko.md +35 -4
  8. package/README.md +41 -12
  9. package/README.pt.md +35 -4
  10. package/README.ru.md +35 -4
  11. package/README.zh.md +260 -170
  12. package/assets/demo.gif +0 -0
  13. package/dist/extensions/llm-wiki/lib/bootstrap.js +74 -0
  14. package/dist/extensions/llm-wiki/lib/embeddings.js +401 -0
  15. package/dist/extensions/llm-wiki/lib/guardrails.js +232 -0
  16. package/dist/extensions/llm-wiki/lib/indexing.js +78 -0
  17. package/dist/extensions/llm-wiki/lib/ingest-worker.js +410 -0
  18. package/dist/extensions/llm-wiki/lib/inject.js +65 -0
  19. package/dist/extensions/llm-wiki/lib/knowledge-document.js +442 -0
  20. package/dist/extensions/llm-wiki/lib/knowledge-links.js +206 -0
  21. package/dist/extensions/llm-wiki/lib/legacy-repair.js +443 -0
  22. package/dist/extensions/llm-wiki/lib/metadata.js +505 -0
  23. package/dist/extensions/llm-wiki/lib/model-command.js +85 -0
  24. package/dist/extensions/llm-wiki/lib/observation.js +283 -0
  25. package/dist/extensions/llm-wiki/lib/recall.js +875 -0
  26. package/dist/extensions/llm-wiki/lib/retro.js +158 -0
  27. package/dist/extensions/llm-wiki/lib/runtime.js +187 -0
  28. package/dist/extensions/llm-wiki/lib/source-extractors.js +426 -0
  29. package/dist/extensions/llm-wiki/lib/source-packet.js +229 -0
  30. package/dist/extensions/llm-wiki/lib/subagent.js +41 -0
  31. package/dist/extensions/llm-wiki/lib/task-config.js +201 -0
  32. package/dist/extensions/llm-wiki/lib/tools.js +1199 -0
  33. package/dist/extensions/llm-wiki/lib/trajectories-command.js +51 -0
  34. package/dist/extensions/llm-wiki/lib/trajectory.js +467 -0
  35. package/dist/extensions/llm-wiki/lib/utils.js +353 -0
  36. package/dist/extensions/llm-wiki/lib/vault-format.js +247 -0
  37. package/dist/extensions/llm-wiki/lib/visible-status.js +31 -0
  38. package/dist/extensions/llm-wiki/lib/wiki-service.js +128 -0
  39. package/dist/mcp/exec.js +121 -0
  40. package/dist/mcp/index.js +229 -0
  41. package/dist/mcp/operations.js +130 -0
  42. package/dist/package.json +1 -0
  43. package/docs/api.md +5 -2
  44. package/docs/architecture.md +5 -2
  45. package/docs/configuration.md +25 -0
  46. package/docs/superpowers/plans/2026-08-02-okf-foundation.md +1579 -0
  47. package/docs/superpowers/plans/2026-08-03-okf-foundation-remediation.md +3005 -0
  48. package/docs/superpowers/plans/2026-08-06-authoritative-event-history-phase-1-foundation-hardening.md +937 -0
  49. package/docs/superpowers/plans/2026-08-06-okf-foundation-release-remediation.md +1174 -0
  50. package/docs/superpowers/plans/2026-08-07-synthesis-language.md +98 -0
  51. package/docs/superpowers/specs/2026-08-02-okf-foundation-design.md +593 -0
  52. package/docs/superpowers/specs/2026-08-02-okf-v0.2-interoperability-design.md +542 -0
  53. package/docs/superpowers/specs/2026-08-07-synthesis-language-design.md +94 -0
  54. package/extensions/llm-wiki/index.ts +22 -36
  55. package/extensions/llm-wiki/lib/bootstrap.ts +87 -0
  56. package/extensions/llm-wiki/lib/embeddings.ts +9 -3
  57. package/extensions/llm-wiki/lib/guardrails.ts +26 -18
  58. package/extensions/llm-wiki/lib/indexing.ts +2 -1
  59. package/extensions/llm-wiki/lib/ingest-worker.ts +304 -28
  60. package/extensions/llm-wiki/lib/knowledge-document.ts +663 -0
  61. package/extensions/llm-wiki/lib/knowledge-links.ts +282 -0
  62. package/extensions/llm-wiki/lib/legacy-repair.ts +572 -0
  63. package/extensions/llm-wiki/lib/metadata.ts +550 -128
  64. package/extensions/llm-wiki/lib/model-command.ts +0 -1
  65. package/extensions/llm-wiki/lib/observation.ts +37 -43
  66. package/extensions/llm-wiki/lib/recall.ts +61 -33
  67. package/extensions/llm-wiki/lib/retro.ts +65 -41
  68. package/extensions/llm-wiki/lib/runtime.ts +0 -3
  69. package/extensions/llm-wiki/lib/source-extractors.ts +12 -17
  70. package/extensions/llm-wiki/lib/source-packet.ts +45 -32
  71. package/extensions/llm-wiki/lib/task-config.ts +36 -0
  72. package/extensions/llm-wiki/lib/tools.ts +413 -342
  73. package/extensions/llm-wiki/lib/trajectory.ts +15 -1
  74. package/extensions/llm-wiki/lib/utils.ts +127 -131
  75. package/extensions/llm-wiki/lib/vault-format.ts +363 -0
  76. package/extensions/llm-wiki/lib/wiki-service.ts +183 -0
  77. package/mcp/exec.ts +122 -0
  78. package/mcp/index.ts +60 -250
  79. package/mcp/operations.ts +176 -0
  80. package/package.json +8 -2
  81. package/scripts/migrate-llm-wiki.js +801 -0
  82. package/skills/llm-wiki/SKILL.md +12 -8
@@ -0,0 +1,98 @@
1
+ # Configurable Synthesis Language Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use /skill:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** Allow vault owners to configure the narrative language used by background ingest synthesis via `.pi/settings.json`.
6
+
7
+ **Architecture:** Add `synthesisLanguage` field to `TaskConfig`, parse it in `readNamespacedConfig`, pass it through `wiki_ingest` → `runIngestSynthesis`, and conditionally append a language instruction to the ingest worker's system prompt.
8
+
9
+ **Tech Stack:** TypeScript (ES2022, ESM), Vitest, Biome
10
+
11
+ **Roadmap:** None
12
+
13
+ **Phase:** Single-plan implementation
14
+
15
+ ---
16
+
17
+ ### Task 1: Add `synthesisLanguage` to TaskConfig
18
+
19
+ **Files:**
20
+ - Modify: `extensions/llm-wiki/lib/task-config.ts`
21
+
22
+ - [ ] Add `synthesisLanguage?: string` field to `TaskConfig` interface (after `trajectories`)
23
+ - [ ] In `readNamespacedConfig`, parse `section.synthesisLanguage` as a non-empty trimmed string:
24
+ ```ts
25
+ const lang = section.synthesisLanguage;
26
+ if (typeof lang === "string" && lang.trim()) out.synthesisLanguage = lang.trim();
27
+ ```
28
+ - [ ] Run `pnpm typecheck` — confirm no errors
29
+ - [ ] Commit: `feat: add synthesisLanguage config field`
30
+
31
+ ### Task 2: Wire `synthesisLanguage` into ingest worker
32
+
33
+ **Files:**
34
+ - Modify: `extensions/llm-wiki/lib/ingest-worker.ts`
35
+
36
+ - [ ] Add `synthesisLanguage?: string` to `RunIngestSynthesisArgs` interface
37
+ - [ ] In `runIngestSynthesis`, after destructuring args, build the system prompt:
38
+ ```ts
39
+ const languageInstruction = synthesisLanguage
40
+ ? `\n\nWrite all generated narrative content in ${synthesisLanguage}. Preserve product names, repository names, APIs, paths, commands, code, field names, and technical identifiers in their original form.`
41
+ : "";
42
+ const systemPrompt = INGEST_SYSTEM + languageInstruction;
43
+ ```
44
+ - [ ] Pass `systemPrompt` (instead of `INGEST_SYSTEM`) to `runSubAgent`
45
+ - [ ] Run `pnpm typecheck` — confirm no errors
46
+ - [ ] Commit: `feat: inject synthesisLanguage into ingest system prompt`
47
+
48
+ ### Task 3: Pass `synthesisLanguage` from wiki_ingest tool
49
+
50
+ **Files:**
51
+ - Modify: `extensions/llm-wiki/lib/tools.ts`
52
+
53
+ - [ ] In the `wiki_ingest` tool's background synthesis block (around line 409), pass `synthesisLanguage` to `runIngestSynthesis`:
54
+ ```ts
55
+ const committed = await runIngestSynthesis({
56
+ model: resolved.model as Parameters<typeof runIngestSynthesis>[0]["model"],
57
+ apiKey: resolved.apiKey,
58
+ headers: resolved.headers,
59
+ paths,
60
+ sourceId: s.id,
61
+ manifest: s.manifest,
62
+ extracted: s.extracted,
63
+ synthesisLanguage: runtime.config.synthesisLanguage,
64
+ });
65
+ ```
66
+ - [ ] Run `pnpm typecheck` — confirm no errors
67
+ - [ ] Run `pnpm test` — confirm existing tests pass
68
+ - [ ] Commit: `feat: wire synthesisLanguage through wiki_ingest tool`
69
+
70
+ ### Task 4: Add unit test for synthesis language injection
71
+
72
+ **Files:**
73
+ - Create: `extensions/llm-wiki/test/ingest-worker-synthesis-language.test.ts`
74
+
75
+ - [ ] Write a focused test: verify that when `synthesisLanguage` is set, the language instruction is appended to the system prompt
76
+ - Mock `runSubAgent` or inspect the constructed prompt
77
+ - Assert the instruction contains the configured language tag and the preservation clause
78
+ - [ ] Run `pnpm test` — confirm test passes
79
+ - [ ] Commit: `test: verify synthesisLanguage injection`
80
+
81
+ ### Task 5: Update documentation
82
+
83
+ **Files:**
84
+ - Modify: `docs/configuration.md`
85
+
86
+ - [ ] Add a section for `synthesisLanguage` under the `llm-wiki` config docs:
87
+ - Description: language for background ingest synthesis narrative content
88
+ - Type: BCP 47 language tag (string)
89
+ - Default: undefined (English synthesis)
90
+ - Example JSON snippet
91
+ - [ ] Commit: `docs: document synthesisLanguage config`
92
+
93
+ ### Task 6: Final verification
94
+
95
+ - [ ] Run `pnpm lint` — confirm no Biome issues
96
+ - [ ] Run `pnpm test` — confirm all tests pass
97
+ - [ ] Run `pnpm typecheck` — confirm no TypeScript errors
98
+ - [ ] Commit: `ci: verify synthesisLanguage implementation`
@@ -0,0 +1,593 @@
1
+ # OKF Foundation Design
2
+
3
+ **Status:** Ready for fresh-context spec review
4
+
5
+ **Date:** 2026-08-02
6
+
7
+ **Parent:** [OKF v0.2 Interoperability Design](./2026-08-02-okf-v0.2-interoperability-design.md)
8
+
9
+ ## Purpose
10
+
11
+ This child spec defines the first implementation phase of OKF support in `@zosmaai/pi-llm-wiki`: one shared document model, safe YAML parsing, dual legacy/OKF reading, OKF-canonical new documents, explicit vault mode, standard Markdown links, and deterministic OKF indexes and logs.
12
+
13
+ This spec is normative for Foundation. The parent design is non-normative.
14
+
15
+ ## Scope
16
+
17
+ Foundation includes:
18
+
19
+ - a shared parser and serializer for legacy and OKF v0.2 frontmatter
20
+ - preservation of unknown producer fields
21
+ - explicit vault format mode
22
+ - dual-read behavior in every vault mode
23
+ - OKF-canonical output from all page producers
24
+ - support for Markdown links and legacy wikilinks
25
+ - deterministic `wiki/index.md` and `wiki/log.md` in OKF mode
26
+ - continued `meta/index.md` and `meta/log.md` generation
27
+ - integration with registry, backlinks, embeddings, recall readers, Pi tools, and MCP readers
28
+ - conformance fixtures for the shared format layer
29
+
30
+ Foundation excludes:
31
+
32
+ - migration commands or mode changes for existing vaults
33
+ - OKF import, review staging, transactions, and export
34
+ - trust-based recall scoring
35
+ - expanded OKF lint rules beyond parser/projection diagnostics needed by Foundation
36
+ - execution of Attested Computation documents
37
+
38
+ Those requirements belong to later child specs.
39
+
40
+ ## Design Principles
41
+
42
+ 1. **One parser, not legacy and OKF parser chains.** Legacy and OKF pages share Markdown-plus-YAML syntax. The shared parser represents both; compatibility classification happens after parsing.
43
+ 2. **Mode controls bundle behavior, not readability.** Every mode reads both legacy and OKF-shaped pages. Mode controls reserved files and generated projections.
44
+ 3. **Missing metadata does not become invented metadata.** Foundation never fabricates authorship, verification, provenance, or timestamps it cannot know.
45
+ 4. **Unknown data survives rewrites.** Unknown ordinary YAML fields remain semantically equivalent after parse and serialize.
46
+ 5. **Generated files are projections; authoritative extension state is not.** Registry, backlinks, indexes, and logs derive from authoritative pages and events. `meta/events.jsonl` is extension-written state, but it is not generated metadata because no rebuild can reconstruct it.
47
+ 6. **Invalid explicit configuration fails closed.** Unknown mode and OKF version values never silently downgrade to legacy behavior.
48
+
49
+ ## Vault Mode
50
+
51
+ `config.json` gains one field:
52
+
53
+ ```json
54
+ {
55
+ "knowledge_format": "legacy"
56
+ }
57
+ ```
58
+
59
+ Allowed values:
60
+
61
+ - `legacy`
62
+ - `okf-0.2`
63
+
64
+ ### Resolution rules
65
+
66
+ | Vault state | Effective mode | Behavior |
67
+ |---|---|---|
68
+ | Existing config lacks `knowledge_format` | `legacy` | Preserve current reserved-file behavior |
69
+ | New vault bootstrap | `okf-0.2` | Create OKF root index and log |
70
+ | Config explicitly says `legacy` | `legacy` | Dual-read; no generated files under `wiki/` |
71
+ | Config explicitly says `okf-0.2` | `okf-0.2` | Dual-read; generate OKF reserved files |
72
+ | Config contains another value or non-string | Error | Do not rebuild or write wiki metadata |
73
+
74
+ Missing mode means legacy only for backward compatibility with an existing vault. New bootstrap always persists `okf-0.2`; it never relies on the missing-field fallback.
75
+
76
+ Foundation does not change an existing vault's mode. The later Interchange migration spec owns mode activation and the `legacy` → `okf-0.2` transition.
77
+
78
+ ### Compatibility promise
79
+
80
+ In both modes, every newly created concept path uses the canonical OKF shape defined here. Ordinary tool updates to an existing legacy document preserve its existing frontmatter shapes, including scalar or string-list `sources`; they parse, patch only the requested values, and serialize with legacy-shape preservation enabled. Foundation never converts an existing legacy document merely because a tool touched it. Canonical conversion of existing pages belongs exclusively to explicit migration in the later Interchange spec.
81
+
82
+ A user or model may intentionally replace an entire file outside these service operations. The next rebuild parses the resulting file as written but does not infer that a migration occurred.
83
+
84
+ Legacy mode preserves upgraded pi-llm-wiki behavior, not downgrade compatibility with older package versions whose parser cannot understand nested OKF v0.2 metadata.
85
+
86
+ In legacy mode:
87
+
88
+ - `meta/index.md`, `meta/log.md`, registry, backlinks, and embeddings continue to update.
89
+ - `wiki/index.md` and `wiki/log.md` are not created or rewritten.
90
+ - Existing user-owned files named `wiki/index.md` or `wiki/log.md` are not treated as generated Foundation projections.
91
+
92
+ In OKF mode:
93
+
94
+ - `wiki/index.md` and `wiki/log.md` are generated projections.
95
+ - Tool-call guardrails reject direct model edits to those reserved generated files.
96
+ - `meta/**` projections continue to exist for efficient internal lookup and backward-compatible tooling.
97
+
98
+ ## Shared Knowledge Document Model
99
+
100
+ The shared model represents:
101
+
102
+ - canonical concept ID
103
+ - source file path
104
+ - standard OKF fields
105
+ - pi-llm-wiki extension fields
106
+ - unknown producer fields
107
+ - compatibility diagnostics
108
+ - Markdown body
109
+
110
+ Conceptual shape:
111
+
112
+ ```text
113
+ KnowledgeDocument
114
+ id: bundle-relative path without .md
115
+ path: bundle-relative .md path
116
+ frontmatter:
117
+ type
118
+ title?
119
+ description?
120
+ resource?
121
+ tags?
122
+ sources?
123
+ generated?
124
+ verified?
125
+ status?
126
+ stale_after?
127
+ category?
128
+ domain?
129
+ aliases?
130
+ recall_triggers?
131
+ extensions: unknown fields
132
+ body
133
+ compatibility: legacy shapes detected during parsing
134
+ ```
135
+
136
+ The implementation may use smaller nested types. It must not expose YAML-library objects to consumers.
137
+
138
+ ### Concept identity
139
+
140
+ - A concept ID is the NFC-normalized, bundle-relative file path without the final `.md` suffix.
141
+ - `/` is the internal path separator on every platform.
142
+ - `index.md` and `log.md`, compared case-insensitively, are reserved and never concept documents.
143
+ - Display title never determines identity.
144
+ - New concept paths use existing Unicode-aware slug generation and must not produce reserved names.
145
+ - A scan that finds two paths colliding after NFC normalization or target-filesystem case folding returns a diagnostic and does not replace generated metadata with a partial registry.
146
+
147
+ Foundation does not rename existing paths. Import and migration path changes belong to Interchange.
148
+
149
+ ## YAML Parsing and Serialization
150
+
151
+ The current scalar/list parser cannot represent OKF v0.2 nested provenance and trust fields. Foundation replaces it with a maintained YAML parser behind the shared document API.
152
+
153
+ ### Parse requirements
154
+
155
+ - Require one frontmatter mapping delimited by `---` at the start of a concept document.
156
+ - Accept LF and CRLF input.
157
+ - Reject duplicate mapping keys.
158
+ - Reject aliases and alias expansion.
159
+ - Reject custom tags.
160
+ - Reject multiple YAML documents.
161
+ - Reject nesting deeper than 32 mappings/sequences.
162
+ - Reject frontmatter larger than 128 KiB measured as UTF-8 bytes.
163
+ - Return structured diagnostics; never throw a YAML-library error through tool boundaries.
164
+ - Accept unknown ordinary scalar, sequence, and mapping values.
165
+ - Parse YAML timestamps as preserved scalar values rather than converting them into host-language date objects implicitly.
166
+
167
+ The selected parser configuration and tests must prove these restrictions. A new dependency is acceptable because implementing general nested YAML safely in-house is out of scope.
168
+
169
+ ### Serialization requirements
170
+
171
+ - Emit UTF-8 and LF line endings.
172
+ - Emit the opening fence as `---\n`, YAML ending in one newline, and the closing fence as `---\n`.
173
+ - For a non-empty body, emit exactly one blank separator line after the closing fence, then the body with exactly one final newline.
174
+ - For an empty body, emit no blank separator line after the closing fence; the file ends with the closing fence's newline.
175
+ - The parser removes one optional blank separator line from the model body; additional leading blank lines belong to the body.
176
+ - Preserve unknown fields semantically.
177
+ - Preserve explicit empty lists and mappings.
178
+ - Do not promise preservation of comments, quote style, key order, scalar style, or blank-line formatting inside frontmatter.
179
+ - Never emit aliases, custom tags, or multiple YAML documents.
180
+ - Keep the Markdown body byte-equivalent except for normalizing the separator immediately after frontmatter and the final newline when the caller requested serialization.
181
+
182
+ A parse → serialize → parse round trip must preserve known and unknown YAML values semantically and preserve body text under the documented newline normalization.
183
+
184
+ ## Compatibility Classification
185
+
186
+ There is no fallback parser. The shared parser parses the YAML document once and records legacy shapes that later migration may convert.
187
+
188
+ Foundation recognizes, without rejecting:
189
+
190
+ - scalar or string-list legacy `sources`
191
+ - `created` and `updated`
192
+ - `summary`
193
+ - `raw_path` and `source_id`
194
+ - existing lowercase pi-llm-wiki type values
195
+ - legacy wikilinks in the body
196
+
197
+ Legacy shapes produce compatibility metadata, not conformance errors during ordinary reads. Foundation consumers can index them. The later migration and lint specs decide how to report or convert each shape.
198
+
199
+ A malformed frontmatter block is a parse error. It is never retried as plain Markdown or silently interpreted as legacy.
200
+
201
+ ## OKF Version Resolution
202
+
203
+ Only the root `wiki/index.md` may declare bundle version metadata.
204
+
205
+ In `okf-0.2` mode:
206
+
207
+ - generated root index declares `okf_version: "0.2"`
208
+ - missing generated root index is repairable by metadata rebuild
209
+ - an existing root index declaring another version blocks projection writes until explicitly handled
210
+ - malformed version frontmatter blocks projection writes
211
+ - version mismatch does not prevent best-effort ordinary reads of parseable concept files; readers surface the version diagnostic alongside results
212
+
213
+ In legacy mode, root index version metadata does not activate OKF behavior. Explicit mode remains source of truth. If a legacy-mode root index declares an unsupported version, tools report the mismatch but do not change mode or rewrite that file.
214
+
215
+ ## Canonical New Document Output
216
+
217
+ All page-producing flows use the shared serializer:
218
+
219
+ - source capture and ingestion
220
+ - entity/concept/synthesis/analysis creation
221
+ - observations and retrospectives
222
+ - requirements
223
+ - trajectories, cases, and skills when enabled
224
+ - `wiki_ensure_page`
225
+
226
+ Required output:
227
+
228
+ - non-empty `type`
229
+ - standard YAML frontmatter
230
+ - standard Markdown body
231
+
232
+ Recommended fields are emitted only when known. Foundation does not invent `generated`, `verified`, `sources`, `resource`, or `stale_after`.
233
+
234
+ For a new document, `sources` uses the OKF v0.2 sequence-of-mappings shape. For an existing legacy document, scalar and string-list `sources` values remain unchanged during ordinary field patches. The shared model records those values separately from canonical structured sources so no caller can accidentally reinterpret a string as a structured provenance entry.
235
+
236
+ Existing pi-llm-wiki extensions remain optional top-level fields:
237
+
238
+ - `category`
239
+ - `domain`
240
+ - `aliases`
241
+ - `recall_triggers`
242
+ - `created`
243
+ - `updated`
244
+ - source-packet identifiers needed by existing workflows
245
+
246
+ For new synthesized documents, `description` is the canonical one-sentence preview field. Existing `summary` may remain when it carries longer content or compatibility value.
247
+
248
+ ## Link Support
249
+
250
+ Foundation recognizes two internal-link syntaxes:
251
+
252
+ 1. standard Markdown links
253
+ 2. existing folder-qualified wikilinks
254
+
255
+ ### Markdown links
256
+
257
+ Link extraction follows CommonMark 0.31.2 parsing rules. A CommonMark-compatible AST parser, not a regular expression over raw Markdown, identifies links.
258
+
259
+ Backlink-producing nodes include inline links and resolved full, collapsed, and shortcut reference links. Images, image references, autolinks, raw HTML links, footnote references, and bare URLs do not produce backlinks. Link-like text inside inline code, fenced code blocks, indented code blocks, or escaped Markdown remains text. A reference definition produces an edge only when a link node uses it. GFM tables and task lists may be accepted as body syntax but add no separate link semantics.
260
+
261
+ Supported concept targets:
262
+
263
+ - bundle-root-relative: `/concepts/retrieval.md`
264
+ - file-relative: `../concepts/retrieval.md`
265
+ - same-directory relative: `other.md` or `./other.md`
266
+
267
+ Resolution:
268
+
269
+ - strip query and fragment before concept resolution
270
+ - percent-decode each path segment once
271
+ - normalize separators and dot segments
272
+ - reject a target that escapes bundle root
273
+ - normalize target identity to NFC
274
+ - ignore external URI schemes for backlink purposes
275
+
276
+ New generated knowledge uses Markdown links. Bundle-root-relative links are preferred in concept bodies. Generated directory indexes use links relative to their directory.
277
+
278
+ ### Wikilinks
279
+
280
+ Existing forms remain readable:
281
+
282
+ ```text
283
+ [[concepts/retrieval]]
284
+ [[concepts/retrieval|RAG]]
285
+ ```
286
+
287
+ Wikilinks continue to participate in registry backlinks and recall metadata. Foundation does not rewrite them; migration owns conversion.
288
+
289
+ ### Backlinks
290
+
291
+ Backlinks combine resolved Markdown links and resolved wikilinks, deduplicated by `(source concept ID, target concept ID)`. Unresolved links produce diagnostics but do not abort ordinary page reading. Generated metadata stores only links whose targets resolve to a known concept.
292
+
293
+ ## Deterministic Directory Indexes
294
+
295
+ Directory indexes exist only in `okf-0.2` mode. The root and every directory containing a concept directly or transitively receive `index.md`.
296
+
297
+ ### Root template
298
+
299
+ ```markdown
300
+ ---
301
+ okf_version: "0.2"
302
+ ---
303
+
304
+ # <vault name>
305
+
306
+ ## Directories
307
+
308
+ - [concepts/](concepts/)
309
+
310
+ ## Concepts
311
+
312
+ - [Welcome](welcome.md) — Entry point for the knowledge bundle.
313
+ ```
314
+
315
+ ### Subdirectory template
316
+
317
+ ```markdown
318
+ # concepts
319
+
320
+ ## Directories
321
+
322
+ - [architecture/](architecture/)
323
+
324
+ ## Concepts
325
+
326
+ - [Retrieval-Augmented Generation](retrieval-augmented-generation.md) — Grounds generation using retrieved evidence.
327
+ ```
328
+
329
+ ### Generation rules
330
+
331
+ - Root index frontmatter contains only `okf_version: "0.2"`. Foundation does not emit `profile` or another producer key there because OKF v0.2 is ambiguous about additional root-index frontmatter keys. The pi-llm-wiki profile remains documentation, not a bundle-level conformance claim, until OKF defines a portable profile-discovery mechanism.
332
+ - Root H1 is `config.name`, falling back to `Wiki` when absent or empty.
333
+ - Subdirectory H1 is the literal final directory segment.
334
+ - Omit `## Directories` when there are no immediate child directories.
335
+ - Omit `## Concepts` when there are no direct concepts.
336
+ - List immediate child directories before direct concepts.
337
+ - Sort both groups by NFC-normalized relative path using Unicode code-point order, independent of process locale.
338
+ - Concept title is `title` when non-empty, otherwise the final concept-ID segment.
339
+ - Include ` — <description>` only when `description` is a non-empty single-line string.
340
+ - Collapse description line breaks and repeated whitespace to one space.
341
+ - Escape Markdown link labels for backslash, `[` and `]`.
342
+ - Encode each link path segment for use as a relative URI while preserving `/` separators.
343
+ - Emit LF line endings and exactly one final newline.
344
+ - Include no generated timestamp, page count, or other nondeterministic value.
345
+ - Prune generated subdirectory indexes whose directories no longer contain concepts directly or transitively.
346
+
347
+ An index is a projection. Users and importers cannot use it to hide a concept from scanning; concept discovery scans eligible files directly.
348
+
349
+ ## Deterministic Root Log
350
+
351
+ `meta/events.jsonl` remains the authoritative append-only event source in both modes. `wiki/log.md` is a generated OKF projection only in `okf-0.2` mode. Foundation generates no per-directory logs.
352
+
353
+ `meta/events.jsonl` is durable extension-owned vault state. Users who need activity continuity must preserve it when backing up or synchronizing a complete pi-llm-wiki vault. It is not derivable from canonical pages, raw source packets, `meta/log.md`, or `wiki/log.md`.
354
+
355
+ Foundation does not make the JSONL event source part of the distributable OKF bundle. `wiki/log.md` is a portable snapshot of recorded activity at projection time, not a recovery format and not a promise that an imported bundle can continue the originating vault's event stream. Import, export, and imported-history composition belong to the later Interchange child specification.
356
+
357
+ The event stream records selected extension operations. It is not a complete revision history: manual file edits do not fabricate events, while extension-owned operational actions may emit events. Documentation and UI text must call it an activity history rather than a complete content audit trail.
358
+
359
+ ### Authoritative event shape
360
+
361
+ Each valid JSONL line must contain:
362
+
363
+ ```json
364
+ {
365
+ "timestamp": "2026-08-02T10:00:00.000Z",
366
+ "kind": "capture"
367
+ }
368
+ ```
369
+
370
+ Additional JSON-compatible fields are allowed. Event production is mode-independent: the same successful capture, creation, update, retro, observation, ingestion, and other tool-owned mutations append the same event in legacy and OKF modes. Event writers append only after the associated authoritative wiki mutation succeeds. A projection rebuild itself does not append an event. Manual file edits do not fabricate events because the extension cannot infer actor or intent safely.
371
+
372
+ Fields projected into `wiki/log.md` must be safe for a distributable bundle. A local file capture event records its stable `source_id` and format but not the caller-supplied `file_path`; the exact path remains in the extension-owned raw source manifest. Manual event details are user-controlled and documentation must warn callers not to include secrets or machine-local paths intended to remain private.
373
+
374
+ ### Log template
375
+
376
+ ```markdown
377
+ # Wiki Update Log
378
+
379
+ ## 2026-08-02
380
+
381
+ - **capture**: {"source_id":"SRC-2026-08-02-001"}
382
+ - **bootstrap**: {"mode":"personal","topic":"AI Engineering"}
383
+ ```
384
+
385
+ ### Generation rules
386
+
387
+ - Parse events in source line order and retain each line number as sequence.
388
+ - A malformed JSON line, missing timestamp, invalid timestamp, or empty kind is a diagnostic and is omitted from the projection.
389
+ - Group valid events by UTC date derived from timestamp.
390
+ - Sort date groups newest first.
391
+ - Within a date, sort timestamp newest first; ties use source sequence newest first.
392
+ - Render `kind` as plain text inside `**...**`, escaping backslash, `*`, `_`, `[`, `]`, and collapsing line breaks to one space.
393
+ - Render all fields except `timestamp` and `kind` as canonical JSON with recursively sorted object keys, no insignificant whitespace, and JSON array order preserved.
394
+ - Omit the colon and details when no additional fields exist.
395
+ - Emit LF line endings and exactly one final newline.
396
+
397
+ `meta/log.md` may retain its existing richer internal rendering for backward compatibility. Both logs derive from the same events and neither is authoritative.
398
+
399
+ ## Projection Rebuild Semantics
400
+
401
+ A rebuild computes all outputs in memory before replacing any generated file.
402
+
403
+ If any concept has malformed frontmatter, normalized identity collision, or unsupported explicit mode/version:
404
+
405
+ - return a blocking diagnostic
406
+ - preserve the previous registry, backlinks, indexes, and logs
407
+ - do not publish a partial metadata generation
408
+
409
+ Unresolved links and malformed event lines are non-blocking projection diagnostics: valid concepts may still be indexed, and valid event lines may still be projected. A missing or unreadable `meta/events.jsonl` is different from a present empty stream. Rebuild reports `event_source_missing` or `event_source_unreadable`, continues publishing registry, backlink, and index projections, and leaves existing `meta/log.md` and `wiki/log.md` byte-identical. A present zero-byte event file is an explicitly empty authoritative stream and generates the normal empty log projections.
410
+
411
+ Non-blocking diagnostics include:
412
+
413
+ - `link_unresolved`
414
+ - `event_invalid_json`
415
+ - `event_source_missing`
416
+ - `event_source_unreadable`
417
+
418
+ On successful rebuild:
419
+
420
+ 1. write temporary projection files
421
+ 2. atomically rename each individual file
422
+ 3. update registry/backlinks before optional embedding refresh
423
+ 4. schedule embedding refresh only after metadata succeeds
424
+
425
+ Multi-file crash recovery is not introduced in Foundation because these outputs are derived and fully rebuildable. Interchange transactions apply only to authoritative concept changes.
426
+
427
+ ## Guardrails
428
+
429
+ In `okf-0.2` mode, direct model edits are blocked for:
430
+
431
+ - `.llm-wiki/wiki/index.md`
432
+ - every generated `.llm-wiki/wiki/**/index.md`
433
+ - `.llm-wiki/wiki/log.md`
434
+
435
+ The block message directs callers to `wiki_rebuild_meta` or the page-producing tool that owns the source mutation.
436
+
437
+ In legacy mode, Foundation does not newly claim ownership of `wiki/index.md` or `wiki/log.md` because they may be user files.
438
+
439
+ Existing protection for `raw/**` and `meta/**` remains unchanged.
440
+
441
+ ## Pi and MCP Integration
442
+
443
+ Foundation adds no separate business logic to command handlers or MCP handlers.
444
+
445
+ Shared service functions own:
446
+
447
+ - mode resolution
448
+ - parsing and serialization
449
+ - page discovery
450
+ - link resolution
451
+ - registry/backlink construction
452
+ - index/log projection
453
+
454
+ The current MCP surface has five operations; Foundation maps them exactly:
455
+
456
+ | MCP operation | Shared behavior required |
457
+ |---|---|
458
+ | `wiki_recall` | Uses shared mode resolution, registry entries, concept IDs, titles, descriptions, and page parsing. Interface-specific vault selection and rendering may differ from Pi. |
459
+ | `wiki_search` | Uses the same generated registry schema and type/title/extension metadata as Pi `wiki_search`. |
460
+ | `wiki_status` | Reports resolved `knowledge_format`, page counts, and blocking projection diagnostics from shared status data. |
461
+ | `wiki_retro` | Creates its source page through the same canonical new-document serializer as Pi `wiki_retro`. |
462
+ | `wiki_capture_source` | Creates its skeleton source page through the same canonical new-document serializer as the Pi capture tool. |
463
+
464
+ Foundation adds no MCP read operation. Behavioral parity means that, after selecting the same vault and invoking equivalent operations, Pi and MCP expose the same concept identity and parsed metadata and route writes through the same services. UI text, automatic context injection, and vault-selection transport remain interface-specific.
465
+
466
+ Parity is tested through shared service fixtures plus thin interface tests; MCP does not reimplement parsing, registry scoring fields, or page serialization.
467
+
468
+ ## Operation Table
469
+
470
+ | Operation | Mode/input | Authoritative state change | Generated result |
471
+ |---|---|---|---|
472
+ | Bootstrap new vault | No config | Persist `knowledge_format: okf-0.2`; create normal scaffolding | Build meta projections plus `wiki/index.md` and `wiki/log.md` |
473
+ | Open old vault | Mode field absent | None | Resolve as legacy |
474
+ | Create page in old vault | Legacy | Write one OKF-canonical concept and append the same mode-independent event after success | Rebuild only `meta/**`; do not create wiki reserved files |
475
+ | Create page in new vault | OKF 0.2 | Write one OKF-canonical concept and append the same mode-independent event after success | Rebuild `meta/**`, directory indexes, and root log |
476
+ | Manual valid page edit | Either | Existing file edit | End-of-turn rebuild appropriate to mode; no fabricated event |
477
+ | Rebuild with malformed page | Either | None | Return diagnostics; retain previous projections |
478
+ | Rebuild with unresolved link | Either | None | Publish valid projections and report unresolved link |
479
+ | Config has unknown mode | Invalid | None | Blocking mode diagnostic; no writes |
480
+ | OKF root declares unsupported version | OKF 0.2 | None | Blocking version diagnostic; no writes |
481
+ | Read unknown concept type | Either | None | Treat as generic concept and preserve type |
482
+
483
+ ## Diagnostics
484
+
485
+ Foundation uses stable codes:
486
+
487
+ - `config_invalid_knowledge_format`
488
+ - `frontmatter_missing`
489
+ - `frontmatter_parse_error`
490
+ - `frontmatter_duplicate_key`
491
+ - `frontmatter_alias_forbidden`
492
+ - `frontmatter_custom_tag_forbidden`
493
+ - `frontmatter_multiple_documents`
494
+ - `frontmatter_limit_bytes`
495
+ - `frontmatter_limit_depth`
496
+ - `concept_missing_type`
497
+ - `concept_identity_collision`
498
+ - `concept_reserved_name`
499
+ - `okf_version_mismatch`
500
+ - `link_path_escape`
501
+ - `link_unresolved`
502
+ - `event_invalid_json`
503
+ - `event_invalid_timestamp`
504
+ - `event_missing_kind`
505
+
506
+ Each diagnostic includes severity, code, file path, and message. Frontmatter diagnostics include line/column when provided safely by the parser.
507
+
508
+ ## Testing
509
+
510
+ ### Parser and serializer
511
+
512
+ - nested `sources`, `generated`, `verified`, and Attested Computation fields
513
+ - unknown nested producer fields
514
+ - CRLF input and LF output
515
+ - duplicate key, alias, custom tag, multiple document, byte-limit, and depth-limit rejection
516
+ - scalar timestamps remain scalar values
517
+ - parse/serialize semantic round trip
518
+ - exact non-empty-body separator and final newline
519
+ - exact empty-body output with no separator blank line
520
+ - documented handling of additional leading body blank lines
521
+
522
+ ### Mode behavior
523
+
524
+ - missing field resolves old vault to legacy
525
+ - new bootstrap persists OKF mode
526
+ - unknown or malformed explicit mode fails closed
527
+ - legacy mode never generates reserved wiki files
528
+ - OKF mode generates and protects reserved files
529
+ - OKF-canonical pages remain readable in legacy mode
530
+ - unsupported root version blocks OKF-mode rebuild
531
+
532
+ ### Identity and links
533
+
534
+ - Unicode NFC identity normalization
535
+ - case-fold and normalization collision detection
536
+ - reserved filename detection
537
+ - CommonMark inline and full/collapsed/shortcut reference links
538
+ - images, autolinks, HTML, footnotes, code spans/blocks, escapes, and unused reference definitions excluded from backlinks
539
+ - root-relative, file-relative, fragment, query, and percent-encoded Markdown links
540
+ - bundle escape rejection
541
+ - wikilink compatibility
542
+ - mixed-link backlink deduplication
543
+
544
+ ### Index fixtures
545
+
546
+ Golden fixtures cover:
547
+
548
+ - empty bundle
549
+ - root concepts only
550
+ - nested directories
551
+ - title/description fallback
552
+ - Unicode paths and labels
553
+ - Markdown escaping and URI encoding
554
+ - deterministic order independent of file enumeration order and locale
555
+ - pruning obsolete generated indexes
556
+
557
+ ### Log fixtures
558
+
559
+ Golden fixtures cover:
560
+
561
+ - empty event stream
562
+ - multiple UTC dates
563
+ - equal timestamps with sequence tie-break
564
+ - recursively sorted detail keys
565
+ - arrays preserving order
566
+ - malformed lines omitted with diagnostics
567
+ - deterministic output independent of object insertion order
568
+
569
+ ### Integration
570
+
571
+ - every page producer routes through shared serialization
572
+ - registry, backlinks, recall readers, embeddings, Pi tools, and MCP consume shared documents
573
+ - malformed authoritative input preserves previous projections
574
+ - unresolved links do not prevent valid projection publication
575
+ - existing tests remain green
576
+
577
+ ## Acceptance Criteria
578
+
579
+ Foundation is complete when:
580
+
581
+ 1. Every existing and new page producer uses the shared document API.
582
+ 2. Existing vaults open in legacy mode without creating `wiki/index.md` or `wiki/log.md`.
583
+ 3. New vaults declare `okf-0.2` and contain conformant deterministic reserved files.
584
+ 4. Nested OKF v0.2 metadata and unknown fields parse and round-trip semantically.
585
+ 5. Markdown links and legacy wikilinks both produce correct backlinks.
586
+ 6. Projection output matches golden fixtures byte-for-byte.
587
+ 7. Invalid explicit mode/version or malformed concepts cannot replace a known-good registry with partial metadata.
588
+ 8. Pi and MCP readers return equivalent shared-model results.
589
+ 9. Package tests, typecheck, lint, and coverage gates pass.
590
+
591
+ ## Planning Boundary
592
+
593
+ The implementation plan for Foundation must stop at these acceptance criteria. It must not add import, export, migration, transaction journals, trust weighting, graph UI, git snapshots, or expanded extraction adapters.