Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion apps/elf-api/src/routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ struct KnowledgePageRebuildBody {
page_key: String,
title: Option<String>,
#[serde(default)]
doc_ids: Vec<Uuid>,
#[serde(default)]
doc_chunk_ids: Vec<Uuid>,
#[serde(default)]
note_ids: Vec<Uuid>,
#[serde(default)]
event_ids: Vec<Uuid>,
Expand Down Expand Up @@ -3286,6 +3290,8 @@ async fn knowledge_page_rebuild(
page_kind: payload.page_kind,
page_key: payload.page_key,
title: payload.title,
doc_ids: payload.doc_ids,
doc_chunk_ids: payload.doc_chunk_ids,
note_ids: payload.note_ids,
event_ids: payload.event_ids,
relation_ids: payload.relation_ids,
Expand Down Expand Up @@ -4045,7 +4051,7 @@ mod tests {
assert!(html.contains("Providers And Ranking"));
assert!(html.contains("Relation Context"));
assert!(html.contains("Knowledge Page Snippets"));
assert!(html.contains("Derived page: source notes"));
assert!(html.contains("Derived page: source documents"));
assert!(html.contains("directTraceId"));
assert!(html.contains("trace_id"));
assert!(html.contains("loadInitialTrace"));
Expand Down
2 changes: 1 addition & 1 deletion apps/elf-api/static/viewer.html
Original file line number Diff line number Diff line change
Expand Up @@ -1157,7 +1157,7 @@ <h2>Recent Traces</h2>
["status", page.status],
["updated_at", dateText(page.updated_at)],
["rebuilt_at", dateText(page.rebuilt_at)],
["derived notice", "Derived page: source notes, events, relations, and proposals remain authoritative."]
["derived notice", "Derived page: source documents, spans, memory notes, events, relations, and proposals remain authoritative."]
]),
make("div", { className: "split-stack", style: "margin-top: 12px;" }, [
make("div", { className: "title", text: "Source coverage" }),
Expand Down
2 changes: 2 additions & 0 deletions apps/elf-eval/src/bin/real_world_live_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4645,6 +4645,8 @@ async fn materialize_elf_knowledge(
page_kind: KnowledgePageKind::Project,
page_key,
title: Some(loaded.job.title.clone()),
doc_ids: Vec::new(),
doc_chunk_ids: Vec::new(),
note_ids: note_ids.clone(),
event_ids: Vec::new(),
relation_ids: Vec::new(),
Expand Down
13 changes: 6 additions & 7 deletions docs/spec/agent_memory_knowledge_system_v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@ tags:
- spec
- agent-memory
- knowledge
source_refs:
source_refs: []
code_refs:
- Makefile.toml
related:
- docs/evidence/benchmarking/2026-06-20-agent-knowledge-os-closeout-benchmark-report.md
- docs/evidence/benchmarking/2026-06-22-p1-memory-authority-closeout-report.md
- docs/runbook/benchmarking/real_world_agent_memory_benchmark.md
- docs/spec/real_world_agent_memory_benchmark_v1.md
- docs/spec/system_elf_memory_service_v2.md
code_refs:
- Makefile.toml
related:
- docs/spec/system_elf_memory_service_v2.md
- docs/spec/system_knowledge_pages_v1.md
- docs/spec/system_recall_debug_panel_v1.md
- docs/spec/system_graph_memory_postgres_v1.md
Expand Down Expand Up @@ -64,7 +63,7 @@ The product is composed of six typed layers:
| --- | --- | --- |
| Source Library | Captured documents, excerpts, imports, and source refs. | Sources remain evidence. Derived memory and pages must cite sources instead of replacing them. |
| Memory Authority | Notes, core blocks, ingest decisions, history, corrections, and rollback evidence. | Memory writes are policy-gated, evidence-linked, auditable, and reversible. |
| Knowledge Workspace | Derived project, entity, concept, issue, and decision pages. | Pages are rebuildable derived artifacts with citations, lint, and stale-source detection. |
| Knowledge Workspace | Derived project, entity, concept, issue, decision, author, and timeline pages. | Pages are rebuildable derived artifacts with citations, lint, and stale-source detection. |
| Graph-lite Facts | Postgres-backed relation facts and temporal markers. | Graph facts are source-backed context, not a separate authority store. |
| Dreaming Review | Reviewable consolidation, summary, brief, tag, correction, and promotion proposals. | Derived proposals must be reviewable and must not mutate sources without an explicit accepted transition. |
| Recall Debug | Search traces, dropped candidates, source/doc/page/graph/proposal rows, and replay aids. | Recall must expose why context was selected, dropped, unavailable, blocked, or not requested. |
Expand Down Expand Up @@ -151,7 +150,7 @@ implement every item in a phase at once.
| --- | --- | --- | --- |
| P0 | Product contract and phase gate | Codify this product boundary, roadmap, competitor absorption rules, validation expectations, and closeout checklist. | Docs are reviewed, repo docs validation passes, claim boundaries match the June 20 closeout evidence, and the main thread accepts the next phase. |
| P1 | Memory Authority MVP loop | Deliver one source-backed memory-authority vertical slice: capture source evidence, create/review one proposal through a proposal inbox, record the authority ledger, apply/correct/rollback, recall through agent-facing tools, and debug stale/correction behavior. | The slice has service tests, provenance/history evidence, recall/debug readback, and at least one real-world stale/correction benchmark job. |
| P2 | Knowledge Workspace | Promote source-linked project/entity/concept/timeline pages with rebuild, lint, watch, search, and version-diff readback. | Pages stay derived, every section is cited or explicitly unsupported, stale-source lint runs, and benchmark reports publish citation/staleness metrics. |
| P2 | Knowledge Workspace | Promote source-linked project/entity/concept/issue/decision/author/timeline pages with rebuild, lint, watch, search, and version-diff readback. | Pages stay derived, every section is cited or explicitly unsupported, stale-source lint runs, and benchmark reports publish citation/staleness metrics. |
| P3 | Competitor-strength adapters | Add contained comparison adapters for qmd replay, PageIndex/OpenKB, mem0/OpenMemory, Letta, Graphiti/Zep, OpenViking, graph/RAG references, and other accepted deltas. | Each adapter preserves typed non-pass states and emits same-corpus evidence before any parity, win, tie, or loss claim. |
| P4 | Benchmark and quality hardening | Expand adversarial jobs, public comparison grammar, quality metrics, latency/cost/resource reporting, and unsupported-claim detection. | Reports preserve job/suite/project typed states, expected evidence recall, irrelevant context ratio, unsupported claims, and resource metrics. |
| P5 | Productization | Improve local setup, agent recipes, operator UI, privacy/delete/export boundaries, and production-quality workflows. | Operator workflows have documented setup, privacy/delete/export semantics, and validation evidence without weakening source authority. |
Expand Down
51 changes: 42 additions & 9 deletions docs/spec/system_knowledge_pages_v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,31 @@ resource: docs/spec/system_knowledge_pages_v1.md
status: active
authority: normative
owner: spec
last_verified: 2026-06-18
last_verified: 2026-06-22
tags:
- docs
- spec
source_refs: []
code_refs: []
code_refs:
- packages/elf-domain/src/knowledge.rs
- packages/elf-service/src/knowledge.rs
- packages/elf-storage/src/knowledge.rs
- sql/tables/035_knowledge_pages.sql
- sql/tables/037_knowledge_page_source_refs.sql
related: []
drift_watch:
- docs/spec/system_knowledge_pages_v1.md
- packages/elf-domain/src/knowledge.rs
- packages/elf-service/src/knowledge.rs
- packages/elf-storage/src/knowledge.rs
- sql/tables/035_knowledge_pages.sql
- sql/tables/037_knowledge_page_source_refs.sql
---
# Derived Knowledge Pages v1 Specification

Purpose: Define derived knowledge page storage, rebuild, citation, and lint contracts.
Purpose: Define derived knowledge page storage, rebuild, citation, source-span, and lint contracts.
Status: normative
Read this when: You are implementing, validating, or reviewing project/entity/concept/issue/decision page rebuild behavior.
Read this when: You are implementing, validating, or reviewing project/entity/concept/issue/decision/author/timeline page rebuild behavior.
Not this document: Viewer integration, search ranking, live LLM page generation, or source-note mutation.
Defines: `elf.knowledge_page/v1` pages, sections, source refs, lint findings, and deterministic rebuild metadata.

Expand Down Expand Up @@ -52,9 +62,13 @@ Allowed `knowledge_pages.page_kind` values:
- `concept`
- `issue`
- `decision`
- `author`
- `timeline`

Allowed `knowledge_page_source_refs.source_kind` values:

- `doc`
- `doc_chunk`
- `note`
- `event`
- `relation`
Expand All @@ -76,6 +90,7 @@ The normalized source ref must preserve:

- `source_kind`
- `source_id`
- Source Library document id and chunk/span locator when `source_kind = "doc_chunk"`
- source status when available
- source `updated_at` or equivalent freshness timestamp when available
- source content hash when available
Expand All @@ -87,6 +102,8 @@ The v1 rebuild path is deterministic for the same explicit source snapshot.

Rebuild input sources may include:

- active Source Library `doc_documents`
- active Source Library `doc_chunks` as cited source spans
- active or historical `memory_notes`
- durable `add_event` audit rows from `memory_ingest_decisions`
- `graph_facts` plus `graph_fact_evidence`
Expand All @@ -110,6 +127,9 @@ Unreviewed consolidation proposals must not be used as source input for persiste
- `schema = "elf.knowledge_page.rebuild/v1"`
- `source_snapshot_hash`
- `deterministic`
- `generated_by` metadata with actor agent id, runtime path, mode, and per-kind source input counts
- `version_identity` with schema `elf.knowledge_page.version_identity/v1`, page kind, page key, source snapshot hash, content hash, section hashes, and `source_mutation_allowed = false`
- `memory_candidate_policy` with schema `elf.knowledge_page.memory_candidate_policy/v1`, `review_required = true`, `review_surface = "consolidation_proposals"`, allowed memory-promotion apply intents, `direct_memory_ledger_mutation_allowed = false`, and `source_mutation_allowed = false`
- `provider_metadata`
- `allowed_variance`
- `previous_version_diff`
Expand All @@ -122,9 +142,9 @@ unchanged section key lists and counts, a human-readable summary, and
`source_mutation_allowed = false`.

Previous-version diff metadata is rebuild readback metadata, not source content. Page
content hashes must not include `previous_version_diff`; otherwise repeating the same
source rebuild would appear nondeterministic solely because the previous-version
metadata changed.
content hashes must not include `previous_version_diff`, `generated_by`,
`version_identity`, or `memory_candidate_policy`; otherwise repeating the same source
rebuild would appear nondeterministic solely because readback metadata changed.

When future provider-backed or LLM-derived page text is persisted,
`rebuild_metadata.deterministic` must be false unless the provider output is fully
Expand Down Expand Up @@ -160,6 +180,19 @@ advisory and must not mutate source memory.
Lint findings are derived diagnostics. They must not mutate authoritative source
memory.

## Memory Candidate Boundary

Generated knowledge page content may feed memory candidates only through reviewable
consolidation proposals. Knowledge page rebuild, list, detail, search, and lint
readback must not insert, update, delete, deprecate, restore, or enqueue indexing for
`memory_notes`.

When a page section becomes candidate memory, the candidate must be represented as a
`consolidation_proposals` row with `contract_schema = "elf.consolidation/v1"` and
`apply_intent` of `create_derived_note` or `update_derived_note`. Applying that
proposal follows the Memory Promotion Apply Contract in
`system_consolidation_proposals_v1.md`.

## Search and Viewer Readback

Knowledge page search is a derived-artifact readback surface, not the authoritative
Expand All @@ -177,8 +210,8 @@ Page search results must include:
- rebuild metadata, including previous-version diff metadata when present
- lint summary and trust state that distinguishes clean, warning, error, and low
coverage results
- a derived-result notice that source notes, event audits, relation facts, and applied
proposals remain authoritative
- a derived-result notice that source documents, spans, approved memory notes, event
audits, relation facts, and applied proposals remain authoritative
- repair or rebuild guidance when lint or source coverage indicates stale,
unsupported, missing, or weakly covered content

Expand Down
16 changes: 16 additions & 0 deletions packages/elf-domain/src/knowledge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ pub enum KnowledgePageKind {
Issue,
/// Decision page.
Decision,
/// Author page.
Author,
/// Timeline page.
Timeline,
}
impl KnowledgePageKind {
/// Returns the canonical storage string.
Expand All @@ -35,6 +39,8 @@ impl KnowledgePageKind {
Self::Concept => "concept",
Self::Issue => "issue",
Self::Decision => "decision",
Self::Author => "author",
Self::Timeline => "timeline",
}
}

Expand All @@ -46,6 +52,8 @@ impl KnowledgePageKind {
"concept" => Some(Self::Concept),
"issue" => Some(Self::Issue),
"decision" => Some(Self::Decision),
"author" => Some(Self::Author),
"timeline" => Some(Self::Timeline),
_ => None,
}
}
Expand All @@ -55,6 +63,10 @@ impl KnowledgePageKind {
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum KnowledgeSourceKind {
/// Source Library document source.
Doc,
/// Source Library document chunk or span source.
DocChunk,
/// Memory note source.
Note,
/// Event source reserved for future durable event rows.
Expand All @@ -68,6 +80,8 @@ impl KnowledgeSourceKind {
/// Returns the canonical storage string.
pub fn as_str(self) -> &'static str {
match self {
Self::Doc => "doc",
Self::DocChunk => "doc_chunk",
Self::Note => "note",
Self::Event => "event",
Self::Relation => "relation",
Expand All @@ -78,6 +92,8 @@ impl KnowledgeSourceKind {
/// Parses a canonical storage string.
pub fn parse(raw: &str) -> Option<Self> {
match raw {
"doc" => Some(Self::Doc),
"doc_chunk" => Some(Self::DocChunk),
"note" => Some(Self::Note),
"event" => Some(Self::Event),
"relation" => Some(Self::Relation),
Expand Down
Loading