docs(06): create phase plans for consensus & export

Phase 06: Consensus & Export
- 2 plans created
- 4 total tasks defined
- Ready for execution

Plan 06-01: Consensus generation (M6)
Plan 06-02: Markdown export (M7)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikkel Georgsen 2026-01-16 19:58:51 +00:00
parent bd1db003b7
commit ddb0de0757
2 changed files with 286 additions and 0 deletions

View file

@ -0,0 +1,129 @@
---
phase: 06-consensus-export
plan: 01
type: execute
---
<objective>
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.
</objective>
<execution_context>
~/.claude/get-shit-done/workflows/execute-phase.md
~/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.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
</context>
<tasks>
<task type="auto">
<name>Task 1: Add consensus generation to orchestrator and service</name>
<files>src/moai/core/orchestrator.py, src/moai/core/services/discussion.py</files>
<action>
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.
</action>
<verify>Python imports succeed: `python -c "from moai.core.orchestrator import generate_consensus; from moai.core.services.discussion import save_consensus, get_consensus"`</verify>
<done>generate_consensus() returns dict with agreements/disagreements, save_consensus() persists to DB, get_consensus() retrieves</done>
</task>
<task type="auto">
<name>Task 2: Create /consensus command handler</name>
<files>src/moai/bot/handlers/discussion.py, src/moai/bot/handlers/commands.py, src/moai/bot/handlers/__init__.py</files>
<action>
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
</action>
<verify>Bot responds to /consensus with either consensus output or appropriate error message</verify>
<done>/consensus generates and displays consensus for active discussion, or shows existing if already generated</done>
</task>
</tasks>
<verification>
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
</verification>
<success_criteria>
- 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
</success_criteria>
<output>
After completion, create `.planning/phases/06-consensus-export/06-01-SUMMARY.md`
</output>

View file

@ -0,0 +1,157 @@
---
phase: 06-consensus-export
plan: 02
type: execute
---
<objective>
Implement markdown export for discussions and projects.
Purpose: Enable users to export discussion history and consensus to shareable markdown documents (M7 milestone).
Output: Working /export command that generates and sends markdown files via Telegram.
</objective>
<execution_context>
~/.claude/get-shit-done/workflows/execute-phase.md
~/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
# Prior plan context:
@.planning/phases/06-consensus-export/06-01-SUMMARY.md
# Source files to reference:
@src/moai/core/models.py
@src/moai/core/services/discussion.py
@src/moai/core/services/project.py
@src/moai/bot/handlers/__init__.py
@src/moai/bot/handlers/commands.py
**Tech stack available:** python-telegram-bot, sqlalchemy
**Established patterns:** Service layer, handler registration, get_selected_project helper
**SPEC.md export format:**
```markdown
# {Project Name}
**Date:** {date}
**Models:** Claude, GPT, Gemini
**Discussions:** {count}
---
## Discussion 1: {Question}
### Initial Responses (Open)
**Claude:**
> {response}
### Discussion (N rounds)
**Round 1:**
**Claude:** {response}
**GPT:** {response}
### Consensus
**Agreements:**
- point 1
**Disagreements:**
- **Topic:** {topic}
- Claude: {position}
```
</context>
<tasks>
<task type="auto">
<name>Task 1: Create exporter module</name>
<files>src/moai/core/exporter.py</files>
<action>
Create new file src/moai/core/exporter.py with:
1. Module docstring explaining markdown export functionality.
2. `export_discussion(discussion: Discussion) -> str` function:
- Format discussion as markdown following SPEC format
- Include question as heading
- Group messages by round, label round type (parallel = "Initial Responses", sequential = "Round N")
- Format each message as `**Model:** response`
- Include consensus section if consensus exists (agreements as bullets, disagreements with positions)
- Return markdown string
3. `export_project(project: Project, discussions: list[Discussion]) -> str` function:
- Header with project name, date, models list, discussion count
- Separator (---)
- Each discussion formatted via export_discussion()
- Separators between discussions
- Return full markdown string
4. Helper `_format_consensus(consensus: Consensus) -> str`:
- Format agreements as bullet list
- Format disagreements with topic and model positions
- Return formatted string or empty if no consensus
Use datetime.now().strftime("%Y-%m-%d") for date formatting.
</action>
<verify>`python -c "from moai.core.exporter import export_discussion, export_project"` succeeds</verify>
<done>Exporter module creates properly formatted markdown matching SPEC format</done>
</task>
<task type="auto">
<name>Task 2: Create /export command handler</name>
<files>src/moai/bot/handlers/export.py, src/moai/bot/handlers/__init__.py, src/moai/bot/handlers/commands.py</files>
<action>
1. Create new file src/moai/bot/handlers/export.py with:
- Import exporter functions, services, telegram types
- `export_command(update, context)` handler:
- Get selected project (error if none)
- Parse args: no args = export active discussion, "project" = export full project
- For discussion export:
- Get active discussion (error if none)
- Call export_discussion()
- Send as document: `update.message.reply_document(io.BytesIO(md.encode()), filename=f"{project.name}-discussion.md")`
- For project export:
- Get all discussions for project via list_discussions()
- Fetch each with full eager loading via get_discussion()
- Call export_project()
- Send as document with filename `{project.name}-export.md`
- Use io.BytesIO for in-memory file, import io module
2. Update handlers/__init__.py:
- Import export_command from export module
- Register `CommandHandler("export", export_command)`
3. Update HELP_TEXT in commands.py, Output section:
`/export` - Export current discussion as markdown
`/export project` - Export entire project as markdown
</action>
<verify>Bot responds to /export with a markdown document attachment</verify>
<done>/export sends discussion markdown, /export project sends full project markdown as Telegram documents</done>
</task>
</tasks>
<verification>
Before declaring plan complete:
- [ ] `ruff check src/moai/core/exporter.py src/moai/bot/handlers/export.py`
- [ ] `python -c "from moai.core.exporter import export_discussion, export_project"` succeeds
- [ ] `python -c "from moai.bot.handlers.export import export_command"` succeeds
</verification>
<success_criteria>
- Exporter module generates SPEC-compliant markdown
- /export sends discussion as .md document
- /export project sends full project as .md document
- Help text updated
- No ruff errors
- Phase 6 complete (M6 + M7 milestones)
</success_criteria>
<output>
After completion, create `.planning/phases/06-consensus-export/06-02-SUMMARY.md`
</output>