UAT: bug(resource-registry): contextual resource binding type compatibility check does not use full inheritance chain #2929

Closed
opened 2026-04-05 02:51:25 +00:00 by freemo · 7 comments
Owner

Metadata

  • Commit Message: fix(resource-registry): use full inheritance chain in contextual binding type compatibility
  • Branch: bugfix/binding-resolution-inheritance-chain
  • Parent Epic: #353
  • Milestone: v3.1.0

Background and Context

ADR-042 (Resource Type Inheritance) requires polymorphic matching: tools bound to a parent type automatically work with all subtypes. The spec states:

Core polymorphism guarantee: Tools bound to a parent type automatically work with all subtypes. Auto-discovery child type matching and DAG queries that reference a parent type automatically include subtypes.

The binding resolution service must use the full inheritance chain when checking type compatibility, not just the immediate parent_types list.

Current Behavior

In src/cleveragents/application/services/binding_resolution_service.py, _is_type_compatible only checks one level of parent_types:

def _is_type_compatible(
    self,
    required_type: str,
    actual_type: str,
) -> bool:
    if actual_type == required_type:
        return True

    try:
        spec: ResourceTypeSpec = self._registry.show_type(actual_type)
    except NotFoundError:
        return False

    return required_type in spec.parent_types  # ← Only checks immediate parents!

This means if a tool requires type container-instance and the resource is of type devcontainer-instance (which inherits from container-instance), the binding will fail because container-instance is not in devcontainer-instance.parent_types directly — it's in the inheritance chain.

Reproduction scenario:

  1. Register a tool with a resource slot requiring type container-instance
  2. Link a devcontainer-instance resource to a project
  3. Attempt contextual binding — it will fail even though devcontainer-instance IS a container-instance subtype

Expected Behavior

_is_type_compatible should use is_subtype_of() from cleveragents.resource.inheritance (already imported in the service) to walk the full inheritance chain:

from cleveragents.resource.inheritance import is_subtype_of

def _is_type_compatible(self, required_type: str, actual_type: str) -> bool:
    if actual_type == required_type:
        return True
    registry = self._registry._load_type_registry()  # or equivalent
    return is_subtype_of(actual_type, required_type, registry)

The is_subtype_of function already exists in cleveragents/resource/inheritance.py and correctly walks the full chain.

Acceptance Criteria

  • _is_type_compatible uses is_subtype_of() to check the full inheritance chain
  • A tool requiring container-instance can bind to a devcontainer-instance resource
  • A tool requiring git-checkout cannot bind to an unrelated type like fs-directory
  • Static and parameter binding also use the corrected type compatibility check
  • Unit tests cover multi-level inheritance in binding resolution

Subtasks

  • Update _is_type_compatible in binding_resolution_service.py to use is_subtype_of()
  • Update _check_type_compatibility similarly
  • Expose _load_type_registry() or equivalent for use in the binding service
  • Add unit tests for polymorphic binding with inherited types
  • Run nox and ensure all sessions pass

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly.
  • The commit is submitted as a pull request to master, reviewed, and merged.

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-uat-tester

