LISAOS // DOCS
GATEWAY // CONTEXT

Gateway Module — `context/`

1. Purpose

The RAG assembly engine — the single retrieval surface behind assemble_context. It fans out parallel searches across five source stores (psychic_cache, memory, agent_memory_own, agent_memory_peer, vault_index), applies per-caller adaptive source weights and recency boosts, enforces per-source token caps within a resolved budget, optionally enriches with knowledge-graph triples and cross-namespace expansion, and returns a formatted context_block with a logged assembly_id. It owns the other half of the RAG loop too: context_feedback records which sources were used, and a nightly eval cycle adjusts weights and budgets from that feedback (Dream Phase 6.8).

2. File Inventory

FileLinesResponsibility
service.ts498createContextAssemblyService.assemble(): budget resolution, query embed (+fallback), cross-namespace expansion, 6-way parallel fanout, weight/recency/priority scoring, dedup, KG enrichment pass, explicit-link reading (path-traversal-guarded), per-source-cap token allocation + greedy overflow, context_block formatting, assembly logging
repository.ts414createContextRepository: source-weight + token-share + budget getters (caller→wildcard fallback), logAssembly, recordFeedback, runEvalCycle (3-dimension weight/share/budget learning), assembly-log query, distinct callers
index.ts253createContextLayer factory + 4 search adapters (memory, psychic, agentMemory-own, peerMemory) that normalise each store to SearchResult
types.ts220AssembleContextInputSchema, ContextFeedbackSchema, SourceStore/SourceEntry, GraphContextEntry (8-field, KG), SourceWeight, CallerBudgetConfig, AssemblyLogEntry, eval result types, SearchAdapter, repo/service/layer interfaces
routes.ts146createContextRouter: /assemble, /feedback, /weights, /budgets, /log, /log/callers, /eval
Total1,531

3. Public API Surface

REST Endpoints

Mounted at /api/context. Auth per AK-415: GETs → Bearer; writes → Bearer (write only). /api/context was explicitly dropped from the former GET-exemption set (D913 Fix 2) — every route is authed.

MethodPathAuthBody / QueryResponseSide Effects
POST/assembleBearerAssembleContextInputSchema{assembly_id, context_block, sources[], total_tokens, retrieval_ms} / 400 / 500Embeds query; 5-store fanout; writes context_assembly_log (unless log:false); logs memory_search activity
POST/feedbackBearerContextFeedbackSchema{success:true} / 400Updates context_assembly_log.used_source_ids + tokens_used
GET/weightsBearer{weights: SourceWeight[]}none
GET/budgetsBearer{budgets: CallerBudgetConfig[]}none
GET/logBearer?caller&mission_namespace&limit&offset{data: AssemblyLogEntry[]}none
GET/log/callersBearer{data: string[]}none
POST/evalBearer{weight_adjustments[], budget_adjustments[], weights_count, budgets_count}Runs eval cycle → updates source_weights + caller_budget_config + source_weight_history; marks log rows processed

MCP Tools

Tool NameRaw payload?EndpointNotes
assemble_contextNoPOST /api/context/assemblePrimary retrieval tool; returns assembly_id + sources[]
context_feedbackNoPOST /api/context/feedbackCloses the RAG loop
context_feedback_rawYes ({payload})POST /api/context/feedbackStaleness-immune twin

4. Internal API

  • createContextLayer(db, embeddingProvider, memoryRepo, embeddingRepo, psychicRepo, agentMemoryRepo, activityRepo?, fallbackProvider?, vaultIndexRepo?, kgRepo?, crossRefRepo?): {service, contextRepo, router} — 9 required + optional additive positional args (KG/cross-ref threaded D1484; pre-Fuda 9-arg callers stay valid).
  • ContextRepositorygetWeight/getTokenShare/getDefaultBudget (with caller='*' wildcard fallback), logAssembly, recordFeedback, runEvalCycle, getAssemblyLog, getDistinctCallers. Consumed by dashboard-api + curator + Dream.
  • Search adapters (module-private): each wraps a repo's search into the SearchAdapter interface with RRF + normaliseRrfScores so all stores share a [0,1] metric space.

