docs(03): create phase 3 plans for project CRUD

Phase 03: Project CRUD
- 3 plans created
- 6 total tasks defined
- Covers M2 milestone (full project management)

Plan breakdown:
- 03-01: Project service + /projects, /project new
- 03-02: /project select, /project info
- 03-03: /project models, /project delete

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikkel Georgsen 2026-01-16 18:33:06 +00:00
parent dfdadc62f0
commit e3d72dab60
3 changed files with 301 additions and 0 deletions

View file

@ -0,0 +1,105 @@
---
phase: 03-project-crud
plan: 01
type: execute
---
<objective>
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.
</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
@.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
</context>
<tasks>
<task type="auto">
<name>Task 1: Create project service module</name>
<files>src/moai/core/services/__init__.py, src/moai/core/services/project.py</files>
<action>
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.
</action>
<verify>python -c "from moai.core.services.project import list_projects, create_project, get_project"</verify>
<done>Service module imports without errors, all three functions defined</done>
</task>
<task type="auto">
<name>Task 2: Implement /projects and /project new handlers</name>
<files>src/moai/bot/handlers/projects.py, src/moai/bot/handlers/__init__.py</files>
<action>
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).
</action>
<verify>ruff check src/moai/bot/handlers/projects.py && python -c "from moai.bot.handlers.projects import projects_command, project_command"</verify>
<done>/projects lists projects, /project new "Name" creates project with confirmation message</done>
</task>
</tasks>
<verification>
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
</verification>
<success_criteria>
- 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
</success_criteria>
<output>
After completion, create `.planning/phases/03-project-crud/03-01-SUMMARY.md`
</output>

View file

@ -0,0 +1,94 @@
---
phase: 03-project-crud
plan: 02
type: execute
---
<objective>
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.
</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/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
</context>
<tasks>
<task type="auto">
<name>Task 1: Add get_project_by_name to service</name>
<files>src/moai/core/services/project.py</files>
<action>
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.
</action>
<verify>python -c "from moai.core.services.project import get_project_by_name"</verify>
<done>get_project_by_name function exists and is importable</done>
</task>
<task type="auto">
<name>Task 2: Implement /project select and /project info handlers</name>
<files>src/moai/bot/handlers/projects.py</files>
<action>
Extend project_command handler to support:
/project select <id|name>:
- 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 <name> 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.
</action>
<verify>ruff check src/moai/bot/handlers/projects.py</verify>
<done>/project select stores selection, /project info displays project details</done>
</task>
</tasks>
<verification>
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
</verification>
<success_criteria>
- All tasks completed
- All verification checks pass
- /project select stores selection in user_data
- /project info shows project details
- Error messages are user-friendly
</success_criteria>
<output>
After completion, create `.planning/phases/03-project-crud/03-02-SUMMARY.md`
</output>

View file

@ -0,0 +1,102 @@
---
phase: 03-project-crud
plan: 03
type: execute
---
<objective>
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.
</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/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
</context>
<tasks>
<task type="auto">
<name>Task 1: Add update_models and delete_project to service</name>
<files>src/moai/core/services/project.py</files>
<action>
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.
</action>
<verify>python -c "from moai.core.services.project import update_project_models, delete_project"</verify>
<done>Both functions exist and are importable</done>
</task>
<task type="auto">
<name>Task 2: Implement /project models and /project delete handlers</name>
<files>src/moai/bot/handlers/projects.py</files>
<action>
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 <id>:
- 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.
</action>
<verify>ruff check src/moai/bot/handlers/projects.py</verify>
<done>/project models updates models, /project delete removes project, M2 milestone complete</done>
</task>
</tasks>
<verification>
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
</verification>
<success_criteria>
- 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)
</success_criteria>
<output>
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).
</output>