Slice 78 - Structured Page Sources Read Model
Date: 2026-07-01
Scope#
Make structured page sources: part of the Python read model:
- parse supported structured source entries from page frontmatter
- keep page markdown frontmatter as the source of truth
- derive file references from
sources[type=file]sosearch --mentionsworks - project page sources into SQLite as
page_sources - expose sources through
show --meta,show --json, and viewer page APIs - render sources in the local viewer side panel
- add health categories for missing citations, unused sources, and duplicate source ids
This slice does not add migrate legacy-sources, a public sources query
command, source snapshots, web fetching, source-currentness scoring, or the
archive-era review command family.
Why Now#
The live agreement says structured page sources: are not optional prompt
advice. They are the page evidence model. Current Python code only parses legacy
files: and inline file wikilinks, so file-aware search and page readback ignore
canonical sources[type=file] entries.
Shape#
frontmatter = parse_frontmatter(raw)
document = PageDocument(
sources=frontmatter.sources,
file_refs=file_refs_from_legacy_files_and_file_sources(...),
)The SQLite projection remains derived state:
page_sources(page_slug, source_id, source_type, target, title, retrieved_at, note)Viewer and CLI consume PageSource from PageView; they do not reread markdown
frontmatter.
Decisions#
- Supported source types for this slice are
file,web,commit,pr,issue,conversation,wiki, andmanual. targetis a display/query projection. It is not the full typed source object. Type-specific fields stay in frontmatter for now.- File sources derive
file_refs; legacyfiles:still derive refs too. - Duplicate source ids stay visible because
page_sourcesstores every parsed source row with its frontmatter order; health groups by page and source id to report duplicates. - Citation markers are page-local
[@source-id]markers in body prose. - Health warnings are report-only. No migration or body citation insertion is added.
Cosmic Python Transfer#
Chapter 2 says the model should have "no dependencies whatsoever," so page
source normalization belongs in wiki/domain code before SQLite projection.
Chapter 4 says the service layer defines the system use cases; read commands and
viewer APIs should consume the indexed PageView instead of parsing markdown at
the edges. Chapter 6 frames Unit of Work as atomic operations; index replacement
continues to write pages, sources, refs, links, and metadata inside one SQLite
transaction.
Files#
src/codealmanac/services/wiki/models.pysrc/codealmanac/services/wiki/frontmatter.pysrc/codealmanac/services/wiki/documents.pysrc/codealmanac/services/index/models.pysrc/codealmanac/services/index/store.pysrc/codealmanac/services/index/views.pysrc/codealmanac/services/viewer/models.pysrc/codealmanac/services/viewer/service.pysrc/codealmanac/server/assets/viewer/renderers.jssrc/codealmanac/server/assets/viewer/components.jssrc/codealmanac/cli/render/root.py- focused tests under
tests/test_read_model.py,tests/test_topics_health.py,tests/test_viewer_service.py,tests/test_server.py, and public contract docs.
Verification#
Focused:
uv run pytest tests/test_read_model.py tests/test_topics_health.py tests/test_viewer_service.py tests/test_server.py tests/test_public_contract.py
uv run ruff check src/codealmanac/services/wiki src/codealmanac/services/index src/codealmanac/services/viewer src/codealmanac/server src/codealmanac/cli tests/test_read_model.py tests/test_topics_health.py tests/test_viewer_service.py tests/test_server.py tests/test_public_contract.pyBroad:
uv run pytest
uv run ruff check .
git diff --check