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/04-gsd-integration/04-03-PLAN.md
T

9.1 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, user_setup, must_haves
phase plan type wave depends_on files_modified autonomous requirements user_setup must_haves
04-gsd-integration 03 execute 2
04-01
04-02
src/gsd_openclaw/command_executor.py
src/gsd_openclaw/orchestrator.py
tests/test_command_executor.py
tests/test_orchestrator.py
true
BRDG-06
truths artifacts key_links
Long commands (execute-phase, plan-phase, discuss-phase, new-project) don't timeout
Regular commands still use 60 second default timeout
Long command detection is based on command name matching
Create New Project button callback works from error card
path provides exports
src/gsd_openclaw/command_executor.py Extended CommandExecutor with long command support
CommandExecutor.LONG_COMMANDS
CommandExecutor._is_long_command
path provides exports
src/gsd_openclaw/orchestrator.py Orchestrator with adaptive timeout and button callback
Orchestrator._is_long_command
path provides exports
tests/test_command_executor.py Tests for long command detection
TestLongCommands
from to via pattern
src/gsd_openclaw/orchestrator.py src/gsd_openclaw/command_executor.py execute() with timeout=None for long commands _is_long_command|LONG_COMMANDS
Extend CommandExecutor with long command support and update Orchestrator for adaptive timeout and button callback.

Purpose: Ensure long-running GSD commands don't timeout prematurely, and the "Create New Project" button from error cards works correctly.

Output: CommandExecutor with LONG_COMMANDS detection, Orchestrator with adaptive timeout handling, and button callback support.

<execution_context> @/home/starmen1265/.claude/get-shit-done/workflows/execute-plan.md @/home/starmen1265/.claude/get-shit-done/templates/summary.md </execution_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

From src/gsd_openclaw/command_executor.py:

class CommandExecutor:
    ERROR_KEYWORDS: List[str] = [...]
    DEFAULT_TIMEOUT: float = 60.0

    def execute(self, session, command: str, timeout: Optional[float] = None) -> CommandResult:
        """Execute command with optional timeout override."""
        timeout = timeout if timeout is not None else self.DEFAULT_TIMEOUT
        # ...

From src/gsd_openclaw/orchestrator.py:

class Orchestrator:
    COMMAND_PATTERN = re.compile(r'^/gsd:(\S+)\s*(.*)$')
    MAX_OUTPUT_LENGTH = 2000

    def handle_callback(self, callback_data: Dict[str, Any]) -> Dict[str, Any]:
        """Handle button callback - currently only supports approve/reject."""

Long commands from CONTEXT.md:

  • execute-phase, plan-phase, discuss-phase, new-project have no timeout
  • Detection via command name matching
Task 1: Add LONG_COMMANDS detection to CommandExecutor src/gsd_openclaw/command_executor.py, tests/test_command_executor.py - Test 1: LONG_COMMANDS contains 'execute-phase', 'plan-phase', 'discuss-phase', 'new-project' - Test 2: _is_long_command returns True for commands in LONG_COMMANDS - Test 3: _is_long_command returns False for commands not in LONG_COMMANDS - Test 4: _is_long_command handles commands with arguments correctly Add long command detection to CommandExecutor:
  1. Add LONG_COMMANDS class attribute:

    class CommandExecutor:
        ERROR_KEYWORDS: List[str] = [...]
        DEFAULT_TIMEOUT: float = 60.0
        LONG_COMMANDS: Set[str] = {'execute-phase', 'plan-phase', 'discuss-phase', 'new-project'}
    
  2. Add _is_long_command method:

    def _is_long_command(self, command: str) -> bool:
        """Check if command requires no timeout.
    
        Args:
            command: The full command string (e.g., '/gsd:execute-phase').
    
        Returns:
            True if command is in LONG_COMMANDS, False otherwise.
        """
        # Extract command name from /gsd:command format
        match = re.match(r'^/gsd:(\S+)', command)
        if match:
            command_name = match.group(1)
            return command_name in self.LONG_COMMANDS
        return False
    
  3. Add TestLongCommands class to tests/test_command_executor.py:

    • Test LONG_COMMANDS set contents
    • Test _is_long_command for each long command
    • Test _is_long_command returns False for regular commands
    • Test _is_long_command handles commands with args pytest tests/test_command_executor.py::TestLongCommands -x -v CommandExecutor has LONG_COMMANDS set and _is_long_command method with tests
Task 2: Update Orchestrator to use adaptive timeout src/gsd_openclaw/orchestrator.py, tests/test_orchestrator.py - Test 1: _is_long_command in Orchestrator returns True for long commands - Test 2: execute() is called with timeout=None for long commands - Test 3: execute() is called with default timeout for regular commands - Test 4: handle_message passes correct timeout based on command type Add adaptive timeout to Orchestrator:
  1. Add LONG_COMMANDS and _is_long_command to Orchestrator (mirror CommandExecutor):

    class Orchestrator:
        LONG_COMMANDS = {'execute-phase', 'plan-phase', 'discuss-phase', 'new-project'}
    
        def _is_long_command(self, command: str) -> bool:
            """Check if command requires no timeout."""
            # Extract command name from parsed command
            if command in self.LONG_COMMANDS:
                return True
            return False
    
  2. Update handle_message to use adaptive timeout:

    # In handle_message, before execute call:
    timeout = None if self._is_long_command(command) else self.executor.DEFAULT_TIMEOUT
    result = self.executor.execute(session, full_command, timeout=timeout)
    
  3. Update _handle_new_project to use timeout=None (already a long command):

    result = self.executor.execute(session, f"/gsd:new-project {project_name}", timeout=None)
    
  4. Add tests in TestSpecialCommands for adaptive timeout:

    • Test that long commands get timeout=None
    • Test that regular commands get DEFAULT_TIMEOUT pytest tests/test_orchestrator.py::TestSpecialCommands -x -v Orchestrator uses adaptive timeout based on command type
Task 3: Update handle_callback to support Create New Project button src/gsd_openclaw/orchestrator.py, tests/test_orchestrator.py - Test 1: Callback with action="new-project" creates new session - Test 2: Callback with action="new-project" executes /gsd:new-project command - Test 3: Callback with action="new-project" returns success card - Test 4: Callback with action="new-project" and missing name returns error Update handle_callback to support new-project action:
  1. Add new-project action handling to handle_callback:

    def handle_callback(self, callback_data: Dict[str, Any]) -> Dict[str, Any]:
        action = callback_data.get("action", "")
    
        if action == "new-project":
            project_name = callback_data.get("name", "")
            user_id = callback_data.get("user_id", "")
    
            if not project_name:
                return self.formatter.format_error(
                    title="Invalid Request",
                    content="Project name is required"
                )
    
            return self._handle_new_project(user_id, project_name)
    
        # Existing approval handling...
        if action == "approve":
            ...
    
  2. Update _handle_use_project to include user_id in button value:

    CardButton(
        text="Create New Project",
        value={
            "action": "new-project",
            "name": project_name,
            "user_id": user_id
        }
    )
    
  3. Add tests in TestHandleCallback for new-project action

  4. Ensure backward compatibility with existing approval callbacks pytest tests/test_orchestrator.py::TestHandleCallback -x -v handle_callback supports "new-project" action from error card button

- All tests in tests/test_command_executor.py pass - All tests in tests/test_orchestrator.py pass - Long commands execute with no timeout - Regular commands still use 60 second timeout - "Create New Project" button callback works correctly

<success_criteria>

  • CommandExecutor has LONG_COMMANDS detection
  • Orchestrator uses adaptive timeout based on command type
  • handle_callback supports "new-project" action
  • All existing tests still pass </success_criteria>
After completion, create `.planning/phases/04-gsd-integration/04-03-SUMMARY.md`