docs(02): create phase plan for bot core
Phase 02: Bot Core - 2 plans created (02-01 infrastructure, 02-02 handlers) - 6 total tasks defined - Ready for execution Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
ad396eca0e
commit
4d6768e55c
2 changed files with 359 additions and 0 deletions
167
.planning/phases/02-bot-core/02-01-PLAN.md
Normal file
167
.planning/phases/02-bot-core/02-01-PLAN.md
Normal file
|
|
@ -0,0 +1,167 @@
|
||||||
|
---
|
||||||
|
phase: 02-bot-core
|
||||||
|
plan: 01
|
||||||
|
type: execute
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
Set up Telegram bot infrastructure with Application builder, config loading, and handler registration pattern.
|
||||||
|
|
||||||
|
Purpose: Establish the bot entry point and configuration loading so handlers can be added incrementally.
|
||||||
|
Output: Working bot main.py that starts, loads config, and registers handlers (empty initially).
|
||||||
|
</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/phases/01-foundation/01-03-SUMMARY.md
|
||||||
|
@src/moai/core/database.py
|
||||||
|
@pyproject.toml
|
||||||
|
|
||||||
|
**Tech stack available:**
|
||||||
|
- SQLAlchemy async with aiosqlite (from Phase 1)
|
||||||
|
- python-telegram-bot (in dependencies, not yet used)
|
||||||
|
|
||||||
|
**Established patterns:**
|
||||||
|
- Async context manager for sessions
|
||||||
|
- Module-level globals for engine/session factory
|
||||||
|
|
||||||
|
**Constraining decisions:**
|
||||||
|
- Phase 1: Module-level globals for database (simple singleton)
|
||||||
|
- Phase 1: expire_on_commit=False for async sessions
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 1: Create bot configuration module</name>
|
||||||
|
<files>src/moai/bot/config.py</files>
|
||||||
|
<action>
|
||||||
|
Create config.py that loads bot configuration from environment variables:
|
||||||
|
- BOT_TOKEN (required): Telegram bot token
|
||||||
|
- ALLOWED_USERS (optional): Comma-separated list of Telegram user IDs for allowlist auth
|
||||||
|
- DATABASE_URL (optional): Database URL, defaults to sqlite+aiosqlite:///./moai.db
|
||||||
|
- LOG_LEVEL (optional): Logging level, defaults to INFO
|
||||||
|
|
||||||
|
Use pydantic-settings or simple os.environ with dataclass. Keep it simple - use dataclass with classmethod from_env().
|
||||||
|
Raise ValueError if BOT_TOKEN is missing.
|
||||||
|
|
||||||
|
Do NOT use pydantic-settings - it adds a dependency. Use stdlib dataclass + os.environ.
|
||||||
|
</action>
|
||||||
|
<verify>python -c "from moai.bot.config import BotConfig; print('Config module loads')"</verify>
|
||||||
|
<done>BotConfig dataclass exists with from_env() classmethod, raises on missing BOT_TOKEN</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 2: Create bot main.py with Application setup</name>
|
||||||
|
<files>src/moai/bot/main.py</files>
|
||||||
|
<action>
|
||||||
|
Create main.py as the bot entry point using python-telegram-bot v21+ patterns:
|
||||||
|
|
||||||
|
1. Import ApplicationBuilder from telegram.ext
|
||||||
|
2. Load config via BotConfig.from_env()
|
||||||
|
3. Create Application with ApplicationBuilder().token(config.bot_token).build()
|
||||||
|
4. Add post_init callback to initialize database (init_db, create_tables)
|
||||||
|
5. Add post_shutdown callback to close database (close_db)
|
||||||
|
6. Import and register handlers from handlers/ (empty for now, will add in 02-02)
|
||||||
|
7. Call app.run_polling()
|
||||||
|
|
||||||
|
Structure:
|
||||||
|
```python
|
||||||
|
import logging
|
||||||
|
from telegram.ext import ApplicationBuilder
|
||||||
|
from moai.bot.config import BotConfig
|
||||||
|
from moai.core.database import init_db, create_tables, close_db
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
async def post_init(application):
|
||||||
|
init_db(config.database_url)
|
||||||
|
await create_tables()
|
||||||
|
logger.info("Database initialized")
|
||||||
|
|
||||||
|
async def post_shutdown(application):
|
||||||
|
await close_db()
|
||||||
|
logger.info("Database closed")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
config = BotConfig.from_env()
|
||||||
|
app = (
|
||||||
|
ApplicationBuilder()
|
||||||
|
.token(config.bot_token)
|
||||||
|
.post_init(post_init)
|
||||||
|
.post_shutdown(post_shutdown)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
# Handlers will be registered here in 02-02
|
||||||
|
logger.info("Starting bot...")
|
||||||
|
app.run_polling()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: post_init receives the application as argument. Store config at module level or pass via application.bot_data.
|
||||||
|
</action>
|
||||||
|
<verify>python -c "from moai.bot.main import main; print('Main module loads')" (will fail at runtime without BOT_TOKEN, but import should work)</verify>
|
||||||
|
<done>main.py exists with ApplicationBuilder setup, post_init/post_shutdown hooks for database lifecycle</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 3: Create handlers package structure</name>
|
||||||
|
<files>src/moai/bot/handlers/__init__.py</files>
|
||||||
|
<action>
|
||||||
|
Create handlers/__init__.py with a register_handlers function that takes an Application and registers all handlers.
|
||||||
|
|
||||||
|
For now, it's empty (no handlers yet), but the structure allows 02-02 to add handlers cleanly:
|
||||||
|
|
||||||
|
```python
|
||||||
|
"""Telegram command handlers for MoAI bot."""
|
||||||
|
|
||||||
|
from telegram.ext import Application
|
||||||
|
|
||||||
|
def register_handlers(app: Application) -> None:
|
||||||
|
"""Register all command handlers with the application.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app: The telegram Application instance.
|
||||||
|
"""
|
||||||
|
# Handlers will be imported and registered here
|
||||||
|
# from moai.bot.handlers import commands
|
||||||
|
# app.add_handler(CommandHandler("help", commands.help_command))
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
Update main.py to call register_handlers(app) before run_polling().
|
||||||
|
</action>
|
||||||
|
<verify>python -c "from moai.bot.handlers import register_handlers; print('Handlers package loads')"</verify>
|
||||||
|
<done>handlers/__init__.py exists with register_handlers function, main.py calls it</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
Before declaring plan complete:
|
||||||
|
- [ ] `python -c "from moai.bot.config import BotConfig"` succeeds
|
||||||
|
- [ ] `python -c "from moai.bot.main import main"` succeeds
|
||||||
|
- [ ] `python -c "from moai.bot.handlers import register_handlers"` succeeds
|
||||||
|
- [ ] `ruff check src/moai/bot/` passes
|
||||||
|
- [ ] All new files have docstrings
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
- All tasks completed
|
||||||
|
- All verification checks pass
|
||||||
|
- Bot infrastructure ready for handler registration
|
||||||
|
- No TypeScript errors or ruff violations
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.planning/phases/02-bot-core/02-01-SUMMARY.md` using summary template.
|
||||||
|
</output>
|
||||||
192
.planning/phases/02-bot-core/02-02-PLAN.md
Normal file
192
.planning/phases/02-bot-core/02-02-PLAN.md
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
---
|
||||||
|
phase: 02-bot-core
|
||||||
|
plan: 02
|
||||||
|
type: execute
|
||||||
|
---
|
||||||
|
|
||||||
|
<objective>
|
||||||
|
Implement /help and /status command handlers completing M1 milestone.
|
||||||
|
|
||||||
|
Purpose: Get the bot responding to basic commands, proving the infrastructure works end-to-end.
|
||||||
|
Output: Working /help and /status commands that respond in Telegram.
|
||||||
|
</objective>
|
||||||
|
|
||||||
|
<execution_context>
|
||||||
|
~/.claude/get-shit-done/workflows/execute-phase.md
|
||||||
|
~/.claude/get-shit-done/templates/summary.md
|
||||||
|
~/.claude/get-shit-done/references/checkpoints.md
|
||||||
|
</execution_context>
|
||||||
|
|
||||||
|
<context>
|
||||||
|
@.planning/PROJECT.md
|
||||||
|
@.planning/ROADMAP.md
|
||||||
|
@.planning/phases/02-bot-core/02-01-SUMMARY.md (created in previous plan)
|
||||||
|
@src/moai/bot/main.py
|
||||||
|
@src/moai/bot/config.py
|
||||||
|
@src/moai/bot/handlers/__init__.py
|
||||||
|
@SPEC.md (for command format reference)
|
||||||
|
|
||||||
|
**From SPEC.md:**
|
||||||
|
- /help - Show commands
|
||||||
|
- /status - Show current project/discussion state
|
||||||
|
|
||||||
|
**Tech stack available:**
|
||||||
|
- python-telegram-bot v21+ with ApplicationBuilder
|
||||||
|
- Async handlers with Update, ContextTypes
|
||||||
|
|
||||||
|
**Constraining decisions:**
|
||||||
|
- Phase 2-01: Handlers registered via register_handlers() in handlers/__init__.py
|
||||||
|
</context>
|
||||||
|
|
||||||
|
<tasks>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 1: Create commands.py with /help and /start handlers</name>
|
||||||
|
<files>src/moai/bot/handlers/commands.py</files>
|
||||||
|
<action>
|
||||||
|
Create commands.py with help_command and start_command handlers:
|
||||||
|
|
||||||
|
```python
|
||||||
|
"""Basic command handlers for MoAI bot."""
|
||||||
|
|
||||||
|
from telegram import Update
|
||||||
|
from telegram.ext import ContextTypes
|
||||||
|
|
||||||
|
HELP_TEXT = """
|
||||||
|
*MoAI - Master of AIs*
|
||||||
|
|
||||||
|
Multi-AI collaborative brainstorming platform.
|
||||||
|
|
||||||
|
*Project Commands:*
|
||||||
|
/projects - List all projects
|
||||||
|
/project new "Name" - Create new project
|
||||||
|
/project select <id|name> - Switch to project
|
||||||
|
/project delete <id> - Delete project
|
||||||
|
/project models claude,gpt - Set models
|
||||||
|
/project info - Show current project
|
||||||
|
|
||||||
|
*Discussion Commands:*
|
||||||
|
/open <question> - Ask all models (parallel)
|
||||||
|
/discuss [rounds] - Start discussion (default: 3)
|
||||||
|
/next - Trigger next round
|
||||||
|
/stop - Stop current discussion
|
||||||
|
|
||||||
|
*Output Commands:*
|
||||||
|
/consensus - Generate consensus summary
|
||||||
|
/export - Export project as markdown
|
||||||
|
|
||||||
|
*Utility:*
|
||||||
|
/status - Show current state
|
||||||
|
/help - Show this message
|
||||||
|
""".strip()
|
||||||
|
|
||||||
|
async def start_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||||
|
"""Handle /start command - welcome message."""
|
||||||
|
await update.message.reply_text(
|
||||||
|
"Welcome to MoAI! 🤖\n\n"
|
||||||
|
"Use /help to see available commands.\n"
|
||||||
|
"Use /project new \"Name\" to create your first project."
|
||||||
|
)
|
||||||
|
|
||||||
|
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||||
|
"""Handle /help command - show available commands."""
|
||||||
|
await update.message.reply_text(HELP_TEXT, parse_mode="Markdown")
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: Use Markdown parse_mode for formatting. Keep HELP_TEXT as a module constant for easy updates.
|
||||||
|
</action>
|
||||||
|
<verify>python -c "from moai.bot.handlers.commands import help_command, start_command; print('Commands module loads')"</verify>
|
||||||
|
<done>commands.py has start_command and help_command handlers with proper docstrings</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 2: Create status.py with /status handler</name>
|
||||||
|
<files>src/moai/bot/handlers/status.py</files>
|
||||||
|
<action>
|
||||||
|
Create status.py with status_command handler:
|
||||||
|
|
||||||
|
```python
|
||||||
|
"""Status command handler for MoAI bot."""
|
||||||
|
|
||||||
|
from telegram import Update
|
||||||
|
from telegram.ext import ContextTypes
|
||||||
|
|
||||||
|
async def status_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
||||||
|
"""Handle /status command - show current project/discussion state.
|
||||||
|
|
||||||
|
For now, shows a placeholder since project management isn't implemented yet.
|
||||||
|
Will be expanded in Phase 3 to show actual project state.
|
||||||
|
"""
|
||||||
|
# TODO: Phase 3 - Query actual project/discussion state from database
|
||||||
|
status_text = (
|
||||||
|
"*MoAI Status*\n\n"
|
||||||
|
"Bot: ✅ Online\n"
|
||||||
|
"Database: ✅ Connected\n\n"
|
||||||
|
"_No project selected. Use /project new \"Name\" to create one._"
|
||||||
|
)
|
||||||
|
await update.message.reply_text(status_text, parse_mode="Markdown")
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a placeholder that will be enhanced in Phase 3 when project CRUD is implemented.
|
||||||
|
</action>
|
||||||
|
<verify>python -c "from moai.bot.handlers.status import status_command; print('Status module loads')"</verify>
|
||||||
|
<done>status.py has status_command handler with placeholder implementation</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
<task type="auto">
|
||||||
|
<name>Task 3: Register handlers in __init__.py</name>
|
||||||
|
<files>src/moai/bot/handlers/__init__.py</files>
|
||||||
|
<action>
|
||||||
|
Update handlers/__init__.py to import and register all command handlers:
|
||||||
|
|
||||||
|
```python
|
||||||
|
"""Telegram command handlers for MoAI bot."""
|
||||||
|
|
||||||
|
from telegram.ext import Application, CommandHandler
|
||||||
|
|
||||||
|
from moai.bot.handlers.commands import help_command, start_command
|
||||||
|
from moai.bot.handlers.status import status_command
|
||||||
|
|
||||||
|
|
||||||
|
def register_handlers(app: Application) -> None:
|
||||||
|
"""Register all command handlers with the application.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
app: The telegram Application instance.
|
||||||
|
"""
|
||||||
|
# Basic commands
|
||||||
|
app.add_handler(CommandHandler("start", start_command))
|
||||||
|
app.add_handler(CommandHandler("help", help_command))
|
||||||
|
|
||||||
|
# Status
|
||||||
|
app.add_handler(CommandHandler("status", status_command))
|
||||||
|
```
|
||||||
|
</action>
|
||||||
|
<verify>python -c "from moai.bot.handlers import register_handlers; from telegram.ext import ApplicationBuilder; print('Handler registration ready')"</verify>
|
||||||
|
<done>register_handlers imports and registers start, help, and status command handlers</done>
|
||||||
|
</task>
|
||||||
|
|
||||||
|
</tasks>
|
||||||
|
|
||||||
|
<verification>
|
||||||
|
Before declaring plan complete:
|
||||||
|
- [ ] `python -c "from moai.bot.handlers.commands import help_command, start_command"` succeeds
|
||||||
|
- [ ] `python -c "from moai.bot.handlers.status import status_command"` succeeds
|
||||||
|
- [ ] `python -c "from moai.bot.handlers import register_handlers"` succeeds
|
||||||
|
- [ ] `ruff check src/moai/bot/` passes
|
||||||
|
- [ ] All handler files have module and function docstrings
|
||||||
|
</verification>
|
||||||
|
|
||||||
|
<success_criteria>
|
||||||
|
- All tasks completed
|
||||||
|
- All verification checks pass
|
||||||
|
- /start, /help, and /status handlers implemented
|
||||||
|
- Handlers registered via register_handlers()
|
||||||
|
- M1 milestone requirements met (bot responds to /help, /status)
|
||||||
|
</success_criteria>
|
||||||
|
|
||||||
|
<output>
|
||||||
|
After completion, create `.planning/phases/02-bot-core/02-02-SUMMARY.md` using summary template.
|
||||||
|
|
||||||
|
Note: Phase 2 complete after this plan. Ready for Phase 3 (Project CRUD).
|
||||||
|
</output>
|
||||||
Loading…
Add table
Reference in a new issue