Repository navigation
refactor(intrinsics): remove deprecation shims; rewrite intrinsics_and_adapters.md; write 3 tutorials (Epic #929 Phase 4) #1144
Description
Parent epic: #929
Design proposal: PR #1080 §16 Phase 4, Part I §5 Q4
Phase: 4 (final)
Depends on: #1141, #1142, #1516, #1465, #1018 — all merged. Deprecation window opened 2026-09-02 (last dependency, #1018/PR #1593); team has decided to proceed now.
Update (2026-09-03) — scope correction: this is not just a deletion
The original scope below assumed callers were "already on new types" and this issue was cleanup. That's false as of 2026-09-03, verified against current main. Neither LocalHFBackend.add_adapter nor OpenAIBackend.add_adapter accepts a composed Adapter (_core.Adapter) directly — both reject it via isinstance gates and raise TypeError. The only working path today for LoRA/embedded intrinsic use is through the three deprecated shim classes (IntrinsicAdapter, EmbeddedIntrinsicAdapter, CustomIntrinsicAdapter), and that's true of production code, not just docs/examples:
AdapterMixin.resolve_adapter()(mellea/backends/adapters/adapter.py:612-724) — the shared lazy-registration path every backend inherits — directly constructsEmbeddedIntrinsicAdapter.from_source(...)(L675) orIntrinsicAdapter(name, adapter_type=AdapterType.LORA, base_model_name=base)(L688).mellea/backends/huggingface.py(LocalHFBackend):add_adapter()(L2375, isinstance gate L2397-2403),register_embedded_adapter_model()(L2442, L2465),load_peft_adapter()(L2493 guard),_generate_from_intrinsic()(isinstance dispatch L891, L932, L1012).mellea/backends/openai.py(OpenAIBackend):add_adapter()(L310, isinstance gate L327 —EmbeddedIntrinsicAdapteris the only accepted reality),register_embedded_adapter_model()(L361, L379),_generate_from_intrinsic()(gates at L760, L784, L884/890),self._added_adapters: dict[str, EmbeddedIntrinsicAdapter]type annotation (L278).- Product-facing, easy to miss:
cli/alora/README_TEMPLATE.jinja(L44, L52) — everym alora upload --intrinsicinvocation generates user scaffolding that subclassesCustomIntrinsicAdapter. This has to change in lockstep with the backend code, not as an afterthought.
Given this, the work splits into two PRs, stacked:
PR1 — build the composed-Adapter-direct path (additive, land first)
Goal: both backends accept a composed Adapter(identity, io_contract, weights_binding) directly, alongside the existing shim path (which keeps working unchanged — no behaviour change for existing callers in this PR).
Code:
LocalHFBackend.add_adapter/OpenAIBackend.add_adapter— extend theisinstancegates to accept a composedAdapterinstance and dispatch correctly (LocalFileBinding→ PEFT path,EmbeddedBinding→ embedded path).AdapterMixin.resolve_adapter()— construct a composedAdapterinstead of the shim classes when registering. (This is the one call site both backends inherit — get this right once.)register_embedded_adapter_model(),load_peft_adapter()(HF only),_generate_from_intrinsic()in both backends — same treatment, dispatch on binding type rather than the shim's own type.cli/alora/README_TEMPLATE.jinja— generate composed-Adapterscaffolding instead of aCustomIntrinsicAdaptersubclass.
Tests (new — none of this exists today, so none of it is covered today):
- Unit tests for the new
isinstance/dispatch branches in both backends. - Integration test exercising the composed path end-to-end through
call_intrinsic/Intrinsic. - A real-GPU e2e case for the composed path, matching the pattern test: intrinsic HF generation (adapter_scope routing) has no real-model e2e coverage #1574/PR test(backends): add real-model GPU e2e for intrinsic adapter_scope routing #1608 established (public API, real model, asserts on hook payload + activation state, not generated content).
- Rewrite the five test files that currently exercise production code through the shim classes to also/instead cover the composed path:
test/backends/test_adapters/test_embedded_integration.py,test/backends/test_openai_intrinsics_unit.py,test/backends/test_huggingface_unit.py,test/backends/test_huggingface.py, and theTestOpenAIBackendRegistrationclass intest/backends/test_adapters/test_embedded_adapter.py.
Docs/examples (8 files):
docs/docs/advanced/intrinsics.md— rewrite the "Composable adapter construction (advanced)" section (currently accurately states neither backend supports this — flip it to the real, working example) and the "Direct adapter function usage" section (currently recommendsCustomIntrinsicAdapterdirectly).docs/docs/advanced/lora-and-alora-adapters.md— "Use the adapter in Mellea" section already self-flags as pending this issue; update it.docs/docs/integrations/openai.md— priority: the "load adapters manually" section has no deprecation caveat today (unlike the other two docs) and reads as the unqualified recommended way. Most likely to mislead someone who reads it before this issue lands.docs/examples/aLora/101_example.py,docs/examples/aLora/README.md,docs/examples/aLora/stembolts_intrinsic.py,docs/examples/granite-switch/manual_adapter_loading.py,docs/examples/granite-switch/README.md,docs/examples/intrinsics/intrinsics.py— all construct a shim class directly as their canonical pattern; update to the composed path.
Tutorials (write here, not deferred to PR2):
- "Adding a custom adapter function in 20 lines" — replaces the
CustomIntrinsicAdaptermonkey-patch story. - "Handling a breaking schema change without breaking users" —
requirement-checkv1→v2 worked example; HF revision pinning andAdapterSchemaMismatchError. - "Reading adapter function telemetry" — dashboard-building guide referencing
mellea.adapter_function.parse_failures,mellea.adapter_function.phase_duration, and the span tree.
PR1 acceptance criteria:
- Both backends accept a composed
Adapterdirectly; existing shim path unchanged/still passing - New unit + integration + real-GPU e2e coverage for the composed path (see Tests above)
- The five shim-routed test files updated to also cover the composed path
- CLI template generates composed-
Adapterscaffolding - All 8 docs/examples files updated;
docs/docs/integrations/openai.mdexplicitly prioritized - All three tutorials written, validated against current source, linked from
docs/docs/advanced/intrinsics.md - markdownlint clean on all touched docs
- Full test suite + mypy + ruff clean (existing CI gate — no new exemptions)
PR2 — delete the shims (stacked on PR1)
Goal: remove the now-genuinely-unused deprecated path. This PR's own green CI run against PR1-merged-into-main is the actual proof "we have no use left" — that's the validation, not a comment claiming it.
Code:
- Delete
IntrinsicAdapter,EmbeddedIntrinsicAdapter,CustomIntrinsicAdapter(mellea/backends/adapters/adapter.py) and their re-exports inmellea/backends/adapters/__init__.py. - Remove the now-dead
isinstancebranches in both backends that PR1 made redundant.
Tests:
- Delete outright (these test the shim's own deprecated behaviour, not anything that survives):
test/backends/test_adapters/test_shims.py,test/backends/test_adapters/test_adapter.py, and thefrom_hub/from_model_directory/construction tests intest/backends/test_adapters/test_embedded_adapter.py(keep any parts of that file that ended up testing the composed path instead, if PR1 added them there).
Final sweep (required, full-repo, not spot-check):
- Re-run the same method used to scope this issue —
gh api search/codeforIntrinsicAdapter,EmbeddedIntrinsicAdapter,CustomIntrinsicAdapteracrossgenerative-computing/mellea— confirm zero hits outside historical/changelog text anddocs/versioned_docs/(old version snapshots, out of scope). - Confirm
mellea/stdlib/components/intrinsic/intrinsic.py's module docstring (currently referencesIntrinsicAdapterdescriptively) is updated. - Changelog entry: removal + migration note (import path change).
PR2 acceptance criteria:
- Shim classes and re-exports removed
- Full-repo sweep shows zero remaining references (code, docs, examples, CLI templates) outside changelog/historical text
- Shim-behaviour test files deleted; nothing left asserting deprecated-class behaviour
- Changelog entry with migration note
- Full test suite + mypy + ruff clean
- Closes this issue; triggers epic Epic: Fix Adapter Function Lifecycle & Consistency in Mellea #929 status reconciliation
Out of scope (either PR)
- IBM adapter-function symbol rename — separate issue if not confirmed by the time this lands.
- Any new functionality beyond the composed-path parity described above.
- Epic Epic: Fix Adapter Function Lifecycle & Consistency in Mellea #929 items 3a (adapter name vs.
intrinsic_name, still an open question per the epic's original text) and 6 (catalog removal/repurpose) — neither is resolved by this issue; flag separately if the epic is to close around this issue's completion.
Not part of this issue (confirmed clean elsewhere)
generative-computing/mellea-contribs— checked 2026-09-03, zero references to any of the three shim classes or old catalog-construction patterns. Nothing there needs updating.
References
- PR docs: design proposal for adapter lifecycle (#929) — review channel, do not merge #1080 §16 Phase 4, §15 (tutorial list), Part I §5 Q4
- Full shim-usage inventory (this update's line numbers) verified against
mainon 2026-09-03 viagh api search/codeacross all three class names, all pages, no truncation.
Activity
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).planetf1 commentedon Jun 11, 2026
Scope note from #1192: The Phase 0 terminology sweep (#1192 / PR #1256) intentionally left
docs/dev/intrinsics_and_adapters.mdand ~15 other published doc pages (docs/docs/advanced/intrinsics.md,lora-and-alora-adapters.md, etc.) untouched — these contain substantial prose that belongs in this issue's broader rewrite scope. When picking up #1144, those pages will need the same vocabulary pass applied as part of the full rewrite.chore(terminology): adopt agreed Granite Switch / Mellea glossary (ge…
chore(terminology): sweep Guardian Intrinsics → Guardian adapter func…
chore(terminology): address review findings from generative-computing…
chore(terminology): adopt agreed Granite Switch / Mellea glossary (ge…
chore(terminology): sweep Guardian Intrinsics → Guardian adapter func…
chore(terminology): address review findings from generative-computing…
18 remaining items
fix: address remaining review suggestions on aLora examples
fix: rewrite broken aLora 101 example for the intrinsics API (generat…
planetf1 commentedon Aug 27, 2026
Scope clarification
#1018 may add LocalHF embedded-adapter support through the existing compatibility shims. Before #1144 removes
IntrinsicAdapter,EmbeddedIntrinsicAdapter, andCustomIntrinsicAdapter, backend generation paths must stop reading shim-only state such as.configand use the composed adapter representation:identity,io_contract, andweights.This is an internal compatibility migration required for shim removal. It does not require #1018 to expose a new generic registration API.
For #1144, the supported replacement for
CustomIntrinsicAdaptershould be a composedAdapter, not another custom shim or catalogue mutation. A backend should accept a composed adapter only when its weights binding is a reality that backend supports. The generic adapter-function component is currently instantiated asIntrinsic("my-capability"); high-level helpers continue to target only their canonical adapter functions.Embedded-adapter discovery must retain the existing convenience path while replacing
EmbeddedIntrinsicAdapter.from_source()with a non-shim factory that readsadapter_index.jsonandio.yamlinto an identity, a concrete I/O contract, and an embedded binding.Telemetry is out of scope for both migrations. #1018 reuses
EmbeddedBinding.apply_activation()unchanged; lifecycle observability remains tracked in #1466.Add these acceptance criteria:
Adapter, without a shim class or catalogue mutation.Intrinsicappears only as the current Python symbol.planetf1 commentedon Sep 2, 2026
Tracking note (2026-09-02): all listed dependencies (#1141, #1142, #1516, #1465, #1018) are now merged — #1018 was the last, via PR #1593 (merged 2026-09-02). Per this issue's stated policy, the deprecation window (≥1 minor release, ≈4–6 weeks) starts today, 2026-09-02. Earliest start: ~mid-to-late October 2026, pending confirmation the window has actually elapsed and no user impact warrants extending it. Not code-blocked, time-blocked.
fix(backends): fix Qwen-review findings on composed-Adapter path (gen…
fix(backends): fix Bob-round-2 findings on composed-Adapter path (gen…
planetf1 commentedon Sep 4, 2026
#1619 now completes the work here, effectively closing the epic.
There remains #1621 which will remove deprecated shims at a future point
feat(backends): accept composed Adapter directly (Epic generative-com…
docs(adapters): trim transient issue references from aLoRA guard docs
fix(adapters): raise or fall back when an aLoRA cannot activate (gene…
fix(adapters): raise or fall back when an aLoRA cannot activate (gene…
fix(adapters): raise or fall back when an aLoRA cannot activate (gene…
fix(adapters): raise or fall back when an aLoRA cannot activate (gene…