-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Context
The weaver-spec defines RoutingDecision as contextweaver's primary output — the structured result of the routing phase, containing a list of ChoiceCards and optional selection metadata. contextweaver currently outputs a RouteResult dataclass that has a fundamentally different shape:
# Current: RouteResult (contextweaver)
@dataclass
class RouteResult:
candidate_items: list[SelectableItem] = []
candidate_ids: list[str] = []
paths: list[list[str]] = []
scores: list[float] = []
debug_trace: list[dict[str, Any]] = []
# Spec: RoutingDecision (weaver-spec)
@dataclass
class RoutingDecision:
id: str
choice_cards: list[ChoiceCard]
timestamp: datetime
selected_item_id: Optional[str] = None
selected_card_id: Optional[str] = None
context_summary: Optional[str] = None
metadata: Dict[str, Any] = {}RouteResult is a flat list of scored candidates. RoutingDecision is a structured decision record with grouped ChoiceCards and selection tracking. Without a RoutingDecision type, contextweaver's output is not spec-compliant, and the contract adapter (#143) has no internal type to map from.
Why it matters
- Blocks Add weaver-spec contract adapters (SelectableItem / ChoiceCard / RoutingDecision / Frame) #143 — the contract adapter needs an internal
RoutingDecisionequivalent to implementto_weaver()/from_weaver()round-trip mapping. - Spec invariant I-03 — "Routing presents bounded choices, not full schema catalogs."
RoutingDecisionembeds groupedChoiceCards, enforcing this invariant structurally. - Cross-repo interop — ChainWeaver and agent-kernel both consume
RoutingDecision. Without one, contextweaver can't participate in the ecosystem contract chain.
Acceptance Criteria
-
RoutingDecisiondataclass insrc/contextweaver/envelope.py(ortypes.py) with fields matching the spec contract shape:id: str— unique decision identifierchoice_cards: list[ChoiceCard]— the bounded choices presentedtimestamp: datetimeselected_item_id: str | None— which item was ultimately selectedselected_card_id: str | None— from which cardcontext_summary: str | None— optional rendering of the decision contextmetadata: dict[str, Any]
-
to_dict()/from_dict()methods onRoutingDecision(per conventions) -
Router.route()returns or can produce aRoutingDecision(in addition to or replacingRouteResult) -
RouteResultpreserved for backward compatibility (or deprecated with migration path) - Unit tests for construction, serialization round-trip, and integration with Router
- Exported from
__init__.py
Implementation Notes
Option A (preferred): Router.route() returns RoutingDecision which embeds the RouteResult data in a spec-compliant envelope. RouteResult becomes an internal detail or is deprecated.
Option B: Add a Router.decide() method that returns RoutingDecision, keeping route() unchanged for backward compatibility.
Files likely touched:
src/contextweaver/envelope.py— newRoutingDecisiondataclasssrc/contextweaver/routing/router.py— produceRoutingDecisionsrc/contextweaver/__init__.py— exporttests/test_envelope.pyortests/test_router.py— tests
Dependencies
- Prerequisite for Add weaver-spec contract adapters (SelectableItem / ChoiceCard / RoutingDecision / Frame) #143 (contract adapters)
- Related: ChoiceCard semantic alignment (the
choice_cardsfield here depends on the ChoiceCard shape) - Reference: weaver-spec
contracts/python/src/weaver_contracts/core.py