Repository navigation
refactor(intrinsics): rag.py whole-file migration to new Adapter types (Epic #929 Phase 1) #1137
Description
Parent epic: #929
Design proposal: PR #1080
Phase: 1 (Wave 3 — start after 1.A merges)
Depends on: 1.A
Independent of: 1.C, 1.D, 2.1 (all run in parallel in Wave 3)
Problem
mellea/stdlib/components/intrinsic/rag.py contains six helpers in one file: check_answerability, rewrite_question, clarify_query, find_citations, check_context_relevance, flag_hallucinated_content. All construct via IntrinsicAdapter(...) (a deprecation shim after 1.A). Signatures do not consistently accept model_options=. None has output validation — schema drift from upstream _RAG_REPO weights silently changes behaviour.
Per-helper PRs would all touch the same file and serialise behind one another. One PR migrates the whole file.
Agreed design
Follows the per-helper-file migration template from PR #1080:
- Migrate construction — replace
IntrinsicAdapter(...)withAdapter(identity=..., io_contract=..., weights=...) - Normalise signature — add
model_options: dict | None = Noneas keyword argument to every helper - Add output validation — declare each helper's expected output contract; wire
io_contract.parse()to raiseAdapterSchemaMismatchErroron contract-breaking deltas only (missing required field, type change). Forward-compatible additions (extra optional fields) do NOT raise. - Update docs and examples — docstrings must document declared output contract + new parameters;
docs/examples/intrinsics/examples that call these helpers must be updated in the same PR
Six helpers, six declared output contracts. Implementer confirms each contract against current _RAG_REPO weights before writing the tests — document the verification in the PR description.
Scope
mellea/stdlib/components/intrinsic/rag.py- Tests under
test/stdlib/components/intrinsic/test_rag.py
Out of scope
Other helper files (1.C, 1.D), backend changes (Phase 2), shim removal (4.1), refactoring beyond additive model_options=.
Acceptance criteria
For each of the six helpers:
- Constructs via
Adapter(identity=..., io_contract=..., weights=...)— noIntrinsicAdapter(...)calls in helper code - Accepts
model_options: dict | None = None - Has a declared output contract documented in its docstring
- Forward-compat: synthetic output with an extra optional field does NOT raise
- Contract-break: synthetic output missing a required field raises
AdapterSchemaMismatchError - Existing helper tests pass (behavioural neutrality)
-
docs/examples/intrinsics/examples that call these helpers updated; examples passuv run pytest docs/examples/intrinsics/(or skipped with correct marker if backend-gated) -
ruff format,ruff check,mypyclean
Test plan
Per helper (six pairs of tests):
test_<helper>_contract_enforced— feed synthetic output missing a required field; assertAdapterSchemaMismatchErrortest_<helper>_forward_compat— feed output with an extra optional field; assert it does NOT raise
Existing happy-path tests pass unchanged.
Note on
flag_hallucinated_content: return type is boolean-like. Document expected output type explicitly in docstring; coercion responsibility stays with caller.
Breaking changes
None at signature level (additive model_options=). Callers that previously swallowed KeyError on schema mismatch will now see AdapterSchemaMismatchError — surface in changelog.
References
- PR docs: design proposal for adapter lifecycle (#929) — review channel, do not merge #1080 §13
- Per-helper-file migration template in PR docs: design proposal for adapter lifecycle (#929) — review channel, do not merge #1080 /
docs/dev/proposals/929-issue-plan.md - Jake req 4
- Before starting:
gh issue list --search "rag" --state open— check for any open issues against specific RAG helpers and reference them in PR
Activity
planetf1 commentedon May 27, 2026
planetf1 commentedon Jun 11, 2026
This issue uses vocabulary that has been superseded by the agreed Epic #929 glossary. Please use the following terms in any new work related to this issue:
The canonical definitions are now in the project glossary and were established as part of #1192. Python symbol names (
IntrinsicAdapter,fetch_intrinsic_metadata, etc.) keep their current names until Phase 1 (#1136) and Phase 4 (#1144).feat(intrinsics): shim old adapters onto Adapter dataclass; rewrite c…
feat(intrinsics): shim old adapters onto Adapter dataclass; rewrite c…
feat(intrinsics): shim old adapters onto Adapter dataclass; rewrite c…
feat(intrinsics): shim old adapters onto Adapter dataclass; rewrite c…
feat(intrinsics): shim old adapters onto Adapter dataclass; rewrite c…
feat(intrinsics): shim old adapters onto Adapter dataclass; rewrite c…
feat(intrinsics): shim old adapters onto Adapter dataclass; call_intr…
planetf1 commentedon Jun 24, 2026
#1332 (guardian.py IOContract subclasses) is blocked on this issue merging: it needs the
call_intrinsic(io_contract=…)parameter that this PR adds to_util.py.refactor(intrinsics): migrate rag.py to new Adapter types (Epic gener…
refactor(intrinsics): migrate rag.py to new Adapter types (Epic gener…
docs(backends): document shim scaffolding as current behaviour, no tr…
docs(backends): document shim scaffolding as current behaviour, no tr…
docs(backends): document shim scaffolding as current behaviour, no tr…
docs(backends): document shim scaffolding as current behaviour, no tr…
feat(backends): EmbeddedBinding implements apply_activation (Granite …