Skip to main content
The WARDEN knowledge base (KB) is a single portable SQLite file (one per project), opened with KnowledgeBase("project.db"). The schema is applied (idempotently via CREATE TABLE IF NOT EXISTS) on every open from src/warden/kb/schema.sql, loaded at runtime through importlib.resources. No migration runner is required. Two SQLite PRAGMAs are set at open time: PRAGMA journal_mode = WAL (concurrent readers alongside the single writer, which matters when warden mcp and a local agent run simultaneously) and PRAGMA foreign_keys = ON (version-scoped tables cascade-delete when a module_versions row is removed).
Status: alpha. The schema is functional and exercised end-to-end by warden demo. Additional columns (DWARF source info, wasm2c harness references) are tracked in the roadmap.

The linchpin design choice

Annotations are keyed on a function’s stable content identity, not on a per-version row-ID.
The functions table is the per-version appearance log: it records that function index 42 appeared in version v1 with a given stable_id. The symbols table is the durable annotation layer: it holds names, types, summaries, and evidence keyed on that same stable_id. When a vendor ships v2.wasm and every table index shifts, WARDEN re-ingests and re-fingerprints. A function that was index 42 in v1 might become index 51 in v2, but its stable_id (a composite content hash) stays the same. The annotation in symbols is still there, automatically. That is the carry-over mechanism that makes RE incremental. See core concepts for how stable_id is computed from structural, semantic, fuzzy, and exact fingerprints.

Table reference

meta

Lightweight key/value store for project-level metadata. Accessed via KnowledgeBase.get_meta() and set_meta().

module_versions

One row per ingested .wasm file, representing a point in the target’s version history. The id here is the foreign key anchor for functions, thread_model, and diffs.

functions

The per-version appearance log. Each row records one function as it appeared in one version, with all fingerprinting data needed for identity matching and Oracle lookup. This table does not hold human annotations. Those live in symbols. Unique constraint: (version_id, func_index). One row per function per version. Indices: idx_functions_stable on stable_id; idx_functions_version on version_id; idx_functions_struct on structural_hash.

symbols

The durable annotation layer. Keyed on stable_id so that an annotation created against v1 is automatically present when the same function appears in v2, v3, and beyond. All writes go through KnowledgeBase.upsert_symbol(), which enforces the provenance/confidence economy (see below). Unique constraint: (stable_id, kind). One annotation record per identity per kind.
Never insert directly into symbols. Always go through upsert_symbol(). A direct INSERT bypasses the economy gate and can silently clobber a human-verified, locked annotation.

structs

Recovered memory-region and struct layouts, stored as first-class structured data rather than free-text comments. Written via KnowledgeBase.upsert_struct(), which uses ON CONFLICT(name) DO UPDATE.

thread_model

The concurrency spine: lock-to-guarded-data relationships, atomic sites, TLS references, and worker entry points. Version-scoped because the threading model may change between releases. Written via KnowledgeBase.add_thread_fact(); retrieved via thread_facts(version_id).

oracle_matches

Records of individual Oracle identifications: a function fingerprint matched to a known upstream runtime or libc function. References functions.id (not stable_id), so each match is version-specific: the same logical function may match at a different func_index in each version, generating a separate row. Unique constraint: (function_id, matched_name). An Oracle match is a separate record from the symbols annotation it triggers. warden oracle identify writes both: the match record here, and a symbols row (provenance "oracle") via upsert_symbol.

diffs

Stored cross-version diff reports (the semantic changelogs produced by warden diff). One row per ordered pair of versions. The report column holds the full JSON classification (unchanged, structurally-equivalent, fuzzy-matched, added, removed) and carry-over counts. Unique constraint: (from_version_id, to_version_id).

audit_log

Append-only trail of every symbol write attempt, whether accepted or rejected. Rows are never modified, only inserted. Used to answer “who changed this name and when?” and “why was this agent proposal rejected?”. Retrieve recent entries with KnowledgeBase.audit_log(limit=100).

Deep analysis tables: per-function analysis, renames, and live events

Schema version 2 adds three tables for the per-function deep agent engine. They are created with CREATE TABLE IF NOT EXISTS, so an existing project upgrades in place on the next open.

function_analysis

One row per function (keyed on stable_id, like symbols) holding the distilled per-function understanding that flows up to a parent agent. Raw WASM is re-derived from the module on demand and is never stored here. Read with KnowledgeBase.get_analysis(stable_id) or analyses_for_version(version_id); write with upsert_analysis(...), which is partial (a None field keeps the existing value).

rename_history

Append-only log of every name, variable, and summary change, so the whole session is reversible. add_rename(...) records a change; revert_rename(rename_id) applies the inverse; rename_history_for(stable_id) lists the trail.

agent_events

The live activity feed the UI polls so you can watch the per-function agents work in real time. record_event(...) appends an event; events_since(after_id) returns newer events for polling.

Provenance ranking

Every symbol write carries a provenance label. PROVENANCE_RANK in src/warden/kb/models.py assigns an integer priority that the may_overwrite() gate uses to decide whether a new write may displace an existing annotation.
Any provenance string not present in this dict defaults to rank 10. Human is sovereign at the top; raw agent proposals sit at the bottom. The ranking is also shown in the core concepts table.

The may_overwrite() economy

may_overwrite() in src/warden/kb/models.py is the gatekeeper called by every KnowledgeBase.upsert_symbol() invocation. It receives the new write’s provenance and confidence alongside the existing annotation’s provenance, confidence, and lock state, and returns (allowed: bool, reason: str). The rules, exactly as implemented:
1

Empty slot: always allow

If existing_provenance is None the slot is empty and any write succeeds. Reason: "new symbol".
2

Human write: always allow

If new_provenance == "human" the write wins unconditionally, regardless of what already exists. Reason: "human override". A subsequent lock_symbol() call then sets locked = 1 to protect it.
3

Locked symbol: reject any non-human write

If existing_locked is true and the writer is not "human", the write is rejected. Reason: "existing symbol is locked (human-verified)". The locked flag is set by warden set-name (which locks by default) and by KnowledgeBase.lock_symbol().
4

Agent write: narrow overwrite rights

An agent may only write if one of two conditions holds:
  • The existing annotation is also "agent" and new_confidence > existing_confidence (strictly higher). Reason: "higher-confidence agent write".
  • The existing provenance has a rank strictly below 30 (the agent rank), i.e. an unknown source. Reason: "outranks existing automated source".
An agent can never overwrite oracle, export, import, string-xref, diff-carry, or human annotations. The rejection reason names the existing provenance and its confidence.
5

Other automated sources: rank then confidence

For all other provenances (oracle, export, import, string-xref, diff-carry):
  • Higher rank wins outright.
  • At equal rank, new_confidence >= existing_confidence is required.
  • Otherwise the existing annotation takes precedence.
Rejected writes are not errors. They return (False, reason) and are appended to audit_log with action='rejected'. This lets you re-run the entire agent crew on every update without clobbering any verified human work or high-confidence Oracle annotations.

Example economy decisions


KnowledgeBase API

KnowledgeBase (in src/warden/kb/database.py) is a pure-stdlib sqlite3-backed class that supports the context-manager protocol. Schema is applied idempotently on every open.

Representative calls

coverage_pct is computed over defined functions only (imports excluded from the denominator).
Equivalent to warden set-name <label> <index> <name> (which locks by default).

The kb-text export format

warden export <label> --format kb-text emits a stable, deterministic text dump of every symbol in a version, sorted by func_index. Because the output uses fixed-width fields and a consistent sort, it diffs cleanly in git alongside version-controlled .wasm artifacts.
The lk column is L for locked (human-verified) symbols and a space otherwise. The provenance and conf columns are - for functions that have no symbol record yet.
Commit the kb-text dump to version control after each warden diff run. The resulting git diff shows exactly which names were carried over, which were new, and which remain unnamed. It is a human-readable changelog of your RE progress.

Storage notes

Pure stdlib

KnowledgeBase imports only sqlite3 and json. No C extensions or native dependencies on the core path.

WAL mode

PRAGMA journal_mode = WAL allows concurrent readers alongside the single writer, so warden mcp and a local agent can run simultaneously without blocking each other.

Foreign-key cascade

ON DELETE CASCADE is set on all version-scoped tables. Deleting a module_versions row automatically cleans up functions, oracle_matches, thread_model, and diffs.

JSON columns

Columns such as minhash, histogram, call_targets, inferred_flags, glue_info, evidence, layout, and report store structured data as JSON strings. KnowledgeBase handles serialization transparently; callers work with Python list and dict objects.

Core concepts

How stable_id is computed and why the provenance economy exists.

CLI reference

Commands that read and write the KB: ingest, oracle, agent, diff, export.

MCP reference

Serve KB data to external tools over the Model Context Protocol.
Last modified on June 10, 2026