251 lines
9.6 KiB
Markdown
251 lines
9.6 KiB
Markdown
---
|
|
phase: 04-gsd-integration
|
|
plan: 02
|
|
type: execute
|
|
wave: 1
|
|
depends_on: []
|
|
files_modified:
|
|
- src/gsd_openclaw/orchestrator.py
|
|
- tests/test_orchestrator.py
|
|
autonomous: true
|
|
requirements:
|
|
- BRDG-06
|
|
user_setup: []
|
|
must_haves:
|
|
truths:
|
|
- "User can send /gsd:new-project through chat and get a pre-created session"
|
|
- "User can send /gsd:use <project> to switch their current project context"
|
|
- "User receives clear error when /gsd:use references non-existent project"
|
|
- "Generic GSD commands pass through correctly"
|
|
artifacts:
|
|
- path: "src/gsd_openclaw/orchestrator.py"
|
|
provides: "Extended Orchestrator with special command handling"
|
|
exports: ["Orchestrator._handle_new_project", "Orchestrator._handle_use_project"]
|
|
- path: "tests/test_orchestrator.py"
|
|
provides: "Tests for special command handling"
|
|
exports: ["TestSpecialCommands"]
|
|
key_links:
|
|
- from: "src/gsd_openclaw/orchestrator.py"
|
|
to: "src/gsd_openclaw/user_context.py"
|
|
via: "UserContextManager for context tracking"
|
|
pattern: "UserContextManager"
|
|
- from: "src/gsd_openclaw/orchestrator.py"
|
|
to: "src/gsd_openclaw/tmux_session.py"
|
|
via: "TmuxSessionManager.create_session for new-project"
|
|
pattern: "create_session"
|
|
---
|
|
|
|
<objective>
|
|
Extend Orchestrator with special command handling for /gsd:new-project and /gsd:use.
|
|
|
|
Purpose: Enable key GSD commands that require orchestrator-level logic: pre-creating sessions for new-project and tracking user context for use.
|
|
|
|
Output: Orchestrator with _handle_new_project and _handle_use_project methods integrated into handle_message routing.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@/home/starmen1265/.claude/get-shit-done/workflows/execute-plan.md
|
|
@/home/starmen1265/.claude/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/PROJECT.md
|
|
@.planning/ROADMAP.md
|
|
@.planning/STATE.md
|
|
@.planning/phases/04-gsd-integration/04-CONTEXT.md
|
|
@.planning/phases/04-gsd-integration/04-RESEARCH.md
|
|
|
|
<interfaces>
|
|
<!-- Key types and contracts from existing codebase -->
|
|
|
|
From src/gsd_openclaw/orchestrator.py (current implementation):
|
|
```python
|
|
class Orchestrator:
|
|
COMMAND_PATTERN = re.compile(r'^/gsd:(\S+)\s*(.*)$')
|
|
MAX_OUTPUT_LENGTH = 2000
|
|
|
|
def parse_command(self, message: str) -> Optional[Tuple[str, str]]:
|
|
"""Parse a message for /gsd:* command pattern."""
|
|
# Returns (command, args) or None
|
|
|
|
def handle_message(self, user_id: str, message: str, channel: str, context: Dict) -> Dict:
|
|
"""Main entry point - currently auto-creates session for all commands."""
|
|
```
|
|
|
|
From src/gsd_openclaw/response_formatter.py:
|
|
```python
|
|
@dataclass
|
|
class CardButton:
|
|
"""Interactive button for Feishu Card actions."""
|
|
text: str
|
|
value: Dict[str, Any]
|
|
button_type: str = "primary" # primary, default, danger
|
|
```
|
|
|
|
From src/gsd_openclaw/tmux_session.py:
|
|
```python
|
|
class TmuxSessionManager:
|
|
def create_session(self, project_name: str, ...) -> TmuxSession:
|
|
"""Create a new tmux session for a project."""
|
|
|
|
def get_session(self, project_name: str) -> Optional[TmuxSession]:
|
|
"""Get existing session without creating new one."""
|
|
```
|
|
|
|
Special command handling requirements (from CONTEXT.md):
|
|
- /gsd:new-project: Pre-create session, then pass command to tmux
|
|
- /gsd:use: Track user context, show error + "Create New Project" button if not exists
|
|
</interfaces>
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto" tdd="true">
|
|
<name>Task 1: Add UserContextManager to Orchestrator and implement /gsd:new-project handling</name>
|
|
<files>src/gsd_openclaw/orchestrator.py, tests/test_orchestrator.py</files>
|
|
<behavior>
|
|
- Test 1: Orchestrator initializes with UserContextManager instance
|
|
- Test 2: _handle_new_project creates tmux session before executing command
|
|
- Test 3: _handle_new_project updates user context with new project
|
|
- Test 4: _handle_new_project executes the command in the new session
|
|
- Test 5: _handle_new_project returns success card with output
|
|
- Test 6: handle_message routes 'new-project' command to _handle_new_project
|
|
</behavior>
|
|
<action>
|
|
Extend Orchestrator with UserContextManager and new-project handling:
|
|
|
|
1. Add import: from gsd_openclaw.user_context import UserContextManager
|
|
|
|
2. Update Orchestrator.__init__:
|
|
- Add: self.user_context_managers: Dict[str, UserContextManager] = {}
|
|
- Add helper: _get_user_context_manager(user_id) -> UserContextManager
|
|
|
|
3. Add LONG_COMMANDS class attribute:
|
|
```python
|
|
LONG_COMMANDS = {'execute-phase', 'plan-phase', 'discuss-phase', 'new-project'}
|
|
```
|
|
|
|
4. Implement _handle_new_project(user_id: str, project_name: str) -> Dict:
|
|
- If project_name is empty, return format_error with "Project name required"
|
|
- Create session via tmux_manager.create_session(project_name)
|
|
- Execute "/gsd:new-project {project_name}" in the session with timeout=None
|
|
- Update user context: user_context.set_current_project(project_name)
|
|
- Return formatted result (success or error based on command result)
|
|
|
|
5. Update handle_message to route 'new-project' to _handle_new_project
|
|
|
|
6. Add TestSpecialCommands class to tests/test_orchestrator.py with tests for new-project
|
|
</action>
|
|
<verify>
|
|
<automated>pytest tests/test_orchestrator.py::TestSpecialCommands::test_new_project -x -v</automated>
|
|
</verify>
|
|
<done>Orchestrator has _handle_new_project method that pre-creates session and updates user context</done>
|
|
</task>
|
|
|
|
<task type="auto" tdd="true">
|
|
<name>Task 2: Implement /gsd:use command handling with context tracking</name>
|
|
<files>src/gsd_openclaw/orchestrator.py, tests/test_orchestrator.py</files>
|
|
<behavior>
|
|
- Test 1: _handle_use_project updates user context to new project
|
|
- Test 2: _handle_use_project returns success card when project exists
|
|
- Test 3: _handle_use_project returns error card with "Create New Project" button when project doesn't exist
|
|
- Test 4: handle_message routes 'use' command to _handle_use_project
|
|
- Test 5: _handle_use_project with no args returns error card
|
|
- Test 6: Subsequent commands use the project from user context
|
|
</behavior>
|
|
<action>
|
|
Implement _handle_use_project method:
|
|
|
|
1. Implement _handle_use_project(user_id: str, project_name: str) -> Dict:
|
|
- If project_name is empty, return format_error with "Project name required"
|
|
- Check if project session exists: tmux_manager.get_session(project_name)
|
|
- If session exists:
|
|
* Update user context: user_context.set_current_project(project_name)
|
|
* Return format_success with "Switched to project '{project_name}'"
|
|
- If session doesn't exist:
|
|
* Return format_error with:
|
|
- title: "Project not found"
|
|
- content: "Project '{project_name}' does not exist"
|
|
- buttons: [CardButton(text="Create New Project", value={"action": "new-project", "name": project_name})]
|
|
|
|
2. Update handle_message to route 'use' command to _handle_use_project
|
|
|
|
3. Add tests for _handle_use_project in TestSpecialCommands class
|
|
|
|
4. Ensure CardButton import is available from response_formatter
|
|
</action>
|
|
<verify>
|
|
<automated>pytest tests/test_orchestrator.py::TestSpecialCommands::test_use_project tests/test_orchestrator.py::TestSpecialCommands::test_use_nonexistent -x -v</automated>
|
|
</verify>
|
|
<done>Orchestrator has _handle_use_project method with context tracking and error handling</done>
|
|
</task>
|
|
|
|
<task type="auto" tdd="true">
|
|
<name>Task 3: Update handle_message routing to use user context for project selection</name>
|
|
<files>src/gsd_openclaw/orchestrator.py, tests/test_orchestrator.py</files>
|
|
<behavior>
|
|
- Test 1: Generic commands use project from user context when not in context param
|
|
- Test 2: Generic commands fall back to "default" project if no context
|
|
- Test 3: Special commands (new-project, use) are routed correctly
|
|
- Test 4: Generic pass-through works for all other commands
|
|
</behavior>
|
|
<action>
|
|
Update handle_message routing logic:
|
|
|
|
1. Modify handle_message to get project from user context:
|
|
```python
|
|
def handle_message(self, user_id, message, channel, context):
|
|
# Parse command
|
|
parsed = self.parse_command(message)
|
|
if not parsed:
|
|
return format_error(...)
|
|
|
|
command, args = parsed
|
|
|
|
# Special commands
|
|
if command == 'new-project':
|
|
return self._handle_new_project(user_id, args)
|
|
if command == 'use':
|
|
return self._handle_use_project(user_id, args)
|
|
|
|
# Generic commands - get project from user context
|
|
user_ctx = self._get_user_context_manager(user_id)
|
|
project_name = user_ctx.get_current_project()
|
|
if not project_name:
|
|
project_name = context.get("project", "default")
|
|
|
|
# Rest of existing logic...
|
|
```
|
|
|
|
2. Ensure existing tests still pass (backward compatibility)
|
|
|
|
3. Add integration tests in TestIntegrationFlows for:
|
|
- Command after /gsd:use goes to correct project
|
|
- Context persists across multiple commands
|
|
</action>
|
|
<verify>
|
|
<automated>pytest tests/test_orchestrator.py -x -v</automated>
|
|
</verify>
|
|
<done>handle_message routes special commands and uses user context for project selection</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<verification>
|
|
- All tests in tests/test_orchestrator.py pass
|
|
- /gsd:new-project pre-creates session and updates context
|
|
- /gsd:use tracks context and shows error for non-existent projects
|
|
- Generic commands use user context for project selection
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- Orchestrator has _handle_new_project and _handle_use_project methods
|
|
- Special commands are routed correctly in handle_message
|
|
- User context is used for project selection in generic commands
|
|
- Error cards include "Create New Project" button for missing projects
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/04-gsd-integration/04-02-SUMMARY.md`
|
|
</output>
|