Skip to content

Epic: Fix Adapter Function Lifecycle & Consistency in Mellea #929

Description

@jakelorocco

Resolve systemic issues with how adapter functions are loaded, invoked, and configured across backends. We should finalize a design for the below points and then create issues for that finalized implementation.

Initial implementation of EmbeddedIntrinsicAdapters in: #881
Initial removal of OpenAI adapters: #543

  1. Adapter Loading & Unloading
    a. Clean up divergent control flow between EmbeddedAdapters and regular adapter function loading.
    b. Fix bug where obtain_lora is always called during call_intrinsic when embedded_adapters=False, which masks the real error from users and conflicts with different loading methods.
    c. Address that adapter loading/unloading is both backend-specific and adapter-type-specific — design a coherent abstraction for this.

  2. Model Option Handling
    a. Fix adapter function rewriters overwriting model options unconditionally.
    b. Decide and document how adapter functions should interact with model options.
    c. There's a larger question of hierarchy with model options as well. Model options can technically be defined in all the following places: hf base model defaults in generation_config.json, adapter defaults in generation_config.json, io.yaml defaults, io.yaml values specified in the Mellea adapter function, mellea model options.

  3. Naming Consistency
    a. Resolve whether adapter name must equal adapter.intrinsic_name or can differ (open issue).
    b. Standardize usage of "adapter name", "adapter function name", and "qualified name" across the codebase.
    c. refactor(intrinsics): decouple capability registry from catalog entry names (Epic #929 Phase 0) #1186 Decouple the capability registry from catalog entry names — Phase 0 follow-up. The rolecapability rename is merged in feat(intrinsics): introduce Adapter/Identity/IOContract/WeightsBinding scaffolding (Epic #929 Phase 0) #1134 (PR feat(intrinsics): introduce Adapter/Identity/IOContract/WeightsBinding scaffolding (Epic #929 Phase 0) #1158); the catalog-side decoupling is next in sequence once fix(intrinsics): pin catalogue entries to HF revision SHAs + deduplicate requirement_check (#1135) #1157 (fix(intrinsics): pin catalogue entries to HF revision SHAs + deduplicate requirement_check entries (Epic #929 Phase 0) #1135) and feat(intrinsics): introduce Adapter/Identity/IOContract/WeightsBinding scaffolding (Epic #929 Phase 0) #1158 (feat(intrinsics): introduce Adapter/Identity/IOContract/WeightsBinding scaffolding (Epic #929 Phase 0) #1134) merge.
    d. fix(adapters): correct IntriniscsCatalogEntry class name typo (Epic #929 Naming) #1268 Fix IntriniscsCatalogEntry class name misspelling (Intriniscs → Intrinsics) — mechanical rename across 5 files; do after chore(terminology): adopt agreed Granite Switch / Mellea glossary (#1192) #1256 and refactor(adapters): decouple KNOWN_CAPABILITIES from catalog entry names (#1186) #1266 merge.

  4. Output Parsing & Generic Adapter Function Contracts
    a. Address the problem where top-level call_intrinsics helpers assume a single output structure (e.g., result_json["answerability"] vs result_json["answerability_likelihood"]). We likely need to work with the Granite Switch team here to set common assumptions.
    b. Determine whether all adapters of a given type must conform to a standard output schema (e.g., a single output field, required keys) or whether parsing should be adapter-specific.
    c. This also encompasses "versioning" of adapter functions. The same adapter function may be updated / changed to have a different expected output format and our top-level call_intrinsic functions only allow one version.

  5. OpenAI Backend Support
    a. Add OpenAIAdapters back — requires discussion on the logic for pulling/registering these. EmbeddedIntrinsicAdapters should technically inherit from these.

  6. Cleanup
    a. Remove or repurpose the catalog. We shouldn't mandate all adapter functions be part of the known catalog.

Settled design decisions

Phase Tracker

Phase Issue Title Status Depends on
0 #1186 Decouple KNOWN_CAPABILITIES from catalog names ✅ Merged
0 #1135 Catalogue revision pinning + deduplication ✅ Merged
0 #1134 Scaffolding: Adapter / Identity / IOContract / WeightsBinding ✅ Merged
0 #1192 Terminology sweep (docs/docs + backends) ✅ Merged
1 #1136 Internal shims + call_intrinsic rewrite ✅ Merged (PR #1269)
1 #1137 rag.py whole-file migration ✅ Merged (PR #1321) #1136
1 #1138 requirement_check migration ✅ Merged (PR #1320) #1136
1 #1139 guardian.py migration (behavioural) ✅ Merged (PR #1323) #1136
1 #1332 guardian.py IOContract subclasses + Adapter constants ✅ Merged (PR #1357) #1139, #1137
2 #1140 AdapterMixin verb narrow + resolve_model_options + AdapterFunctionMetricsPlugin ✅ Merged (PR #1422) Phase 1
2 #1141 LocalFileBinding verbs (PEFT / aLoRA path) + from_catalog() ✅ Merged (PR #1454, 2026-08-17) #1140
2 #1142 EmbeddedBinding implements apply_activation; remove render_controls + set_request_adapter ✅ Merged (PR #1559, 2026-08-26) #1134, #1140
2 #1516 Resolve the output contract from the adapter, not a parallel argument ✅ Merged (PR #1556, 2026-08-25)
2 #1465 Route intrinsic generation through adapter_scope; fix lock reentrancy ✅ Merged (PR #1555, 2026-08-25) #1141
2 #1560 Wire real adapter_function_invocation_complete outcome for Embedded activation 🔄 PR #1609 approved, finishing CI/merge queue #1465
cross-cutting #1464 Document + enforce the hook/plugin span-production rule ✅ Closed — intentionally dropped after PR #1545 review; source guidance is sufficient
2 #1528 release() leaves the adapter registered — and is a binding reusable after release() at all? ✅ Merged (PR #1554, 2026-08-24)
2 #1561 IntrinsicAdapter.__init__ sets Identity.capability from the raw catalogue name, not effective_capability 🗑️ Closed as duplicate of #1563 (2026-08-21)
2 #1562 resolve_adapter() registers into _added_adapters outside _generation_lock 🔄 PR #1607 approved, finishing CI/merge queue #1465
2 #1563 Adapter shim Identity uses catalog name instead of effective_capability, causing spurious KNOWN_CAPABILITIES warnings ✅ Merged (PR #1580, 2026-08-25)
2 #1575 OpenAIBackend: user-supplied model in model_options collides with the hardcoded model kwarg ✅ Merged (PR #1578, 2026-08-25)
3 #1018 EmbeddedBinding × LocalHFBackend — acceptance test for #1486's shape ✅ Merged (PR #1593, 2026-09-02) #1142
2+ #1574 Real-model GPU e2e for the intrinsic HF path (adapter_scope routing) 🔄 PR #1608 approved, finishing CI/merge queue #1465
cleanup #1268 Fix IntriniscsCatalogEntry class name typo ✅ Merged (PR #1370)
cleanup #1279 Terminology prose sweep (docs/examples/ + docstrings) ✅ Merged (PR #1322)
cleanup #385 Fix broken aLora example ✅ Merged (PR #1557, 2026-08-24) #1141
cleanup #1338 Remove deprecated check_context_relevance and its adapter ✅ Merged (PR #1579, 2026-08-25)
cleanup #1412 Promote _DictContract to shared adapters module; collapse guardian.py's duplicate factuality contracts ✅ Merged (PR #1428)
cleanup #1413 Document policy_guardrails exception-type change (ValueErrorAdapterSchemaMismatchError) ✅ Merged (PR #1427)
4 (final) #1144 Build composed-Adapter-direct backend support, then remove deprecation shims 🏗️ In progress — spec rewritten 2026-09-03 (real scope: backend build, not just deletion; see issue for full detail). Two stacked PRs: PR1 additive (backend + docs + tutorials + CLI template + tests), PR2 deletion (shim removal, stacked on PR1) #1141, #1142, #1516, #1465, #1018 (all merged)
deferred #1358 validate() should surface parse errors as a third outcome, not raise ✅ Merged (PR #1591, 2026-08-27) #1516
#1611 IOContract mismatches record success in embedded invocation-complete outcome ⬜ New — surfaced during #1560/PR #1609, filed as a separate follow-on #1560

Statuses and the "Depends on" column were reconciled against live issue, pull-request, and formal-dependency state on 2026-09-03. #1560, #1562, and #1574 all have approved PRs (#1609, #1607, #1608) finishing CI/merge queue — no code work left, just merge. #1111 has been unlinked from this epic (see Settled design decisions) and no longer appears in this tracker. #1144 is now the epic's only remaining active item — its scope was corrected today after research showed neither backend accepts a composed Adapter directly yet, so it's genuinely the epic's last unbuilt piece, not cleanup.

"⬜ Open, unclaimed" means no PR exists yet, not that the issue is unassigned.

Current status (reconciled 2026-09-03)

#1018 is merged. #1560, #1562, and #1574 are approved and finishing CI/merge queue — nothing left to do but merge. #1144 is now the epic's sole remaining active work: rewritten with a full stacked-PR spec (PR1 builds the composed-Adapter-direct path both backends currently lack, plus tests/docs/tutorials/CLI-template updates; PR2, stacked on PR1, deletes the three deprecated shim classes once nothing references them). #1111 removed from formal tracking, left open standalone. #1466 was already removed from formal tracking (2026-08-27, confirmed unlinked both directions) and isn't part of this epic.

Suggested order

  1. Merge fix(backends): fire adapter_function_invocation_complete for embedded adapter calls #1609, fix(backends): serialize resolve_adapter() registration under the activation lock #1607, test(backends): add real-model GPU e2e for intrinsic adapter_scope routing #1608 (all approved, finishing CI).
  2. Execute refactor(intrinsics): remove deprecation shims; rewrite intrinsics_and_adapters.md; write 3 tutorials (Epic #929 Phase 4) #1144's PR1 (additive), then PR2 (deletion, stacked) — see refactor(intrinsics): remove deprecation shims; rewrite intrinsics_and_adapters.md; write 3 tutorials (Epic #929 Phase 4) #1144 for the full spec.
  3. Once refactor(intrinsics): remove deprecation shims; rewrite intrinsics_and_adapters.md; write 3 tutorials (Epic #929 Phase 4) #1144/PR2 merges, this epic's numbered scope is structurally complete; close Epic: Fix Adapter Function Lifecycle & Consistency in Mellea #929.

Activity

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, vLLMenhancementNew feature or requestepicHigh level Epicp1High: important bugs (workaround exists) or high-value core features. Do soon, not on fire.

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions