diff --git a/.planning/phases/03-project-crud/03-01-PLAN.md b/.planning/phases/03-project-crud/03-01-PLAN.md new file mode 100644 index 0000000..467f2d9 --- /dev/null +++ b/.planning/phases/03-project-crud/03-01-PLAN.md @@ -0,0 +1,105 @@ +--- +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` + diff --git a/.planning/phases/03-project-crud/03-02-PLAN.md b/.planning/phases/03-project-crud/03-02-PLAN.md new file mode 100644 index 0000000..24d84b1 --- /dev/null +++ b/.planning/phases/03-project-crud/03-02-PLAN.md @@ -0,0 +1,94 @@ +--- +phase: 03-project-crud +plan: 02 +type: execute +--- + + +Implement project selection and info display commands. + +Purpose: Enable users to switch between projects and view project details. +Output: Working /project select and /project info commands with user state tracking. + + + +~/.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/03-project-crud/03-01-SUMMARY.md + +# Relevant source files +@src/moai/core/services/project.py +@src/moai/bot/handlers/projects.py +@src/moai/bot/handlers/__init__.py + +**Established patterns:** +- user_data dict in context for per-user state (python-telegram-bot pattern) +- Handler pattern: async def xxx_command(update, context) -> None + + + + + + Task 1: Add get_project_by_name to service + src/moai/core/services/project.py + +Add function to project service: +- get_project_by_name(name: str) -> Project | None: Query project by exact name match (case-insensitive using ilike) + +This allows /project select to work with either ID or name. + + python -c "from moai.core.services.project import get_project_by_name" + get_project_by_name function exists and is importable + + + + Task 2: Implement /project select and /project info handlers + src/moai/bot/handlers/projects.py + +Extend project_command handler to support: + +/project select : +- Store selected project ID in context.user_data["selected_project_id"] +- Reply with confirmation: "Selected project: {name}" +- If not found: "Project not found. Use /projects to list available projects." + +/project info: +- Get selected project from user_data +- If no project selected: "No project selected. Use /project select first." +- Display: name, ID, models list, created_at, discussion count + +Helper function get_selected_project(context) -> Project | None to retrieve currently selected project from user_data. + + ruff check src/moai/bot/handlers/projects.py + /project select stores selection, /project info displays project details + + + + + +Before declaring plan complete: +- [ ] `ruff check src/moai/bot/handlers/projects.py` passes +- [ ] `python -c "from moai.core.services.project import get_project_by_name"` succeeds +- [ ] project_command handles select and info subcommands + + + + +- All tasks completed +- All verification checks pass +- /project select stores selection in user_data +- /project info shows project details +- Error messages are user-friendly + + + +After completion, create `.planning/phases/03-project-crud/03-02-SUMMARY.md` + diff --git a/.planning/phases/03-project-crud/03-03-PLAN.md b/.planning/phases/03-project-crud/03-03-PLAN.md new file mode 100644 index 0000000..364ff6a --- /dev/null +++ b/.planning/phases/03-project-crud/03-03-PLAN.md @@ -0,0 +1,102 @@ +--- +phase: 03-project-crud +plan: 03 +type: execute +--- + + +Implement project model configuration and deletion commands to complete M2 milestone. + +Purpose: Enable users to configure which AI models a project uses and delete unwanted projects. +Output: Working /project models and /project delete commands, completing full Project CRUD. + + + +~/.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/03-project-crud/03-02-SUMMARY.md + +# Relevant source files +@src/moai/core/services/project.py +@src/moai/bot/handlers/projects.py + +**Established patterns:** +- Service layer handles database operations +- Handlers are thin, delegate to services +- user_data["selected_project_id"] for current project + + + + + + Task 1: Add update_models and delete_project to service + src/moai/core/services/project.py + +Add functions to project service: + +- update_project_models(project_id: str, models: list[str]) -> Project | None: + Update project's models list, return updated project or None if not found. + +- delete_project(project_id: str) -> bool: + Delete project by ID, return True if deleted, False if not found. + Cascade delete will handle discussions/rounds/messages via SQLAlchemy relationship config. + + python -c "from moai.core.services.project import update_project_models, delete_project" + Both functions exist and are importable + + + + Task 2: Implement /project models and /project delete handlers + src/moai/bot/handlers/projects.py + +Extend project_command handler to support: + +/project models claude,gpt,gemini: +- Require project to be selected first +- Parse comma-separated model names from args +- Update via service, confirm: "Models updated: claude, gpt, gemini" +- If no args: show current models list + +/project delete : +- Require explicit project ID (not name) for safety +- Delete via service, confirm: "Deleted project: {name}" +- If deleted project was selected, clear user_data["selected_project_id"] +- If not found: "Project not found." + +Update /status handler (if exists) to show selected project info now that project CRUD is complete. + + ruff check src/moai/bot/handlers/projects.py + /project models updates models, /project delete removes project, M2 milestone complete + + + + + +Before declaring plan complete: +- [ ] `ruff check src/moai/core/services/ src/moai/bot/handlers/` passes +- [ ] All service functions importable +- [ ] Full CRUD cycle works: new → select → info → models → delete + + + + +- All tasks completed +- All verification checks pass +- /project models configures AI models for project +- /project delete removes project with confirmation +- M2 milestone complete (full project CRUD via Telegram) + + + +After completion, create `.planning/phases/03-project-crud/03-03-SUMMARY.md` + +Summary should note M2 milestone completion and readiness for Phase 4 (Single Model Q&A). +