refactor(db): split import_economics.py; single generator-source registry (T-1067)

import_economics.py 2,620 → 309 lines — a thin orchestrator keeping the
exact CLI, single-transaction/rollback contract, and exit codes. The 16
import steps, MIGRATION_SQL, brands shell-out, validators, and stamp
write now live in tooling/economy-db/economy_import/ (db, migration,
economy, corporations, brands, bodies, atlas, specialization, traits,
validators, stamp, paths, errors). Full type hints throughout.

tooling/generator_sources.py replaces the triplicated source registry
(importer / stamp checker / pr-process watch list — the skill now derives
its list via --list). The registry stamps itself, and economy_import/
modules are globbed fail-closed, so a future module is stamped the moment
it exists — closing the silently-weakened-stamp failure mode.

Rider: connector config helpers centralized in tooling/db/common.py.

Byte-identical behavior proven: full-import table dump diff EMPTY over
107,843 lines / 37 tables (volatile timestamp fields excluded); dry-run
output parity; generated_brands.toml sha unchanged. make test-tooling
PASS; ruff clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 20:13:28 +02:00
co-authored by Claude Fable 5
parent 5b3f18da65
commit 4f73624eff
25 changed files with 2785 additions and 2472 deletions
+7 -48
View File
@@ -19,7 +19,6 @@ Usage (interactive):
Decision refs: #855 (generator versioning), #857 (pre-push hook)
"""
import hashlib
import re
import sqlite3
import sys
@@ -32,52 +31,12 @@ REPO_ROOT = Path(__file__).resolve().parent.parent
DB_PATH = REPO_ROOT / "server" / "data" / "systems.db"
# Maps generator_name (as stored in meta.generator_name) to the source
# file(s) whose SHA is stamped. The SHA is computed as SHA-1 of the
# concatenated bytes of all files in sorted order.
#
# import_economics' source set includes the Rust generate_brands binary it now
# invokes as a subroutine (#136 review T2/H3). Keep this list in sync with
# IMPORT_ECONOMICS_SOURCES in tooling/economy-db/import_economics.py.
# The atlas geometry generator (generate_atlas) was retired in #951 (D-223).
# import_economics is now the sole regen-db generator that writes systems.db; it
# owns the atlas index (names-only pool + empty geometry tables). The surviving
# planet-gen importers (import_heightmaps, import_province_boundaries) are
# one-time build imports baked into the committed DB, not part of regen-db, so
# they are intentionally not stamped here.
GENERATOR_SOURCES: dict[str, list[Path]] = {
"import_economics": [
REPO_ROOT / "tooling" / "economy-db" / "import_economics.py",
REPO_ROOT / "server" / "src" / "bin" / "generate_brands" / "main.rs",
REPO_ROOT / "server" / "src" / "bin" / "generate_brands" / "names.rs",
# Shared surname corpus extracted from the two names.rs copies (T-1064).
REPO_ROOT / "server" / "src" / "bin" / "shared" / "surname_corpus.rs",
REPO_ROOT / "tooling" / "generate-brands",
REPO_ROOT / "tooling" / "schema_version.py",
# D-237 authored specialization layer data TOMLs (#1013). Keep in sync
# with IMPORT_ECONOMICS_SOURCES in tooling/economy-db/import_economics.py.
REPO_ROOT / "wiki" / "economics" / "specialization_vocabulary.toml",
REPO_ROOT / "wiki" / "economics" / "system_specialization.toml",
# D-232 architecture-flavor trait catalog + hero bias (#993).
REPO_ROOT / "wiki" / "economics" / "architecture_trait_catalog.toml",
REPO_ROOT / "wiki" / "economics" / "architecture_trait_bias.toml",
],
}
def file_sha1(*paths: Path) -> str:
"""SHA-1 of concatenated file contents (sorted paths).
Missing files raise FileNotFoundError rather than silently contributing
an empty-string hash (H2): a ghost SHA could mask real breakage when
stored and current SHAs converge on the empty-bytes digest.
"""
h = hashlib.sha1()
for p in sorted(paths):
if not p.exists():
raise FileNotFoundError(f"generator source not found: {p}")
h.update(p.read_bytes())
return h.hexdigest()
# The generator-source registry and the SHA helper live in the shared module
# tooling/generator_sources.py (T-1067) — the single source of truth, also
# imported by the importer's stamp writer and consumed by /pr-process via
# `python3 tooling/generator_sources.py --list`.
sys.path.insert(0, str(Path(__file__).resolve().parent))
from generator_sources import GENERATOR_SOURCES, file_sha1 # noqa: E402
def check(verbose: bool = False) -> int:
@@ -172,7 +131,7 @@ def check(verbose: bool = False) -> int:
file=sys.stderr,
)
print(
" Update GENERATOR_SOURCES in tooling/check-systems-db-stamp to "
" Update GENERATOR_SOURCES in tooling/generator_sources.py to "
"register them before pushing.",
file=sys.stderr,
)