diff --git a/tooling/atlas-check b/tooling/atlas-check new file mode 100755 index 000000000..f3322badc --- /dev/null +++ b/tooling/atlas-check @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +"""Quick diagnostic for an atlas proposal — shows planet count, body summary, and flags. + +Usage: + tooling/atlas-check docs/atlas/proposals/GJ1075.json +""" +import json +import sys +from pathlib import Path + + +def check(path: Path): + with open(path) as f: + p = json.load(f) + + bodies = p.get("bodies", []) + stations = p.get("stations", []) + + planets = [b for b in bodies if b["body_type"] == "planet" and not b.get("parent_body_id")] + gas_giants = [b for b in bodies if b["body_type"] == "gas_giant"] + moons = [b for b in bodies if b["body_type"] == "moon"] + belts = [b for b in bodies if b["body_type"] == "asteroid_belt"] + oort = [b for b in bodies if b["body_type"] == "oort_cloud"] + + sc = p.get("spectral_class", "") + if sc.startswith(("G", "F")): + min_p = 8 + elif sc.startswith("K"): + min_p = 7 + else: + min_p = 6 + + print(f"=== {path.name} — {p.get('proper_name') or p['system_id']} ===") + print(f" star_type: {p.get('star_type')} spectral: {sc}") + print(f" planets: {len(planets)} (need {min_p}+) gas_giants: {len(gas_giants)} moons: {len(moons)}") + print(f" belts: {len(belts)} oort: {len(oort)} stations: {len(stations)}") + + if planets: + print(f" orbits: {' → '.join(str(b['orbit_index']) for b in planets)}") + print(f" gravity: {' / '.join(str(b['surface_gravity']) for b in planets)}") + print(f" periods: {' / '.join(str(b['orbital_period_days']) for b in planets)} days") + + inhabited = [b for b in bodies if b.get("inhabited")] + if inhabited: + for b in inhabited: + print(f" inhabited: {b['body_id']} ({b.get('proper_name', '?')}) pop={b.get('population')}") + + for s in stations: + print(f" station: {s['station_id']} ({s.get('proper_name', '?')}) type={s['station_type']} pop={s.get('population')}") + + # Flags + if len(planets) < min_p: + print(f" ⚠ need {min_p - len(planets)} more planet(s)") + if not belts: + print(f" ⚠ no asteroid belt") + if not oort: + print(f" ⚠ no oort cloud") + horizons = [s for s in stations if s["station_type"] == "horizon"] + if not horizons: + print(f" ⚠ no horizon station") + elif not any(s.get("has_gate_infrastructure") for s in horizons): + print(f" ⚠ horizon station missing gate_infrastructure") + + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("usage: tooling/atlas-check [...]") + sys.exit(1) + for arg in sys.argv[1:]: + check(Path(arg)) + print() diff --git a/tooling/atlas-verify b/tooling/atlas-verify index 3e67cfb9c..c06b6e070 100755 --- a/tooling/atlas-verify +++ b/tooling/atlas-verify @@ -98,7 +98,7 @@ def verify_proposal(path: Path) -> list[str]: # 9. star_type vs spectral_class consistency star_type_field = p.get("star_type", "") spectral = p.get("spectral_class", "") - if star_type_field and spectral and star_type_field != "binary": + if star_type_field and spectral and star_type_field not in ("binary", "unusual"): # Strip dwarf/subdwarf prefixes (d, sd) to get actual class letter s = spectral.lstrip("sd").upper() spectral_letter = s[0] if s else ""