- make test-tooling: planet-gen determinism guard + import_economics
--dry-run, wired into pre-push on TOOLING_CHANGED; ruff widened to
E4/E7/E9/F/W (90 safe auto-fixes applied; E402/E702/F841 ignored with
documented counts)
- one-generator reality fixed in DEVOPS.md, asset-pipeline rule, CLAUDE.md
(import_economics sole generator since #951/D-223); dead check-protocol
target deleted; DEVOPS hook/config sections rewritten from the actual
hook sources; team-patterns gate description updated (client+tooling)
- project.yaml: 0.2.0 → 0.4.0 per the 0.{phase}.{n} scheme, description
refreshed from the v0.1 Sova narration to cascade reality
- stale comment sweep: voxel.rs stub claims (all 8 families implemented),
cascade.rs TODO recited to T-1044, main.rs D-192 handshake claim,
relationships.rs/chunk_streaming.rs version targets → phase language
- gitignore: client/settings.db* e2e-run artifacts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
389 lines
13 KiB
Python
389 lines
13 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
atlas_cohesion_audit.py — Quality analysis script for atlas atlas_* tables.
|
|
|
|
Runs a set of SQL queries against server/data/systems.db atlas_* tables to
|
|
identify names that need hand-refining:
|
|
|
|
1. Stem duplicates within a system (same root token, different bodies)
|
|
2. Cross-feature same-body near-duplicates (e.g. Aureus River + Aureus Range)
|
|
3. Cardinal direction density per body (Western X / Northern X patterns)
|
|
4. Generic / lazy outputs (Great %, Hilly %, Sector %, The %)
|
|
5. Empty or single-character names
|
|
6. Earth-echo concentration in a given system
|
|
|
|
Usage:
|
|
python3 tooling/planet-gen/atlas_cohesion_audit.py
|
|
python3 tooling/planet-gen/atlas_cohesion_audit.py --system GJ 144
|
|
python3 tooling/planet-gen/atlas_cohesion_audit.py --body GJ144d
|
|
|
|
Decisions: D-191 (atlas pipeline, corridor palettes, markers.json format)
|
|
"""
|
|
|
|
import argparse
|
|
import sqlite3
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = (Path(__file__).resolve().parent / ".." / "..").resolve()
|
|
DB_PATH = REPO_ROOT / "server" / "data" / "systems.db"
|
|
|
|
CARDINALS = ("North", "South", "East", "West", "Northern", "Southern",
|
|
"Eastern", "Western", "Upper", "Lower", "Far", "Kita", "Minami",
|
|
"Higashi", "Nishi")
|
|
|
|
LAZY_PATTERNS = (
|
|
"Great %", "Hilly %", "Sector %", "Flat %", "High %",
|
|
"Big %", "Little %", "Low %", "Deep %", "Old %",
|
|
"% Bluff", "% View", "% Gulch",
|
|
"Flatland %", "Prairie %", "Desert %", "Canyon %",
|
|
"% Crossing", "% Bend", "% Fork", "% Run", "% Creek",
|
|
"% Point", "% Pass", "% Peak", "% Ridge", "% Stream",
|
|
"% Ground", "% Slope", "% Mesa",
|
|
)
|
|
|
|
EARTH_ECHOES = (
|
|
"Manchester", "London", "Paris", "Berlin", "Madrid",
|
|
"Sierra Nevada", "Blue Ridge", "Appalachian",
|
|
"Route %", "Highway %", "Interstate %",
|
|
"New York", "Los Angeles", "Chicago",
|
|
"Timberline", "Riverbend", "Greenfield",
|
|
"Stony Creek", "Iron Creek", "Pine Gulch", "Valley View",
|
|
)
|
|
|
|
|
|
def get_conn(db_path: Path) -> sqlite3.Connection:
|
|
conn = sqlite3.connect(str(db_path))
|
|
conn.row_factory = sqlite3.Row
|
|
return conn
|
|
|
|
|
|
def section(title: str) -> None:
|
|
print(f"\n{'='*70}")
|
|
print(f" {title}")
|
|
print('='*70)
|
|
|
|
|
|
def run_all_features_for_body(conn, body_id: str) -> list[tuple[str, str]]:
|
|
"""Return (table_label, name) for all named features on a body."""
|
|
features = []
|
|
for table, label in [
|
|
("atlas_cities", "city"),
|
|
("atlas_rivers", "river"),
|
|
("atlas_oceans", "ocean"),
|
|
("atlas_mountain_ranges", "mountain"),
|
|
("atlas_pois", "poi"),
|
|
]:
|
|
rows = conn.execute(
|
|
f"SELECT name FROM {table} WHERE body_id=? AND name != ''", (body_id,)
|
|
).fetchall()
|
|
for r in rows:
|
|
features.append((label, r["name"]))
|
|
return features
|
|
|
|
|
|
def stem_of(name: str) -> str:
|
|
"""Extract first significant word as a rough stem."""
|
|
parts = name.replace("The ", "").replace("the ", "").strip().split()
|
|
return parts[0].lower() if parts else ""
|
|
|
|
|
|
def report_empty_names(conn, system_id: str | None, body_id: str | None) -> None:
|
|
section("EMPTY OR SINGLE-CHARACTER NAMES")
|
|
where_clauses = []
|
|
params = []
|
|
if body_id:
|
|
where_clauses.append("body_id = ?")
|
|
params.append(body_id)
|
|
elif system_id:
|
|
where_clauses.append("body_id IN (SELECT body_id FROM bodies WHERE system_id = ?)")
|
|
params.append(system_id)
|
|
w = f"WHERE {' AND '.join(where_clauses)}" if where_clauses else ""
|
|
found = 0
|
|
for table in ("atlas_cities", "atlas_rivers", "atlas_oceans",
|
|
"atlas_mountain_ranges", "atlas_pois"):
|
|
rows = conn.execute(
|
|
f"SELECT body_id, local_id, name FROM {table} {w} "
|
|
f"AND (name = '' OR LENGTH(name) < 2)", params
|
|
).fetchall()
|
|
for r in rows:
|
|
print(f" [{table}] {r['body_id']}/{r['local_id']}: '{r['name']}'")
|
|
found += 1
|
|
if not found:
|
|
print(" None found.")
|
|
|
|
|
|
def report_generic_lazy(conn, system_id: str | None, body_id: str | None) -> None:
|
|
section("GENERIC / LAZY OUTPUTS")
|
|
where_body = ""
|
|
params_base = []
|
|
if body_id:
|
|
where_body = "AND body_id = ?"
|
|
params_base = [body_id]
|
|
elif system_id:
|
|
where_body = "AND body_id IN (SELECT body_id FROM bodies WHERE system_id = ?)"
|
|
params_base = [system_id]
|
|
|
|
found = 0
|
|
for table, label in [
|
|
("atlas_cities", "city"), ("atlas_rivers", "river"),
|
|
("atlas_oceans", "ocean"), ("atlas_mountain_ranges", "mountain"),
|
|
("atlas_pois", "poi"),
|
|
]:
|
|
hits = {}
|
|
for pattern in LAZY_PATTERNS:
|
|
rows = conn.execute(
|
|
f"SELECT body_id, local_id, name FROM {table} "
|
|
f"WHERE name LIKE ? {where_body}",
|
|
[pattern] + params_base,
|
|
).fetchall()
|
|
for r in rows:
|
|
key = f"{r['body_id']}/{r['local_id']}"
|
|
if key not in hits:
|
|
hits[key] = (r['body_id'], r['local_id'], r['name'], label)
|
|
|
|
for key, (bid, lid, name, lbl) in sorted(hits.items()):
|
|
print(f" [{lbl}] {bid}/{lid}: '{name}'")
|
|
found += 1
|
|
|
|
if not found:
|
|
print(" None found.")
|
|
|
|
|
|
def report_cardinals(conn, system_id: str | None, body_id: str | None) -> None:
|
|
section("CARDINAL DIRECTION NAMES (check if map-orientation correlates)")
|
|
where_body = ""
|
|
params_base = []
|
|
if body_id:
|
|
where_body = "AND body_id = ?"
|
|
params_base = [body_id]
|
|
elif system_id:
|
|
where_body = "AND body_id IN (SELECT body_id FROM bodies WHERE system_id = ?)"
|
|
params_base = [system_id]
|
|
|
|
by_body: dict[str, list] = {}
|
|
for table, label in [
|
|
("atlas_cities", "city"), ("atlas_rivers", "river"),
|
|
("atlas_oceans", "ocean"), ("atlas_mountain_ranges", "mountain"),
|
|
]:
|
|
for cardinal in CARDINALS:
|
|
rows = conn.execute(
|
|
f"SELECT body_id, local_id, name FROM {table} "
|
|
f"WHERE (name LIKE ? OR name LIKE ?) {where_body}",
|
|
[f"{cardinal} %", f"% {cardinal} %"] + params_base,
|
|
).fetchall()
|
|
for r in rows:
|
|
by_body.setdefault(r["body_id"], []).append(
|
|
(label, r["local_id"], r["name"])
|
|
)
|
|
|
|
if not by_body:
|
|
print(" None found.")
|
|
return
|
|
for bid, entries in sorted(by_body.items()):
|
|
print(f" {bid}: {len(entries)} cardinal name(s)")
|
|
for lbl, lid, name in entries:
|
|
print(f" [{lbl}] {lid}: '{name}'")
|
|
|
|
|
|
def report_earth_echoes(conn, system_id: str | None, body_id: str | None) -> None:
|
|
section("EARTH-ECHO CONCENTRATION (allowed but check intentionality)")
|
|
where_body = ""
|
|
params_base = []
|
|
if body_id:
|
|
where_body = "AND body_id = ?"
|
|
params_base = [body_id]
|
|
elif system_id:
|
|
where_body = "AND body_id IN (SELECT body_id FROM bodies WHERE system_id = ?)"
|
|
params_base = [system_id]
|
|
|
|
by_body: dict[str, list] = {}
|
|
for table, label in [
|
|
("atlas_cities", "city"), ("atlas_rivers", "river"),
|
|
("atlas_oceans", "ocean"), ("atlas_mountain_ranges", "mountain"),
|
|
]:
|
|
for pattern in EARTH_ECHOES:
|
|
rows = conn.execute(
|
|
f"SELECT body_id, local_id, name FROM {table} "
|
|
f"WHERE name LIKE ? {where_body}",
|
|
[f"%{pattern.replace('%', '')}%"] + params_base,
|
|
).fetchall()
|
|
for r in rows:
|
|
key = (r["body_id"], label, r["local_id"])
|
|
by_body.setdefault(r["body_id"], []).append(
|
|
(label, r["local_id"], r["name"])
|
|
)
|
|
|
|
if not by_body:
|
|
print(" None found.")
|
|
return
|
|
for bid, entries in sorted(by_body.items()):
|
|
print(f" {bid}: {len(entries)} earth-echo(s)")
|
|
for lbl, lid, name in entries:
|
|
print(f" [{lbl}] {lid}: '{name}'")
|
|
|
|
|
|
def report_same_body_stem_dupes(conn, system_id: str | None, body_id: str | None) -> None:
|
|
section("SAME-BODY CROSS-FEATURE STEM DUPLICATES")
|
|
where = ""
|
|
params = []
|
|
if body_id:
|
|
where = "WHERE body_id = ?"
|
|
params = [body_id]
|
|
elif system_id:
|
|
where = "WHERE system_id = ?"
|
|
params = [system_id]
|
|
|
|
bodies_q = conn.execute(
|
|
f"SELECT body_id FROM bodies {where}", params
|
|
).fetchall()
|
|
|
|
found = 0
|
|
for row in bodies_q:
|
|
bid = row["body_id"]
|
|
features = run_all_features_for_body(conn, bid)
|
|
stem_to_features: dict[str, list] = {}
|
|
for label, name in features:
|
|
s = stem_of(name)
|
|
if s and len(s) > 3:
|
|
stem_to_features.setdefault(s, []).append((label, name))
|
|
for stem, items in sorted(stem_to_features.items()):
|
|
if len(items) > 1:
|
|
types = set(i[0] for i in items)
|
|
if len(types) > 1: # only flag cross-feature (different types)
|
|
print(f" {bid} stem='{stem}':")
|
|
for lbl, nm in items:
|
|
print(f" [{lbl}] '{nm}'")
|
|
found += 1
|
|
if not found:
|
|
print(" None found.")
|
|
|
|
|
|
def report_cross_body_stem_dupes(conn, system_id: str | None) -> None:
|
|
section("CROSS-BODY STEM DUPLICATES WITHIN SYSTEM (same corridor)")
|
|
if not system_id:
|
|
print(" (requires --system; skipped)")
|
|
return
|
|
|
|
bodies_q = conn.execute(
|
|
"SELECT body_id FROM bodies WHERE system_id = ?", (system_id,)
|
|
).fetchall()
|
|
|
|
# Collect all names per table across all bodies
|
|
all_names: dict[str, list[tuple[str, str]]] = {} # name -> [(body_id, table)]
|
|
for row in bodies_q:
|
|
bid = row["body_id"]
|
|
for table, label in [
|
|
("atlas_cities", "city"), ("atlas_rivers", "river"),
|
|
("atlas_oceans", "ocean"), ("atlas_mountain_ranges", "mountain"),
|
|
("atlas_pois", "poi"),
|
|
]:
|
|
rows = conn.execute(
|
|
f"SELECT name FROM {table} WHERE body_id=? AND name != ''", (bid,)
|
|
).fetchall()
|
|
for r in rows:
|
|
name = r["name"]
|
|
s = stem_of(name)
|
|
if s and len(s) > 3:
|
|
all_names.setdefault(s, []).append((bid, label, name))
|
|
|
|
found = 0
|
|
for stem, hits in sorted(all_names.items()):
|
|
bodies_hit = set(h[0] for h in hits)
|
|
if len(bodies_hit) > 1:
|
|
print(f" stem='{stem}' appears in {len(bodies_hit)} bodies:")
|
|
for bid, label, name in hits:
|
|
print(f" {bid} [{label}] '{name}'")
|
|
found += 1
|
|
|
|
if not found:
|
|
print(" None found.")
|
|
|
|
|
|
def report_summary_score(conn, system_id: str | None, body_id: str | None) -> None:
|
|
section("BODY SUMMARY SCORES")
|
|
where = ""
|
|
params = []
|
|
if body_id:
|
|
where = "WHERE body_id = ?"
|
|
params = [body_id]
|
|
elif system_id:
|
|
where = "WHERE system_id = ?"
|
|
params = [system_id]
|
|
else:
|
|
where = "WHERE inhabited = 1"
|
|
|
|
bodies_q = conn.execute(
|
|
f"SELECT body_id, proper_name, population FROM bodies {where}", params
|
|
).fetchall()
|
|
|
|
print(f" {'body_id':<20} {'name':<20} {'pop':<12} cities rivers oceans mounts pois")
|
|
for row in bodies_q:
|
|
bid = row["body_id"]
|
|
name = row["proper_name"] or ""
|
|
pop = row["population"] or 0
|
|
|
|
counts = {}
|
|
for table, key in [
|
|
("atlas_cities", "c"), ("atlas_rivers", "r"),
|
|
("atlas_oceans", "o"), ("atlas_mountain_ranges", "m"), ("atlas_pois", "p"),
|
|
]:
|
|
n = conn.execute(
|
|
f"SELECT COUNT(*) FROM {table} WHERE body_id=?", (bid,)
|
|
).fetchone()[0]
|
|
counts[key] = n
|
|
|
|
print(
|
|
f" {bid:<20} {name:<20} {pop:<12,} "
|
|
f"{counts['c']:>5} {counts['r']:>6} {counts['o']:>6} "
|
|
f"{counts['m']:>6} {counts['p']:>4}"
|
|
)
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--system", help="GJ catalog ID (e.g. 'GJ 144')")
|
|
parser.add_argument("--body", help="Body ID (e.g. 'GJ144d')")
|
|
parser.add_argument("--db", default=str(DB_PATH), help="Path to systems.db")
|
|
args = parser.parse_args()
|
|
|
|
db = Path(args.db)
|
|
if not db.exists():
|
|
print(f"error: database not found at {db}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
conn = get_conn(db)
|
|
|
|
system_id = args.system
|
|
body_id = args.body
|
|
|
|
if body_id and not system_id:
|
|
row = conn.execute(
|
|
"SELECT system_id FROM bodies WHERE body_id=?", (body_id,)
|
|
).fetchone()
|
|
if row:
|
|
system_id = row["system_id"]
|
|
|
|
print("\nAtlas Cohesion Audit")
|
|
print(f" DB: {db}")
|
|
if system_id:
|
|
print(f" System: {system_id}")
|
|
if body_id:
|
|
print(f" Body: {body_id}")
|
|
|
|
report_summary_score(conn, system_id, body_id)
|
|
report_empty_names(conn, system_id, body_id)
|
|
report_generic_lazy(conn, system_id, body_id)
|
|
report_cardinals(conn, system_id, body_id)
|
|
report_earth_echoes(conn, system_id, body_id)
|
|
report_same_body_stem_dupes(conn, system_id, body_id)
|
|
if system_id and not body_id:
|
|
report_cross_body_stem_dupes(conn, system_id)
|
|
|
|
conn.close()
|
|
print("\nDone.\n")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|