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-0069: Context packer bounded DP knapsack
ADRs

ADR-0069: Context packer bounded DP knapsack

Architecture decision record 0069 — bucketed 0/1 knapsack DP with greedy fallback for context memory packing; interim packer score until memory HTTP exposes composite.

ADR-0069: Context packer bounded DP knapsack

  • Status: Accepted
  • Date: 2026-09-05
  • Authors: IBEX Harness team
  • Milestone: 3.5.C.4 Packer v2 — Bounded DP Knapsack
  • Depends on: ADR-0067 (token estimates), ADR-0068 (memory-side composite + gate — not wired into context HTTP)

Context

Track C needs a packing stage under services/context that selects memories within TokenBudget.usable_budget. Discovery confirmed:

  • No packer existed before this milestone.
  • Memory HTTP search/hot responses expose similarity / confidence / rank only — not composite_score.
  • Memory ranks with full composite_score (recency / usefulness / frequency) internally (ADR-0068), but that value never reaches context.
  • Token counting must reuse estimate_tokens + capability-catalog family policy (ADR-0067).
  • Latency docs disagree: PERFORMANCE.md states Ranking + packing ≤ 15ms (100 candidates); ARCHITECTURE.md and the C.4 milestone state packing < 5ms at n=70.

Decision

1) Bucketed 0/1 knapsack DP with greedy fallback

  • Module: services/context/app/packer.py (ContextPacker)
  • Discretize budget into buckets of BUCKET_SIZE=16
  • Numpy-vectorized DP for the default path; if n * (buckets+1) exceeds IBEX_CONTEXT_PACKER_DP_CELL_CEILING, fall back to score-descending greedy with consecutive-skip limit
  • After DP selection, repair so exact estimate_tokens sums never exceed the token budget
  • Packed order: descending interim score, then memory_id (deterministic)

2) Interim packer score (labeled, not memory composite)

Until memory HTTP carries the real composite:

interim = 0.85 * similarity + 0.15 * confidence

Implemented in services/context/app/scoring.py. Field name on ScoredMemory is composite_score for formatter/proto alignment, but module docs and this ADR state it is not services/memory/app/scoring/composite.py. Follow-up: expose real composite on search/hot responses and delete the interim formula.

3) Thin pipeline glue only

pack_retrieval(RetrievalResult, TokenBudget, packer=...) merges hot+cold (dedupe by memory_id), scores, and packs under usable_budget. No gRPC / AssembleContext (3.5.C.6).

4) Latency gate for CI

Packing-only unit latency test asserts p99 < 5ms at n=70. That matches ARCHITECTURE.md’s packing line and the milestone success signal.

Follow-up (doc reconciliation): align PERFORMANCE.md’s combined ranking+packing ≤15ms@100 with ARCHITECTURE.md’s packing <5ms / ranking <10ms split so contributors have one authoritative table. Not blocking this ADR.

5) Dependency

numpy>=2.0.0 in services/context/pyproject.toml (same floor as embedder).

Consequences

  • Context can pack without calling memory’s scoring internals or changing the proto
  • Packer quality is limited by interim scores until the HTTP composite field lands
  • Pathological DP sizes degrade to greedy with a structured warning log
  • Formatter (3.5.C.5) consumes PackedMemories (content via embedded MemoryHit)

Alternatives considered

  1. Extend memory HTTP with composite_score in this milestone — correct long-term, but expands scope into memory schemas/clients and is not required to ship a correct packer algorithm.
  2. Pure-Python DP only — discovery microbenches showed ~20ms+ at n=70 / ~6250 buckets; misses the <5ms packing gate at the sketch’s worst-case table size.
  3. Copy the milestone MDX sketch verbatim — rejected: sketch numpy slicing is incorrect for edge weights.

Was this page helpful?

Edit on GitHub

Last updated on

PreviousADR-0068: Composite scoring-time relevance gateNextADR-0070: Context formatting locked ordering and session nonce

On this page

  • Context
  • Decision
  • 1) Bucketed 0/1 knapsack DP with greedy fallback
  • 2) Interim packer score (labeled, not memory composite)
  • 3) Thin pipeline glue only
  • 4) Latency gate for CI
  • 5) Dependency
  • Consequences
  • Alternatives considered
0%