core/recognition/registry.py
Shay 81718a0952
feat(W-007): wire DerivedRecognizer registry into CognitiveTurnPipeline (ADR-0149) (#274)
- RecognizerRegistry.first_admitted() — deterministic first-registered selection
- CognitiveTurnPipeline consults runtime registry when no recognizer explicitly passed
- ChatRuntime gains _pending_recognizer_examples + record_recognition_example()
- checkpoint_engine_state() derives and registers recognizer from accumulated examples
- RuntimeConfig.recognition_grounded_graph gate (already existed) controls wiring
- ADR-0149 decision record
2026-05-25 12:24:48 -07:00

46 lines
1.4 KiB
Python

"""RecognizerRegistry -- per-teaching-set recognizer store (ADR-0146).
Holds DerivedRecognizer instances keyed by teaching_set_id. Wired into
EngineStateStore for Shape B persistence. Empty registry is the valid
initial state (no teaching examples yet).
"""
from __future__ import annotations
from recognition.anti_unifier import DerivedRecognizer
class RecognizerRegistry:
def __init__(self) -> None:
self._registry: dict[str, DerivedRecognizer] = {}
def register(self, recognizer: DerivedRecognizer) -> None:
self._registry[recognizer.teaching_set_id] = recognizer
def get(self, teaching_set_id: str) -> DerivedRecognizer | None:
return self._registry.get(teaching_set_id)
def all(self) -> list[DerivedRecognizer]:
return list(self._registry.values())
def first_admitted(self) -> DerivedRecognizer | None:
"""Return the first registered recognizer, or None if registry is empty."""
if not self._registry:
return None
return next(iter(self._registry.values()))
def __len__(self) -> int:
return len(self._registry)
@classmethod
def from_recognizers(
cls,
recognizers: list[DerivedRecognizer],
) -> "RecognizerRegistry":
reg = cls()
for recognizer in recognizers:
reg.register(recognizer)
return reg
__all__ = ["RecognizerRegistry"]