Replaces the dead atlas_body_heightmaps DB-BLOB importer (Tyre review B2 —
it asserted 256×512 and wrote a dropped table) with the canonical asset bake:
- one-time rename of the legacy color heightmap.png → reliefmap.png for ALL
bodies (incl. Sol — display-file rename only, no re-sim);
- for each non-Sol inhabited body: simulate() at 1024×512 → clean reliefmap.png
(render_heightmap, no painted features) + 16-bit grayscale heightmap.png with
sea_level in a tEXt chunk;
- no systems.db writes; uses parse_system for proper body defs; run via uv.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
From the Hoshe/Tyre review:
- drainage: assert flow_accumulation/max_accumulation determinism + clamp ≥ 1
(the D-209 strength denominator); isolated-basin merge path (no panic).
- subbiome: each derivable variant reachable + Volcanic never emitted.
- planet_simulation: new test_sim_determinism.py — same body simulates to a
bit-identical elevation array at 1024×512 (the 271-body bake can't be cheaply
re-run, so a silent drift = full re-bake). Verified PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Review (Tyre) caught a determinism hole: corp-HQ→city matching iterated a
Python set (sys_body_ids), so on a name collision across bodies in the same
system, which row received corp_id depended on set order — nondeterministic
output landing in the committed DB (violates D-010 #4). Iterate sorted().
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- planet_simulation: GRID 512×256 → 1024×512. The elevation noise is
resolution-independent (normalized coords + absolute freqs), so the
finer grid samples the SAME terrain — features keep physical size,
generation stays deterministic. Pixel-unit constants (gaussian sigma,
crater radii, peak-filter window, erosion slope) scale by GRID_W/512.
Validated: non-Sol bodies render same-world-crisper at 1024.
- Remove compute_rivers + _rivers_to_grid + the rivers/river_grid terrain
keys: rivers are the Rust cascade's job (D8 drainage, D-208), the single
source of river truth. The old heuristic didn't even reach the sea.
- render_heightmap: stop painting rivers onto the relief (cascade/Atlas
overlay computed rivers instead).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
Rework the regen-db atlas path for the names-only marker pool:
- populate_atlas_city_names now reads the names.cities pool instead of
the retired geometry-bearing cities[] records; population/kind are
deferred to placement (#955). Adds a deterministic clear-then-insert
(no UNIQUE on (body_id, name)) that fixes a latent duplicate-
accumulation bug — atlas_city_names dropped from an inflated 3276 to a
clean 329 pooled names + 134 corp-HQ rows.
- ensure_atlas_index_schema applies the canonical ATLAS INDEX block from
systems-schema.sql and empties the 8 geometry tables every regen; the
Phase 4 server cascade fills them (they start empty — the revealed gap).
- Sol (system 'GJ 0') is permanently exempt from the normal generators:
skipped in both the name-pool importer and the corp-HQ cross-ref.
- MIGRATION_SQL drops the retired generate_atlas meta stamp row so the
fail-closed stamp checker accepts older committed DBs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move the shared atlas-DB utilities (schema application, inhabited-body
query, body-def loader, grid constants) out of the soon-to-be-retired
generate_atlas.py into a dedicated atlas_common.py with no dependency on
geometry-production code. Repoint the surviving build-time importers
(import_heightmaps, import_province_boundaries) at the new module.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ruff F401 — unused 'import os'. Pre-existing in the globe-coverage script; ruff
runs at pre-push (not pre-commit), so it surfaced only now and blocked the push.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The per-commit clerk had three flaws, exposed by a 20-commit push where 6 of 7
rejections were false (incl. a CHANGELOG-only commit):
1. No-verdict / max-turns / timeout defaulted to REJECTED — an unfinished review
read as 'hard contradiction found'. Now a third outcome, INCOMPLETE, which is
non-blocking (the push proceeds with a warning); only a real REJECTED blocks.
2. Turn/time budget too tight (6 turns / 150s) for decision-heavy commits. Raised
defaults to 15 turns / 300s, and the prompt now biases to APPROVED when no
concrete contradiction is found ('unsure' means APPROVED, never REJECTED).
3. The skip valve matched its own feature commit because it scanned for the token
anywhere in the message. Moved to a trailer-line match so prose/subject mentions
no longer trip it.
Pre-push hook updated to treat INCOMPLETE as a non-blocking warning. The git-commit
skill documents the trailer form.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A commit whose message contains the token [clerk-skip] is auto-approved by
the pre-push clerk without spawning an agent. Intended for bulk content/data
commits — e.g. shipping thousands of generated planetary description files —
where D-record review is moot and would only burn agents on noise.
Documented in the /git-commit skill with the caveat: never use it on commits
that touch decisions/, code, or ticket-bearing work.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The clerk pre-push review spawned a single claude -p over the entire combined
diff (truncated at 50k chars) with a 3-turn budget. On a large push (e.g. 754
files / 2.8M chars) it ran out of turns before emitting a verdict, which the
wrapper defaulted to REJECTED.
Rewrite to review one commit at a time — commits are the logical units, so each
clerk agent sees a self-contained change plus its commit message (enabling the
'does this match ticket #NNN?' check). Commits are reviewed by a bounded pool of
parallel clerk agents and the verdicts aggregated (REJECTED if any commit
contradicts an active D-record). Oversized commit diffs truncate to a budget.
Adds --plan (print the per-commit plan, no agents spawned) and env knobs:
SR_CLERK_COMMIT_BUDGET / SR_CLERK_WORKERS / SR_CLERK_MAX_TURNS / SR_CLERK_TIMEOUT.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Generated oort cloud and asteroid belt generic globe images via Gemini.
Background-masked with flood-fill (shadow-preserving). Donor fill script
copies matching globe.png from same planet_class+body_type pool with
per-body hash selection, no repeats within a system. 629 bodies filled,
3240/3240 now have globe.png.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deterministic ±scatter on body radii seeded by body_id hash — no two
bodies share the same radius. Gas giants 40k-60k km, moons 200-2600 km,
rocky planets ±15% from class base. Oort/asteroid skip radius (NULL).
Sol system gets real planetary radii. body_radius_km exported to
star_map_data.json for client orbital diagram sizing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sprint-based workflow (38 sprints) replaced by kanban + milestones.
Milestones are many-to-many with tickets and can block each other.
New: /whats-next skill (dependency-driven batch selection with Si
refinement review), /pr-process skill (renamed from pr-push, adds
review comment pickup), clerk agent + pre-push hook for D-record
consistency checks.
Deleted: sprint CLI, sprint-start/sprint-plan/sprint-status skills,
team-scoped file restrictions. Si rewritten as refinement manager.
All 19 agent briefings updated from stale PROJECT_STATE.md reference
to live ticket milestone queries.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Export pre-computed drainage basin boundaries from atlas_province_boundaries
into markers.json during generate_atlas. AtlasMarkerOverlay draws province
polylines with semi-transparent fill under the political_zones overlay.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
gen_queue: add in_flight_count tracking for all work item types (not
just AnalyzeBody). Rewrite saturation test with AnalyzeBody items.
Fix priority_ordering test thread count to match new gate.
rng: collapse to single AtlasRng::new(seed) constructor — callers
own their seed transform.
import_province_boundaries: fix "savepoint" comment to "transaction".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New tables: atlas_body_heightmaps (D-202), atlas_city_names (D-207),
atlas_feature_names, atlas_province_boundaries (D-205), body_radius_km
column (D-204). Three new importers: heightmap BLOBs, city names from
wiki markers.json, province boundaries via D8 watershed analysis.
economic_role normalized to 7 canonical values (D-194). Stamp fix in
generate_atlas.py to hash all tracked source files. systems.db regenerated.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
gemma_naming.py now re-queries affected bodies when >40% suffix
clustering is detected. naming_core.py build_batch_prompt accepts
cultural_history param threading secondary corridor substyles into
the few-shot prompt for richer cross-cultural name blending.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add gemma_naming.py and naming_core.py to generate_atlas source
tracking in check-systems-db-stamp. Mirror in pr-push watch list.
Prevents naming helper changes from bypassing stale-stamp detection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. decisions_sync.py: fix refs_created inflation (check rowcount),
remove dead IntegrityError except block
2. Extract SCHEMA_VERSION to shared tooling/schema_version.py —
both generators import from single source of truth
3. generate_atlas.py: narrow bare except to OperationalError +
"duplicate column" check
4. check-systems-db-stamp: add cross-generator schema_version
agreement assertion (defense-in-depth)
5. decision wrapper: add show + orphan-tickets to usage text
6. Add schema_version.py to all three source watch lists
(GENERATOR_SOURCES, IMPORT_ECONOMICS_SOURCES, generate_atlas
_write_stamp) — prevents silent staleness on version bump
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace SHA-1 hash in meta.schema_version with an orderable semver
string ("1.0.0"). SHA preserved in new schema_sha column for tamper
detection. Enables savegame migration lineage in Phase 5+ — saves can
record their schema version and determine which migrations to apply.
Updated both generators, check-systems-db-stamp validation (rejects
old SHA-hex values), schema DDL, and asset-pipeline docs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New `tooling/db/decision orphan-tickets` subcommand scans tickets with
a decision_ref that doesn't match any row in the decisions table.
Surfaces silently orphaned tickets from typo'd or renumbered D-IDs.
Makefile target: `make decisions-orphan-tickets`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Addresses five of seven subtasks from atlas-generator-refinement-notes:
- Cross-body dedup: corpus keyed by (corridor, feature_type) instead of
(system_id, feature_type), seeded from existing atlas_* rows so re-runs
don't collide with already-committed names. §1, §2.
- Empty-name fallback for mountain ranges when Gemma returns fewer names
than needed ({body_proper} Range {i+1}). §2.
- Suffix monotony detection: flags bodies where >40% of mountain names
share a trailing word (warning only — batch pipeline has no voice
access for auto-fix). §3. Follow-up in #886.
- Compass-direction ban: build_batch_prompt explicitly forbids
"Eastern/Northern/Western X" in few-shot instructions. §4.
- River vocabulary filter: is_valid_name rejects "X Flow" / "X Current"
when feature_type="river" — these are ocean terms bleeding through. §6.
- Infrastructure naming: deterministic post-pass assigns "{CityA}–{CityB}
{corridor_suffix}" to unnamed roads and railroads (Corridor/Road/Estrada/
Strasse/Track by corridor). §7.
Cultural-history prompt threading (§5) remains as existing corridor_substyles
refill mechanism; explicit cultural-history blurb deferred to #886.
naming_core bumped to v0.3.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Addresses all blocking + minor items from PR #136 review.
Architectural change (T2/H3 — the review's main complaint):
generate_brands was previously a separate Rust binary that produced a TOML
artifact, with its stamp written "on behalf" by import_economics.py at the
end of its own run. Reviewers flagged the invisible coupling: two sources
of truth in a system designed to have one, and no way to tell from the
stamp that one "generator" was really a subroutine of the other.
import_economics now invokes tooling/generate-brands as the first step of
its main() flow, before opening its own DB connection. The TOML artefact
is still produced and still committed (useful for diff-review of brand
changes), but there's now one pipeline owner. The meta table carries two
rows (import_economics, generate_atlas) not three; the Rust binary's
source SHA folds into import_economics' stamp via IMPORT_ECONOMICS_SOURCES.
A MIGRATION_SQL DELETE cleans up pre-merge DBs that still have the
orphan generate_brands row.
Other review items addressed in-line:
H1 generate_atlas._write_stamp no longer commits — transaction ownership
stays with the caller (matches import_economics pattern). Stamp +
atlas data now commit atomically; a failed stamp rolls back the
atlas data rather than leaving a stamp-missing-data intermediate.
H2 _file_sha1 (in both import_economics, generate_atlas,
check-systems-db-stamp) raises FileNotFoundError on missing sources
instead of silently contributing an empty-bytes hash. A ghost-SHA
convergence could otherwise produce vacuous "fresh" passes.
H4 pre-push no-meta-table warning rephrased — was "run after next
regeneration", now "run now if this DB was generated by you".
T1 asset-pipeline.md determinism claim softened: the stamp is
deterministic (same source → same recorded SHA), the DB binary is
not (generated_at + SQLite rowids/freelist churn).
T3 asset-pipeline.md gains a "migration escape hatch" section naming
MIGRATION_SQL in import_economics.py as the only sanctioned path
for direct writes, and forbidding hand-run sqlite-exec / one-off
patch scripts / SQLite-GUI edits.
T4 Makefile regen-db now runs as a single shell with `set -e`. A
failure in one generator halts the pipeline immediately, preventing
the "stale data, fresh stamp" state where a later step stamped a
DB whose earlier step had failed. import_economics' exit code 2
(coverage gate warning) remains explicitly tolerated.
T5 pre-push stamp check now runs on a branch's first push too —
compares against origin/main instead of origin/$BRANCH, closing
the gap where a new branch could ship a stale DB via the first push.
T6 check-systems-db-stamp fails closed on unknown generator_names in
meta — a future branch adding a new generator without registering
it in GENERATOR_SOURCES will now be rejected, not silently skipped.
T7 /pr-push watch list gains a mutual cross-reference comment with
GENERATOR_SOURCES in check-systems-db-stamp, plus the missing
names.rs source file, so the two lists cannot silently drift.
Follow-up tickets created:
#887 T8 decisions-orphan-tickets CLI — surfaces tickets whose
decision_ref points at a non-existent D-record.
#888 T9 meta.schema_version monotonic semver — for savegame migration
lineage in Phase 5+ (SHA comparison can't be ordered).
Verified:
make regen-db end-to-end — OK
make check-systems-db — OK, 2 generator(s) up to date
STALE detection — OK, verified by touching generate_atlas.py
/pr-push watch list — OK, flags this branch's changed sources
decision show D-159 — OK, structured output with tickets + refs
Refs: #855#856#857#858#859 PR #136
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Closes the decision-to-ticket coverage gap (#723). The `decisions-coverage`
Makefile target already reported per-decision counts; this adds the
single-decision drill-down via `tooling/db/decision show D-159`, returning
linked tickets, outbound refs, and inbound refs in one shot.
Schema unchanged — reverse link is a SELECT on tickets.decision_ref.
Refs: #723
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds systems.db regeneration discipline (#855) via a `meta` table (#856)
stamped by every generator, a pre-push hook that rejects stale DBs (#857),
and the top-level `make regen-db` / `make check-systems-db` targets that
drive the whole pipeline.
The stamp stores SHA-1 of generator source + schema, so the pre-push hook
can cheaply detect "you changed a generator but forgot to regen the DB"
before a binary merge conflict lands. Sprint 36 hit that class of conflict
on two branches touching systems.db simultaneously — this is the systemic
fix.
Regenerated systems.db is stamped; `make check-systems-db` passes.
Refs: #855#856#857
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- tooling/planet-gen/earth_blocklist.txt: document GJ0d (Earth body) as
blocklist-exempt so Brussels (and other Earth-canonical city names) are
not flagged on next sol_import.py run (R2 issue 1)
- wiki/star-systems/GJ-380/bodies/GJ380c/markers.json: rename Selet Basin
→ Subin Basin (Kumasi river namesake). Brings Akan register on GJ380c
to 3/29 features distributed across river, mountain, lake — credible
multi-generational trade corridor read instead of minimum-viable patch
(R2 issue 2)
- server/data/systems.db: atlas_oceans resynced for GJ380c
- docs/atlas/hand-refine-log.md:119: corrected stale log entry — Aldren
Pass was subsequently renamed Randalfoss to eliminate the cross-system
Aldren stem collision with GJ380c (R2 nit 3)
- tooling/planet-gen/refine_log_849.md: Groombridge cross-corridor
addendum updated to reflect 3/29 Akan register distribution
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Parallel addition to the rebalance addendum already in the GJ 0 Sol
section — Paula's header-style entry at the summary level complements
the in-context detail.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
price_tier was documented in D-189 §5 and present in brands.toml but
silently discarded on import — absent from schema, INSERT, and V-B06.
- Add price_tier TEXT column to brand_products CREATE TABLE
- Add COLUMN_MIGRATIONS entry for ALTER TABLE on existing DBs
- Add VALID_PRICE_TIERS constant (mass/premium/luxury/flagship/institutional)
- Include price_tier in product_rows tuple and INSERT OR REPLACE
- Add price_tier to V-B06 enum checks; skip NULL (nullable column)
- Backfill 4 pre-amendment anchor brands (8 entries): Calloway flagship/premium,
VGV luxury/premium, thrds luxury/premium, Bífröst flagship/luxury
V-B01..V-B06 all pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Addresses 6 mechanical issues from PR review:
- ImplantAppManifest: drop dead display_name and icon_path fields.
default_key carries a TODO noting its future migration to a keybinds
manifest (input concern in app manifest is a layering violation,
tracked explicitly).
- default_mode wire format is now a String ("fullscreen" / "insert") for
mod-author discovery. ImplantRegistry parses via _MODE_MAP, caches the
resolved int in _resolved_modes, and exposes get_resolved_mode(app_path).
main.gd reads the resolved int directly instead of re-parsing.
- Extract client/ui/implant/widgets/system_index.gd (class_name SystemIndex,
static get_sorted_systems). Removes duplicated star_map_data.json loader +
sort lambda from atlas_app and economics overview_screen.
- ImplantApp.on_insert_deactivated() default auto-closes only when the app
is active in INSERT mode. FULLSCREEN apps no longer spuriously close on
insert state changes.
- tooling/db/sqlite-query and sqlite-exec: --help output goes to stderr
(exit 0). Keeps stdout reserved for JSON payloads so JSON-parsing
callers can't get silently corrupted.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Finalizes #849 core-world atlas cohesion: GJ0d (Earth/Sol) markers.json
cleaned of erroneous data, refine_log updated with Sol body gap notes,
atlas_quality_analysis.py added for ongoing metric tracking.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Names all 33 null-name auto-detected Sol features: Earth ocean + 3 rivers,
24 Luna mountain ranges (real IAU lunar mountain names), 4 Mars mountains,
1 Europa mountain. All using real-world geographic names. Cross-reference
arcs added on Mars (Hellas-, Chryse-) and Europa (Conamara-, Pwyll-).
Adds sol_name_fixes.py for reproducible Sol feature naming. Updates refine
log to mark Sol complete with full audit metrics for all 6 touched systems.
DB synced: GJ0d, GJ0d-1, GJ0e, GJ0f-2 (all Sol inhabited bodies).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds two reusable scripts for the core-world hand-refine pass:
- atlas_cohesion_audit.py: SQL analysis against atlas_* tables. Reports
empty names, lazy/generic outputs, cardinal direction density, earth-echo
concentration, same-body cross-feature stem duplicates, and cross-body
stem collisions within a system. Supports --system, --body, --db flags.
Baseline run ranked Ran and Tau Ceti as highest-priority targets.
- apply_name_fixes.py: Applies curated name replacement tables to
markers.json files (name fields only; geometry preserved). Supports
--dry-run. After running, caller syncs DB via generate_atlas.py --body.
- refine_log_849.md: Hand-refine log documenting each body touched, the
rationale per change, cross-reference arcs established, and systems
flagged as blocked or needing follow-up (Sol, Barnard's Star, Proxima).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both wrappers previously silently treated --help as a SQL comment and
returned empty result JSON. They now intercept --help/-h before
delegating to the Python connector and print proper usage text with
the correct JSON key names (affected_rows, not rows_affected).
ticket, sprint, and decision already supported --help — no change.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix "Gemma 2 GGUF" in user-facing error message (line 2073)
- Fix gemma2.gguf in docstring usage example (line 32)
- Fix O(N) _is_duplicate: pre-build lowercase shadow sets for O(1) lookup
- Expand vestigial note to enumerate full ~750-line dead island boundaries
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hoshe:
- Mark --dump-prompts / name_feature() as vestigial with TODO note
- Fix --refresh help string: 200 → 1000 (matches actual default)
- Fix _RIVER_POOLS comment numbering: Pool 6 before Pool 5 → correct order
- Remove dead first-pass code in fix_fewshot_bleed.py
- _CAPTURE_FILE leak noted in vestigial TODO
Tyre:
- Fix stale "Gemma 2" strings in banner, argparse description, model help
- Note dead code for cleanup pass (name_feature ~700 lines)
Hoshe (prune):
- prune_atlas_features.py: named features sort before unnamed, preventing
silent discard of hand-authored names during pruning
naming_core:
- v0.2: few-shot blocklist, stricter is_valid_name (min 3 chars, no digits,
no brackets), prompt fragment rejection expanded
Miri clarification: the 261 "empty-string" files contain only roads (37)
and railroads (37) — infrastructure features never in naming scope. All
cities/rivers/oceans/mountains/POIs are clean.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the one-at-a-time Gemma 2 naming pipeline with a batch-oriented
Gemma 4 E2B pipeline. Key changes:
- naming_core.py: shared library with Levenshtein distinctiveness ranking,
batch prompt building, mood injection pool, name validation, and
adjacent-register refill logic
- Wiki-grounded register selection: per-system LLM call picks the cultural
register based on wiki/GTTR content instead of hash randomizer
- Batch naming: requests N*2 names per call, ranks by word-average
Levenshtein distance, fills quota from most-distinct candidates
- Mood pool: 13 emotional seeds randomized per-body for vocabulary
divergence (ambition, fear, isolation, defiance, etc.)
- Adjacent-register refill: when primary register exhausts, automatically
switches to next corridor substyle
- Inhabited-first body ordering: habitable worlds get first pick of
register vocabulary, barren moons get leftovers
- Process group cleanup: SIGTERM/SIGKILL the full distrobox chain on
subprocess refresh to prevent GPU zombie processes
- qa_naming.py: QA report, fix_fewshot_bleed.py: post-hoc fix script
- test_batch_naming.py, test_register_selection.py: test harnesses
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>