--- phase: 03-project-crud plan: 01 type: execute --- Create project service layer and implement /projects and /project new commands. Purpose: Enable users to list existing projects and create new ones via Telegram. Output: Working project service with list/create functions and corresponding handlers. ~/.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 @.planning/phases/02-bot-core/02-02-SUMMARY.md # Relevant source files @src/moai/core/models.py @src/moai/core/database.py @src/moai/bot/handlers/__init__.py @src/moai/bot/handlers/commands.py **Established patterns:** - SQLAlchemy 2.0 async with get_session() context manager - Handler pattern: async def xxx_command(update, context) -> None - Markdown parse_mode for formatted output **Constraining decisions:** - String(36) for UUID storage - JSON type for models list - expire_on_commit=False for async session usability Task 1: Create project service module src/moai/core/services/__init__.py, src/moai/core/services/project.py Create services package and project service module with: - list_projects() -> list[Project]: Query all projects ordered by created_at desc - create_project(name: str, models: list[str] | None = None) -> Project: Create and return new project - get_project(project_id: str) -> Project | None: Get project by ID Use get_session() context manager for database operations. Return the refreshed objects after commit. Default models list to ["claude", "gpt", "gemini"] if not provided. python -c "from moai.core.services.project import list_projects, create_project, get_project" Service module imports without errors, all three functions defined Task 2: Implement /projects and /project new handlers src/moai/bot/handlers/projects.py, src/moai/bot/handlers/__init__.py Create projects.py with: - projects_command: List all projects with name and ID, or "No projects yet" message - project_new_command: Parse quoted name from args (e.g., /project new "My Project"), create project, confirm creation Handle edge cases: - /project new without name: Reply "Usage: /project new \"Project Name\"" - Empty project list: Reply "No projects yet. Use /project new \"Name\" to create one." Register handlers in __init__.py: - CommandHandler("projects", projects_command) - CommandHandler with MessageHandler for "project" + args pattern (use ConversationHandler or simple args parsing) For /project subcommands, use a single handler that parses context.args[0] to determine action (new/select/delete/models/info). ruff check src/moai/bot/handlers/projects.py && python -c "from moai.bot.handlers.projects import projects_command, project_command" /projects lists projects, /project new "Name" creates project with confirmation message Before declaring plan complete: - [ ] `ruff check src/moai/core/services/ src/moai/bot/handlers/projects.py` passes - [ ] `python -c "from moai.core.services.project import list_projects, create_project"` succeeds - [ ] `python -c "from moai.bot.handlers.projects import projects_command, project_command"` succeeds - All tasks completed - All verification checks pass - No TypeScript errors - Project service provides list/create/get functions - /projects command lists all projects - /project new "Name" creates a project and confirms After completion, create `.planning/phases/03-project-crud/03-01-SUMMARY.md`