Architecture
The Git repository's human-readable YAML is authoritative. PostgreSQL and Neo4j are disposable, reproducible query projections. The public application does not edit canonical records.
YAML + JSON Schema + semantic validation
|
CI and review
|
Alembic + atomic import
|
PostgreSQL
|
FastAPI
/ \
JSON API Jinja website
Validated YAML → graph JSON / Cypher → optional Neo4j
Boundaries
The ontology owns stimulus, sensor/receptor, transduction, signal, processing and sensation. Context and candidate percepts describe conditional associations. Appraisal, emotion, decision and action remain outside the core. There is no inference engine or sensor-fusion implementation.
Database projection
entities stores identity, kind, slug, searchable definition, classification and category. A (kind, slug) unique constraint prevents ambiguous lookups. claims stores scoped statements and evidence status. claim_sources is a source-reference join table. relations holds typed edges and a foreign key to the exact claim. dimensions holds quantity, unit, stage and optional numeric bounds. expert_reviews has reviewer and claim foreign keys. dataset_state holds version, schema, content hash, import time and source Git commit.
Species, temporal/spatial metadata, typed source details, context, range definitions and mechanism-specific attributes live in an entity's validated details JSON. This is deliberate schema flexibility: identity, claims and queryable relationships are normalized, while sparse domain-specific attributes avoid hundreds of mostly-null SQL columns. The same Pydantic contract validates reconstruction from SQL.
An import validates the complete dataset before opening a write transaction. PostgreSQL advisory locking serializes imports. Existing entity identities are upserted, dependent projection tables are rebuilt, absent canonical records are removed, and the dataset marker changes in the same transaction. Identical imports return without changes. API versions come from the imported marker, not an environment variable that could mislabel old data.
Runtime
FastAPI and Jinja share the query service. Lists use bounded pagination and batched reconstruction to avoid per-record database queries. SQLAlchemy expressions bind user filters. SQLite is a portable development/test fallback; PostgreSQL is the production target and is exercised by CI and Docker checks. Start containers against a dedicated database; migration privileges are not appropriate for a shared unrelated schema.
For multiple application replicas, run migrations/import as one release job, then start workers directly with Uvicorn. A single container's entrypoint runs these before worker startup. Do not run concurrent schema migrations from multiple replicas.
Future semantic search
A future entity_embeddings table can reference stable entity IDs, content hash, embedding model/version and vector dimension. Build it asynchronously from approved records with pgvector, return provenance with neighbors, and invalidate embeddings on content changes. Embeddings are a discovery aid, not evidence or truth scores. No external model calls are required by v0.1.