[AP0] Retrieval intelligence, embeddings, source-aware KB, and RLM integration #219
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
nsaspy/prolog-rlm#219
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Priority
AP0 — next coding move.
This epic captures the complete design discussed for making
prolog-rlmsmarter as a reusable library for building LLM harnesses, while preserving the existing default/reference RLM runtime.This work is ADARD, human-gated. Do not silently advance through the full implementation/merge loop.
Human-gated ADARD contract
Use distinct fresh reasoning phases and preserve evidence/decisions between them:
If implementation uncovers a material architecture change, return to the human decision gate.
0. Architectural thesis / non-negotiables
prolog-rlmis a reusable Prolog library/runtime substrate for writing harnesses. It may ship a default/reference RLM harness, CLI, agent runtime, graph runtime, prompt compiler, etc., but new work must remain composable and reusable by other harnesses.Think:
Do not turn the library into a required daemon. Do not require a filesystem watcher. Do not bake one application persona/workflow into core primitives.
The model may request standard structured actions/tool calls, but Prolog/runtime code owns dispatch, capabilities, budgets, validation, state, and execution. Final model prose does not need to be structured.
1. Reuse existing provider layer
Do not duplicate model/provider plumbing in downstream harnesses.
Reuse and extend
rlm_chainconventions:Credentials remain referenced indirectly (for example
env('OPENROUTER_API_KEY')) and are resolved at execution time. A host/editor may set that environment variable from its own config file, but raw secrets must not leak into provider terms, traces, errors, fixtures, or logs.2. Provider-neutral embeddings
Add a first-class embedding abstraction separate from chat-completion models.
API direction (exact naming/arity should follow repo conventions):
Requirements:
3. Generic
rlm_retrievallibraryAdd backend-neutral retrieval infrastructure. Keep it deliberately dumb and reusable.
Conceptual surface:
Support normalized capabilities/strategies for:
Do not make Chroma semantics the generic retrieval API.
4. Basic Chroma adapter
Add
rlm_chroma(or equivalent) on top ofrlm_retrieval.First useful slice:
Chroma is one adapter, not the architecture.
5.
retrieval_expert: symbolic/non-LLM retrieval intelligenceBuild a separate reusable expert-system layer on top of
rlm_retrievalandrlm_embedding.This is intentionally classic/symbolic AI driving modern generative AI. It must be able to make useful retrieval decisions without calling an LLM.
Conceptual API:
Initial intelligence should support extensible rules/facts for:
exact,lexical,vector,graph,structural,hybrid;Embeddings are a sensor, not the decision-maker.
Example intent:
The expert should be inspectable/explainable and reusable by arbitrary harnesses.
6. Existing source parsing / project-KB plan is part of this epic
Integrate with the existing Project/source work rather than creating a parallel code-index system.
Existing dependency chain:
Preserve the existing layering:
For Prolog source, keep SWI-native semantic analysis where it is stronger than Tree-sitter.
The project KB must remain useful independently of any coding agent or LLM.
7. Source-KB freshness is a hard correctness invariant
A served source-derived KB fact must never silently appear current when it was derived from different source bytes.
Every material source-derived fact must resolve to provenance including at least:
Current-vs-stale state must be explicit.
Do not rely on mtimes alone. Exact bytes/hash are authoritative.
8. No required watcher: lazy freshness is baked into access/loop boundaries
A filesystem watcher may exist only as an optional host hint interface. Correctness must not require a running background process.
Authoritative model:
Possible abstraction:
Do not re-hash the entire repository on every tiny predicate call. Validate at meaningful acquisition/retrieval/RLM-loop boundaries, cache within a coherent snapshot, and narrow work to relevant/dirty files where safely known.
Optional host hint:
A watcher, Emacs, IDE, Git integration, etc. may call that. It is an optimization only.
9. Harness-owned writes update the KB directly
When a Prolog-RLM tool/harness writes or patches source, the runtime already knows what changed. Exploit that immediately rather than waiting for later rediscovery.
Conceptual flow:
Conceptual API direction:
Do not couple this to one particular file-writing tool. Define a reusable source-update boundary that canonical effectful write tools can call.
10. Multiple writes must be coalesced
Do not thrash parsing/indexing for every intermediate write when several writes occur in one logical tool/agent/RLM step.
Maintain a bounded dirty-set/edit journal:
Conceptual behavior:
Intermediate half-written source must not become a supposedly complete current KB generation.
11. Multiple programs/editors and concurrent writers
A file being open in multiple programs is normal. No open handle implies ownership.
Use optimistic concurrency and exact-byte validation.
For indexing/publication:
For harness writes, use expected-hash/generation semantics where possible:
If another program changed the file between read and write, return a structured conflict rather than clobbering or publishing a KB based on stale assumptions.
Concurrent source publication must serialize/linearize per relevant Project/File generation and never expose mixed generations as one complete current snapshot.
12. Coherent snapshot semantics
RLM/retrieval consumers should query a coherent project/source snapshot rather than observe a mixture of:
Provide a snapshot identity/reference and make current queries bind to it where appropriate.
Conceptual direction:
Publishing a new generation must be atomic at the defined visibility boundary. Reindexing/error/partial states must never masquerade as complete current evidence.
13. RLM integration: two entry points
Retrieval/source knowledge must plug into the existing RLM as a library capability, not become a second orchestration system.
A. Initial context acquisition
Before the planner/model receives project evidence:
This should compose with the existing context-budget/prompt-compiler machinery.
B. Retrieval during recursive execution
A running RLM/subagent must be able to request more evidence through the normal typed/tool execution boundary.
Conceptual operation/tool:
The model expresses an information need;
retrieval_expertdecides how to satisfy it using exact/lexical/vector/graph/source retrieval. Model output does not bypass retrieval policy or source-freshness guarantees.Do not invent an incompatible proprietary model protocol if standard tool/function-calling + internal Prolog terms already suffice.
14. Prompt/tool boundary
Keep the existing distinction clear:
The library supplies prompting/selection/runtime mechanics; individual harnesses own their domain persona, goals, project workflow, and application-level instructions.
15. Testing / acceptance
At minimum, the eventual implementation path must prove:
Embeddings/retrieval
Source knowledge
Regression
rlm_chain,rlm_context,rlm_tool,rlm_agent,rlm_graph, prompt compiler, MCP, trace, and source APIs remain usable independently;dlopenauthority;16. First coding move after human design approval
Do not try to land the entire epic in one PR.
During ADARD design, identify the smallest dependency-correct vertical slice. Strong candidate ordering to evaluate:
rlm_context/RLM retrieval path;The ADARD design/adversarial phases may reorder these if repository dependencies prove a different smallest safe slice.
Human approval is required before realization and again before merge.
Refs: #93 #94 #95 #96 #97 #98 #99 and existing provider/context/tool/agent/graph/prompt compiler work.
Fresh ADARD decision gate — current-main reconciliation
A — Analyze / research
Current executable truth changes the safest first slice:
rlm_embeddingorrlm_retrievalimplementation on current main.rlm_chainalready owns the canonical async-first/sync-await provider execution direction and closedprovider(Name, Config)shape.rlm_openai_compatiblealready owns endpoint/model/env-credential validation, timeout/address-family handling, secret-safe exception normalization, and the concrete OpenAI-compatible HTTP boundary. Do not create a second credential/HTTP policy stack for embeddings.rlm_contextalready establishes the correct trusted-adapter pattern: executable callbacks are process-local trusted registry state; model-visible/serializable state stays closed data; registration is not authority.rlm_project_sourceis the merged #95 registry layer only. It explicitly does not parse source or materialize syntax/semantic facts.D — Design
Slice E1 — provider-neutral embeddings first
Add a dedicated
rlm_embeddingpublic runtime, separate from chat completion semantics but following the same provider/async conventions.Proposed public surface (names may be adjusted only to repository naming conventions):
Canonical direction remains:
Use the existing ground
provider(Name, Config)convention. Chat and embeddings may use entirely different provider terms/endpoints/models; no implicit inheritance from the active chat model.Extend the existing OpenAI-compatible transport module (or factor only the minimum genuinely shared private helper) so embedding execution reuses its current provider-config, env-credential, timeout/address-family, redaction and transport-exception semantics. Do not copy those policies into a new transport stack.
First provider capability:
The configured endpoint is the embeddings endpoint. No special OpenRouter dependency is required for E1; a local OpenAI-compatible embedding server remains a normal provider configuration.
Normalized result should be closed ground data equivalent to:
Preserve current
chain_usagefield semantics so embeddings can later participate in one accounting surface. Unknown/missing provider cost remains the same conservative zero/default convention already used by chain normalization; provenance must say which provider/model produced the vector.E1 options should stay narrow: optional requested dimensions plus bounded input/batch limits. Do not expose arbitrary wire JSON as options. Use float vectors in the first slice; no base64 vector format.
E1 tests
TDD-first deterministic acceptance:
dimensionsis transmitted and reflected/validated;Use a tiny SWI local HTTP fixture for deterministic OpenAI-compatible wire behavior; no Python/Node service. Add an optional explicitly gated real/local-compatible smoke configured by environment/provider terms. Missing external endpoint must be reported as unavailable, never counted as correctness evidence.
Slice E2 — generic dumb retrieval contract
Only after E1. Add
rlm_retrievalwith the same trusted-adapter architecture style asrlm_context:Latency-bearing retrieval gets canonical async APIs plus sync-await wrappers. Registration/availability never grants model capability or network/write authority.
Do not force all scores into a fake universal similarity number. Canonical hits must preserve score semantics/direction and provenance, e.g. distance vs similarity vs rank, with an optional normalized relevance only when the backend can justify it. This prevents invalid hybrid comparisons.
Slice E3 — Chroma adapter
Implement Chroma solely as an
rlm_retrievalbackend. Chroma is an optional service selected by the host, not a required daemon for prolog-rlm. Store/return source provenance metadata but never treat the Chroma index as source-of-truth freshness authority.Slice E4 — symbolic retrieval expert
Build
retrieval_expertabove E1+E2. Initial policy is non-LLM and explainable: cheap exact/structural routes before vector where appropriate; deterministic exact-vs-vector/hybrid selection; rule IDs/evidence in explanations. Embeddings are a sensor, not authority.Do not add a second scheduler or agent runtime. Execution delegates to
rlm_retrieval.Source integration ordering
Source-aware structural/graph retrieval must consume the existing #93 chain:
Do not create a parallel filename/symbol index just to make #219 appear complete sooner.
When that chain is ready, #219 adds the access-boundary semantics already specified in the epic:
Watcher/editor notifications remain optional dirty hints only. Harness-owned writes feed the same dirty/edit journal directly and coalesce until a logical flush boundary.
A — Adversarial review
The design must reject these failure modes:
R/D — Decision gate
Recommended first coding transaction after explicit human approval: E1 only —
rlm_embedding+ OpenAI-compatible embedding transport + deterministic fixture + optional gated real/local smoke.Do not include
rlm_retrieval, Chroma, source freshness, or RLM tool integration in that first PR. This keeps the dependency graph small and gives later retrieval code a stable, provider-neutral embedding sensor.Per #219's human-gated ADARD contract: STOP before realization until explicit human approval.
prolog-rlmthe reference harness with DeepSeek Harness IDE #231