---
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