Files
settled-reach/tooling/archive/wiki-bootstrap/process-wiki-system-changes
T
jpmschweitzerandClaude Opus 5.5 4537b71b92 refactor(tooling): T-1290 — the wiki domain, and the renderer that must not run
`reach wiki stats` and `reach wiki gttr-hook` replace tooling/db/wiki_sync.py
and populate_gttr_hook.py. Both are output-identical to the originals:
`stats` byte-for-byte, and all 301 extracted GTTR hooks line-for-line.

wiki_sync.py moved whole, but generate_wiki() and import_from_wiki() are NOT
verbs. Before porting, the old `--generate` was run against a clean tree to get
a parity baseline. It changed all 301 system pages, +940 / -10,761, and was
reverted at once. It deletes the Celestial Bodies / Stations blocks (owned by
the Rust atlas sync, which it does not know about), deletes the
Industries / Exports / Imports rows (nothing writes those any more), and
rewrites star types where systems.db and the pages disagree. D-262, CLAUDE.md
and the wiki skill all described it as the routine, prose-preserving render.
CLAUDE.md and the skill now say not to run it; D-262 needs amending — T-1292.

Provenance moves to tooling/archive/, with a README naming what each script
did and why it is not run:

- pql-migrate/ (the T-1271 ruling)
- wiki-bootstrap/: assign-astro-ids + its catalog, migrate-s-to-gj,
  patch-core-sector (hardcodes a dead path), fill-missing-globes,
  generate-stubs and find-stubs (finds 0 stubs — Phase 1 is done),
  backfill_cultural_corridor (a raw systems.db patch script, outside D-262),
  and process-wiki-system-changes, whose last step is the destructive render

Also:

- stats() printed "run import first" and exited 0 when a table was missing;
  it now fails with a remedy. generate_wiki() counted created pages after
  writing them, so `created` was always 0.
- tooling/godot-cold-parse and godot-parse-sweep were never retired after
  T-1283, and the pr-process skill still told agents to run them. Removed;
  the skill and parse_sweep.gd now name the reach verbs.
- systems.db re-stamped: schema comments changed, and the stamp records the
  schema file's SHA for tamper detection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 16:25:51 +02:00

200 lines
6.0 KiB
Python
Executable File

