feat: implement phase_tracker.py
This commit is contained in:
114
scripts/phase_tracker.py
Normal file
114
scripts/phase_tracker.py
Normal file
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
[OPS] Phase Progression Tracker
|
||||
Part of the Gemini Sovereign Infrastructure Suite.
|
||||
|
||||
Tracks the fleet's progress through the Paperclips-inspired evolution arc.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import argparse
|
||||
|
||||
MILESTONES_FILE = "fleet/milestones.md"
|
||||
COMPLETED_FILE = "fleet/completed_milestones.json"
|
||||
|
||||
class PhaseTracker:
|
||||
def __init__(self):
|
||||
# Find files relative to repo root
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
repo_root = os.path.dirname(script_dir)
|
||||
|
||||
self.milestones_path = os.path.join(repo_root, MILESTONES_FILE)
|
||||
self.completed_path = os.path.join(repo_root, COMPLETED_FILE)
|
||||
|
||||
self.milestones = self.parse_milestones()
|
||||
self.completed = self.load_completed()
|
||||
|
||||
def parse_milestones(self):
|
||||
if not os.path.exists(self.milestones_path):
|
||||
return {}
|
||||
|
||||
with open(self.milestones_path, "r") as f:
|
||||
content = f.read()
|
||||
|
||||
phases = {}
|
||||
current_phase = None
|
||||
|
||||
for line in content.split("\n"):
|
||||
if line.startswith("## Phase"):
|
||||
current_phase = line.replace("## ", "").strip()
|
||||
phases[current_phase] = []
|
||||
elif line.startswith("### M"):
|
||||
m_id = line.split(":")[0].replace("### ", "").strip()
|
||||
title = line.split(":")[1].strip()
|
||||
phases[current_phase].append({"id": m_id, "title": title})
|
||||
|
||||
return phases
|
||||
|
||||
def load_completed(self):
|
||||
if os.path.exists(self.completed_path):
|
||||
with open(self.completed_path, "r") as f:
|
||||
try:
|
||||
return json.load(f)
|
||||
except:
|
||||
return []
|
||||
return []
|
||||
|
||||
def save_completed(self):
|
||||
with open(self.completed_path, "w") as f:
|
||||
json.dump(self.completed, f, indent=2)
|
||||
|
||||
def show_progress(self):
|
||||
print("--- Fleet Phase Progression Tracker ---")
|
||||
total_milestones = 0
|
||||
total_completed = 0
|
||||
|
||||
if not self.milestones:
|
||||
print("[ERROR] No milestones found in fleet/milestones.md")
|
||||
return
|
||||
|
||||
for phase, ms in self.milestones.items():
|
||||
print(f"\n{phase}")
|
||||
for m in ms:
|
||||
total_milestones += 1
|
||||
done = m["id"] in self.completed
|
||||
if done:
|
||||
total_completed += 1
|
||||
status = "✅" if done else "⭕"
|
||||
print(f" {status} {m['id']}: {m['title']}")
|
||||
|
||||
percent = (total_completed / total_milestones) * 100 if total_milestones > 0 else 0
|
||||
print(f"\nOverall Progress: {total_completed}/{total_milestones} ({percent:.1f}%)")
|
||||
|
||||
def mark_complete(self, m_id: str):
|
||||
if m_id not in self.completed:
|
||||
self.completed.append(m_id)
|
||||
self.save_completed()
|
||||
print(f"[SUCCESS] Marked {m_id} as complete.")
|
||||
else:
|
||||
print(f"[INFO] {m_id} is already complete.")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Gemini Phase Tracker")
|
||||
subparsers = parser.add_subparsers(dest="command")
|
||||
|
||||
subparsers.add_parser("status", help="Show current progress")
|
||||
|
||||
complete_parser = subparsers.add_parser("complete", help="Mark a milestone as complete")
|
||||
complete_parser.add_argument("id", help="Milestone ID (e.g. M1)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
tracker = PhaseTracker()
|
||||
|
||||
if args.command == "status":
|
||||
tracker.show_progress()
|
||||
elif args.command == "complete":
|
||||
tracker.mark_complete(args.id)
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user