Skip to content

refactor(intrinsics): internal migration with shims — old classes inherit from Adapter; call_intrinsic rewritten (Epic #929 Phase 1) #1136

Closed

Description

@planetf1

Parent epic: #929
Design proposal: PR #1080
Phase: 1 (Wave 2 — start after 0.1 has a draft PR)
Depends on: 0.1
Blocks: 1.B, 1.C, 1.D, 2.1, 4.1

⚠️ Phase 1 bottleneck. This is the only serialisation point before Wave 3 opens four parallel tracks. Keep the PR narrow (~300–500 LOC) to merge quickly.


Problem

mellea/stdlib/components/intrinsic/_util.py:call_intrinsic and mellea/stdlib/requirements/requirement.py (requirement rerouting) branch on the old IntrinsicAdapter / EmbeddedIntrinsicAdapter subclasses. Until these internal callers operate on the new Adapter type from 0.1, no helper file can migrate. External users may also construct the old classes directly — migrating internals without a backward-compat path breaks them.

Agreed design

Two tightly-coupled changes in one PR (splitting creates ordering pain and conflicting branch state):

(a) Old classes become inheriting shims

IntrinsicAdapter, EmbeddedIntrinsicAdapter, CustomIntrinsicAdapter are restructured to:

  • Inherit from Adapter (new dataclass from 0.1) — isinstance(x, IntrinsicAdapter) and isinstance(x, Adapter) both work
  • Translate constructor args into Identity + IOContract + WeightsBinding triple, then call Adapter.__init__
  • Emit a DeprecationWarning once per construction site (stacklevel=2) pointing at the new construction pattern
  • Carry no behavioural state of their own — delegate to inherited Adapter machinery

(b) Internal callers operate on Adapter

_util.call_intrinsic and requirement rerouting rewritten to:

adapter = backend.resolve_adapter(name)
with backend.adapter_scope(adapter):
    raw = backend.generate(adapter.io_contract.build_prompt(...))
return adapter.io_contract.parse(raw)
  • adapter_scope wraps activate()/deactivate() per call; this is the future telemetry parent — Phase 2 wraps it in an intrinsic.call OTel span; the hook point must exist at the right call-site boundary now
  • prepare() at session start (2.2); release() at session teardown
  • Capability-based lookup for requirement rerouting uses Identity.capability instead of isinstance branching
  • Backends grow stub resolve_adapter / adapter_scope implementations delegating to old code paths (real implementations in Phase 2)

Docs update

  • docs/dev/requirement_aLoRA_rerouting.md — update to describe capability-based lookup (using Identity.capability) instead of hardcoded requirement-check string. This resolves thread 7 in the design proposal's thread mapping.

Scope

  • mellea/backends/adapters/__init__.py — old classes as inheriting shims
  • mellea/stdlib/components/intrinsic/_util.py — call_intrinsic rewritten
  • mellea/stdlib/requirements/requirement.py — rerouting rewritten
  • Abstract backend + concrete backend stubs: resolve_adapter, adapter_scope (no instrumentation yet)
  • docs/dev/requirement_aLoRA_rerouting.md — capability-based lookup documentation

Out of scope

Helper file migration (1.B–D), backend verb implementations (Phase 2), AdapterMixin rename (2.1), shim removal (4.1).

Acceptance criteria

  • IntrinsicAdapter(...) returns instance satisfying both isinstance(x, IntrinsicAdapter) and isinstance(x, Adapter)
  • Same for EmbeddedIntrinsicAdapter and CustomIntrinsicAdapter
  • Each old constructor emits exactly one DeprecationWarning per call (not per import), stacklevel=2
  • _util.call_intrinsic operates on Adapter; no isinstance branching on old subclasses
  • Requirement rerouting uses Identity.capability
  • adapter_scope exists at the correct call-site boundary; pass-through context manager at this stage
  • docs/dev/requirement_aLoRA_rerouting.md updated; markdownlint passes
  • All existing tests pass (behavioural neutrality is the bar)
  • ruff format, ruff check, mypy clean

Test plan

test/backends/adapters/test_old_class_shims.py:

  • test_old_classes_inherit_from_adapter
  • test_old_constructor_emits_deprecation_warning — once per call, stacklevel=2
  • test_old_constructor_drop_in_replaceable — construct via old API, assert behaviour matches Adapter(...) directly

New tests for capability-based lookup with multiple registered capabilities.

Breaking changes

  • Subclassing the old classes: anyone overriding internal methods of IntrinsicAdapter etc. may break. Public constructor signature preserved.
  • isinstance checks against the old Adapter ABC: depends on the naming-collision resolution chosen in 0.1.

Document both in the PR description with migration examples.

References

Activity

  1. self-assigned this
    on May 22, 2026
  2. added
    area/backendsProvider-specific work: Ollama, HF, LiteLLM, OpenAI, Bedrock, vLLM
    area/adapter-functionsGranite adapter functions: framework and adaptiers including RAG, Guardian, Core
    area/stdlibCore abstractions: Context, MOT, SamplingStrategy, formatters, serialization
    on May 22, 2026
  3. added this to the Release 0.6.0 milestone on May 22, 2026
  4. planetf1 commented on Jun 11, 2026

    @planetf1
    ContributorAuthor

    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:

    Old term Preferred term
    intrinsic / intrinsic function adapter function
    activated-LoRA / Activated LoRA aLoRA
    Project Granite Switch Granite Switch
    cache rewrite (re: aLoRA) cache hit / cache miss

    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).

  5. 2 remaining items

  6. added a commit that references this issue on Jun 17, 2026
    14bb0ae
  7. added
    p1High: important bugs (workaround exists) or high-value core features. Do soon, not on fire.
    on Jun 18, 2026
  8. planetf1 commented on Jun 18, 2026

    @planetf1
    ContributorAuthor

    Testing summary

    All 216 unit and integration intrinsic tests pass on both macOS and GPU.

    Five GPU-only tests flagged during review turned out to be pre-existing issues on upstream/main, not regressions. To get solid data we ran them 10× each on the same GPU cluster, comparing main (317d5d9) against this branch (f6fb2e7):

    Test main branch
    context_relevance_alora 0/10 0/10
    uncertainty_alora 0/10 0/10
    requirement_check_alora 1/10 1/10
    context-attribution 1/10 5/10 ↑
    groundedness_e2e_string_documents 2/10 4/10 ↑

    No regressions. The two tests that improved (context-attribution, groundedness) appear to benefit from the _find_adapter ordering fix — when aLoRA is available and working, these tests get better results from it.

    The consistently-failing pair (context_relevance_alora, uncertainty_alora) are a pre-existing peft bug tracked in #1286. The remaining three are GPU score non-determinism tracked in #1291.

  9. added a commit that references this issue on Jun 23, 2026
    26a5e1e
  10. added a commit that references this issue on Jun 23, 2026
    54cedc7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area/adapter-functionsGranite adapter functions: framework and adaptiers including RAG, Guardian, Corearea/backendsProvider-specific work: Ollama, HF, LiteLLM, OpenAI, Bedrock, vLLMarea/stdlibCore abstractions: Context, MOT, SamplingStrategy, formatters, serializationp1High: important bugs (workaround exists) or high-value core features. Do soon, not on fire.refactor

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions