ADR-0059: Hot cache read path
Architecture decision record 0059 — distinct MemoryHotCacheReader (not find_similar hijack), top-50 atomic trim, hydrate-time filtering, deferred HTTP.
ADR-0059: Hot cache read path
- Status: Accepted
- Date: 2026-08-29
- Authors: IBEX Harness team
- Milestone: 3.D.3 Hot cache (Redis sorted set)
Context
Milestone 3.C.5 / ADR-0057 writes per-agent hot sorted sets ({org_id}:hot_memories:{agent_id}) on memory create using composite_score() with relevance=1.0 (no query at write time). Before 3.D.3:
- No trim — ZSETs grew unbounded past the spec'd top-50 capacity.
- No read consumer — hot cache was write-only; context assembly's parallel retrieval design (ARCHITECTURE.md) expects a distinct hot-memory source separate from semantic search.
Options Considered
1) Blend hot cache into find_similar() as cache-first semantic search
Pros: Single read API for callers.
Cons: Hot ZSET scores lack query relevance (relevance=1.0 at write time). Serving cache hits as semantic search results would return frequently-accessed but query-irrelevant memories — violates POST /v1/memories/search contract. Conflicts with Phase 3.5 parallel retrieval (hot + cold are separately budgeted inputs).
2) Distinct MemoryHotCacheReader.get_hot_memories() (chosen)
Pros: Matches context assembly architecture; preserves semantic search contract; service-layer API ready for Phase 3.5.C.2 and Track E ISO-* tests without proxy changes (Phase 3 exit #10).
Cons: No HTTP surface in 3.D.3 (deferred like VectorStore before 3.D.1).
Decision
- Read API:
MemoryHotCacheReader.get_hot_memories(HotMemoryQuery)—ZREVRANGE+ Postgres hydrate withorg_id+agent_iddefense-in-depth filters.find_similar()unchanged. - HTTP: Deferred — internal service API only until Phase 3.5 context assembly consumes it.
- Write trim: Atomic Lua script —
ZADD,ZREMRANGEBYRANK 0 -51,EXPIRE— keeps top 50 by score per write (app/cache/hot_write.py). - Scoring: Reuse
compute_hot_cache_score()→ sharedcomposite_score()/CATEGORY_HALF_LIFE_DAYS(ADR-0057). - Stale members: Hydrate-time filtering (
status='active',deleted_at IS NULL) — stale ZSET members dropped on read. ExplicitZREMon delete/supersede deferred until unified write-path invalidation (Track E GDPR cascade). - Metrics:
ibex_memory_hot_cache_read_total{result="hit|empty|error"}. - Result shape:
MemorySearchResultwithsource="hot_cache";similarity= write-time ZSET composite score (not query relevance).
Consequences
- Phase 3.5.C.2 parallel retriever wires
get_hot_memoriesalongside cold semantic search. - Track E 3.E.1 ISO-* matrix can assert Redis key + hydrate isolation without new HTTP routes.
- Hot cache capacity remains fixed at 50; changing the capacity is out of scope.
Related
- ADR-0057 — write-path ZADD
- ADR-0058 — semantic search (orthogonal)
- 3.5.C.2 Parallel retrieval — consumer milestone
Was this page helpful?
Last updated on