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 v2
ADRs›ADR-0047: Memory temporal validity foundation
ADRs

ADR-0047: Memory temporal validity foundation

Architecture decision record 0047 — CREATE ibex_core.memories with bi-temporal validity columns in Phase 2.5 Track E; defer pgvector/HNSW to Phase 3.1.1 expand.

ADR-0047: Memory temporal validity foundation

  • Status: Accepted
  • Date: 2026-08-24
  • Authors: IBEX Harness team
  • Milestone: 2.5.G5.M1 Temporal validity columns

Context

Phase 3 contradiction detection needs when a fact was true (world/valid time) distinct from when IBEX learned it (observation time). Track E (2.5.G5) is migration-only schema readiness before the memory write pipeline.

The milestone sketch assumed ALTER TABLE ibex_core.memories …. Applied migrations through 000013 have no memories table. A bare ALTER cannot ship. G5.M2/M3 also need memories(id) (and org-safe composite FKs) as parents.

Phase 3 milestone 3.1.1 still owns HNSW / pgvector / remaining quality columns. ADR-0005 forbids CREATE EXTENSION vector until needed; CI postgres:16 has no vector extension. Roadmap text that referred to “ADR-0040 memory schema” conflicts with shipped ADR-0040 (Anthropic adapter) — this ADR is 0047.

Bi-temporal inspiration: Graphiti / Zep — without Graphiti’s full four-timestamp edge invalidation (Phase 3 Track C).

Decision

1) CREATE foundation table in 000014 (not ALTER)

Ship 000014_create_memories_temporal as a lean CREATE TABLE ibex_core.memories that includes temporal columns from day one:

ColumnRoleNullability
valid_fromWhen the fact became true in the world (Graphiti valid_at)NOT NULL DEFAULT NOW()
valid_untilWhen it ceased (NULL = still open; Graphiti invalid_at)nullable
observed_atWhen IBEX learned the factNOT NULL DEFAULT NOW()
created_at / updated_atRow bookkeepingstandard

Interval semantics: half-open [valid_from, valid_until). Integrity:

SQL
CONSTRAINT memories_valid_interval_chk
  CHECK (valid_until IS NULL OR valid_until > valid_from)

Do not require observed_at >= valid_from (retrospective reporting is valid).

2) Keep observed_at even if 3.1.1 sketches omit it

Observation time is distinct from world time (“moved to Berlin three years ago”). Phase 3.1.1 expands the existing table; it must not drop observed_at.

3) Omit embedding / pgvector / HNSW in M1

No embedding column and no vector extension in 000014. Phase 3.1.1 adds embedding + HNSW as expand-contract ALTER / index work on the live foundation table — not a conflicting greenfield CREATE.

4) Tenancy and FK shape

  • UNIQUE (id, org_id) for child composite FKs (G5.M2/M3)
  • Composite (agent_id, org_id) → agents(id, org_id)
  • Optional session_id with composite (session_id, org_id) → sessions; clear via trigger on session delete (composite ON DELETE SET NULL would also null org_id)
  • FORCE ROW LEVEL SECURITY + ibex_core.rls_org_visible (string compare app.is_service_account = 'true', not draft ::BOOLEAN)
  • Grants to ibex_app; reuse set_updated_at

5) Lean content / lifecycle only

Include content, content_hash, content_tokens, scalar category (G5.M2 backward-compat), status, deleted_at. Operational indexes: active agent lookup + content_hash. No usefulness/feedback/search_vector columns yet.

6) No application writers in this milestone

No ORM, REST, or proto changes. Columns exist for Phase 3 to consume.

Consequences

Positive

  • Track E can proceed (M2/M3 have a real parent table)
  • Temporal integrity enforced before any write pipeline
  • Avoids CI/pgvector coupling and a doomed ALTER

Negative

  • 3.1.1 docs/sketches must be re-read as expand, not CREATE-from-scratch
  • Full Phase 3 memory shape lands across multiple migrations (intentional expand-contract)

Rollout

  • Migration: infra/migrations/postgres/000014_create_memories_temporal.{up,down}.sql
  • Down is dev/test only; production forward-only per ADR-0005

References

  • ADR-0005 (golang-migrate, expand-contract, no vector until needed)
  • ADR-0046 (embedding profiles; geometry for later 3.1.1)
  • Milestone 2.5.G5.M1
  • Milestone 3.1.1 (expand note)

Was this page helpful?

Edit on GitHub

Last updated on

PreviousADR-0046: Embedder interface and profile registryNextADR-0048: Memory multi-label categories

On this page

  • Context
  • Decision
  • 1) CREATE foundation table in 000014 (not ALTER)
  • 2) Keep observed_at even if 3.1.1 sketches omit it
  • 3) Omit embedding / pgvector / HNSW in M1
  • 4) Tenancy and FK shape
  • 5) Lean content / lifecycle only
  • 6) No application writers in this milestone
  • Consequences
  • Positive
  • Negative
  • Rollout
  • References
0%