## Metadata - **Commit Message**: `fix(resource-registry): use full inheritance chain in contextual binding type compatibility` - **Branch**: `bugfix/binding-resolution-inheritance-chain` - **Parent Epic**: #353 - **Milestone**: v3.1.0 ## Background and Context ADR-042 (Resource Type Inheritance) requires polymorphic matching: tools bound to a parent type automatically work with all subtypes. The spec states: > **Core polymorphism guarantee:** Tools bound to a parent type automatically work with all subtypes. Auto-discovery child type matching and DAG queries that reference a parent type automatically include subtypes. The binding resolution service must use the full inheritance chain when checking type compatibility, not just the immediate `parent_types` list. ## Current Behavior In `src/cleveragents/application/services/binding_resolution_service.py`, `_is_type_compatible` only checks one level of `parent_types`: ```python def _is_type_compatible( self, required_type: str, actual_type: str, ) -> bool: if actual_type == required_type: return True try: spec: ResourceTypeSpec = self._registry.show_type(actual_type) except NotFoundError: return False return required_type in spec.parent_types # ← Only checks immediate parents! ``` This means if a tool requires type `container-instance` and the resource is of type `devcontainer-instance` (which inherits from `container-instance`), the binding will fail because `container-instance` is not in `devcontainer-instance.parent_types` directly — it's in the inheritance chain. **Reproduction scenario:** 1. Register a tool with a resource slot requiring type `container-instance` 2. Link a `devcontainer-instance` resource to a project 3. Attempt contextual binding — it will fail even though `devcontainer-instance` IS a `container-instance` subtype ## Expected Behavior `_is_type_compatible` should use `is_subtype_of()` from `cleveragents.resource.inheritance` (already imported in the service) to walk the full inheritance chain: ```python from cleveragents.resource.inheritance import is_subtype_of def _is_type_compatible(self, required_type: str, actual_type: str) -> bool: if actual_type == required_type: return True registry = self._registry._load_type_registry() # or equivalent return is_subtype_of(actual_type, required_type, registry) ``` The `is_subtype_of` function already exists in `cleveragents/resource/inheritance.py` and correctly walks the full chain. ## Acceptance Criteria - [ ] `_is_type_compatible` uses `is_subtype_of()` to check the full inheritance chain - [ ] A tool requiring `container-instance` can bind to a `devcontainer-instance` resource - [ ] A tool requiring `git-checkout` cannot bind to an unrelated type like `fs-directory` - [ ] Static and parameter binding also use the corrected type compatibility check - [ ] Unit tests cover multi-level inheritance in binding resolution ## Subtasks - [x] Update `_is_type_compatible` in `binding_resolution_service.py` to use `is_subtype_of()` - [x] Update `_check_type_compatibility` similarly - [x] Expose `_load_type_registry()` or equivalent for use in the binding service - [x] Add unit tests for polymorphic binding with inherited types - [x] Run `nox` and ensure all sessions pass ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged**. --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-uat-tester
Author
Owner

Label compliance fix applied:

  • Added missing labels: Priority/High, State/Unverified, Type/Bug
  • Reason: Issue was missing all required labels per CONTRIBUTING.md. Inferred Type/Bug from the "UAT: bug" prefix. Applied Priority/High and State/Unverified as defaults.

Automated by CleverAgents Bot
Supervisor: Backlog Grooming | Agent: ca-backlog-groomer

Label compliance fix applied: - Added missing labels: `Priority/High`, `State/Unverified`, `Type/Bug` - Reason: Issue was missing all required labels per CONTRIBUTING.md. Inferred `Type/Bug` from the "UAT: bug" prefix. Applied `Priority/High` and `State/Unverified` as defaults. --- **Automated by CleverAgents Bot** Supervisor: Backlog Grooming | Agent: ca-backlog-groomer
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: Confirmed
  • MoSCoW: Should Have

Valid finding verified during batch triage.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: ca-project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: Confirmed - **MoSCoW**: Should Have Valid finding verified during batch triage. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
freemo added this to the v3.2.0 milestone 2026-04-05 04:49:29 +00:00
Author
Owner

Milestone compliance fix applied:

  • Assigned to milestone: v3.2.0
  • Reason: Issue is State/Verified (ready for implementation) but had no milestone. Issue body references Milestone: v3.1.0 which is no longer an active open milestone. Assigned to the earliest active milestone v3.2.0 as the appropriate target.

Automated by CleverAgents Bot
Supervisor: Backlog Grooming | Agent: ca-backlog-groomer

Milestone compliance fix applied: - Assigned to milestone: `v3.2.0` - Reason: Issue is `State/Verified` (ready for implementation) but had no milestone. Issue body references `Milestone: v3.1.0` which is no longer an active open milestone. Assigned to the earliest active milestone `v3.2.0` as the appropriate target. --- **Automated by CleverAgents Bot** Supervisor: Backlog Grooming | Agent: ca-backlog-groomer
Author
Owner

Starting implementation on branch bugfix/binding-resolution-inheritance-chain.

Bug confirmed: _is_type_compatible in binding_resolution_service.py only checks required_type in spec.parent_types (one level), instead of using is_subtype_of() from cleveragents.resource.inheritance which walks the full chain.

Fix plan:

  1. Update _is_type_compatible to use is_subtype_of() with a type registry map
  2. Update _check_type_compatibility similarly (it delegates to _is_type_compatible so this is covered)
  3. Expose _load_type_registry() or equivalent via a protocol method on the registry
  4. Add BDD tests for multi-level inheritance binding
  5. Run nox quality gates

