diff --git a/scripts/phase_tracker.py b/scripts/phase_tracker.py new file mode 100644 index 00000000..be6229a8 --- /dev/null +++ b/scripts/phase_tracker.py @@ -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()