Merge pull request #1617 from CREDO23/feature-okf

[Feat] Serve the knowledge base in Open Knowledge Format (OKF)
This commit is contained in:
Rohan Verma 2026-07-21 15:39:59 -07:00 committed by GitHub
commit 08d431454f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 1249 additions and 24 deletions

View file

@ -79,6 +79,33 @@ class TestDocToVirtualPath:
assert path == f"{DOCUMENTS_ROOT}/notes/A.xml"
class TestConceptIdentityRoundTrip:
"""A document's virtual path must parse back to the same (folder, title) - the
OKF path-identity guarantee at the grammar level, no DB required."""
def test_folder_nested_document_roundtrips(self):
index = PathIndex(folder_paths={5: f"{DOCUMENTS_ROOT}/Research/AI"})
path = doc_to_virtual_path(
doc_id=2, title="My Note", folder_id=5, index=index
)
assert path == f"{DOCUMENTS_ROOT}/Research/AI/My Note.xml"
folder_parts, title = parse_documents_path(path)
assert folder_parts == ["Research", "AI"]
assert title == "My Note"
def test_colliding_title_roundtrips_to_base_title(self):
# Second doc with the same title gets a " (<id>)" suffix; parsing the
# path must strip the disambiguator and recover the original title.
index = PathIndex(occupants={f"{DOCUMENTS_ROOT}/Hello.xml": 7})
path = doc_to_virtual_path(
doc_id=8, title="Hello", folder_id=None, index=index
)
assert path == f"{DOCUMENTS_ROOT}/Hello (8).xml"
folder_parts, title = parse_documents_path(path)
assert folder_parts == []
assert title == "Hello"
class TestParseDocumentsPath:
def test_extracts_folder_parts_and_title(self):
parts, title = parse_documents_path(f"{DOCUMENTS_ROOT}/foo/bar/baz.xml")

View file

@ -0,0 +1,44 @@
"""A real export bundle - concepts plus reserved ``index.md``/``log.md`` - must
pass the same ``validate_bundle`` a consumer would run.
"""
from datetime import UTC, datetime
from app.db import Document, DocumentType
from app.services.okf import (
LogEntry,
document_to_concept,
folder_to_index,
folder_to_log,
validate_bundle,
)
def _sample_bundle() -> dict[str, str]:
note = Document(
title="Weekly Sync",
document_type=DocumentType.NOTE,
document_metadata={"tags": ["team"]},
updated_at=datetime(2026, 5, 28, tzinfo=UTC),
)
page = Document(title="Docs Home", document_type=DocumentType.CRAWLED_URL)
return {
"weekly-sync.md": document_to_concept(note, body="# Agenda"),
"docs-home.md": document_to_concept(page, body="content"),
# Reserved files carry no frontmatter and must be exempt from the check.
"index.md": folder_to_index(),
"log.md": folder_to_log(
[LogEntry(title="Weekly Sync", timestamp="2026-05-28T00:00:00+00:00")]
),
}
def test_real_export_bundle_is_conformant() -> None:
assert validate_bundle(_sample_bundle()) == {}
def test_audit_flags_a_drifted_concept() -> None:
bundle = _sample_bundle()
bundle["broken.md"] = "no frontmatter at all"
problems = validate_bundle(bundle)
assert list(problems) == ["broken.md"]

View file

@ -0,0 +1,51 @@
"""Every ``DocumentType`` must serialize to a concept a permissive OKF consumer
can read: parseable frontmatter with a non-empty ``type``. Covers all types plus
missing metadata, empty body, and non-ASCII titles.
"""
from datetime import UTC, datetime
import pytest
from app.db import Document, DocumentType
from app.services.okf import document_to_concept, is_conformant_concept
from app.services.okf.validator import (
RECOMMENDED_FRONTMATTER_KEYS,
REQUIRED_FRONTMATTER_KEYS,
)
@pytest.mark.parametrize("document_type", list(DocumentType))
def test_every_document_type_serializes_to_conformant_concept(
document_type: DocumentType,
) -> None:
doc = Document(
title="Sample",
document_type=document_type,
document_metadata={"url": "https://example.com/x"},
updated_at=datetime(2026, 5, 28, tzinfo=UTC),
)
assert is_conformant_concept(document_to_concept(doc, body="body"))
def test_conformant_without_metadata_or_body() -> None:
doc = Document(title="Bare", document_type=DocumentType.NOTE)
assert is_conformant_concept(document_to_concept(doc, body=""))
def test_conformant_with_non_ascii_title() -> None:
doc = Document(title="日本語ノート", document_type=DocumentType.NOTE)
concept = document_to_concept(doc, body="本文")
assert is_conformant_concept(concept)
assert "日本語ノート" in concept
def test_contract_marks_only_type_as_required() -> None:
assert REQUIRED_FRONTMATTER_KEYS == ("type",)
assert set(RECOMMENDED_FRONTMATTER_KEYS) == {
"title",
"description",
"resource",
"tags",
"timestamp",
}

View file

