Back to docs
Guide 00

Wiki knowledge engine — schema-governed archives, wikilinks, synthesis

The wiki engine gives each archive a three-layer instruction model: hard rules enforced by code, a per-archive schema prompt (advisory editorial guidelines), and structured fields (persona, purpose, scope). Mental model: schemaPrompt is to the wiki what …

3 min read

The wiki engine gives each archive a three-layer instruction model: hard rules enforced by code, a per-archive schema prompt (advisory editorial guidelines), and structured fields (persona, purpose, scope). Mental model: schemaPrompt is to the wiki what a CLAUDE.md is to a code repo.

Community feature. Operator reference for the Wiki Schema Layer (Phase 187, audited at the v0.25 gate — WIKS-01/02, verified against the live code). Source: docs/WIKI_SCHEMA_LAYER.md (v0.28.1). Provenance rows: FACT-CENSUS.md F-WIKI-1.

The 3-layer model

LayerNatureEnforcementScope
Hard rulesCode-enforced, unconditionalvalidateWritablePath + the always-injected prompt blockEvery archive-bound write path
schemaPromptPer-archive editorial guidelinesData + prompt only (never a gate)Per archive, opt-in (empty = off)
Structured fieldsConfig-injected persona/purpose/scopeThe existing synthesis/orchestrator behaviorPer archive, unchanged

Hard rules (code-enforced)

Two unconditional mechanisms, config-independent:

  1. The filesystem guard. validateWritablePath (packages/server/src/utils/archivePath.ts:39-54) rejects any write target outside <archiveBase>/wiki/: the anti-traversal check runs first (validateArchivePath), then the wiki/-prefix check — a target outside wiki/ throws Write target outside wiki/ directory: <path>. raw_sources/ is immutable. Both createPage and updatePage call it before any fs.writeFile. No API endpoint writes under raw_sources/ — it is immutable by design.
  2. The prompt-layer mirror. HARD_RULE_RAW_SOURCES (archiveConfigService.ts:52-53) is an always-on block appended to every archive-bound prompt: its wording mirrors the guard (raw_sources/ is immutable), so the model never even attempts the way out of wiki/ — and if it did, the code guarantees nothing lands.

schemaPrompt (advisory)

A free-text field persisted inside the archive's config JSON:

  • Schema: schemaPrompt: z.string().max(10000).optional() on archiveConfigSchema — an additive key, zero migrations. 10000 chars ≈ ~2500 tokens.
  • Validation: Zod on every write (PUT /api/archives/:id/config); an over-cap payload → 400 { error: "Invalid config", details.schemaPrompt }.
  • Read contract: GET /api/archives/:id/config on an archive with no stored row → 200 with the schema-default config ({ rawSourcesImmutable: true }): the first-save hydration path; archives with a row return the stored blob verbatim.
  • The injection-time cap: stored legacy blobs over 10000 chars are truncated at injection with the (truncated at 10000 characters) annotation — legacy rows are never re-validated on read.
  • Advisory by design: the block enters as DATA with an explicit advisory label, never as a system-prompt privilege grant. No sanitization beyond the length cap; contradictory instructions = an accepted quality risk, mitigated by the UI's helper text and template.

Precedence

text
hard rules (code) > schemaPrompt (advisory) > structured fields
  1. schemaPrompt can never override the hard rules (the prompt declares it; the code enforces it).
  2. On conflict with the structured fields, schemaPrompt wins (On conflict with the structured fields (persona, purpose, scope), these guidelines take precedence over them.).
  3. An archive without schemaPrompt behaves as baseline + the hard rule — zero enhancement, zero degradation (no empty placeholder sections in prompts).

Where the block lands in the prompt

SeamWhereNotes
Chat orchestrator (non-streaming)orchestrator.ts:295-302 (runAgent)hard rule ALWAYS + the advisory block when present
Chat orchestrator (streaming)orchestrator.ts:805-812 (runAgentStreaming)the streaming twin, the same order
Synthesis Pass 4 (decision)synthesisStages.ts:784-788the advisory block rides the SYSTEM role; Passes 1/2 and the contradiction judging stay undefined

Inside the system prompt: after the MANDATORY SEARCH RULE block, before the systemPrompt ternary.

wiki_query and wiki_write

The builtins wiki_query and wiki_write are skills whose execute() paths make no LLM call: the write path generates deterministic previews (wikiWriteService.ts contains zero LLM invocations) — per-skill injection would reach no model; the only LLM-facing surface is the orchestrator system prompt.

rawSourcesImmutable

rawSourcesImmutable: boolean (default true) on archiveConfigSchema is a documentation flag, never an enforcement toggle: the immutability rule applies regardless of the flag (the validateWritablePath guard + the always-on block guarantee it).

This guide covers the operator surface for the wiki knowledge engine; the engineering deep dive lives in the twin post:

Provenance

SectionSource
The 3-layer model / hard rulesdocs/WIKI_SCHEMA_LAYER.md (§ The 3-layer model, § Layer 1) — F-WIKI-1
schemaPrompt / precedence / seamsdocs/WIKI_SCHEMA_LAYER.md (§ Layer 2, § Precedence chain, § Injection seams)
AuditPhase 187 commits; finalized at the v0.25 gate (WIKS-01/02, Phase 194)

---

Operator reference — Simmetric Chat v0.28.1 (docs refreshed 2026-10-02, census SHA `aca5b8ff`).