Skip to content

Express context-aware controllers in the type system instead of duck-typing #17

Description

@davidkfoss

Problem

The "context-aware controller" capability is detected at runtime via getattr:

  • episode.py:56-63 does getattr(controller, "set_context", None) to decide whether to feed a context bucket.
  • scheduler.py:348 types the noise controller as object | list[object] | None because BaseController (Protocol at controller.py:12-22) does not express the set_context capability.

Proposal

Split the protocol:

class BaseController(Protocol):
    def select(...) -> ...: ...
    def update(...) -> ...: ...

class ContextualController(BaseController, Protocol):
    def set_context(self, context: Hashable) -> None: ...

Then:

  • Use isinstance(controller, ContextualController) (with @runtime_checkable) instead of getattr probing.
  • Replace object | list[object] | None typing in scheduler.py:348 with the real protocol union.

Acceptance criteria

  • ContextualController protocol introduced.
  • getattr(..., "set_context", None) calls in episode.py replaced with isinstance checks.
  • object typing in scheduler.py replaced with the proper protocol type.
  • mypy / pyright passes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions