12 KiB
12 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
| phase | plan | type | wave | depends_on | files_modified | autonomous | requirements | must_haves | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 02-integration-layer | 03 | execute | 1 |
|
true |
|
|
Purpose: Provide reusable prompt templates that Phase 3's orchestrator will use to generate context-aware prompts for Claude. Templates use simple {{variable}} syntax with string.Template for substitution.
Output:
- src/gsd_openclaw/prompts/ directory with 3 template files
- src/gsd_openclaw/prompt_loader.py - Template loader implementation
- tests/test_prompt_templates.py - Template tests
<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/02-integration-layer/02-CONTEXT.md @.planning/phases/02-integration-layer/02-RESEARCH.mdUse string.Template with safe_substitute() for {{variable}} syntax:
from string import Template
from pathlib import Path
class PromptLoader:
def __init__(self, template_dir: Path):
self.template_dir = template_dir
self._cache: Dict[str, Template] = {}
def render(self, name: str, **variables) -> str:
path = self.template_dir / f"{name}.md"
template = Template(path.read_text(encoding='utf-8'))
return template.safe_substitute(**variables)
Note: string.Template uses $variable syntax by default. For {{variable}} syntax, need to override the delimiter pattern or use simple string substitution.
Task 1: Create test scaffold for prompt templates tests/test_prompt_templates.py - Test 1: context_recovery.md template exists - Test 2: command_mapping.md template exists - Test 3: error_recovery.md template exists - Test 4: PromptLoader.render substitutes variables - Test 5: PromptLoader handles missing variables gracefully (safe_substitute) - Test 6: PromptLoader raises error for missing template file Create tests/test_prompt_templates.py with test classes:class TestPromptTemplatesExist:
1. test_context_recovery_template_exists():
- Assert prompts_dir / "context_recovery.md" exists
2. test_command_mapping_template_exists():
- Assert prompts_dir / "command_mapping.md" exists
3. test_error_recovery_template_exists():
- Assert prompts_dir / "error_recovery.md" exists
4. test_templates_contain_variable_placeholders():
- Read each template
- Assert {{variable}} pattern exists in each
class TestPromptLoader:
5. test_render_substitutes_variables():
- Create PromptLoader with prompts directory
- Call render("context_recovery", project_name="test-project", last_active_at="2026-03-11")
- Assert "test-project" appears in output
- Assert "{{project_name}}" does NOT appear
6. test_render_handles_missing_variables():
- Call render with partial variables
- Assert output contains literal {{missing_var}} (safe_substitute behavior)
7. test_render_raises_for_missing_template():
- Call render("nonexistent_template")
- Assert FileNotFoundError is raised
Use Path(__file__).parent.parent / "src" / "gsd_openclaw" / "prompts" for prompts_dir.
Follow test pattern from tests/test_state_manager.py.
pytest tests/test_prompt_templates.py -v
- tests/test_prompt_templates.py exists with 7 tests
- Tests fail initially (no templates yet)
Task 2: Create prompt template files
- src/gsd_openclaw/prompts/__init__.py
- src/gsd_openclaw/prompts/context_recovery.md
- src/gsd_openclaw/prompts/command_mapping.md
- src/gsd_openclaw/prompts/error_recovery.md
- Test: All 4 tests in TestPromptTemplatesExist pass
Create prompts directory and template files:
1. src/gsd_openclaw/prompts/__init__.py:
- Empty file (marks directory as package)
2. src/gsd_openclaw/prompts/context_recovery.md:
```markdown
# Context Recovery
You are resuming a GSD session that was interrupted.
## Session Information
- **Project**: {{project_name}}
- **Last Active**: {{last_active_at}}
- **Current Phase**: {{current_phase}}
- **Commands Executed**: {{command_count}}
## Last Known State
{{last_output_snapshot}}
## Instructions
Continue from where the session left off. Do not repeat completed steps.
```
3. src/gsd_openclaw/prompts/command_mapping.md:
```markdown
# Command Mapping
Map the following user input to a GSD slash command.
## User Input
{{user_input}}
## Available Commands
- /gsd:new-project <name> - Create a new project
- /gsd:use <project> - Switch to a project
- /gsd:status - Show current status
- /gsd:plan - Run planning phase
- /gsd:ship - Ship current phase
- /gsd:help - Show help
## Current Context
- Project: {{current_project}}
- Phase: {{current_phase}}
## Instructions
Determine the most appropriate command based on the user input and context.
```
4. src/gsd_openclaw/prompts/error_recovery.md:
```markdown
# Error Recovery
An error occurred while processing a GSD command.
## Error Details
**Command**: {{command}}
**Error**: {{error_message}}
## Context
- Project: {{project_name}}
- Phase: {{current_phase}}
## Instructions
Generate a user-friendly error message in Chinese that:
1. Explains what went wrong
2. Suggests possible solutions
3. Offers next steps the user can take
```
User decision (LOCKED): Template format is Markdown with {{variable}} syntax.
pytest tests/test_prompt_templates.py::TestPromptTemplatesExist -v
- All 3 template files exist with {{variable}} placeholders
- 4 tests in TestPromptTemplatesExist pass
Task 3: Implement PromptLoader class
src/gsd_openclaw/prompt_loader.py
- Test: All 7 tests in test_prompt_templates.py pass
Create src/gsd_openclaw/prompt_loader.py:
```python
"""Prompt template loader for GSD-OpenClaw."""
from __future__ import annotations
import re
from pathlib import Path
from typing import Dict, Any
class PromptLoader:
"""Load and render prompt templates with {{variable}} substitution.
Uses simple regex-based substitution for {{variable}} syntax.
Missing variables are left as-is (safe substitution behavior).
"""
def __init__(self, template_dir: Path | None = None):
"""Initialize PromptLoader.
Args:
template_dir: Directory containing template files.
Defaults to src/gsd_openclaw/prompts/.
"""
if template_dir is None:
template_dir = Path(__file__).parent / "prompts"
self.template_dir = Path(template_dir)
self._cache: Dict[str, str] = {}
def get(self, name: str) -> str:
"""Get raw template content by name (cached).
Args:
name: Template name without .md extension.
Returns:
Raw template content.
Raises:
FileNotFoundError: If template file doesn't exist.
"""
if name not in self._cache:
path = self.template_dir / f"{name}.md"
if not path.exists():
raise FileNotFoundError(f"Template not found: {name}")
self._cache[name] = path.read_text(encoding='utf-8')
return self._cache[name]
def render(self, name: str, **variables: Any) -> str:
"""Render a template with variable substitution.
Uses {{variable}} syntax. Missing variables are left as literal
{{variable}} strings (safe substitution).
Args:
name: Template name without .md extension.
**variables: Variable values to substitute.
Returns:
Rendered template content.
Raises:
FileNotFoundError: If template file doesn't exist.
"""
content = self.get(name)
for key, value in variables.items():
content = content.replace("{{" + key + "}}", str(value))
return content
```
Note: Using simple string.replace() for {{variable}} syntax instead of
string.Template which uses $variable syntax. This matches the user's
decision for {{variable}} format.
pytest tests/test_prompt_templates.py -v
- PromptLoader class implements get() and render() methods
- All 7 tests pass
- Missing variables are left as {{variable}} (safe substitution)
- Run pytest tests/test_prompt_templates.py -v (all tests pass)
- Verify all 3 template files have {{variable}} placeholders
- Verify PromptLoader.render substitutes variables correctly
<success_criteria>
- src/gsd_openclaw/prompts/ directory exists with __init__.py
- context_recovery.md, command_mapping.md, error_recovery.md templates exist
- PromptLoader class can load and render templates
- Variable substitution uses {{variable}} syntax
- All 7 tests in tests/test_prompt_templates.py pass </success_criteria>