scripts-generate-sprint-plans
#!/usr/bin/env python3 """
title: "Configuration" component_type: script version: "1.0.0" audience: contributor status: stable summary: "Generate Sprint Plans for V2 Project Structure" keywords: ['automation', 'ci/cd', 'database', 'deployment', 'generate'] tokens: ~500 created: 2025-12-22 updated: 2025-12-22 script_name: "generate-sprint-plans.py" language: python executable: true usage: "python3 scripts/generate-sprint-plans.py [options]" python_version: "3.10+" dependencies: [] modifies_files: false network_access: false requires_auth: false
Generate Sprint Plans for V2 Project Structure
Creates SPRINT-PLAN.md files for Sprint 26-56 based on epic allocations """
from V2-MASTER-PROJECT-PLAN.md.
Usage: python3 scripts/generate-sprint-plans.py """
import os from datetime import datetime, timedelta from pathlib import Path
Configuration
START_SPRINT = 26 END_SPRINT = 56 SPRINT_25_END = datetime(2025, 12, 27) # Sprint 25 ends Dec 27 SPRINT_DURATION = 14 # days
Epic allocation to sprints (from V2-MASTER-PROJECT-PLAN.md)
SPRINT_EPIC_ALLOCATION = { # E001 completes in Sprint 25-26 26: {"epics": ["E001"], "goal": "Complete Core Platform Autonomy", "tasks": 546}, # E002: Sprint 27-30 27: {"epics": ["E002"], "goal": "Toon UI - React Component Library Start", "tasks": 585}, 28: {"epics": ["E002"], "goal": "Toon UI - Core Components Complete", "tasks": 585}, 29: {"epics": ["E002"], "goal": "Toon UI - Generative UI System", "tasks": 586}, 30: {"epics": ["E002"], "goal": "Toon UI - Design System Integration Complete", "tasks": 585}, # E003: Sprint 31-34 31: {"epics": ["E003"], "goal": "Memory Intelligence - Context DB Enhancement", "tasks": 469}, 32: {"epics": ["E003"], "goal": "Memory Intelligence - Decision Extraction", "tasks": 469}, 33: {"epics": ["E003"], "goal": "Memory Intelligence - Knowledge Graph", "tasks": 469}, 34: {"epics": ["E003"], "goal": "Memory Intelligence - Anti-Forgetting Complete", "tasks": 469}, # E004: Sprint 35-38 35: {"epics": ["E004"], "goal": "Workflow Automation - Custom Engine Start", "tasks": 549}, 36: {"epics": ["E004"], "goal": "Workflow Automation - Business Process Templates", "tasks": 549}, 37: {"epics": ["E004"], "goal": "Workflow Automation - State Machine Integration", "tasks": 550}, 38: {"epics": ["E004"], "goal": "Workflow Automation - Approval System Complete", "tasks": 550}, # E005: Sprint 39-41 39: {"epics": ["E005"], "goal": "Quality Assurance - Testing Framework Start", "tasks": 514}, 40: {"epics": ["E005"], "goal": "Quality Assurance - Quality Gates & Hooks", "tasks": 514}, 41: {"epics": ["E005"], "goal": "Quality Assurance - Performance & Security Testing", "tasks": 514}, # E006: Sprint 42-44 42: {"epics": ["E006"], "goal": "Deployment Infrastructure - CI/CD Enhancement", "tasks": 411}, 43: {"epics": ["E006"], "goal": "Deployment Infrastructure - Container Orchestration", "tasks": 411}, 44: {"epics": ["E006"], "goal": "Deployment Infrastructure - Production Monitoring", "tasks": 412}, # E007: Sprint 45-46 45: {"epics": ["E007"], "goal": "Documentation System - Auto-Generated Docs Start", "tasks": 493}, 46: {"epics": ["E007"], "goal": "Documentation System - Interactive Tutorials Complete", "tasks": 494}, # E008: Sprint 47-49 47: {"epics": ["E008"], "goal": "Security & Compliance - Auth System Start", "tasks": 551}, 48: {"epics": ["E008"], "goal": "Security & Compliance - Secrets & Audit", "tasks": 551}, 49: {"epics": ["E008"], "goal": "Security & Compliance - Compliance Reporting", "tasks": 552}, # E009: Sprint 50-51 50: {"epics": ["E009"], "goal": "Analytics & Observability - Metrics Collection", "tasks": 716}, 51: {"epics": ["E009"], "goal": "Analytics & Observability - Tracing & Dashboards", "tasks": 716}, # E010: Sprint 52-56 52: {"epics": ["E010"], "goal": "Rollout - Beta Testing Program Start", "tasks": 637}, 53: {"epics": ["E010"], "goal": "Rollout - Beta Testing Complete", "tasks": 638}, 54: {"epics": ["E010"], "goal": "Rollout - Pilot Deployment (10 Customers)", "tasks": 638}, 55: {"epics": ["E010"], "goal": "Rollout - Public Launch (GTM)", "tasks": 638}, 56: {"epics": ["E010"], "goal": "Rollout - Post-Launch Support Complete", "tasks": 638}, }
Epic details for reference
EPIC_DETAILS = { "E001": {"name": "Core Platform Autonomy", "features": ["F001.1", "F001.2"]}, "E002": {"name": "Toon UI Integration", "features": ["F002.1", "F002.2", "F002.3"]}, "E003": {"name": "Memory Intelligence", "features": ["F003.1", "F003.2", "F003.3", "F003.4"]}, "E004": {"name": "Workflow Automation", "features": ["F004.1", "F004.2", "F004.3", "F004.4", "F004.5"]}, "E005": {"name": "Quality Assurance", "features": ["F005.1", "F005.2", "F005.3", "F005.4"]}, "E006": {"name": "Deployment Infrastructure", "features": ["F006.1", "F006.2", "F006.3"]}, "E007": {"name": "Documentation System", "features": ["F007.1", "F007.2", "F007.3"]}, "E008": {"name": "Security & Compliance", "features": ["F008.1", "F008.2", "F008.3", "F008.4"]}, "E009": {"name": "Analytics & Observability", "features": ["F009.1", "F009.2", "F009.3"]}, "E010": {"name": "Rollout & GTM", "features": ["F010.1", "F010.2", "F010.3", "F010.4"]}, }
def get_sprint_dates(sprint_num: int) -> tuple: """Calculate sprint start and end dates.""" days_from_sprint25 = (sprint_num - 25) * SPRINT_DURATION start_date = SPRINT_25_END + timedelta(days=days_from_sprint25 - SPRINT_DURATION + 1) end_date = start_date + timedelta(days=SPRINT_DURATION - 1) return start_date, end_date
def generate_sprint_plan(sprint_num: int, allocation: dict) -> str: """Generate SPRINT-PLAN.md content for a sprint.""" start_date, end_date = get_sprint_dates(sprint_num) epics = allocation["epics"] goal = allocation["goal"] tasks = allocation["tasks"]
epic_names = ", ".join([f"{e}: {EPIC_DETAILS[e]['name']}" for e in epics])
content = f"""# Sprint {sprint_num} Plan
Sprint ID: Sprint-{sprint_num} Dates: {start_date.strftime('%Y-%m-%d')} to {end_date.strftime('%Y-%m-%d')} (2 weeks) Goal: {goal} Status: Planned
Sprint Metrics
| Metric | Planned | Actual |
|---|---|---|
| Tasks | {tasks} | - |
| Story Points | {tasks // 10} | - |
| Capacity (hours) | {tasks * 2} | - |
Epics in Sprint
{epic_names}
Sprint Goal: {goal}
"""
# Add feature sections
for epic in epics:
details = EPIC_DETAILS[epic]
for feature in details["features"]:
content += f"""#### {feature}: Feature Tasks
- Phase tasks to be assigned from epic tasklist
- See
epics/{epic}-*/TASKLIST.mdfor detailed breakdown
"""
content += f"""---
Dependencies & Risks
Blockers:
- None identified
Dependencies: """
# Add dependencies based on sprint number
if sprint_num > 26:
prev_sprint = sprint_num - 1
content += f"- Sprint {prev_sprint} completion required\n"
content += f"""
Risks:
- Velocity may vary from estimates
- Cross-team coordination overhead
Definition of Done
- All {tasks} tasks completed and checked off
- Code reviewed and merged
- Tests passing (80%+ coverage)
- Documentation updated
- Sprint retrospective completed
Daily Progress Tracking
Week 1
| Day | Completed | Remaining | Notes |
|---|---|---|---|
| Mon | - | {tasks} | Sprint start |
| Tue | - | - | |
| Wed | - | - | |
| Thu | - | - | |
| Fri | - | - | Week 1 review |
Week 2
| Day | Completed | Remaining | Notes |
|---|---|---|---|
| Mon | - | - | |
| Tue | - | - | |
| Wed | - | - | |
| Thu | - | - | |
| Fri | - | 0 | Sprint complete |
Retrospective
What went well:
- [To be filled after sprint]
What could improve:
- [To be filled after sprint]
Action items:
- [To be filled after sprint]
Created: {datetime.now().strftime('%Y-%m-%d')} Last Updated: {datetime.now().strftime('%Y-%m-%d')} """
return content
def main(): """Generate all sprint plan files.""" base_path = Path(file).parent.parent / "docs" / "05-project-planning" / "v2" / "sprints"
print(f"Generating Sprint Plans for Sprint {START_SPRINT}-{END_SPRINT}")
print(f"Output directory: {base_path}")
print()
created_count = 0
skipped_count = 0
for sprint_num in range(START_SPRINT, END_SPRINT + 1):
sprint_dir = base_path / f"Sprint-{sprint_num}"
sprint_dir.mkdir(parents=True, exist_ok=True)
plan_path = sprint_dir / "SPRINT-PLAN.md"
if sprint_num in SPRINT_EPIC_ALLOCATION:
allocation = SPRINT_EPIC_ALLOCATION[sprint_num]
content = generate_sprint_plan(sprint_num, allocation)
with open(plan_path, 'w') as f:
f.write(content)
start_date, end_date = get_sprint_dates(sprint_num)
print(f" ✓ Sprint {sprint_num}: {allocation['goal'][:40]}... ({allocation['tasks']} tasks)")
created_count += 1
else:
print(f" ⚠ Sprint {sprint_num}: No allocation defined, skipping")
skipped_count += 1
print()
print(f"Summary:")
print(f" Created: {created_count} sprint plans")
print(f" Skipped: {skipped_count}")
print()
# Calculate total tasks
total_tasks = sum(a["tasks"] for a in SPRINT_EPIC_ALLOCATION.values())
print(f"Total tasks across Sprint {START_SPRINT}-{END_SPRINT}: {total_tasks}")
# Insert sprints into database
print()
print("Inserting sprints into database...")
import sqlite3
# ADR-114 & ADR-118: Use centralized path discovery
# sprints table is in sessions.db (Tier 3: project/session management data)
script_dir = Path(__file__).resolve().parent
sys.path.insert(0, str(script_dir / "core"))
try:
from paths import SESSIONS_DB
db_path = SESSIONS_DB
except ImportError:
_user_data = Path.home() / "PROJECTS" / ".coditect-data" / "context-storage"
if _user_data.exists():
db_path = _user_data / "sessions.db"
else:
db_path = script_dir.parent / "context-storage" / "sessions.db"
if db_path.exists():
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
for sprint_num in range(START_SPRINT, END_SPRINT + 1):
if sprint_num in SPRINT_EPIC_ALLOCATION:
allocation = SPRINT_EPIC_ALLOCATION[sprint_num]
start_date, end_date = get_sprint_dates(sprint_num)
cursor.execute("""
INSERT OR REPLACE INTO sprints
(id, project_id, name, goal, start_date, end_date, status, velocity_planned)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""", (
f"Sprint-{sprint_num}",
"P001",
f"Sprint {sprint_num}",
allocation["goal"],
start_date.strftime('%Y-%m-%d'),
end_date.strftime('%Y-%m-%d'),
"planned",
allocation["tasks"]
))
conn.commit()
conn.close()
print(f" ✓ {created_count} sprints inserted into database")
else:
print(f" ⚠ Database not found at {db_path}")
print()
print("Done!")
if name == "main": main()