IBEX Harness
DocsBenchmarksBlogChangelogRoadmap
GitHub
IBEX Harness

Documentation

Architecture Decision RecordsADR-0002: Repository foundation bootstrapADR-0003: Branch protection and merge policyADR-0004: Protobuf and code generation policyADR-0005: Postgres migration strategyADR-0006: Auth protobuf contract (`ibex.auth.v1`)ADR-0007: Auth token validation implementationADR-0008: Security scanning and CI quality gatesADR-0009: Permission bitmap layoutADR-0010: Cryptography policyADR-0011: Proxy auth gRPC client and middlewareADR-0012: Proxy request normalization (OpenAI chat)ADR-0013: Proxy input validation and stable error envelopeADR-0014: Core domain migration sequencingADR-0015: Proxy rate limit skeleton (Phase 1)ADR-0016: Proxy agent identity verification (Phase 1)ADR-0017: Request ID and trace context strategy (Phase 1)ADR-0018: Graceful shutdown contract (Phase 1)ADR-0019: OpenTelemetry provider configuration (Phase 1)ADR-0020: Shared package boundaries — `packages/config` and `packages/apierror`ADR-0021: Prometheus Metric Catalog (Phase 1)ADR-0022: Health check contract (Phase 1)ADR-0023: Docs site architecture (Phase 1.5)ADR-0024: Benchmark data publishing modelADR-0025: LLM provider abstractionADR-0026: OpenAI client designADR-0027: Streaming dual-write strategyADR-0028: Auth cache designADR-0029: Token revocation propagation via Redis pub/subADR-0030: Directive versioning strategyADR-0031: System prompt injection strategyADR-0032: Session data model and retentionADR-0033: ClickHouse llm_traces schema and retentionADR-0034: Proxy overhead performance measurement methodologyADR-0035: Chat Idempotency-Key Redis dedupeADR-0038: Context assembly service design and gRPC contractADR-0039: Proxy Postgres ownership for session and directive storesADR-0040: Anthropic provider adapterADR-0041: Model capability registryADR-0042: Self-hosted OpenAI-compatible LLM adapterADR-0043: Tokenizer registry architectureADR-0044: Non-streaming response pipelineADR-0045: Streaming response transformationADR-0046: Embedder interface and profile registryADR-0047: Memory temporal validity foundationADR-0048: Memory multi-label categoriesADR-0049: Memory relationship graph readinessADR-0050: MCP server skeleton (transport, auth, audit)ADR-0051: Local LGTM observability stack (Phase 2.5 exit pull-forward)ADR-0052: Memory schema v2 expand (HNSW, quality columns)ADR-0053: Vector store abstraction and composite scoring v2ADR-0054: In-process Presidio PII detection in memoryADR-0055: Memory write-path exact and near-duplicate dedupADR-0056: Temporal-interval-aware conflict detectionADR-0057: Memory write-path persistence and orchestrationADR-0058: Semantic search FTS fallback triggerADR-0059: Hot cache read pathADR-0060: Memory service tenant isolation architectureADR-0061: Retrieval-quality benchmark methodologyADR-0062: Worker task observability and dead-letter handlingADR-0063: Extraction output schema v2ADR-0064: Extraction provider registry and batch executionADR-0065: Extraction batch idempotency and turn pointer orderingADR-0066: Extraction quality evaluation harnessADR-0067: Context capability catalog generate-and-diff for token budgetsADR-0068: Composite scoring-time relevance gateADR-0069: Context packer bounded DP knapsackADR-0070: Context formatting locked ordering and session nonceADR-0071: Context assembly gRPC degradation ladder and retrieval deadlineADR-0072: Extraction enqueue via worker HTTP (not Celery Redis wire format)ADR-0073: Organization Lifecycle and Cascading SuspensionADR-0074 Provider Credential StorageADR-0075 Per-Org Model Routing PolicyADR-0076: Circuit Breaker per ProviderADR-0077: Provider Fallback RoutingADR-0078: Operator runtime topology & environment contract (4.P.0)ADR-0079: Operator session RS256 dual-verify and TOTP step-upIBEX Console service rename and boundaryADR-0081: Fail-closed Proxy runtime controlsD2 metadata-only trace read contractD2 publication, identity, query, and lifecycle contract
ADRs›ADR-0059: Hot cache read path
ADRs

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:

  1. No trim — ZSETs grew unbounded past the spec'd top-50 capacity.
  2. 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

  1. Read API: MemoryHotCacheReader.get_hot_memories(HotMemoryQuery) — ZREVRANGE + Postgres hydrate with org_id + agent_id defense-in-depth filters. find_similar() unchanged.
  2. HTTP: Deferred — internal service API only until Phase 3.5 context assembly consumes it.
  3. Write trim: Atomic Lua script — ZADD, ZREMRANGEBYRANK 0 -51, EXPIRE — keeps top 50 by score per write (app/cache/hot_write.py).
  4. Scoring: Reuse compute_hot_cache_score() → shared composite_score() / CATEGORY_HALF_LIFE_DAYS (ADR-0057).
  5. Stale members: Hydrate-time filtering (status='active', deleted_at IS NULL) — stale ZSET members dropped on read. Explicit ZREM on delete/supersede deferred until unified write-path invalidation (Track E GDPR cascade).
  6. Metrics: ibex_memory_hot_cache_read_total{result="hit|empty|error"}.
  7. Result shape: MemorySearchResult with source="hot_cache"; similarity = write-time ZSET composite score (not query relevance).

Consequences

  • Phase 3.5.C.2 parallel retriever wires get_hot_memories alongside 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?

Edit on GitHub

Last updated on

PreviousADR-0058: Semantic search FTS fallback triggerNextADR-0060: Memory service tenant isolation architecture

On this page

  • Context
  • Options Considered
  • 1) Blend hot cache into find_similar() as cache-first semantic search
  • 2) Distinct MemoryHotCacheReader.get_hot_memories() (chosen)
  • Decision
  • Consequences
  • Related
0%