This repository has been archived on 2026-08-07. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
openclaw/skills/gsd-openclaw/.planning/phases/03-orchestration/03-03-PLAN.md
T

256 lines
10 KiB
Markdown

---
phase: 03-orchestration
plan: 03
type: execute
wave: 3
depends_on: [03-01, 03-02]
files_modified:
- src/gsd_openclaw/orchestrator.py
- src/gsd_openclaw/__init__.py
- skill/SKILL.md
- tests/test_orchestrator.py
autonomous: true
requirements: [BRDG-01, OCLW-03, OCLW-05, OCLW-06]
must_haves:
truths:
- "User can send /gsd:* command through chat and receive output"
- "Session is auto-created if it doesn't exist"
- "Error messages are formatted as red cards when commands fail"
- "Approval requests trigger interactive card with buttons"
- "Orchestrator routes commands through appropriate handlers"
artifacts:
- path: "src/gsd_openclaw/orchestrator.py"
provides: "Main command router and OpenClaw skill handler"
exports: ["Orchestrator", "handle_message", "handle_callback"]
- path: "skill/SKILL.md"
provides: "OpenClaw skill definition with orchestrator reference"
contains: "orchestrator.py"
- path: "tests/test_orchestrator.py"
provides: "Test coverage for orchestration"
min_lines: 200
key_links:
- from: "Orchestrator.handle_message"
to: "TmuxSessionManager"
via: "get_session()/create_session()"
pattern: "tmux_manager\\.(get|create)_session"
- from: "Orchestrator.handle_message"
to: "CommandExecutor"
via: "execute(session, command)"
pattern: "executor\\.execute"
- from: "Orchestrator.handle_message"
to: "ApprovalHandler"
via: "detect_approval_request()"
pattern: "approval_handler\\.detect"
- from: "Orchestrator.handle_message"
to: "FeishuResponseFormatter"
via: "format_success()/format_error()"
pattern: "formatter\\.format_(success|error)"
---
<objective>
Implement the main orchestrator that integrates all components into a cohesive command routing system for OpenClaw skill invocation.
Purpose: Create the central command router that receives chat messages, routes them through session management and command execution, handles approvals and progress, and returns formatted responses.
Output: Orchestrator class with handle_message() entry point, SKILL.md update with orchestrator reference.
</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/03-orchestration/03-CONTEXT.md
@.planning/phases/03-orchestration/03-RESEARCH.md
@.planning/phases/03-orchestration/03-01-PLAN.md
@.planning/phases/03-orchestration/03-02-PLAN.md
<interfaces>
<!-- Key types and contracts from Waves 1 and 2 -->
From src/gsd_openclaw/command_executor.py (Wave 1):
```python
@dataclass
class CommandResult:
output: str
completed: bool
has_error: bool
error_type: Optional[str]
class CommandExecutor:
DEFAULT_TIMEOUT: float = 60.0
def execute(self, session: TmuxSession, command: str, timeout: float = None) -> CommandResult: ...
```
From src/gsd_openclaw/approval_handler.py (Wave 2):
```python
@dataclass
class ApprovalState:
approval_id: str
session_id: str
project_name: str
context: dict
created_at: float
class ApprovalHandler:
def detect_approval_request(self, output: str) -> Optional[dict]: ...
def create_approval_card(self, context: dict, session_id: str, project_name: str) -> dict: ...
def handle_callback(self, callback_data: dict) -> str: ...
```
From src/gsd_openclaw/progress_monitor.py (Wave 2):
```python
@dataclass
class ProgressInfo:
type: str # percentage, fraction, phase, completion
value: Optional[int] = None
current: Optional[int] = None
total: Optional[int] = None
class ProgressMonitor:
def extract_progress(self, output: str) -> Optional[ProgressInfo]: ...
def should_send_update(self) -> bool: ...
def create_progress_card(self, progress: ProgressInfo, message: str) -> dict: ...
```
From src/gsd_openclaw/tmux_session.py:
```python
class TmuxSessionManager:
def get_session(self, project_name: str) -> Optional[TmuxSession]: ...
def create_session(self, project_name: str, ...) -> TmuxSession: ...
```
From src/gsd_openclaw/response_formatter.py:
```python
class FeishuResponseFormatter:
def format_success(self, title: str, content: str, buttons=None) -> dict: ...
def format_error(self, title: str, content: str, buttons=None) -> dict: ...
def format_info(self, title: str, content: str, buttons=None) -> dict: ...
```
</interfaces>
</context>
<tasks>
<task type="auto" tdd="true">
<name>Task 1: Create test scaffold for orchestrator</name>
<files>tests/test_orchestrator.py</files>
<behavior>
- Test 1: handle_message routes to session creation when no session exists
- Test 2: handle_message executes command and returns success card
- Test 3: handle_message returns error card when command fails
- Test 4: handle_message returns approval card when approval detected
- Test 5: handle_callback routes approval response correctly
- Test 6: Command parsing extracts /gsd:* pattern
</behavior>
<action>Create test file with pytest test functions. Mock all dependencies (TmuxSessionManager, CommandExecutor, ApprovalHandler, ProgressMonitor). Follow mock patterns from tests/test_tmux_session.py.</action>
<verify>
<automated>pytest tests/test_orchestrator.py -v --collect-only 2>&1 | grep -c "test_" | xargs -I{} bash -c 'test {} -ge 6'</automated>
</verify>
<done>Test file exists with at least 6 test functions, all discoverable by pytest</done>
</task>
<task type="auto" tdd="true">
<name>Task 2: Implement Orchestrator class</name>
<files>src/gsd_openclaw/orchestrator.py, tests/test_orchestrator.py</files>
<behavior>
- Test 1: Orchestrator initializes with all required components
- Test 2: handle_message creates session if not exists (auto-create per CONTEXT.md)
- Test 3: handle_message executes command via CommandExecutor
- Test 4: handle_message returns format_success() for successful commands
- Test 5: handle_message returns format_error() for failed commands
- Test 6: handle_message returns approval card when approval detected
- Test 7: handle_message truncates output to 2000 chars for card limits
- Test 8: handle_callback processes approval/reject actions
</behavior>
<action>
Implement Orchestrator class with:
1. __init__(self, tmux_manager=None, formatter=None) - inject dependencies for testing
2. Command routing via regex: r'^/gsd:(\S+)\s*(.*)$' extracts command and args
3. handle_message(user_id, message, channel, context) -> dict
- Extract project_name from context.get('project', 'default')
- Get or create session via TmuxSessionManager
- Execute command via CommandExecutor.execute()
- Check for approval request via ApprovalHandler.detect_approval_request()
- Return appropriate card (success/error/approval)
4. handle_callback(callback_data) -> dict
- Route to ApprovalHandler.handle_callback()
- Send approval/rejection to tmux session
- Return confirmation card
5. Error handling with try/except, return format_error() on exceptions
6. Use format_error(title="命令执行失败", content=output[-2000:]) for errors
</action>
<verify>
<automated>pytest tests/test_orchestrator.py -v</automated>
</verify>
<done>Orchestrator class implemented with handle_message() and handle_callback(), 8+ tests pass</done>
</task>
<task type="auto">
<name>Task 3: Update SKILL.md and __init__.py exports</name>
<files>skill/SKILL.md, src/gsd_openclaw/__init__.py</files>
<action>
1. Update skill/SKILL.md to add orchestrator integration notes:
- Add section "## How It Works" explaining orchestrator.py entry point
- Document that the skill calls orchestrator.handle_message() for each message
- Keep existing command documentation
2. Update src/gsd_openclaw/__init__.py to export:
- from gsd_openclaw.orchestrator import Orchestrator
- from gsd_openclaw.command_executor import CommandExecutor, CommandResult
- from gsd_openclaw.approval_handler import ApprovalHandler, ApprovalState
- from gsd_openclaw.progress_monitor import ProgressMonitor, ProgressInfo
- Add to __all__ list
</action>
<verify>
<automated>python -c "from gsd_openclaw import Orchestrator, CommandExecutor, ApprovalHandler, ProgressMonitor; print('OK')"</automated>
</verify>
<done>SKILL.md updated with orchestrator documentation, __init__.py exports all new classes</done>
</task>
<task type="auto">
<name>Task 4: Integration test with all components</name>
<files>tests/test_orchestrator.py</files>
<action>
Add integration-style tests to test_orchestrator.py:
1. Test full flow: handle_message -> session creation -> command execution -> success card
2. Test error flow: handle_message -> command fails -> error card
3. Test approval flow: handle_message -> approval detected -> approval card
4. Test callback flow: handle_callback -> approval processed -> confirmation
Use real component instances where possible, mock only tmux server.
Ensure all tests pass with full coverage of integration paths.
</action>
<verify>
<automated>pytest tests/test_orchestrator.py -v --cov=src/gsd_openclaw/orchestrator</automated>
</verify>
<done>Integration tests added and passing, orchestrator coverage >90%</done>
</task>
</tasks>
<verification>
Run full test suite for Phase 3:
```bash
pytest tests/test_command_executor.py tests/test_approval_handler.py tests/test_progress_monitor.py tests/test_orchestrator.py -v --cov=src/gsd_openclaw
```
All tests must pass. Phase 3 coverage should be >85%.
</verification>
<success_criteria>
- Orchestrator integrates all Phase 3 components
- handle_message() provides complete command routing flow
- Auto-session-creation works per CONTEXT.md decision
- Error handling returns formatted error cards
- Approval workflow integrates with callback handling
- All exports added to __init__.py
- SKILL.md documents orchestrator integration
</success_criteria>
<output>
After completion, create `.planning/phases/03-orchestration/03-03-SUMMARY.md`
</output>