feat(backends): EmbeddedBinding implements apply_activation (Granite Switch path); remove render_controls + set_request_adapter (Epic #929 Phase 2) - #1559
Open
planetf1 wants to merge 13 commits into
Conversation
planetf1
added a commit
to planetf1/mellea
that referenced
this pull request
Aug 20, 2026
…date build_prompt message Continues the multi-party review follow-ups on this PR (issue generative-computing#1516): - rag.py / guardian.py: drop the ten module-level Adapter constants. Their only purpose (feeding io_contract= to call_intrinsic) was removed by the earlier commits, nothing in production references them, and the generative-computing#1141/generative-computing#1142 weights work builds on the binding classes (PR generative-computing#1454 merged, PR generative-computing#1559 open) rather than on these constants — whose underscore capability axis would never match _find_adapter's name-keyed scan anyway. test_rag_contracts.py / test_guardian_io_contract.py now look contracts up via get_io_contract(), exercising the registry directly. - _core.py NOTE(generative-computing#1516): re-pointed at the remaining placeholder constructions (the core.py _REQUIREMENT_CHECK_ADAPTER test stub and the shims' _ShimWeightsBinding). - core.py: comment no longer assumes the rag/guardian sibling constants are kept. - build_prompt NotImplementedError message consolidated into the _BUILD_PROMPT_NOT_IMPLEMENTED constant (was five copies). - _util.py: call_intrinsic's Raises ValueError entry now covers well-formed JSON with a contract-rejected top-level shape. Assisted-by: opencode Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
planetf1
marked this pull request as ready for review
August 20, 2026 14:46
This was referenced Aug 20, 2026
planetf1
added a commit
to planetf1/mellea
that referenced
this pull request
Aug 21, 2026
…date build_prompt message Continues the multi-party review follow-ups on this PR (issue generative-computing#1516): - rag.py / guardian.py: drop the ten module-level Adapter constants. Their only purpose (feeding io_contract= to call_intrinsic) was removed by the earlier commits, nothing in production references them, and the generative-computing#1141/generative-computing#1142 weights work builds on the binding classes (PR generative-computing#1454 merged, PR generative-computing#1559 open) rather than on these constants — whose underscore capability axis would never match _find_adapter's name-keyed scan anyway. test_rag_contracts.py / test_guardian_io_contract.py now look contracts up via get_io_contract(), exercising the registry directly. - _core.py NOTE(generative-computing#1516): re-pointed at the remaining placeholder constructions (the core.py _REQUIREMENT_CHECK_ADAPTER test stub and the shims' _ShimWeightsBinding). - core.py: comment no longer assumes the rag/guardian sibling constants are kept. - build_prompt NotImplementedError message consolidated into the _BUILD_PROMPT_NOT_IMPLEMENTED constant (was five copies). - _util.py: call_intrinsic's Raises ValueError entry now covers well-formed JSON with a contract-rejected top-level shape. Assisted-by: opencode Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
… construction onto separate lines Prep step for Epic generative-computing#929 Phase 2: generative-computing#1516 and generative-computing#1142 both need to change one of io_contract/weights on the same call and the same docstring paragraph. This splits each into its own local variable/bullet, separated by blank lines, so the two PRs no longer touch adjacent lines and can merge in either order. No behavior change. Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
…ender_controls + set_request_adapter (Epic generative-computing#929 Phase 2) EmbeddedBinding gets one method, apply_activation(request, identity), for adapters embedded in the served base model (Granite Switch) — there is no weights lifecycle to prepare/activate/deactivate/release, only a field on the outgoing request. OpenAIBackend's inline isinstance(adapter, EmbeddedIntrinsicAdapter) block that wrote chat_template_kwargs.adapter_name and dropped the rewriter-set model param is now owned by the binding, reached through EmbeddedIntrinsicAdapter.weights. Removes the two dead activation methods the previous scope was built around (AdapterMixin.render_controls, AdapterMixin.set_request_adapter) along with OpenAIBackend's no-op render_controls override — neither had a working implementation or caller. adapter_scope() now rejects a non-WeightsBinding adapter with a clear TypeError instead of an AttributeError, since EmbeddedBinding has no activate()/deactivate() to scope. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
generative-computing#1142) Adds an Embedded/Granite Switch construction example to docs/docs/advanced/intrinsics.md (Adapter(weights=EmbeddedBinding.from_base_model(backend))) alongside the existing LocalFileBinding one, plus a backend x reality support matrix. Adds a weights-binding shapes reference table to AGENTS.md Section 14, comparing LocalFileBinding's activate()/deactivate() lifecycle against EmbeddedBinding's single apply_activation(request, identity) request edit. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
…ation Independent review (3 perspectives) found one BLOCKER and several correctness/design issues in the initial generative-computing#1142 implementation, all verified against the pinned source before fixing: - BLOCKER: apply_activation fired its two telemetry hooks via _run_async_in_thread from inside an already-running coroutine (OpenAIBackend._generate_from_intrinsic), spawning a throwaway asyncio loop + daemon thread per call that was never reclaimed (10 calls with metrics enabled leaked 20 threads, confirmed independently). Fixed by making apply_activation async and awaiting invoke_hook directly. - WARNING: apply_activation fired adapter_function_invocation_complete with outcome="success" hardcoded, before generation/parsing (which OpenAIBackend resolves lazily) could possibly have failed. Fixed by no longer firing invocation_complete from apply_activation -- only phase_complete (phase="activate"), which the method genuinely completes. Wiring a real invocation-complete signal in requires the caller to fire it once generation/parsing resolve; documented as a follow-up rather than solved here. - WARNING: EmbeddedActivationRequest, required to call the public apply_activation, wasn't exported from mellea.backends.adapters. Exported it and switched openai.py to import both it and EmbeddedBinding from the public package. - Hardened the openai.py activation branch with an explicit else: raise TypeError for a reassigned .weights (previously would have silently skipped activation), and wired base_model_name into EmbeddedBinding.source in OpenAIBackend.add_adapter (was always ""). - Added the missing adapter_scope TypeError regression test, fixed a _fire_phase_complete naming collision (same name, different first parameter, across two binding classes), corrected the docs' composable-construction example (built a backend it never bound, and implied backend support the code doesn't have), dropped a misapplied openai backend marker from a fully-mocked integration test, and removed a duplicate integration test. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
…ards - Restate the composable-construction callout in intrinsics.md per backend: OpenAIBackend.add_adapter accepts only the deprecated EmbeddedIntrinsicAdapter shim, not a raw weights binding. - Pair the LocalFileBinding example's identity with the LoRA adapter type that from_catalog actually loads (first catalog-listed type), and give the OpenAIBackend example an explicit api_key. - Document the NotImplementedError cases in _generate_from_intrinsic's Raises section. - Pin the registration-time source stamp and the reassigned-.weights fail-loud TypeError in the embedded integration test. Assisted-by: opencode Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
The registration method mutates the caller's EmbeddedBinding (stamping base_model_name into source) but its docstring did not say so; the sibling LocalHFBackend.add_adapter documents its side effects explicitly. Assisted-by: opencode Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
…acker refs The IntrinsicAdapter/EmbeddedIntrinsicAdapter notes and the _Shim* placeholders cited Phase-2 plans and issue numbers that had gone stale (generative-computing#1137 is closed and out of scope; generative-computing#1141 shipped without replacing the shims). Both shim notes now state current behaviour only and agree with each other; the shim raise messages drop the phase/issue prefixes. test_shims.py's message match follows the new wording. Shims themselves are slated for removal, so no forward references are introduced. Assisted-by: opencode Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
- test_embedded_binding.py: import from the public package (sibling style); pin the dispatched HookType in the phase-complete test (a payload-similar hook type would otherwise pass); pin the explicit chat_template_kwargs=None branch; use the module-level HookType import. - EmbeddedBinding.source docstring: state what is actually recorded (the backend's base_model_name, stamped by OpenAIBackend.add_adapter) instead of a future span attribute. - _ShimIOContract docstring: 'intrinsic adapter shims' — the class is used by both deprecated shims, not IntrinsicAdapter alone. - adapter_scope docstring: docs/dev/adapter_observability.md no longer exists; point at the metric schema's actual home (AdapterFunctionMetricsPlugin in mellea/telemetry/metrics_plugins.py). Assisted-by: opencode Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
…ing#1516, not generative-computing#1142) Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
planetf1
added a commit
to planetf1/mellea
that referenced
this pull request
Aug 21, 2026
…date build_prompt message Continues the multi-party review follow-ups on this PR (issue generative-computing#1516): - rag.py / guardian.py: drop the ten module-level Adapter constants. Their only purpose (feeding io_contract= to call_intrinsic) was removed by the earlier commits, nothing in production references them, and the generative-computing#1141/generative-computing#1142 weights work builds on the binding classes (PR generative-computing#1454 merged, PR generative-computing#1559 open) rather than on these constants — whose underscore capability axis would never match _find_adapter's name-keyed scan anyway. test_rag_contracts.py / test_guardian_io_contract.py now look contracts up via get_io_contract(), exercising the registry directly. - _core.py NOTE(generative-computing#1516): re-pointed at the remaining placeholder constructions (the core.py _REQUIREMENT_CHECK_ADAPTER test stub and the shims' _ShimWeightsBinding). - core.py: comment no longer assumes the rag/guardian sibling constants are kept. - build_prompt NotImplementedError message consolidated into the _BUILD_PROMPT_NOT_IMPLEMENTED constant (was five copies). - _util.py: call_intrinsic's Raises ValueError entry now covers well-formed JSON with a contract-rejected top-level shape. Assisted-by: opencode Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
jakelorocco
reviewed
Aug 24, 2026
Comment on lines
+774
to
+784
| # rather than silently skip activation and send an unactivated request. | ||
| if isinstance(adapter.weights, EmbeddedBinding): | ||
| activation_request = EmbeddedActivationRequest( | ||
| extra_body=extra_body, api_params=api_params | ||
| ) | ||
| await adapter.weights.apply_activation(activation_request, adapter.identity) | ||
| else: | ||
| raise TypeError( | ||
| f"EmbeddedIntrinsicAdapter.weights must be an EmbeddedBinding; " | ||
| f"got {type(adapter.weights).__name__}. Activation cannot proceed." | ||
| ) |
Contributor
There was a problem hiding this comment.
Nit: can we change this to be if not isinstance(...): raise TypeError and then unindent the code that's currently in the if branch?
Assisted-by: Codex Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
Keep main's remove_adapter coverage while retaining generative-computing#1559's removal of obsolete request-control verbs. Assisted-by: Codex Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
Assisted-by: Codex Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
planetf1
added a commit
to planetf1/mellea
that referenced
this pull request
Aug 25, 2026
…adapter, not a parallel argument (generative-computing#1556) * chore(adapters): split EmbeddedIntrinsicAdapter's io_contract/weights construction onto separate lines Prep step for Epic generative-computing#929 Phase 2: generative-computing#1516 and generative-computing#1142 both need to change one of io_contract/weights on the same call and the same docstring paragraph. This splits each into its own local variable/bullet, separated by blank lines, so the two PRs no longer touch adjacent lines and can merge in either order. No behavior change. Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * test(adapters): add canonical per-adapter-function output-contract registry Introduces mellea/backends/adapters/io_contracts.py: a capability-keyed registry of IOContract instances, keyed by the same catalog name passed to call_intrinsic() and resolve_adapter(). Moves _ListContract (from rag.py) next to the existing _DictContract in _core.py, adds the guardian-specific contracts, and adds _RequirementCheckContract to consolidate the score-range validation core.requirement_check() previously hand-rolled after each call. This is the single source of truth a later commit wires resolve_adapter() and the intrinsic helpers to consume, instead of each declaring its own IOContract instance that could silently drift from the other's. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * refactor(intrinsics): resolve the output contract from the adapter, not a parallel argument call_intrinsic() resolved the adapter and discarded it, taking the output contract instead as a separate io_contract= argument that each caller supplied from its own module-level Adapter constant. Nothing tied the two together, so a caller could pass a contract that didn't match the adapter resolve_adapter() actually returned. call_intrinsic() now keeps the adapter resolve_adapter() returns and calls its own io_contract.parse() on the raw output; the io_contract= parameter is gone, so a mismatched pair is no longer expressible. IntrinsicAdapter and EmbeddedIntrinsicAdapter (the shims resolve_adapter() constructs) now look up their contract in the io_contracts registry instead of the _ShimIOContract placeholder, which is now unreachable and removed. The ten module-level Adapter constants in rag.py/guardian.py keep their identity and weights as before, and read io_contract from that same registry rather than declaring their own instance. core.py's three helpers (check_certainty, requirement_check, find_context_attributions) previously had no declared contract at all — the first two skipped validation (raw json.loads), and requirement_check hand-rolled its own score-range check after the call. All three now have a declared contract in the registry; requirement_check's hand-rolled validation is replaced by _RequirementCheckContract, and find_context_attributions reads its now-list-wrapped result via ["items"]. Weights binding is untouched — this stays entirely on the io_contract axis (the design discussion in generative-computing#1486 that split the two). The ten constants' placeholder LocalFileBinding() and the backed-out Adapter.__post_init__ cross-check remain future work, as noted in _core.py. Verified against real granite-4.1-3b weights: test/stdlib/components/ intrinsic/test_core.py, test_rag.py, and test_guardian.py (qualitative, GPU-gated) all pass on this run — 3 passed + 2 pre-existing xfails (non-deterministic attribution count, tracked separately) for core.py, 14/14 for rag.py, 6/6 for guardian.py. No test constructs a resolve_adapter() result carrying the old placeholder contract; test_io_contracts.py's registry-completeness test guards that going forward. Fixes generative-computing#1516 Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * refactor(intrinsics): address code review — export registry, drop dead constants, fix real duplicate Three independent reviewers found the same gap from different angles: the registry this PR introduces to close the parallel-declaration problem still had one. mellea/stdlib/requirements/requirement.py's requirement_check_to_bool() hand-rolled the exact score-range validation just consolidated into _RequirementCheckContract, with a comment pointing at code this PR deleted from core.py. It now delegates to get_io_contract("requirement-check").parse(), which is a strict improvement on its undocumented AttributeError-on-non-dict failure mode (now the documented ValueError the contract raises). Also, per review: - Export get_io_contract from mellea.backends.adapters.__init__ (and __all__), matching the sibling adapter-package imports. Unexported, it was invisible to the docs pipeline (io_contracts.mdx was pruned as "not imported by __init__.py") and to the AGENTS.md-mandated docstring quality gate, despite being the function the module's own docstring designates as the mandatory entry point. - Delete _UNCERTAINTY_ADAPTER and _CONTEXT_ATTRIBUTION_ADAPTER from core.py: nothing referenced them — their only purpose (supplying io_contract= to call_intrinsic) was exactly what the prior commit removed. Keep _REQUIREMENT_CHECK_ADAPTER, which test_core_schema.py uses as a resolve_adapter() stub. - Add a regression test per shim class (test_shims.py) asserting IntrinsicAdapter/EmbeddedIntrinsicAdapter carry the real registry contract, not a placeholder. Without it, reverting get_io_contract(intrinsic_name) back to a stub would have passed every existing test in the file. Verified by temporarily reintroducing a stub object in place of get_io_contract(): both new tests failed as expected, then passed again once reverted. - Enforce the registry's exhaustiveness over known_intrinsic_names() at import time in io_contracts.py, mirroring the existing duplicate-effective_capability check in catalog.py, rather than relying solely on a test. - Correct test_core_schema.py's module docstring, which claimed resolve_adapter itself runs; only its stubbed return value does. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * refactor(intrinsics): apply remaining review suggestions and nits Follow-up to the review response commit — the lower-severity items all three reviewers raised, applied where they were cheap and genuinely useful: - adapter.py: convert the remaining `.. deprecated::` RST directives on IntrinsicAdapter/EmbeddedIntrinsicAdapter to Google-style `Deprecated:` sections, matching the `Note:` conversion already done on the same docstrings. (CustomIntrinsicAdapter's directive is untouched by this diff and left alone.) - _core.py / io_contracts.py: replace the stale "not used in Phase 1; implemented in Phase 2" build_prompt placeholder message — self-contradictory now that this module *is* the Phase 2 work — with an accurate description of the current state. Updated the one test asserting on the old wording. - _core.py: module docstring now names _ListContract and explains the generic-vs-capability-specific split with io_contracts.py. - io_contracts.py: get_io_contract's docstring now states its keys are catalog `name`s, not `effective_capability` tokens, and corrects "permissive" to mean permissive about which keys are present, not about the JSON shape. Added the matching inline comment on the fallback return. - io_contracts.py: comment distinguishing the two AdapterSchemaMismatchError raise sites in _PolicyGuardrailsContract (neither key present vs. both). _RequirementCheckContract's docstring now names both production consumers it consolidates (core.py and requirement.py) with full paths. - test_io_contracts.py: new non-GPU test feeding the recorded context-attribution model output (test/stdlib/components/intrinsic/testdata) through the real contract. The GPU-gated equivalent is xfail(strict=False) for unrelated non-determinism, so it gives no CI signal on schema drift; this closes that gap without a GPU. Assisted-by: Claude Code Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * test(intrinsics): add contract-wiring tests and fix docstring accuracy Applies the multi-party review findings on this PR (issue generative-computing#1516): - test_core_contracts.py: CI-runnable wiring tests for check_certainty and find_context_attributions — the two helpers that moved to registry-contract validation (plus the items unwrap) with only GPU-gated qualitative/xfail coverage before - test_requirement.py: cover the newly-typed ValueError for non-object JSON in requirement_check_to_bool (was an undocumented AttributeError) - test_io_contracts.py: guard the reverse direction of the registry exhaustiveness invariant (orphan keys) - core.py: the new Raises: ValueError entries were narrower than the contracts' actual raise paths (wrong top-level shape is also ValueError) - io_contracts.py: the string literal after the registry assignment was a dead expression — dicts have no docstring; make it a comment - test_rag_contracts.py / test_guardian_io_contract.py: the contracts no longer live in rag.py/guardian.py (Phase 1 -> io_contracts.py, generative-computing#1516) - rag.py / guardian.py / core.py: state consistently that the per-helper Adapter constants are weights scaffolding for generative-computing#1141/generative-computing#1142, not a second contract source Assisted-by: opencode Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * refactor(intrinsics): drop dead per-helper Adapter constants, consolidate build_prompt message Continues the multi-party review follow-ups on this PR (issue generative-computing#1516): - rag.py / guardian.py: drop the ten module-level Adapter constants. Their only purpose (feeding io_contract= to call_intrinsic) was removed by the earlier commits, nothing in production references them, and the generative-computing#1141/generative-computing#1142 weights work builds on the binding classes (PR generative-computing#1454 merged, PR generative-computing#1559 open) rather than on these constants — whose underscore capability axis would never match _find_adapter's name-keyed scan anyway. test_rag_contracts.py / test_guardian_io_contract.py now look contracts up via get_io_contract(), exercising the registry directly. - _core.py NOTE(generative-computing#1516): re-pointed at the remaining placeholder constructions (the core.py _REQUIREMENT_CHECK_ADAPTER test stub and the shims' _ShimWeightsBinding). - core.py: comment no longer assumes the rag/guardian sibling constants are kept. - build_prompt NotImplementedError message consolidated into the _BUILD_PROMPT_NOT_IMPLEMENTED constant (was five copies). - _util.py: call_intrinsic's Raises ValueError entry now covers well-formed JSON with a contract-rejected top-level shape. Assisted-by: opencode Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * docs(intrinsics): document registered-adapter contract precedence call_intrinsic now parses via the resolved adapter's io_contract, so a user-registered Adapter for a catalog name takes precedence over the io_contracts registry for parsing. State that in the registry's module docstring and in call_intrinsic, where the single-source-of-truth claim otherwise overreaches for the registered-adapter path. Assisted-by: opencode Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * docs(intrinsics): fix increment review findings — stale docs, unguarded stub, missing negative test Closes out the 3-party review of the follow-up increment (b88b17d..50ff6a5): - io_contracts.py: the module docstring still described the constant carrying model the increment deleted (and contradicted the precedence paragraph three lines below); re-point at the shims and the core.py test stub as the construction-time readers - _core.py: NOTE(generative-computing#1516) claimed the shims would make the backed-out type-agreement check fire; _ShimWeightsBinding has no adapter_type to compare and shim identities track the configured type — split the two cases - test_core_schema.py: pin _REQUIREMENT_CHECK_ADAPTER to the registry instance (the is get_io_contract(...) guard test_shims.py established was not extended to the one non-shim construction that survived) - test_io_contracts.py: negative test for the context-attribution contract's required item keys (every sibling contract has one; shrinking the frozenset used to pass the whole suite) - rag.py / guardian.py: complete the Raises ValueError accuracy pass the increment started on core.py/_util.py — dict contracts are not a JSON object, list contracts are not a JSON array / non-object element - _util.py: the new Raises clause now covers the array element case, and says 'same capability' (the field _find_adapter actually matches) - small wording fixes: 'only other tests' (docs/examples e2e runs also exist), missing relative pronoun in two docstrings, and the issue reference form in the two rewritten test headers Assisted-by: opencode Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> * fix(intrinsics): address remaining contract review feedback Move the requirement-check adapter stub into its test, scope registry invariants to built-in catalogue entries, and distinguish policy-guardrails exclusivity errors.\n\nAssisted-by: Codex Signed-off-by: Nigel Jones <jonesn@uk.ibm.com> --------- Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
jakelorocco
approved these changes
Aug 25, 2026
Assisted-by: Codex Signed-off-by: Nigel Jones <jonesn@uk.ibm.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request
Issue
Fixes #1142.
Description
Embedded adapters are already present in a deployment's model weights and must be activated per request. That logic lived as an OpenAI-backend-specific type check, while
EmbeddedBindingremained a stub, so another backend would have had to reproduce hidden request-rewriting details.This PR gives
EmbeddedBindinga realapply_activation()method and routes the OpenAI backend through it. It preserves the required request shape, including removing a conflicting model parameter, and deletes two unused activation methods from the old design.Where this fits
This is Phase 2 work for Epic #929 and the embedded-adapter counterpart to the LocalFile/PEFT work in #1141 / PR #1454. It unblocks HF embedded-adapter support in #1018 and contributes to the shim-removal work in #1144. Output-contract resolution (#1516) and broader telemetry work (#1466) remain separate.
What changed
EmbeddedBinding.apply_activation()for request-scoped adapter selection.render_controlsandset_request_adaptermethods.Caveat
EmbeddedBindingdeliberately has no prepare, activate, deactivate, or release lifecycle: no weights are loaded or toggled. Invocation-complete telemetry remains with #1560 because request activation alone cannot know the eventual generation outcome.Testing
Focused adapter tests, the non-qualitative suite, Ruff, mypy, markdownlint, and the documentation quality gate pass. Required GitHub checks pass.
Testing
Attribution
Adding a new component, requirement, sampling strategy, or tool?
If your PR adds or modifies one of the types below, check the matching box. A checklist of type-specific review items will be posted as a comment.
NOTE: Please ensure you have an issue that has been acknowledged by a core contributor and routed you to open a pull request against this repository. Otherwise, please open an issue before continuing with this pull request.