# Knowledge domain — schema

The knowledge domain is the durable, authoritative current-state documentation of the homelab:
narrative for every node and cross-cutting system, synthesized from live state and evidence. It
answers "what exists and how does it work right now."

It follows the [LLM Wiki layer model](../../shared/llm-wiki.md) and the
[writing-style](../../shared/writing-style.md) and [page-templates](../../shared/page-templates.md)
rules.

## Source of truth — the database

Per ADR 0003, the Postgres database is the single source of truth for all structured data **and**
narrative knowledge. The narrative/substrate split of the Python era is gone: the DB holds both the
structured graph (entities, relationships, status, metrics) and the narrative layer (documents,
investigations, runbooks) in the `knowledge_entities` table.

| Concern | Where it lives | How it gets there |
|---------|----------------|-------------------|
| Knowledge content — documents, investigations, runbooks | `knowledge_entities` table (rows linked to `entities` via `documents` / `about` edges) | Seeded from `seeds/knowledge.yaml` at deploy; mutated at runtime via the API |
| Seed manifest (bootstrap + DR) | `seeds/knowledge.yaml` | Hand-edited or regenerated; ingested idempotently (content-hashed via `seed_versions`) |
| Structured graph — hosts, services, entity types, relationships | `entities`, `relationships`, `entity_types` tables | Seeded from `seeds/{ontology,inventory}.yaml`; mutated via API/MCP |
| Archived narrative wiki (read-only history) | `archive/knowledge/` | Frozen 2026-07-07 when the DB became source of truth |

### Seed ingest

`seeds/knowledge.yaml` has three top-level lists — `documents`, `investigations`, `runbooks` — each
entry carrying `slug`, `title`, `content` (markdown), and tags. `internal/knowledge/seed.go`
ingests each entry by:

1. `getOrCreateEntity` — ensures the slug exists in `entities` (type `document` / `investigation` /
   `runbook`).
2. `upsertKnowledgeEntity` — writes the markdown body into `knowledge_entities`, keyed by
   `content_hash` so re-ingest is a no-op when nothing changed.
3. `createEdge` — links the knowledge entity to its subject(s) via `documents` (for `document`) or
   `about` (for `investigation`) edges. Runbooks bind to an `entity_type` via `applies_to_type`
   rather than to a single entity.

### Runtime mutation

Agents register or update knowledge through the API, not by editing the seed:

- `POST /api/v1/knowledge/{entity_slug}` — upsert a document/investigation on an entity
  (`upsert_knowledge` MCP tool).
- `update_entity_attributes` — merge a discovered fact (IP, version, port) into an entity.
- `create_relationship` — record a discovered edge (`depends-on`, `hosts`, `routes-to`).

> **Export gap.** `oikos export` regenerates `seeds/{ontology,inventory,policy}.yaml` from the DB
> for version control, but **not** `seeds/knowledge.yaml`. Knowledge added via the API today lives
> only in the DB until someone hand-edits the seed. Tracked as a follow-up.

## Knowledge kinds

- **Documents** (`document` entities, linked via `documents` edges) — node and cross-cutting
  narrative pages. Carry `at_glance` (structured attributes) and a parsed `changelog`. Follow the
  container / cross-cutting templates in [page-templates.md](../../shared/page-templates.md).
- **Investigations** (`investigation` entities, linked via `about` edges) — incident evidence,
  written once at incident time. Sections: `## Summary`, `## Timeline`, `## Root cause`,
  `## Mitigations applied`, `## Open questions`.
- **Runbooks** (`runbook` entities, bound by `applies_to_type`) — repeatable procedures. Carry
  `risk_class` and a JSON-schema-validated `procedure`. **Runbooks also live as `SKILL.md` files
  under `.agents/skills/<name>/`** — the DB row is the policy/lifecycle framing, the SKILL.md is
  the executable procedure the agent loads. See
  [the operations schema](../operations/schema.md).

## The two logs

- The per-document **`## Changelog`** records infrastructure changes to that node. Keep the
  `### YYYY-MM-DD — title` shape so the parsed `changelog` field stays structured.
- **`archive/knowledge/log.md`** is the append-only record of *documentation-maintenance*
  operations on the legacy wiki (restructures, source ingests, lint sweeps):
  `## [YYYY-MM-DD] <op> | <summary>`. It is frozen with the rest of `archive/knowledge/`; new
  doc-maintenance operations are recorded in the DB audit trail instead.

## Querying knowledge

Use MCP, not grep:

- `search_knowledge(query)` — ILIKE search over documents, investigations, and runbooks in
  `knowledge_entities`.
- `get_entity_knowledge(entity_slug)` — every document, investigation, and runbook linked to one
  entity, in one call.
- `get_entity(slug)` / `get_relations(entity)` — the structured graph around an entity.

Grep the clone only when MCP is unreachable, and prefer `archive/knowledge/` for historical
narrative (it is not updated when the DB changes).

## Same-session update rule

A change to a node updates the DB in the same session — the entity's attributes, the relationships
that reference it, and any document whose `at_glance` or changelog should reflect the new state. See
[page-templates.md](../../shared/page-templates.md#same-session-update-rule) for the legacy wiki
equivalent (now scoped to `archive/knowledge/` history).
