Repository navigation
feat(intrinsics): introduce Adapter/Identity/IOContract/WeightsBinding scaffolding (Epic #929 Phase 0) #1134
Description
Correction (2026-05-26): the name
AdapterBasedComponentis the
chosen name for the user-facing component class. References to "placeholder"
below are design-tracker language only — they record that, if IBM later
chooses a different upstream term, a rename is scheduled in issue 4.1. The
source code itself asserts the name without hedging. Please disregard the
"placeholder" framing when reviewing the implementation.
Parent epic: #929
Design proposal: PR #1080
Phase: 0 (Wave 1 — file immediately, no dependencies)
Blocks: 1.A, 2.1, 2.2, 2.3, and #1111 (needs AdapterSchemaMismatchError)
Problem
Today's adapter hierarchy (IntrinsicAdapter / EmbeddedIntrinsicAdapter / CustomIntrinsicAdapter + abstract Adapter ABC) leaks the weights-location distinction into every caller via isinstance branching. Seven recent fix-up commits (8b6b8d55, c57aba1d, 8577d092, 4d372b0e, 0617bd96, 75465d29, 1734900d) trace directly to this structure. Adding new realities requires new branches everywhere (blocks #1018).
Separately, IBM is retiring the term "Intrinsic" but has not confirmed the replacement. Mellea uses AdapterBasedComponent as a placeholder.
Agreed design
Replace the four-class hierarchy with a single Adapter composed of three parts plus a pluggable binding:
Adapter
├── identity — name, adapter_type (lora|alora), optional role
├── io_contract — builds prompt + parses output (delegates to granite-common/formatters)
└── weights — pluggable WeightsBinding: LocalFile / Embedded / ServerMediated
Types to introduce:
Adapter— dataclass withidentity,io_contract,weightsIdentity— dataclass:name: str,adapter_type: Literal["lora", "alora"],role: str | None = NoneIOContract— ABC:build_prompt(...) -> Componentandparse(raw: str) -> dict;parseraisesAdapterSchemaMismatchErroronly on contract-breaking failures (not benign additions)WeightsBinding— ABC with four verbs:prepare,activate,deactivate,release- Three stub subclasses raising
NotImplementedError:LocalFileBinding,EmbeddedBinding,ServerMediatedBinding AdapterSchemaMismatchErrorexception: attributesname,observed_keys,expected_keys; message format:"Adapter '{name}' output cannot satisfy declared contract. Observed keys: {observed_keys}; expected: {expected_keys}."
Placeholder module (AdapterBasedComponent):
- New:
mellea.stdlib.components.adapter_based_componentre-exporting today'sIntrinsicasAdapterBasedComponent - Old import
mellea.stdlib.components.intrinsicstays valid - Module docstring notes placeholder rationale
KNOWN_ROLES advisory registry:
mellea/backends/adapters/roles.py—KNOWN_ROLES: frozenset[str]with initial role stringsIdentitywarns (UserWarning) whenrolenot inKNOWN_ROLES; does not reject
⚠️ Critical: naming collision
The existing Adapter ABC at mellea/backends/adapters/adapter.py:24 shares the name with the proposed new Adapter dataclass. The implementer must either:
- (a) Introduce the new type under a different module path, re-export as
Adapterin the public surface, OR - (b) Move the old ABC to a private name
The chosen resolution must be documented in the PR description. Both approaches are acceptable; pick one and commit. Until 4.1 removes the shims, both must coexist.
Scope
mellea/backends/adapters/_core.py(or equivalent) — new typesmellea/backends/adapters/roles.py—KNOWN_ROLESmellea/stdlib/components/adapter_based_component/__init__.py— placeholder re-export- Import new types +
KNOWN_ROLESintomellea/backends/adapters/__init__.py - Existing classes (
IntrinsicAdapter, etc.) not modified — that's 1.A
Out of scope
Any caller migration (1.A), binding verb implementations beyond NotImplementedError (Phase 2), shim removal (4.1), catalogue pinning (0.2), IBM rename.
Acceptance criteria
-
Adapter,Identity,IOContract,WeightsBindingimportable frommellea.backends.adapters -
IOContractABC enforces bothbuild_promptandparseas abstract -
WeightsBindingABC enforces all four verbs as abstract -
LocalFileBinding,EmbeddedBinding,ServerMediatedBindingraiseNotImplementedErroron each verb -
AdapterSchemaMismatchErrorhas correct attributes and message format -
from mellea.stdlib.components.adapter_based_component import AdapterBasedComponentworks -
AdapterBasedComponent is Intrinsicevaluates True (same class object) - Old import
mellea.stdlib.components.intrinsicstill works - Naming-collision resolution documented in PR description
-
KNOWN_ROLESimportable;Identity(role="unknown-role")emitsUserWarning;Identity(role="answerability")does not - All existing tests pass unchanged
-
ruff format,ruff check,mypyclean
Test plan
test/backends/adapters/test_core_types.py:
test_adapter_dataclass_constructiontest_identity_validation— adapter_type literal enforcementtest_io_contract_abc_enforcementtest_weights_binding_abc_enforcementtest_stub_binding_subclasses_raise_not_implementedtest_adapter_schema_mismatch_error_format
test/stdlib/components/test_adapter_based_component.py:
test_adapter_based_component_is_intrinsictest_both_import_paths_work
test/backends/adapters/test_roles.py:
test_known_roles_is_frozensettest_unknown_role_warnstest_known_role_does_not_warntest_none_role_does_not_warn
Breaking changes
None for end users. Implementers importing the old Adapter ABC directly may need to update depending on the chosen naming-collision resolution — document in PR.
References
- PR docs: design proposal for adapter lifecycle (#929) — review channel, do not merge #1080 §4, §9, §9.2, Part I §5 Q5
- Epic: Fix Adapter Function Lifecycle & Consistency in Mellea #929 (parent epic)
- add support for granite-switch / embedded adapters on our huggingface backend #1018 — blocked on this scaffolding
- design: adapter output-schema versioning (deferred from #929) #1111 — already filed; needs
AdapterSchemaMismatchErrorfrom this issue
Activity
fix(intrinsics): address review findings on Phase 0 adapter scaffoldi…
feat(intrinsics): introduce Adapter/Identity/IOContract/WeightsBindin…
fix(intrinsics): address review findings on Phase 0 adapter scaffoldi…
refactor(intrinsics): rename adapter role to capability (generative-c…
feat(intrinsics): introduce Adapter/Identity/IOContract/WeightsBindin…
fix(intrinsics): address review findings on Phase 0 adapter scaffoldi…
refactor(intrinsics): rename adapter role to capability (generative-c…
feat(intrinsics): introduce Adapter/Identity/IOContract/WeightsBindin…
fix(intrinsics): address review findings on Phase 0 adapter scaffoldi…
refactor(intrinsics): rename adapter role to capability (generative-c…
feat(intrinsics): introduce Adapter/Identity/IOContract/WeightsBindin…