NeonClary
feat(conversation): pluggable structures + decision methods (Robert's Rules, ranked-choice, majority)
e661e91
Raw
History Blame Contribute Delete
1.55 kB
"""Consensus — the original CCAI decision-making mode.
This is a thin wrapper over the existing Phase 5/6 implementation in
`app.services.orchestrator`. The structure produces a DecisionInput
with finalized positions; we discard the input fields here because
the consensus phase reads `session.final_opinions`,
`session.alliance_groups`, etc. directly. The wrapper exists so the
dispatcher in orchestrator.py can treat Consensus uniformly with the
new decision methods.
Behavior:
Phase 5: Consensus deliberation (turn-based, alliance-aware,
with dyad caps and addressed-to routing).
Phase 6: Closure — if a majority emerges, emit a majority report;
otherwise either re-run consensus with a surfaced
"unaddressed factor" or emit a no-consensus report.
"""
from __future__ import annotations
from typing import AsyncIterator
from app.services.conversation.decisions.base import DecisionMethod
class ConsensusDecision(DecisionMethod):
NAME = "Consensus"
DESCRIPTION = (
"Participants deliberate until either an alliance forms with "
"majority support, or the orchestrator reports no consensus "
"with the remaining points of disagreement."
)
async def run(self) -> AsyncIterator[str]:
from app.services.orchestrator import (
_phase_consensus,
_phase_closure,
)
async for chunk in _phase_consensus(self.session):
yield chunk
async for chunk in _phase_closure(self.session):
yield chunk