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>
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>