Skip to main content

scripts-pilot-dashboard

#!/usr/bin/env python3 """ PILOT Dashboard - Process Refinement System

Generate real-time progress dashboard for PILOT execution plan. Shows track progress, active tasks, blockers, and session statistics.

Usage: python pilot_dashboard.py python pilot_dashboard.py --track E python pilot_dashboard.py --json

Author: CODITECT Process Refinement Version: 1.0.0 Created: 2026-01-02 """

import argparse import json import re import sys from datetime import datetime, timezone from pathlib import Path from typing import Optional

def get_project_root() -> Path: """Get the project root directory.""" current = Path(file).resolve().parent.parent while current != current.parent: if (current / "CLAUDE.md").exists(): return current current = current.parent return Path(file).resolve().parent.parent

PROJECT_ROOT = get_project_root()

def parse_pilot_plan() -> dict: """Parse PILOT plan to extract track progress.""" pilot_plan = PROJECT_ROOT / "internal" / "project" / "plans" / "PILOT-PARALLEL-EXECUTION-PLAN.md"

if not pilot_plan.exists():
return {"error": "PILOT plan not found"}

content = pilot_plan.read_text()
lines = content.split("\n")

tracks = {}
current_track = None
current_section = None

for line in lines:
# Detect track headers (e.g., "### Track A: Backend")
track_match = re.match(r'^###\s+Track\s+([A-G]):\s+(.+)', line)
if track_match:
current_track = track_match.group(1)
tracks[current_track] = {
"name": track_match.group(2),
"tasks": [],
"completed": 0,
"total": 0
}
continue

# Detect task items
if current_track and ("[ ]" in line or "[x]" in line or "[X]" in line):
completed = "[x]" in line.lower()
# Extract task ID and description
task_match = re.match(r'^-\s*\[.\]\s*([A-G]\.\d+\.?\d*)\s*[-–]\s*(.+)', line)
if task_match:
task_id = task_match.group(1)
description = task_match.group(2).strip()
tracks[current_track]["tasks"].append({
"id": task_id,
"description": description[:80],
"completed": completed
})
tracks[current_track]["total"] += 1
if completed:
tracks[current_track]["completed"] += 1

return tracks

def generate_progress_bar(completed: int, total: int, width: int = 20) -> str: """Generate ASCII progress bar.""" if total == 0: return "░" * width filled = int((completed / total) * width) return "█" * filled + "░" * (width - filled)

def format_dashboard(tracks: dict, filter_track: Optional[str] = None) -> str: """Format tracks as ASCII dashboard.""" now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")

dashboard = f"""

╔══════════════════════════════════════════════════════════════════════════════╗ ║ PILOT EXECUTION DASHBOARD ║ ║ {now} ║ ╠══════════════════════════════════════════════════════════════════════════════╣ """

if "error" in tracks:
dashboard += f"║ ⚠️ {tracks['error']:<72} ║\n"
dashboard += "╚══════════════════════════════════════════════════════════════════════════════╝\n"
return dashboard

# Calculate totals
total_completed = sum(t["completed"] for t in tracks.values())
total_tasks = sum(t["total"] for t in tracks.values())
overall_pct = (total_completed / total_tasks * 100) if total_tasks > 0 else 0

# Overall progress
dashboard += f"║ OVERALL: {generate_progress_bar(total_completed, total_tasks, 40)} {overall_pct:5.1f}% ({total_completed}/{total_tasks}) ║\n"
dashboard += "╠══════════════════════════════════════════════════════════════════════════════╣\n"

# Per-track progress
for track_id in sorted(tracks.keys()):
if filter_track and track_id != filter_track:
continue

track = tracks[track_id]
pct = (track["completed"] / track["total"] * 100) if track["total"] > 0 else 0
status = "✅" if pct == 100 else "🔄" if pct > 0 else "⬜"

dashboard += f"║ ║\n"
dashboard += f"║ {status} Track {track_id}: {track['name']:<40} ║\n"
dashboard += f"║ {generate_progress_bar(track['completed'], track['total'], 30)} {pct:5.1f}% ({track['completed']}/{track['total']}) ║\n"

# Show incomplete tasks
incomplete = [t for t in track["tasks"] if not t["completed"]]
if incomplete and len(incomplete) <= 3:
for task in incomplete[:3]:
dashboard += f"║ └─ [ ] {task['id']}: {task['description'][:50]:<50} ║\n"

dashboard += "║ ║\n"
dashboard += "╚══════════════════════════════════════════════════════════════════════════════╝\n"

return dashboard

def main(): parser = argparse.ArgumentParser(description="PILOT Dashboard") parser.add_argument("--track", help="Filter to specific track (A-G)") parser.add_argument("--json", action="store_true", help="Output as JSON")

args = parser.parse_args()

tracks = parse_pilot_plan()

if args.json:
print(json.dumps(tracks, indent=2))
else:
dashboard = format_dashboard(tracks, args.track)
print(dashboard)

if name == "main": main()