#!/usr/bin/env python3 """ process-wiki-system-changes Pipeline for star systems data. Modes: (default) Import wiki frontmatter → systems.db, update star-map.json, then regenerate wiki pages from DB (infobox + topology). --generate Generate wiki pages from existing DB (no import). --rebuild-db Drop and recreate systems.db from wiki (fresh start). --stats Show fill rates. --dry-run Show what star-map.json changes would occur. Database: server/data/systems.db Schema: server/data/systems-schema.sql """ import argparse import json import sys from pathlib import Path SCRIPT_DIR = Path(__file__).resolve().parent WORKTREE_ROOT = (SCRIPT_DIR / "..").resolve() STAR_MAP_PATH = WORKTREE_ROOT / "docs" / "design" / "star-map.json" DB_PATH = WORKTREE_ROOT / "server" / "data" / "systems.db" # Import wiki_sync sys.path.insert(0, str(SCRIPT_DIR / "db")) import wiki_sync # --------------------------------------------------------------------------- # Star-map.json update (topology fields only) # --------------------------------------------------------------------------- STAR_MAP_NODE_FIELDS = [ "system_id", "gate_topology", "aperture_count", "gate_connections", "hop_distance_from_gateway", ] def update_star_map_from_db(): """Update star-map.json node fields from systems.db.""" conn = wiki_sync.get_connection() with open(STAR_MAP_PATH, "r") as f: data = json.load(f) nodes = data["nodes"] updated = 0 for node in nodes: sid = node["system_id"] row = conn.execute( "SELECT g.gate_topology, g.aperture_count, g.gate_connections " "FROM star_systems s LEFT JOIN system_gates g ON s.system_id = g.system_id " "WHERE s.system_id = ?", (sid,) ).fetchone() if not row: continue changed = False field_map = { "gate_topology": row["gate_topology"], "aperture_count": row["aperture_count"], "gate_connections": row["gate_connections"], } for field, val in field_map.items(): if val is not None and node.get(field) != val: node[field] = val changed = True if changed: updated += 1 conn.close() with open(STAR_MAP_PATH, "w") as f: json.dump(data, f, indent=2) f.write("\n") return {"nodes": len(nodes), "edges": len(data["edges"]), "updated": updated} def dry_run_star_map(): """Show what would change in star-map.json.""" conn = wiki_sync.get_connection() with open(STAR_MAP_PATH, "r") as f: data = json.load(f) changes = [] for node in data["nodes"]: sid = node["system_id"] row = conn.execute( "SELECT g.gate_topology, g.aperture_count, g.gate_connections " "FROM star_systems s LEFT JOIN system_gates g ON s.system_id = g.system_id " "WHERE s.system_id = ?", (sid,) ).fetchone() if not row: continue field_map = { "gate_topology": row["gate_topology"], "aperture_count": row["aperture_count"], "gate_connections": row["gate_connections"], } for field, val in field_map.items(): if val is not None and node.get(field) != val: changes.append(f" {sid}.{field}: {node.get(field)} -> {val}") conn.close() return changes # --------------------------------------------------------------------------- # Main # --------------------------------------------------------------------------- def main(): parser = argparse.ArgumentParser( description="Star systems data pipeline: wiki ↔ systems.db ↔ star-map.json" ) parser.add_argument("--generate", action="store_true", help="Generate wiki from DB only") parser.add_argument("--rebuild-db", action="store_true", help="Drop and recreate DB from wiki") parser.add_argument("--stats", action="store_true", help="Show fill rates") parser.add_argument("--dry-run", action="store_true", help="Show star-map changes without writing") args = parser.parse_args() if args.stats: wiki_sync.stats() return if args.generate: print("--- Generating wiki pages from DB ---") result = wiki_sync.generate_wiki() print(result["summary"]) return if args.rebuild_db: print(f"--- Rebuilding {DB_PATH} from wiki ---") if DB_PATH.exists(): DB_PATH.unlink() print(" Deleted existing DB") if args.dry_run: # Need DB populated first for dry-run to work if not DB_PATH.exists(): print("No DB found. Run without --dry-run first.") sys.exit(1) changes = dry_run_star_map() if changes: print(f"star-map.json changes ({len(changes)}):") for c in changes: print(c) else: print("star-map.json: no changes") return # Full pipeline: wiki → DB → star-map.json → wiki pages print("=== Star Systems Pipeline ===\n") # Step 1: Import wiki frontmatter into DB print("--- Step 1: Wiki → DB ---") result = wiki_sync.import_from_wiki() if not result["ok"]: print(f"ERROR: {result.get('error')}") sys.exit(1) print(result["summary"]) if result["warnings"]: for w in result["warnings"][:5]: print(f" ⚠ {w}") if len(result["warnings"]) > 5: print(f" ... and {len(result['warnings']) - 5} more") # Step 2: Update star-map.json from DB print("\n--- Step 2: DB → star-map.json ---") map_result = update_star_map_from_db() print(f"Nodes: {map_result['nodes']}, Edges: {map_result['edges']}, Updated: {map_result['updated']}") # Step 3: Generate wiki pages from DB print("\n--- Step 3: DB → Wiki pages ---") gen_result = wiki_sync.generate_wiki() print(gen_result["summary"]) # Step 4: Stats print("\n--- Completion ---") wiki_sync.stats() if __name__ == "__main__": main()