--- phase: 06-consensus-export plan: 01 type: execute --- Implement consensus generation for multi-model discussions. Purpose: Enable users to synthesize discussion outcomes into structured agreements/disagreements (M6 milestone). Output: Working /consensus command that generates and displays AI-summarized consensus. ~/.claude/get-shit-done/workflows/execute-phase.md ~/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md # Prior phase context (discussion infrastructure): @.planning/phases/05-multi-model-discussions/05-03-SUMMARY.md # Source files to modify/reference: @src/moai/core/models.py @src/moai/core/orchestrator.py @src/moai/core/services/discussion.py @src/moai/bot/handlers/discussion.py @src/moai/bot/handlers/commands.py **Tech stack available:** python-telegram-bot, sqlalchemy, openai SDK, asyncio **Established patterns:** Service layer in core/services/, orchestrator for AI calls, handler delegation to services **Constraining decisions:** - Phase 05-03: build_context() assembles discussion history for AI context - Phase 05-01: Discussion service with eager loading via selectinload - Phase 04-01: AI client singleton pattern, MODEL_MAP for short names **SPEC.md consensus format:** - agreements: string[] (bullet points) - disagreements: [{topic, positions: {model: position}}] - Consensus model already exists with these fields Task 1: Add consensus generation to orchestrator and service src/moai/core/orchestrator.py, src/moai/core/services/discussion.py 1. In orchestrator.py, add CONSENSUS_PROMPT constant with instructions to analyze discussion and return JSON with "agreements" (list of strings) and "disagreements" (list of {topic, positions} objects). 2. Add `generate_consensus(discussion: Discussion, model: str = "claude") -> dict` function: - Build context from discussion using existing build_context() - Append CONSENSUS_PROMPT as final user message - Call AI client with system prompt explaining the task - Parse JSON response (handle parsing errors gracefully) - Return dict with "agreements" and "disagreements" keys 3. In discussion.py service, add: - `save_consensus(discussion_id: str, agreements: list, disagreements: list, generated_by: str) -> Consensus` - `get_consensus(discussion_id: str) -> Consensus | None` Use existing session patterns (async with get_session()). Import Consensus model. Python imports succeed: `python -c "from moai.core.orchestrator import generate_consensus; from moai.core.services.discussion import save_consensus, get_consensus"` generate_consensus() returns dict with agreements/disagreements, save_consensus() persists to DB, get_consensus() retrieves Task 2: Create /consensus command handler src/moai/bot/handlers/discussion.py, src/moai/bot/handlers/commands.py, src/moai/bot/handlers/__init__.py 1. In discussion.py handlers, add `consensus_command(update, context)`: - Get selected project (error if none) - Get active discussion for project (error if none, suggest /open or /discuss first) - Check if consensus already exists (get_consensus) - if so, display existing - Otherwise call generate_consensus() with discussion - Save consensus via save_consensus() - Format and display: ``` **Consensus Summary** **Agreements:** - point 1 - point 2 **Disagreements:** - **Topic:** {topic} - Claude: {position} - GPT: {position} _Generated by {model}_ ``` - Show typing indicator while generating 2. Register handler in __init__.py: `CommandHandler("consensus", consensus_command)` 3. Update HELP_TEXT in commands.py to add consensus under Output section: `/consensus` - Generate consensus summary Bot responds to /consensus with either consensus output or appropriate error message /consensus generates and displays consensus for active discussion, or shows existing if already generated Before declaring plan complete: - [ ] `ruff check src/moai/core/orchestrator.py src/moai/core/services/discussion.py src/moai/bot/handlers/` - [ ] `python -c "from moai.core.orchestrator import generate_consensus"` succeeds - [ ] `python -c "from moai.core.services.discussion import save_consensus, get_consensus"` succeeds - generate_consensus() calls AI and returns structured dict - Consensus persisted to database via save_consensus() - /consensus command displays formatted consensus - Help text updated - No ruff errors After completion, create `.planning/phases/06-consensus-export/06-01-SUMMARY.md`