5. Background Services

  • Eval cycle (runEvalCycle) — not timer-driven inside the module; fired by POST /api/context/eval (Dream Phase 6.8 nightly + manual). Batches unprocessed context_assembly_log rows per caller (min EVAL_BATCH_SIZE=10); computes effectiveness = 0.5·confidence + 0.3·usageRate + 0.2·appearanceRate; adjusts weight + token_share (learning rate 0.1, clamped) skipping manual rows; adjusts per-caller budget (±10%/−5% on utilisation/saturation, clamped min/max).
  • Assembly logging — synchronous within /assemble (skippable via log:false for health probes; returns assembly_id=0 sentinel).

6. Data Contracts

  • AssembleContextInputSchema = {query≥1, caller≥1, mission_namespace?, token_budget?≤16000, explicit_links?[], log?}.
  • ContextFeedbackSchema = {assembly_id:int>0, used_source_ids[], tokens_used?:int≥0}.
  • SourceStore = 'psychic_cache'|'memory'|'agent_memory_own'|'agent_memory_peer'|'vault_index' (5 members).
  • GraphContextEntry (8-field: id, subject, predicate, object, valid_from, valid_to, tokens, content) — KG enrichment, flows through context_block text with [GRAPH] prefix only; not in sources[].

Scoring constants (service.ts): EXPLICIT_LINK_BUDGET_SHARE=0.3, NULL_NAMESPACE_BUDGET=2000, MIN_KG_BUDGET_TOTAL=500, KG_BUDGET_SHARE=0.075, CROSS_NAMESPACE_SCORE_DISCOUNT=0.5. Eval constants (repository.ts): LEARNING_RATE=0.1, WEIGHT_MIN/MAX=0.1/1.5, TOKEN_SHARE_MIN/MAX=0.05/0.8, EVAL_BATCH_SIZE=10.

Owned tables (declared in memory/db.ts): source_weights, source_weight_history, context_assembly_log (+2 indexes), caller_budget_config.

7. Dependencies

  • Gateway modules consumed: memory/types (EmbeddingProvider, EmbeddingRepository, MemoryRepository), psychic-cache/types (PsychicCacheRepository), agent-memory/types, activity/repository, vault-index/repository (VaultIndexRepository), knowledge-graph/types (KGRepository, CrossRefRepository), shared/search-utils, shared/zod-error.
  • External libraries: better-sqlite3, express, zod, Node crypto (query hash), node:fs/promises + node:path (explicit-link reads).
  • Environment variables: VAULT_ROOT (explicit-link resolution root; defaults to 5-levels-up from import.meta.dirname — path-traversal guarded via resolve + startsWith).

8. Test Coverage

LayerFileTests
Adapters + layer wiringtest/context-index.test.ts11
KG enrichment passtest/context-kg-enrichment.test.ts8
Repository (weights, budgets, eval cycle, log)test/context-repository.test.ts28
Routes (7 endpoints, Zod negatives)test/context-routes.test.ts17
Assembly service (fanout, scoring, caps, links)test/context-service.test.ts18

Note: context-kg-enrichment.test.ts:356-365 carries a preserved-verbatim GraphContextEntry fixture (Fuda v1.1 §15 A15) — the production interface shape is anchored to it; do not drift without updating the fixture.

9. Known Limitations

  • assemble writes dispatch_id: null unconditionally in logAssembly (service.ts:426) — the assembly log never captures the calling dispatch even when one exists. Under-populated analytics dimension.
  • KG + cross-namespace paths are optional-degrade — absent kgRepo/crossRefRepo silently skips enrichment; no signal to the caller that enrichment was unavailable.
  • Entity extraction is heuristicextractEntityCandidates matches uppercase-initial ≥3-char runs; can over/under-match. Capped at 10 entities × 5 triples per assemble.
  • emptyResult + log:false both return assembly_id=0 — callers must treat 0 as "nothing to feed back".

10. Change History

DateDispatchSummary
2026-07-042295Initial per-module spec filed (audit campaign Phase 4)
(historical)D27Removed legacy memoryRetrieval param + dead ContextRetrievalService chain; adapters own retrieval
(historical)D23Score-divergence fix bundle: normaliseRrfScores shared helper; recency boost moved to uniform funnel
(historical)D41log:false opt-out for health-probe assemblies
(historical)D1484 (AK-347)KG enrichment + cross-namespace expansion resurrection (additive positional deps)
(historical)D913 Fix 2/api/context moved off the former GET-exemption set (now Bearer-gated)

On this page