@ -0,0 +1,31 @@
"""A ConnectorDocument (the indexing write door) must serialize to a valid OKF
concept. Per-``DocumentType`` conformance lives in ``test_conformance.py``.
"""
from app.db import Document, DocumentType
from app.indexing_pipeline.connector_document import ConnectorDocument
from app.services.okf import document_to_concept, is_conformant_concept
def _document_from(connector_doc: ConnectorDocument) -> Document:
"""Mirror how prepare_for_indexing builds a Document from a ConnectorDocument."""
return Document(
title=connector_doc.title,
document_type=connector_doc.document_type,
source_markdown=connector_doc.source_markdown,
document_metadata=connector_doc.metadata,
)
def test_minimal_connector_document_yields_conformant_concept() -> None:
connector_doc = ConnectorDocument(
title="Bare",
source_markdown="just a body",
unique_id="u1",
document_type=DocumentType.FILE,
workspace_id=1,
created_by_id="user-1",
)
doc = _document_from(connector_doc)
concept = document_to_concept(doc, body=doc.source_markdown)
assert is_conformant_concept(concept)

View file

@ -0,0 +1,130 @@
"""OKF serializer/validator self-checks: emitted concepts stay conformant and the
frontmatter fields consumers rely on (type/title/timestamp) round-trip.
"""
from datetime import UTC, datetime
from app.db import Document, DocumentType
from app.services.okf import (
ConceptRef,
LogEntry,
SubdirRef,
document_to_concept,
folder_to_index,
folder_to_log,
is_conformant_concept,
parse_frontmatter,
validate_concept,
)
def _make_document() -> Document:
return Document(
title="Weekly Sync Notes",
document_type=DocumentType.NOTE,
document_metadata={"tags": ["team", "meeting"], "url": "https://example.com/n"},
updated_at=datetime(2026, 5, 28, 22, 49, 59, tzinfo=UTC),
)
def test_concept_is_conformant_and_roundtrips() -> None:
concept = document_to_concept(_make_document(), body="# Agenda\n\nShip OKF.")
assert is_conformant_concept(concept)
frontmatter, error = parse_frontmatter(concept)
assert error is None
assert frontmatter["type"] == "Note"
assert frontmatter["title"] == "Weekly Sync Notes"
assert frontmatter["tags"] == ["team", "meeting"]
assert frontmatter["resource"] == "https://example.com/n"
# timestamp must survive as an ISO-8601 string, not a parsed datetime.
assert frontmatter["timestamp"] == "2026-05-28T22:49:59+00:00"
assert "# Agenda" in concept
def test_type_is_always_present_even_without_metadata() -> None:
doc = Document(title="Raw", document_type=DocumentType.CRAWLED_URL)
concept = document_to_concept(doc, body="body")
frontmatter, error = parse_frontmatter(concept)
assert error is None
assert frontmatter["type"] == "Web Page"
# No source URL / tags available -> those recommended keys are omitted.
assert "resource" not in frontmatter
assert "tags" not in frontmatter
def test_validator_rejects_non_conformant_documents() -> None:
assert validate_concept("no frontmatter here")
assert validate_concept("---\ntitle: Missing type\n---\nbody")
def test_folder_index_groups_by_type_and_lists_subdirs() -> None:
index = folder_to_index(
concepts=[
ConceptRef(title="Orders", filename="orders.md", type="Note", description="x"),
],
subdirectories=[SubdirRef(name="tables", description="Table docs")],
)
assert "# Subdirectories" in index
assert "* [tables](tables/index.md) - Table docs" in index
assert "# Note" in index
assert "* [Orders](orders.md) - x" in index
def test_folder_log_lists_concepts_newest_first() -> None:
log = folder_to_log(
[
LogEntry(title="Older", timestamp="2026-01-01T00:00:00+00:00"),
LogEntry(title="Newer", timestamp="2026-06-01T00:00:00+00:00"),
LogEntry(title="Undated", timestamp=None),
]
)
assert "# Change Log" in log
# Newest dated entry precedes the older one; undated sorts last.
assert log.index("Newer") < log.index("Older") < log.index("Undated")
assert "* Newer - 2026-06-01T00:00:00+00:00" in log
def test_folder_log_is_empty_when_no_entries() -> None:
assert folder_to_log([]) == ""
def test_export_log_files_synthesized_only_where_docs_live() -> None:
from app.services.export_service import _build_log_files
files = dict(
_build_log_files(
{
"": [LogEntry(title="Root Doc", timestamp="2026-05-01T00:00:00+00:00")],
"Research/AI": [LogEntry(title="Nested", timestamp=None)],
}
)
)
assert "# Change Log" in files["log.md"]
assert "Root Doc" in files["log.md"]
assert "Nested" in files["Research/AI/log.md"]
# No empty intermediate log: "Research" holds no concepts of its own.
assert "Research/log.md" not in files
def test_export_index_files_include_root_version_and_ancestors() -> None:
from app.services.export_service import _build_index_files
# A concept nested two levels deep, with no direct docs in the middle dir.
files = dict(
_build_index_files(
{
"Research/AI": [
ConceptRef(title="Note", filename="note.md", type="Note")
]
}
)
)
# Root, the empty intermediate dir, and the leaf all get an index.md so the
# hierarchy is fully navigable.
assert files["index.md"].startswith('---\nokf_version: "0.1"\n---')
assert "* [Research](Research/index.md)" in files["index.md"]
assert "* [AI](AI/index.md)" in files["Research/index.md"]
assert "* [Note](note.md)" in files["Research/AI/index.md"]