systems.db: 43 North Reach body catalogs (hops 4-12) tooling: atlas-verify, atlas-names, atlas-systems-done, atlas-helpers.sh Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
94 lines
3.0 KiB
Bash
Executable File
94 lines
3.0 KiB
Bash
Executable File
#!/bin/bash
|
|
# Verify a proposal JSON against integrity checks
|
|
# Usage: tooling/atlas-verify docs/atlas/proposals/GJ273.json
|
|
cd "$(dirname "$0")/.."
|
|
python3 -c "
|
|
import json, sys
|
|
|
|
with open('$1') as f:
|
|
p = json.load(f)
|
|
|
|
errors = []
|
|
bodies = p.get('bodies', [])
|
|
stations = p.get('stations', [])
|
|
|
|
# 1. Inhabited bodies must have names
|
|
for b in bodies:
|
|
if b.get('inhabited') and not b.get('proper_name'):
|
|
errors.append(f\"Inhabited body {b['body_id']} has no proper_name\")
|
|
|
|
# 2. Uninhabited bodies should have null names
|
|
for b in bodies:
|
|
if not b.get('inhabited') and b.get('proper_name'):
|
|
errors.append(f\"Uninhabited body {b['body_id']} has proper_name '{b['proper_name']}' (should be null)\")
|
|
|
|
# 3. All stations must have names
|
|
for s in stations:
|
|
if not s.get('proper_name'):
|
|
errors.append(f\"Station {s['station_id']} has no proper_name\")
|
|
|
|
# 4. Body count check
|
|
planets = [b for b in bodies if b['body_type'] == 'planet']
|
|
star_type = p.get('spectral_class', 'M')
|
|
if star_type.startswith(('G', 'F')):
|
|
min_planets = 8
|
|
elif star_type.startswith('K'):
|
|
min_planets = 7
|
|
else:
|
|
min_planets = 6
|
|
if len(planets) < min_planets:
|
|
errors.append(f\"Only {len(planets)} planets, need {min_planets}+ for {star_type} star\")
|
|
|
|
# 5. Required structures
|
|
oort = [b for b in bodies if b['body_type'] == 'oort_cloud']
|
|
if not oort:
|
|
errors.append('No oort cloud')
|
|
horizon = [s for s in stations if s['station_type'] == 'horizon']
|
|
if not horizon:
|
|
errors.append('No horizon station')
|
|
elif not any(s.get('has_gate_infrastructure') for s in horizon):
|
|
errors.append('Horizon station missing has_gate_infrastructure: true')
|
|
belts = [b for b in bodies if b['body_type'] == 'asteroid_belt']
|
|
if not belts:
|
|
errors.append('No asteroid belt')
|
|
|
|
# 6. Orbit consistency
|
|
top_level = [b for b in bodies if not b.get('parent_body_id')]
|
|
orbits = [b['orbit_index'] for b in top_level]
|
|
if orbits != sorted(orbits):
|
|
errors.append(f\"Top-level orbit_index not monotonic: {orbits}\")
|
|
if len(orbits) != len(set(orbits)):
|
|
errors.append(f\"Duplicate orbit_index in top-level: {orbits}\")
|
|
|
|
# 7. Moon orbit consistency
|
|
parents = {}
|
|
for b in bodies:
|
|
pid = b.get('parent_body_id')
|
|
if pid:
|
|
parents.setdefault(pid, []).append(b['orbit_index'])
|
|
for pid, idxs in parents.items():
|
|
if idxs != sorted(idxs):
|
|
errors.append(f\"Moon orbits under {pid} not monotonic: {idxs}\")
|
|
if len(idxs) != len(set(idxs)):
|
|
errors.append(f\"Duplicate moon orbit_index under {pid}: {idxs}\")
|
|
|
|
# 8. Parent references valid
|
|
body_ids = set(b['body_id'] for b in bodies)
|
|
for b in bodies:
|
|
pid = b.get('parent_body_id')
|
|
if pid and pid not in body_ids:
|
|
errors.append(f\"Body {b['body_id']} references missing parent {pid}\")
|
|
for s in stations:
|
|
oid = s.get('orbits_body_id')
|
|
if oid and oid not in body_ids:
|
|
errors.append(f\"Station {s['station_id']} references missing body {oid}\")
|
|
|
|
if errors:
|
|
print('FAIL')
|
|
for e in errors:
|
|
print(f' - {e}')
|
|
sys.exit(1)
|
|
else:
|
|
print('PASS')
|
|
"
|