#!/usr/bin/env python3
"""
process-wiki-system-changes
Pipeline for star systems data.
Modes:
(default) Import wiki frontmatter → systems.db, update star-map.json,
then regenerate wiki pages from DB (infobox + topology).
--generate Generate wiki pages from existing DB (no import).
--rebuild-db Drop and recreate systems.db from wiki (fresh start).
--stats Show fill rates.
--dry-run Show what star-map.json changes would occur.
Database: server/data/systems.db
Schema: server/data/systems-schema.sql
"""
import argparse
import json
import sys
from pathlib import Path
SCRIPT_DIR = Path(__file__).resolve().parent
WORKTREE_ROOT = (SCRIPT_DIR / "..").resolve()
STAR_MAP_PATH = WORKTREE_ROOT / "docs" / "design" / "star-map.json"
DB_PATH = WORKTREE_ROOT / "server" / "data" / "systems.db"
# Import wiki_sync
sys.path.insert(0, str(SCRIPT_DIR / "db"))
import wiki_sync
# ---------------------------------------------------------------------------
# Star-map.json update (topology fields only)
# ---------------------------------------------------------------------------
STAR_MAP_NODE_FIELDS = [
"system_id",
"gate_topology", "aperture_count", "gate_connections",
"hop_distance_from_gateway",
]
def update_star_map_from_db():
"""Update star-map.json node fields from systems.db."""
conn = wiki_sync.get_connection()
with open(STAR_MAP_PATH, "r") as f:
data = json.load(f)
nodes = data["nodes"]
updated = 0
for node in nodes:
sid = node["system_id"]
row = conn.execute(
"SELECT g.gate_topology, g.aperture_count, g.gate_connections "
"FROM star_systems s LEFT JOIN system_gates g ON s.system_id = g.system_id "
"WHERE s.system_id = ?", (sid,)
).fetchone()
if not row:
continue
changed = False
field_map = {
"gate_topology": row["gate_topology"],
"aperture_count": row["aperture_count"],
"gate_connections": row["gate_connections"],
}
for field, val in field_map.items():
if val is not None and node.get(field) != val:
node[field] = val
changed = True
if changed:
updated += 1
conn.close()
with open(STAR_MAP_PATH, "w") as f:
json.dump(data, f, indent=2)
f.write("\n")
return {"nodes": len(nodes), "edges": len(data["edges"]), "updated": updated}
def dry_run_star_map():
"""Show what would change in star-map.json."""
conn = wiki_sync.get_connection()
with open(STAR_MAP_PATH, "r") as f:
data = json.load(f)
changes = []
for node in data["nodes"]:
sid = node["system_id"]
row = conn.execute(
"SELECT g.gate_topology, g.aperture_count, g.gate_connections "
"FROM star_systems s LEFT JOIN system_gates g ON s.system_id = g.system_id "
"WHERE s.system_id = ?", (sid,)
).fetchone()
if not row:
continue
field_map = {
"gate_topology": row["gate_topology"],
"aperture_count": row["aperture_count"],
"gate_connections": row["gate_connections"],
}
for field, val in field_map.items():
if val is not None and node.get(field) != val:
changes.append(f" {sid}.{field}: {node.get(field)} -> {val}")
conn.close()
return changes
# ---------------------------------------------------------------------------
# Main
# ---------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(
description="Star systems data pipeline: wiki ↔ systems.db ↔ star-map.json"
)
parser.add_argument("--generate", action="store_true", help="Generate wiki from DB only")
parser.add_argument("--rebuild-db", action="store_true", help="Drop and recreate DB from wiki")
parser.add_argument("--stats", action="store_true", help="Show fill rates")
parser.add_argument("--dry-run", action="store_true", help="Show star-map changes without writing")
args = parser.parse_args()
if args.stats:
wiki_sync.stats()
return
if args.generate:
print("--- Generating wiki pages from DB ---")
result = wiki_sync.generate_wiki()
print(result["summary"])
return
if args.rebuild_db:
print(f"--- Rebuilding {DB_PATH} from wiki ---")
if DB_PATH.exists():
DB_PATH.unlink()
print(" Deleted existing DB")
if args.dry_run:
# Need DB populated first for dry-run to work
if not DB_PATH.exists():
print("No DB found. Run without --dry-run first.")
sys.exit(1)
changes = dry_run_star_map()
if changes:
print(f"star-map.json changes ({len(changes)}):")
for c in changes:
print(c)
else:
print("star-map.json: no changes")
return
# Full pipeline: wiki → DB → star-map.json → wiki pages
print("=== Star Systems Pipeline ===\n")
# Step 1: Import wiki frontmatter into DB
print("--- Step 1: Wiki → DB ---")
result = wiki_sync.import_from_wiki()
if not result["ok"]:
print(f"ERROR: {result.get('error')}")
sys.exit(1)
print(result["summary"])
if result["warnings"]:
for w in result["warnings"][:5]:
print(f" ⚠ {w}")
if len(result["warnings"]) > 5:
print(f" ... and {len(result['warnings']) - 5} more")
# Step 2: Update star-map.json from DB
print("\n--- Step 2: DB → star-map.json ---")
map_result = update_star_map_from_db()
print(f"Nodes: {map_result['nodes']}, Edges: {map_result['edges']}, Updated: {map_result['updated']}")
# Step 3: Generate wiki pages from DB
print("\n--- Step 3: DB → Wiki pages ---")
gen_result = wiki_sync.generate_wiki()
print(gen_result["summary"])
# Step 4: Stats
print("\n--- Completion ---")
wiki_sync.stats()
if __name__ == "__main__":
main()