The procedural server cascade (Phase 4) and the frozen names-only pool supersede the Python atlas geometry generator and the LLM namer. Retire: - generate_atlas.py (geometry production — cities/roads/rivers placement) - gemma_naming.py, naming_core.py + tests (test_batch_naming, test_register_selection, qa_naming) and run-atlas-naming.sh (the LLM place-namer; its output is now the frozen pool) - apply_name_fixes.py (name-field patches), fix_fewshot_bleed.py / prune_atlas_features.py (geometry tools) - import_city_names.py (redundant with import_economics name-pool path) Pipeline updates: drop the generate_atlas step + atlas-generate / test-atlas-determinism targets from the Makefile; remove generate_atlas from the stamp registry (import_economics is the sole regen-db generator); drop run-atlas-determinism from tests/run-all; refresh stale references in schema_version, backfill_cultural_corridor, earth_blocklist (kept as reference data), populate_terrain_reference, and heightmap.rs. The Gemma prompting methodology is preserved in docs/gemma-naming-methodology.md (separate commit). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
163 lines
5.7 KiB
Python
Executable File
163 lines
5.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Backfill star_systems.cultural_corridor and bodies.cultural_corridor.
|
|
|
|
The schema has a `cultural_corridor` column on both tables, but
|
|
`wiki_sync.py` never populated it from the wiki index.md files — the
|
|
cultural/geographic identity of each system lives in
|
|
`star_systems.geographic_sector` instead (values: core, north_reach,
|
|
south_reach, east_reach, west_reach, deep_frontier). These two fields
|
|
refer to the same concept: which arc of the reach the system belongs
|
|
to. Leaving `cultural_corridor` NULL on 99%+ of rows defeats every
|
|
downstream consumer that actually wants to filter by corridor
|
|
(the atlas UI, narrative tools, and the server generation cascade).
|
|
|
|
This script treats `geographic_sector` as the source of truth and
|
|
copies it into `cultural_corridor`:
|
|
|
|
star_systems.cultural_corridor := star_systems.geographic_sector
|
|
WHERE cultural_corridor IS NULL
|
|
|
|
bodies.cultural_corridor := parent star_systems.cultural_corridor
|
|
WHERE bodies.cultural_corridor IS NULL
|
|
|
|
It is safe to re-run — idempotent, NULL-only updates, explicit
|
|
transaction wrapper so a crash never leaves a half-populated state.
|
|
Run it after any `wiki_sync.py` pass that creates fresh systems.db
|
|
rows.
|
|
|
|
Usage:
|
|
tooling/db/backfill_cultural_corridor.py
|
|
tooling/db/backfill_cultural_corridor.py --db path/to/systems.db
|
|
tooling/db/backfill_cultural_corridor.py --dry-run
|
|
|
|
Decisions: D-191 (atlas pipeline — downstream consumer)
|
|
"""
|
|
|
|
import argparse
|
|
import sqlite3
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
SCRIPT_DIR = Path(__file__).resolve().parent
|
|
REPO_ROOT = (SCRIPT_DIR / ".." / "..").resolve()
|
|
DB_PATH = REPO_ROOT / "server" / "data" / "systems.db"
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Backfill cultural_corridor on star_systems and bodies"
|
|
)
|
|
parser.add_argument("--db", default=str(DB_PATH), help="Path to systems.db")
|
|
parser.add_argument(
|
|
"--dry-run",
|
|
action="store_true",
|
|
help="Report counts without writing",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
db_path = Path(args.db)
|
|
if not db_path.exists():
|
|
print(f"error: {db_path} not found", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
conn = sqlite3.connect(str(db_path))
|
|
conn.execute("PRAGMA foreign_keys=ON")
|
|
|
|
# Counts before.
|
|
before_systems_null = conn.execute(
|
|
"SELECT COUNT(*) FROM star_systems WHERE cultural_corridor IS NULL"
|
|
).fetchone()[0]
|
|
before_bodies_null = conn.execute(
|
|
"SELECT COUNT(*) FROM bodies WHERE cultural_corridor IS NULL"
|
|
).fetchone()[0]
|
|
|
|
print(f"\n cultural_corridor backfill")
|
|
print(f" DB: {db_path}")
|
|
if args.dry_run:
|
|
print(f" Mode: DRY RUN")
|
|
print()
|
|
print(f" Before:")
|
|
print(f" star_systems.cultural_corridor NULL: {before_systems_null}")
|
|
print(f" bodies.cultural_corridor NULL: {before_bodies_null}")
|
|
|
|
conn.execute("BEGIN")
|
|
try:
|
|
# 1. Star systems — copy geographic_sector into cultural_corridor
|
|
# where the latter is still NULL. If geographic_sector is also
|
|
# NULL, leave cultural_corridor NULL — there is nothing to
|
|
# copy and a bogus placeholder is worse than honest NULL.
|
|
sys_rows_updated = conn.execute(
|
|
"""
|
|
UPDATE star_systems
|
|
SET cultural_corridor = geographic_sector
|
|
WHERE cultural_corridor IS NULL
|
|
AND geographic_sector IS NOT NULL
|
|
"""
|
|
).rowcount
|
|
|
|
# 2. Bodies — inherit from the parent star_systems row.
|
|
body_rows_updated = conn.execute(
|
|
"""
|
|
UPDATE bodies
|
|
SET cultural_corridor = (
|
|
SELECT s.cultural_corridor
|
|
FROM star_systems s
|
|
WHERE s.system_id = bodies.system_id
|
|
)
|
|
WHERE cultural_corridor IS NULL
|
|
AND EXISTS (
|
|
SELECT 1
|
|
FROM star_systems s
|
|
WHERE s.system_id = bodies.system_id
|
|
AND s.cultural_corridor IS NOT NULL
|
|
)
|
|
"""
|
|
).rowcount
|
|
|
|
if args.dry_run:
|
|
conn.rollback()
|
|
print()
|
|
print(f" Would update:")
|
|
print(f" star_systems: {sys_rows_updated}")
|
|
print(f" bodies: {body_rows_updated}")
|
|
print(f"\n Dry run — no changes written.")
|
|
else:
|
|
conn.commit()
|
|
print()
|
|
print(f" Updated:")
|
|
print(f" star_systems: {sys_rows_updated}")
|
|
print(f" bodies: {body_rows_updated}")
|
|
|
|
# Counts after.
|
|
after_systems_null = conn.execute(
|
|
"SELECT COUNT(*) FROM star_systems WHERE cultural_corridor IS NULL"
|
|
).fetchone()[0]
|
|
after_bodies_null = conn.execute(
|
|
"SELECT COUNT(*) FROM bodies WHERE cultural_corridor IS NULL"
|
|
).fetchone()[0]
|
|
print()
|
|
print(f" After:")
|
|
print(f" star_systems.cultural_corridor NULL: {after_systems_null}")
|
|
print(f" bodies.cultural_corridor NULL: {after_bodies_null}")
|
|
|
|
# Show the distribution so the outcome is visible.
|
|
print()
|
|
print(f" star_systems.cultural_corridor distribution:")
|
|
for corridor, count in conn.execute(
|
|
"SELECT cultural_corridor, COUNT(*) FROM star_systems "
|
|
"GROUP BY cultural_corridor ORDER BY COUNT(*) DESC"
|
|
).fetchall():
|
|
print(f" {corridor!r}: {count}")
|
|
except BaseException:
|
|
conn.rollback()
|
|
conn.close()
|
|
raise
|
|
|
|
conn.close()
|
|
print()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|