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-0048: Memory multi-label categories
ADRs

ADR-0048: Memory multi-label categories

Architecture decision record 0048 — ibex_core.memory_labels join table with org-safe FKs, FORCE RLS, and memories.category primary sync for Phase 2.5 Track E.

ADR-0048: Memory multi-label categories

  • Status: Accepted
  • Date: 2026-08-25
  • Authors: IBEX Harness team
  • Milestone: 2.5.G5.M2 Multi-label category support

Context

A single memories.category enum cannot represent facts that span multiple taxonomy buckets (e.g. preference + factual). Track E (2.5.G5) needs the join table before Phase 3 writers and category-conditional scoring.

The milestone sketch named the table memory_categories with only REFERENCES memories(id) and no org_id. Phase 3 sketches (3.1.1, 3.C.4) use memory_labels / label. Live tenancy rules require explicit org_id filtering and composite org-safe FKs (ADR-0047).

Decision

1) Table name memory_labels (not memory_categories)

Ship ibex_core.memory_labels with column label to match Phase 3 consumers and avoid a rename migration. Document the sketch advancement on the milestone page.

2) Tenancy-first DDL

  • org_id NOT NULL + FOREIGN KEY (memory_id, org_id) → memories(id, org_id) ON DELETE CASCADE
  • PRIMARY KEY (memory_id, label)
  • Same taxonomy CHECK as memories.category
  • confidence NUMERIC(3,2) NOT NULL DEFAULT 1.00 CHECK (0..1)
  • Index (org_id, label) for tenant filters
  • FORCE ROW LEVEL SECURITY + ibex_core.rls_org_visible(org_id) (not subquery-on-memories RLS drafts)

3) Primary sync via memories.category

Keep the existing category column (do not add primary_category in M2). Trigger sync_memory_primary_category after INSERT/UPDATE/DELETE on labels:

  • When ≥1 label remains: set category to ORDER BY confidence DESC, label ASC LIMIT 1
  • When zero labels remain: leave category unchanged (NOT NULL)

Labels are source of truth once present. No bidirectional sync from category → labels in this milestone (avoids recursion). Phase 3 writers should maintain ≥1 label.

4) Backfill

INSERT … SELECT id, org_id, category, 1.00 FROM memories ON CONFLICT DO NOTHING in the same up migration.

5) Application writers (3.C.4)

Phase 3.C.4 implements write-path population in the memory service orchestrator: optional labels[] on POST /v1/memories, validation in resolve_write_labels, insert_labels_session in the same transaction as memory insert, and reload_memory_session so HTTP responses reflect the trigger-updated scalar. The primary column remains memories.category (not primary_category; rename deferred per 3.1.1). Application code must not UPDATE memories.category directly — only the sync_memory_primary_category trigger updates it.

6) Expand-contract with 3.1.1

Those milestones must not CREATE TABLE memory_labels. They may later rename category → primary_category if needed; M2 does not dual-column.

3.C.4 implementation note (2026-08-28)

Write-path population landed in milestone 3.C.4: additive labels[] on memory create, backward-compatible scalar category synthesis when labels is omitted, and transactional insert into ibex_core.memory_labels inside the 3.C.5 orchestrator. Primary scalar remains memories.category; the existing trigger selects ORDER BY confidence DESC, label ASC.

Consequences

Positive

  • Phase 3 scoring/extraction can assume multi-label shape
  • Tenant isolation matches live FORCE RLS pattern
  • Deterministic primary selection

Negative

  • Sketch name memory_categories diverges (documented)
  • Direct updates to memories.category while labels exist can be overwritten by the next label write

Rollout

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

References

  • ADR-0005
  • ADR-0047
  • Milestone 2.5.G5.M2
  • Milestones 3.1.1, 3.C.4

Was this page helpful?

Edit on GitHub

Last updated on

PreviousADR-0047: Memory temporal validity foundationNextADR-0049: Memory relationship graph readiness

On this page

  • Context
  • Decision
  • 1) Table name memory_labels (not memory_categories)
  • 2) Tenancy-first DDL
  • 3) Primary sync via memories.category
  • 4) Backfill
  • 5) Application writers (3.C.4)
  • 6) Expand-contract with 3.1.1
  • 3.C.4 implementation note (2026-08-28)
  • Consequences
  • Positive
  • Negative
  • Rollout
  • References
0%