---
phase: 06-consensus-export
plan: 02
type: execute
---
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.
~/.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 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}
```
Task 1: Create exporter module
src/moai/core/exporter.py
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.
`python -c "from moai.core.exporter import export_discussion, export_project"` succeeds
Exporter module creates properly formatted markdown matching SPEC format
Task 2: Create /export command handler
src/moai/bot/handlers/export.py, src/moai/bot/handlers/__init__.py, src/moai/bot/handlers/commands.py
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
Bot responds to /export with a markdown document attachment
/export sends discussion markdown, /export project sends full project markdown as Telegram documents
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
- 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)