data(atlas): update systems.db + add atlas tooling scripts

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>
This commit is contained in:
2026-03-25 22:18:09 +01:00
co-authored by Claude Opus 4.6
parent 0bab772fff
commit 8a3c5af842
5 changed files with 261 additions and 0 deletions
Binary file not shown.
+146
View File
@@ -0,0 +1,146 @@
#!/bin/bash
# Atlas helper functions for batch body catalog authoring
# Usage: source tooling/atlas-helpers.sh
ATLAS="tooling/atlas"
# Get all existing proper names (for collision avoidance)
atlas_existing_names() {
{
$ATLAS list-bodies 2>/dev/null | python3 -c "
import sys,json
d=json.load(sys.stdin)
for b in d:
if b.get('proper_name'): print(b['proper_name'])
"
$ATLAS list-stations 2>/dev/null | python3 -c "
import sys,json
d=json.load(sys.stdin)
for s in d:
if s.get('proper_name'): print(s['proper_name'])
"
} | sort -u
}
# List systems that already have bodies
atlas_systems_with_bodies() {
$ATLAS list-bodies 2>/dev/null | python3 -c "
import sys,json
d=json.load(sys.stdin)
for s in sorted(set(b['system_id'] for b in d)): print(s)
"
}
# Check if a system already has bodies
atlas_system_has_bodies() {
local sys_id="$1"
$ATLAS list-bodies --system "$sys_id" 2>/dev/null | python3 -c "
import sys,json
d=json.load(sys.stdin)
print('yes' if len(d) > 0 else 'no')
"
}
# Show system info
atlas_show() {
$ATLAS show-system "$1" 2>/dev/null
}
# Author system (generate base proposal)
atlas_author() {
$ATLAS author "$1" 2>/dev/null
}
# Verify a proposal JSON against integrity checks
atlas_verify_proposal() {
local proposal="$1"
python3 -c "
import json, sys
with open('$proposal') 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 only, excluding moons/belts/oort)
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 (add one unless wiki contradicts)')
# 6. Orbit consistency for top-level bodies
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 — all integrity checks passed')
"
}
+15
View File
@@ -0,0 +1,15 @@
#!/bin/bash
# List all existing proper names in the atlas DB (for collision avoidance)
cd "$(dirname "$0")/.."
{
tooling/atlas list-bodies 2>/dev/null | python3 -c "
import sys,json
for b in json.load(sys.stdin):
if b.get('proper_name'): print(b['proper_name'])
"
tooling/atlas list-stations 2>/dev/null | python3 -c "
import sys,json
for s in json.load(sys.stdin):
if s.get('proper_name'): print(s['proper_name'])
"
} | sort -u
+7
View File
@@ -0,0 +1,7 @@
#!/bin/bash
# List systems that already have bodies in the atlas DB
cd "$(dirname "$0")/.."
tooling/atlas list-bodies 2>/dev/null | python3 -c "
import sys,json
for s in sorted(set(b['system_id'] for b in json.load(sys.stdin))): print(s)
"
+93
View File
@@ -0,0 +1,93 @@
#!/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')
"