apps/entities: warm caches and memoize obs counts on all-facets path
The all-facets entities listing was re-scanning observations.jsonl line-by-line
and bypassing the in-process entity / relationship caches on every request
(600-950 ms cold, 650-700 ms warm on the founder's journal). Warm both caches
at the API entry and memoize observation counts by (path, mtime_ns).
- think/entities/relationships.py: add load_all_facet_relationships, mirror of
load_all_journal_entities.
- think/entities/observations.py: add count_observations + mtime-keyed
_OBSERVATION_COUNT_CACHE + clear_observation_count_cache.
- apps/entities/routes.py: get_journal_entities_data uses load_all_journal_entities
and warms each facet's relationship cache once before the entity loop;
_get_entity_metadata routes to count_observations.
- think/entities/journal.py: delete_journal_entity now clears the relationship
caches alongside the journal cache (closes a latent invalidation gap surfaced
by warming the cache on read).
- think/entities/__init__.py: export the two new public helpers.
- apps/entities/tests/conftest.py: clear the new cache in all 5 fixture sites.
- apps/entities/tests/test_all_facets_cache.py: prove relationship-cache warm
hits and observation-count mtime invalidation.
No on-the-wire changes; journal-entities / facet-entities / entity-detail API
baselines are unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>