Files
goplt/docs/content/stories/generate_tasks.py

220 lines
6.7 KiB
Python

#!/usr/bin/env python3
"""
Generate task files from plan.md
This script parses the plan.md file and creates detailed task files for each task.
"""
import re
import os
from pathlib import Path
def parse_plan(plan_path):
"""Parse plan.md and extract tasks"""
with open(plan_path, 'r') as f:
content = f.read()
tasks = []
current_phase = None
current_section = None
subtask_num = 1
lines = content.split('\n')
i = 0
while i < len(lines):
line = lines[i].rstrip()
# Phase header
phase_match = re.match(r'^## Phase (\d+):', line)
if phase_match:
current_phase = int(phase_match.group(1))
subtask_num = 1 # Reset subtask counter for new phase
i += 1
continue
# Section header (e.g., "#### 0.1 Repository Bootstrap")
section_match = re.match(r'^#### (\d+\.\d+)', line)
if section_match:
current_section = section_match.group(1)
subtask_num = 1 # Reset subtask counter for new section
i += 1
continue
# Task item (checkbox) - must match exactly
task_match = re.match(r'^- \[ \] (.+)', line)
if task_match and current_phase is not None and current_section is not None:
task_desc = task_match.group(1).strip()
# Handle tasks that end with colon (might have code block or list following)
code_block = ""
# Skip empty lines and code blocks
if i + 1 < len(lines):
next_line = lines[i + 1].strip()
if next_line.startswith('```'):
# Extract code block
j = i + 2
while j < len(lines) and not lines[j].strip().startswith('```'):
code_block += lines[j] + '\n'
j += 1
i = j + 1
elif next_line.startswith('- [ ]') or next_line.startswith('```'):
# Next task or code block, don't skip
i += 1
else:
i += 1
else:
i += 1
# Only add if we have valid phase and section
if current_phase is not None and current_section is not None:
tasks.append({
'phase': current_phase,
'section': current_section,
'subtask': subtask_num,
'description': task_desc,
'code': code_block.strip()
})
subtask_num += 1
continue
i += 1
return tasks
def create_task_file(task, output_dir):
"""Create a task markdown file"""
phase_dir = output_dir / f"phase{task['phase']}"
phase_dir.mkdir(exist_ok=True)
task_id = f"{task['section']}.{task['subtask']}"
# Create safe filename
safe_desc = re.sub(r'[^\w\s-]', '', task['description'])[:50].strip().replace(' ', '-').lower()
filename = f"{task_id}-{safe_desc}.md"
filepath = phase_dir / filename
# Generate content
content = f"""# Task {task_id}: {task['description']}
## Metadata
- **Task ID**: {task_id}
- **Title**: {task['description']}
- **Phase**: {task['phase']} - {get_phase_name(task['phase'])}
- **Section**: {task['section']}
- **Status**: Pending
- **Priority**: High
- **Estimated Time**: TBD
- **Dependencies**: TBD
## Description
{task['description']}
## Requirements
- {task['description']}
## Implementation Steps
1. TODO: Add implementation steps
2. TODO: Add implementation steps
3. TODO: Add implementation steps
## Acceptance Criteria
- [ ] Task {task_id} is completed
- [ ] All requirements are met
- [ ] Code compiles and tests pass
## Related ADRs
- See relevant ADRs in `docs/adr/`
## Implementation Notes
- TODO: Add implementation notes
## Testing
```bash
# TODO: Add test commands
go test ./...
```
"""
if task['code']:
content += f"\n## Code Reference\n\n```go\n{task['code']}\n```\n"
with open(filepath, 'w') as f:
f.write(content)
return filepath
def get_phase_name(phase_num):
"""Get phase name from number"""
phases = {
0: "Project Setup & Foundation",
1: "Core Kernel & Infrastructure",
2: "Authentication & Authorization",
3: "Module Framework",
4: "Sample Feature Module (Blog)",
5: "Infrastructure Adapters",
6: "Observability & Production Readiness",
7: "Testing, Documentation & CI/CD",
8: "Advanced Features & Polish"
}
return phases.get(phase_num, "Unknown")
def main():
script_dir = Path(__file__).parent
plan_path = script_dir.parent / "plan.md"
output_dir = script_dir
if not plan_path.exists():
print(f"Error: {plan_path} not found")
return
print(f"Parsing {plan_path}...")
try:
tasks = parse_plan(plan_path)
print(f"Found {len(tasks)} tasks")
if len(tasks) == 0:
print("Warning: No tasks found. Check the plan.md format.")
return
created = 0
skipped = 0
for task in tasks:
try:
task_id = f"{task['section']}.{task['subtask']}"
# Determine filepath before creating
phase_dir = output_dir / f"phase{task['phase']}"
phase_dir.mkdir(exist_ok=True)
# Create safe filename
safe_desc = re.sub(r'[^\w\s-]', '', task['description'])[:50].strip().replace(' ', '-').lower()
filename = f"{task_id}-{safe_desc}.md"
filepath = phase_dir / filename
# Check if file already exists (skip if so)
if filepath.exists() and filepath.stat().st_size > 100:
skipped += 1
continue
# Create the file
create_task_file(task, output_dir)
created += 1
if created % 10 == 0:
print(f"Created {created} task files...")
except Exception as e:
print(f"Error creating task {task.get('section', '?')}.{task.get('subtask', '?')}: {e}")
import traceback
traceback.print_exc()
print(f"\nCreated {created} new task files")
if skipped > 0:
print(f"Skipped {skipped} existing task files")
print(f"Total tasks processed: {len(tasks)}")
except Exception as e:
print(f"Error: {e}")
import traceback
traceback.print_exc()
if __name__ == '__main__':
main()