Automated by CleverAgents Bot
Supervisor: Implementation | Agent: ca-issue-worker

Starting implementation on branch `bugfix/binding-resolution-inheritance-chain`. Bug confirmed: `_is_type_compatible` in `binding_resolution_service.py` only checks `required_type in spec.parent_types` (one level), instead of using `is_subtype_of()` from `cleveragents.resource.inheritance` which walks the full chain. Fix plan: 1. Update `_is_type_compatible` to use `is_subtype_of()` with a type registry map 2. Update `_check_type_compatibility` similarly (it delegates to `_is_type_compatible` so this is covered) 3. Expose `_load_type_registry()` or equivalent via a protocol method on the registry 4. Add BDD tests for multi-level inheritance binding 5. Run nox quality gates --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: ca-issue-worker
Author
Owner

All subtasks complete. Quality gates passed. Creating PR.

Implementation Summary

Root cause: _is_type_compatible in binding_resolution_service.py only checked required_type in spec.parent_types — a flat one-level check that missed multi-level inheritance chains.

Fix: Replaced the flat parent_types check with a call to self._registry.is_subtype_of(actual_type, required_type), which uses resolve_inheritance_chain() from cleveragents.resource.inheritance to walk the full ADR-042 inheritance chain.

Files changed:

  • src/cleveragents/application/services/binding_resolution_service.py_is_type_compatible now delegates to registry.is_subtype_of(). Removed unused ResourceTypeSpec import.
  • features/consolidated_binding_resolution.feature — 4 new scenarios: 2-level chain, 3-level chain, unrelated type rejection, static binding via chain.
  • features/steps/binding_resolution_steps.py — mock registry now exposes is_subtype_of() backed by the real is_subtype_of() function; new step definitions for inheritance chain setup.

Test results: 20 scenarios passed (16 original + 4 new), 0 failed. lint , typecheck .


Automated by CleverAgents Bot
Supervisor: Implementation | Agent: ca-issue-worker

All subtasks complete. Quality gates passed. Creating PR. ## Implementation Summary **Root cause**: `_is_type_compatible` in `binding_resolution_service.py` only checked `required_type in spec.parent_types` — a flat one-level check that missed multi-level inheritance chains. **Fix**: Replaced the flat `parent_types` check with a call to `self._registry.is_subtype_of(actual_type, required_type)`, which uses `resolve_inheritance_chain()` from `cleveragents.resource.inheritance` to walk the full ADR-042 inheritance chain. **Files changed**: - `src/cleveragents/application/services/binding_resolution_service.py` — `_is_type_compatible` now delegates to `registry.is_subtype_of()`. Removed unused `ResourceTypeSpec` import. - `features/consolidated_binding_resolution.feature` — 4 new scenarios: 2-level chain, 3-level chain, unrelated type rejection, static binding via chain. - `features/steps/binding_resolution_steps.py` — mock registry now exposes `is_subtype_of()` backed by the real `is_subtype_of()` function; new step definitions for inheritance chain setup. **Test results**: 20 scenarios passed (16 original + 4 new), 0 failed. lint ✅, typecheck ✅. --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: ca-issue-worker
Author
Owner

PR #3336 created on branch bugfix/binding-resolution-inheritance-chain: #3336

PR review and merge handled by continuous review stream.


Automated by CleverAgents Bot
Supervisor: Implementation | Agent: ca-issue-worker

PR #3336 created on branch `bugfix/binding-resolution-inheritance-chain`: https://git.cleverthis.com/cleveragents/cleveragents-core/pulls/3336 PR review and merge handled by continuous review stream. --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: ca-issue-worker
Owner

State label reconciliation:

  • Previous state: State/In Review
  • Corrected to: State/Completed
  • Reason: Issue is closed but had a non-terminal state label. CONTRIBUTING.md requires closed issues to have State/Completed or State/Wont Do.

Automated by CleverAgents Bot
Supervisor: Backlog Grooming | Agent: backlog-groomer

State label reconciliation: - Previous state: `State/In Review` - Corrected to: `State/Completed` - Reason: Issue is closed but had a non-terminal state label. CONTRIBUTING.md requires closed issues to have `State/Completed` or `State/Wont Do`. --- **Automated by CleverAgents Bot** Supervisor: Backlog Grooming | Agent: backlog-groomer
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
cleveragents/cleveragents-core#2929
No description provided.