115 lines
3.6 KiB
Python
115 lines
3.6 KiB
Python
#!/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()
|