Commit Graph
169 Commits
Author SHA1 Message Date
jpmschweitzerandClaude Opus 4.6 903efda191 feat(assets): 100% globe coverage — generic images + donor fill
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>
2026-05-03 20:12:00 +02:00
jpmschweitzerandClaude Opus 4.6 29f9945291 feat(db): body_radius_km scatter + gas giant/moon scale classes
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>
2026-05-03 20:11:31 +02:00
jpmschweitzerandClaude Opus 4.6 e6a557e8e7 feat(meta): replace sprint workflow with kanban + milestones (D-221)
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>
2026-05-03 20:11:00 +02:00
jpmschweitzerandClaude Opus 4.6 13259dbfd5 feat(client): render province boundaries on planetary map (#927, D-205)
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>
2026-05-03 16:12:59 +02:00
jpmschweitzerandClaude Opus 4.6 0d09d905e4 fix(simulation): address PR #142 review round 2
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>
2026-05-03 15:51:10 +02:00
jpmschweitzerandClaude Opus 4.6 332b9404be fix(simulation): address PR #142 review — 11 issues resolved
Rust fixes: D-218 Backwater complexity (moved to Full arm), priority
queue dispatch gated on thread saturation, panic→soft-fail in
name_index, duplicated LCG unified into atlas::rng module, misleading
Safety comment removed, D-210 SubBiomeVariant deferred to #948.

Schema/data fixes: atlas_city_positions table (D-211 persistence),
settlement_class column on atlas_city_names, per-body transaction
boundaries in import_province_boundaries, import_city_names.py added
to GENERATOR_SOURCES, Python perf documented.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-03 15:30:50 +02:00
jpmschweitzerandClaude Opus 4.6 5ad8754b85 fix(atlas): remove unused imports in import_province_boundaries.py
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-03 09:46:53 +02:00
jpmschweitzer 64a873fc1a Merge remote-tracking branch 'origin/main' into sprint-38/server
# Conflicts:
#	CHANGELOG.md
#	server/data/systems.db
#	tooling/check-systems-db-stamp
#	tooling/economy-db/import_economics.py
#	tooling/planet-gen/generate_atlas.py
2026-05-03 09:30:48 +02:00
jpmschweitzerandClaude Opus 4.6 b6ca785f74 feat(db): atlas data pipeline — schema, importers, and normalization (#901-#911)
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>
2026-05-02 18:40:33 +02:00
jpmschweitzerandClaude Opus 4.6 d57f0566d2 fix(atlas): suffix monotony auto-fix + cultural-history prompting (#886)
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>
2026-05-02 18:40:21 +02:00
jpmschweitzerandClaude Opus 4.6 91066e4be6 chore(db): expand stamp GENERATOR_SOURCES for naming helpers (#892)
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>
2026-05-02 18:40:12 +02:00
jpmschweitzerandClaude Opus 4.6 873746ff8b fix(ci): address PR #139 review — 5 issues + source list sync
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>
2026-05-02 10:29:24 +02:00
jpmschweitzerandClaude Opus 4.6 5aa998cb86 chore(db): switch meta.schema_version to monotonic semver (#888)
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>
2026-05-02 10:09:13 +02:00
jpmschweitzerandClaude Opus 4.6 ffa638a46c chore(db): add decisions-orphan-tickets CLI (#887)
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>
2026-05-02 10:09:03 +02:00
jpmschweitzer 94a687fc08 Merge remote-tracking branch 'origin/main' into sprint-37/server
# Conflicts:
#	CHANGELOG.md
#	Makefile
#	server/data/systems.db
2026-04-22 09:01:43 +02:00
jpmschweitzerandClaude Opus 4.6 531bb1df5c refactor(assets): atlas naming — dedup, compass filter, river vocab, infra names (#853)
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>
2026-04-22 08:54:37 +02:00
jpmschweitzerandClaude Opus 4.6 3d9dd7d909 chore(ci): merge brand pipeline into import_economics + harden review findings
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>
2026-04-22 08:38:41 +02:00
jpmschweitzerandClaude Opus 4.6 a41f7aa06c feat(tooling): add decision show <D-NNN> with implementing tickets + refs
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>
2026-04-21 17:35:23 +02:00
jpmschweitzerandClaude Opus 4.6 8371e05e52 chore(ci): generator-driven asset pipeline — meta stamp + hook + regen target
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>
2026-04-21 17:34:52 +02:00
jpmschweitzer c3ff7040ae Merge remote-tracking branch 'origin/sprint-36/server'
# Conflicts:
#	server/data/systems.db
2026-04-19 18:45:06 +02:00
jpmschweitzer 9c69f0bd9d Merge remote-tracking branch 'origin/sprint-36/copy' 2026-04-19 16:42:57 +02:00
jpmschweitzerandClaude Opus 4.7 6d9bb6eadd fix(content): PR #133 round 2 review — 3 remaining Miri items
- 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>
2026-04-19 16:34:14 +02:00
jpmschweitzerandClaude Opus 4.7 98b2a9ed94 docs(content): refine log — Paula's Earth rebalance header entry
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>
2026-04-19 15:52:00 +02:00
jpmschweitzerandClaude Opus 4.7 2c3e3ff5eb fix(content): PR #133 review — 9 remaining items resolved
Closes 9 of 10 review items (blocker 1 handled in add2507e + d78d3b59):

- decisions/economics.md: reformat D-189 §5 amendment to standard
  Amendment (YYYY-MM-DD) block pattern (review #4)
- tooling/planet-gen/sol_name_fixes.py: dedup guard + argparse
  --dry-run (reviews #5, #10a)
- tooling/planet-gen/sol_markers/earth_features.json: trim to 11
  cities with selection rationale (review #6A); user-approved
  rebalance Sydney → Lagos and London → Brussels (review #6B)
- wiki/star-systems/GJ-380/bodies/GJ380c/markers.json: 2 secondary
  features renamed to Akan/Asante register — Kesset → Nkwanta Beck,
  Holt Spur → Bosomtwe Spur (review #7)
- docs/atlas/hand-refine-log.md: Aethelred lore-migration
  documentation + see-also cross-link to refine_log_849.md
  (reviews #8, #13)
- tooling/planet-gen/refine_log_849.md: rebalance addendum
- wiki/star-systems/GJ-0/bodies/GJ0d/markers.json, server/data/
  systems.db: re-synced after rebalance

Stub depth (review blocker #2) handled via split — tracked as
follow-up ticket #861 (three-layer narrative authoring).

Final Earth cities (11): Beijing, Brussels, Cairo, Delhi, Istanbul,
Lagos, Moscow, New York, São Paulo, Singapore, Tokyo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:51:17 +02:00
jpmschweitzerandClaude Sonnet 4.6 d78d3b599c fix(content): argparse --dry-run for generate_corp_stubs.py; populate cross_refs (#828 nits)
- generate_corp_stubs.py: add argparse with --dry-run (prints planned stub
  creations without writing files) and --help
- calloway-distillery.md: cross_refs → [thrds, mercado-travessia]
- thrds.md: cross_refs → [calloway-distillery, mercado-travessia]
- vins-de-grand-vide.md: cross_refs → [nordmark-skog]
- thalassa-resort-group.md: cross_refs → [the-registry, prometheus-labs]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 15:39:41 +02:00
jpmschweitzerandClaude Sonnet 4.6 add2507eac fix(content): add price_tier to brand layer schema, import, and V-B06 (#828 blocker)
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>
2026-04-19 15:37:33 +02:00
jpmschweitzerandClaude Opus 4.7 cf3e14cc5e chore(tooling): remove unused imports in generate_corp_stubs.py
Fixes F401 errors caught by pre-push hook.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 14:50:12 +02:00
jpmschweitzerandClaude Opus 4.6 48c8fb7dea fix(ui): PR #131 review round 2 — manifest cleanup, system index helper, stderr help
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>
2026-04-19 14:21:03 +02:00
jpmschweitzerandClaude Sonnet 4.6 6d50096571 feat(content): Sol body name pass and atlas tooling — complete #849 atlas cohesion
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>
2026-04-19 14:13:41 +02:00
jpmschweitzerandClaude Sonnet 4.6 8f807c56f0 feat(content): author 124 notable brand corps across 8 categories (#828)
Adds brands.toml with 124 brand_products entries (plus halo/volume pairs
and brand_inputs) covering all 8 D-189 categories: terroir, heritage_craft,
tech_premium, cultural, service_premium, commodity_branded, design_heritage,
platform_catalogue. Includes 112 new wiki/corporations stub pages for FK
integrity. Brand layer validation V-B01–V-B06 passes; Phase 2 coverage gate
failures are pre-existing raw-commodity gaps (out of scope for #828).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 14:13:31 +02:00
jpmschweitzerandClaude Sonnet 4.6 ed7fa7243d feat(content): Sol body name pass — complete #849 atlas cohesion work
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>
2026-04-19 13:51:22 +02:00
jpmschweitzerandClaude Sonnet 4.6 e11a9c308a feat(engine): generate_brands pipeline — 10K minor brands from templates (#829)
New generate_brands binary reads 126 brand archetype templates
(wiki/economics/archetypes/brand_templates.toml), assigns halo+volume pairs
to all 48 hand-authored corps, outputs wiki/economics/corporations/generated_brands.toml.

Result: 10,000 brand_product rows, 26,750 brand_inputs, all 48 corps covered.
Brand structural validation V-B01..V-B06 passes. Generated file is gitignored
(regenerated on each `make economy-db` run).

make economy-db now runs generate-brands before import_economics.py.
import_economics.py merges generated_brands.toml alongside hand-authored brands.toml.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 13:15:03 +02:00
jpmschweitzerandClaude Sonnet 4.6 d14b242eef feat(content): add Sol city data to sol_markers/ for Luna, Mars, Europa (#849)
Adds city sections to three sol_markers/ feature files so sol_import.py
produces inhabited bodies with atlas_cities coverage.

luna_features.json (GJ0d-1, 350M pop): 3 cities — Artemis (capital, south
polar region, water ice access, 200M), Tranquility Station (Mare
Tranquillitatis, historic first settlement, 90M), Selene (Mare Imbrium,
industrial hub, 60M).

mars_features.json (GJ0e, 1.2B pop): 4 cities — Olympia (capital, Olympus
Mons region, lava tube habitat, 450M), Hellas Station (Hellas Basin, deep
low-pressure warmth, 350M), Elysium City (Elysium Mons, 250M), Chryse
Landing (Chryse Planitia, historic Viking site and port gateway, 150M).

outer_features.json (GJ0f-2 Europa, 30M pop): 2 cities — Conamara Station
(capital, Conamara Chaos, geothermal near ice plate faults, 20M), Pwyll
Base (Pwyll Crater, sub-ice ocean access, 10M).

earth_features.json already had comprehensive city coverage (40+ cities)
and required no changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 13:11:20 +02:00
jpmschweitzerandClaude Sonnet 4.6 c58246284b feat(content): core-world atlas hand-refine pass — Sirius, Groombridge, Barnard's Star (#849)
Continues the core-world cohesion pass. All markers.json edits synced to
atlas_* tables. apply_name_fixes.py extended with all new fix tables.

GJ244Ad Edict (400M pop): 5 fixes — 2 lazy mountain names replaced with
Edict-vocabulary terms ("The Statute", "Charter Spur"); 3 cardinal oceans
replaced with cross-referential names (Veil Shelf → Veil Institute POI,
Concord Mere → Concord Assembly Archive POI, Charter Tarn → Charter Spur
mountain). Note: "Westwall" flagged by Gestalt not found in markers.json
or DB; stale data issue. Arcs established: Charter-, Concord-, Veil-.

GJ380c Lendel (900M pop): 2 fixes — "Pale Run" river renamed "Durneth
Beck" (cross-refs Durneth Range; "beck" = British stream); "Tember Ridge"
renamed "Tember Spine" (keeps stem, removes lazy Ridge suffix). Aldren-
stem arc (capital + river + exchange) is intentional — preserved.

GJ699b Verada (1.9B pop): 8 fixes — all 3 rivers renamed from civic-grid
names to geographic names (Verada Reach, The Meridian, Capitol Beck); 5
oceans renamed to replace architectural/district suffixes with geographic
ones (Prospect Sea, Haven Sea, Meridian Sound, Capitol Mere, Sterling
Pool). Arcs: Capitol- (city + river + ocean), Meridian- (river + ocean),
Haven/Port- (city + ocean).

GJ699b-1 Verada moon: 8 fixes — all 8 mountains renamed from street
addresses (Grandview Avenue, Harmony Boulevard, Beacon Street, etc.) to
geological/institutional cross-references. The moon's peaks now carry the
names of Verada's civic institutions as seen from orbit: Tribunal Spur,
Zenith Spine, Keystone Scarp, Ironwood Spur, Consulate Scarp, Prefecture
Spur, Barnard Heights, Verada Scarp (largest range).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 13:05:36 +02:00
jpmschweitzerandClaude Sonnet 4.6 dd50287af0 feat(content): atlas cohesion analysis tooling for #849
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>
2026-04-19 12:34:47 +02:00
jpmschweitzerandClaude Opus 4.6 3f4d60c8bb feat(tooling): add --help/-h to sqlite-query and sqlite-exec (#722)
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>
2026-04-19 11:52:22 +02:00
jpmschweitzerandClaude Opus 4.6 160c3f1853 fix(tooling): PR #130 round 2 — stale strings, O(1) dedup, vestigial scope (#833)
- 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>
2026-04-18 00:43:11 +02:00
jpmschweitzerandClaude Opus 4.6 8ba3a1d0a7 fix(tooling): address PR #130 review findings (#833)
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>
2026-04-17 23:27:44 +02:00
jpmschweitzerandClaude Opus 4.6 9ad9b88d7c feat(tooling): Gemma 4 batch naming pipeline with wiki-grounded register selection (#833)
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>
2026-04-17 16:09:23 +02:00
jpmschweitzerandClaude Opus 4.6 474b31b214 fix(tooling): only log rejections when all attempts exhausted (#833)
Individual dedup/blocklist/placeholder/empty rejections that recover
on the next attempt are now silent. Only the skipped: summary line
prints when all 5 attempts fail. Subprocess errors still print
immediately (those indicate a real problem).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:39:46 +02:00
jpmschweitzerandClaude Opus 4.6 b63c2be8dd feat(tooling): 5 retry attempts + refresh every 1000 requests (#833)
Bumped max_attempts from 3 to 5 — with per-system dedup and no stem
cap, the remaining dedup hits are mostly per-body collisions which
a couple extra attempts with rotated pools can escape.

Bumped --refresh default from 200 to 1000. Fewer subprocess restarts
= fewer model reloads via distrobox. KV-cache bleed risk is lower
now that the validation gauntlet is lighter.

Reverted the batch-prompt experiment — Gemma 2 2B drifts on
multi-line output; individual calls are more reliable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:36:46 +02:00
jpmschweitzerandClaude Opus 4.6 05a1366544 refactor(tooling): drop stem cap + scope dedup to per-system (#833)
The stem cap (--stem-cap 20) was rejecting valid names because common
feature-type vocabulary tokens like "ridge", "hill", "range" hit the
cap after ~200 bodies and blocked all subsequent names containing
them. With sub-style rotation already providing variety, the cap was
doing more harm than good. Removed entirely.

Cross-body dedup narrowed from (hop, corridor, feature_type) to
(system_id, feature_type). Two rivers in the same system can't share
a name; two rivers in different systems can. This matches how
settlers actually name things — they don't coordinate with other
star systems.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 12:30:13 +02:00
jpmschweitzerandClaude Opus 4.6 cb178a8c57 feat(tooling): per-system sub-style rotation across all corridors (#833)
Replace single-inflection corridor palettes with lists of sub-styles.
Each system picks one deterministically via hash(system_id), so all
bodies in the same system share a cultural register but neighbouring
systems get different registers.

Core corridor splits into 6 sub-styles (English rural, British
colonial, US rural, US cosmopolitan, classical/institutional,
Australian/NZ). North/south/east/west reach each get 5 sub-styles
covering their cultural spectrum. Deep frontier gets 3 (founder-name,
surveyor-descriptive, outpost-functional).

This multiplies Gemma's effective vocabulary per corridor by the
sub-style count, dramatically reducing dedup pressure. A 6-style
core corridor means each sub-style serves ~4 systems instead of 24,
so "The Ridge" exhausts after ~4 systems, not ~24.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 08:53:02 +02:00
jpmschweitzerandClaude Opus 4.6 3ab28138a0 feat(tooling): skip dedup-exhausted features instead of palette fallback (#833)
When all 3 LLM attempts are rejected (dedup, blocklist, etc.),
name_feature now returns None instead of a deterministic palette
fallback. process_body leaves the name as null in markers.json.

The preserved path (_is_blank) treats null as unnamed, so a fill
round (re-running the script) picks up only the skipped features
with a fresh corpus — zero dedup pressure from the first pass. The
fill round can use a different seed, slower prompt, or a different
backend entirely (e.g. Haiku).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 08:42:32 +02:00
jpmschweitzerandClaude Opus 4.6 c767f82fbb feat(tooling): scope cross-body dedup to hop+corridor (#833)
Changed dedup key from (corridor, feature_type) to
(hop, corridor, feature_type). Systems at the same gate-hop distance
in the same corridor are near neighbors and shouldn't share feature
names; systems at different hops can. This prevents corpus exhaustion
where Gemma's narrow range-name distribution ("The Ridge", "Blackwood
Range") collides after ~20 bodies and drives fallback rates toward
100%.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 08:37:28 +02:00
jpmschweitzerandClaude Opus 4.6 e0707d8072 feat(tooling): always log retry reasons in gemma_naming.py (#833)
Retry rejection lines (dedup, blocklist, placeholder, stem_cap, empty,
error) now print unconditionally, not only under --verbose. The
fallback line also includes a tally of the rejection reasons that
exhausted all attempts, e.g.:

    fallback: GJ144e-1/range_43 → 'Kirkwood Spine'  [blocklist=2 dedup=1]

Diagnostic run on 20 bodies confirms dedup is the primary fallback
driver. Gemma converges on a narrow set of range names ("The Ridge",
"Blackwood Range", "The Spine") that collide across bodies in the
same corridor. Blocklist catches "Thames" and "The Great Divide"
correctly. Zero stem-cap or subprocess-error fallbacks observed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 08:20:36 +02:00
jpmschweitzerandClaude Opus 4.6 d5a437ea2d fix(tooling): run-atlas-naming.sh — use grep -a instead of strings (#833)
The gfx1201 preflight check piped `strings` into grep, which fails
silently on a Bazzite host where binutils is not installed and
`strings` is not on PATH. `grep -a` reads the binary directly as
text, works everywhere grep exists, and produces the same result.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 23:18:40 +02:00
jpmschweitzerandClaude Opus 4.6 bcff9f724b feat(tooling): run-atlas-naming.sh — overnight batch naming launcher (#833)
Wraps gemma_naming.py with the validated overnight recipe: gfx1201
ROCm binary path, distrobox reach-build for libhipblas at runtime,
timestamped log under .tmp/.

Preflight checks: binary exists and is executable, model present,
reach-build container exists, binary strings contains gfx1201 kernels.
Fails fast on any missing prerequisite so a broken build can't waste
an overnight window. Script takes no arguments; anything passed is
rejected so a stray --help can't accidentally launch the pipeline.

Estimate ~4-6 h for ~26k features across 2394 bodies at 74 t/s on an
RX 9070. Safe to interrupt and resume — preserved path skips
already-named bodies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 23:15:52 +02:00
jpmschweitzerandClaude Opus 4.6 c089557d65 feat(tooling): out-of-worktree sr-voice discovery + distrobox wrap + prompt capture (#833)
Three additions unlocked by the gfx1201 ROCm debug session.

1. _find_sr_voice() resolves the default binary path to
   ~/Projects/settled-reach/binaries/sr-voice-rocm (persistent across
   worktree lifetimes) with a legacy fallback to the main workdir's
   cargo target dir. Matches #850's plan to ship platform binaries
   outside the repo.

2. --distrobox <name> wraps the sr-voice subprocess in
   `distrobox enter <name> --` when the built binary depends on libs
   that only exist inside a dev container (libhipblas.so.2 on a
   Bazzite host). Stdio JSONL protocol flows through unchanged.

3. --dump-prompts PATH captures the attempt-0 prompt for every
   feature as JSONL without calling an LLM. Force --mock and
   short-circuit name_feature to return a unique deterministic
   placeholder. Used to feed the same prompt set to alternate
   backends (Haiku agent, other models) for offline A/B comparison
   of naming quality independent of the sampling backend.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 23:11:28 +02:00
jpmschweitzer a5fbce4cc9 feat(tooling): per-system gttr context + cosmopolitan corridor palettes (#833)
Two related quality fixes observed mid-run on Sirius + ACB + Ran:

1) Cosmopolitan corridor palettes. The six corridor inflection labels
were single-culture dominant ("administrative English / Gateway-era",
"British / Australian / Irish", "Korean/Japanese/Taiwanese", etc).
Gemma 2 2B interpreted these as "produce ONLY in this register" and
every core body came out anglophone, every east_reach body came out
East Asian. The real Earth diaspora in the setting is cosmopolitan —
a British surveyor on an east_reach moon still names a river after
their aunt in Dorset. The labels now spell out the dominant register
AND explicitly invite cross-cultural variety so Gemma samples from
the full few-shot pool instead of collapsing to one culture.

2) Per-system gttr context (the big one). The gttr.md files under
wiki/star-systems/<slug>/gttr.md already carry a vivid one-sentence
characterisation of every system — "where the rules live", "forty
years old and still in the draft", "the most connected system in
the Reach", "grandparents owned the land". This is a far stronger
cultural signal than the corridor inflection alone.

New column `star_systems.gttr_hook` stores a pre-extracted 45-word
hook per system. `tooling/db/populate_gttr_hook.py` parses each
gttr.md, regex-matches the first `**NAME**` paragraph, normalises
whitespace, truncates softly at a word cap, and stores it. Covers
all 301 systems (full coverage). Idempotent, safe to re-run after
any wiki update. Explicit transaction wrapper.

gemma_naming.py loads the hook cache at startup via
`load_system_gttr_hooks` and threads `system_hook` plus the system
and body proper names through process_body → name_feature →
_build_prompt. The prompt now carries:

    System: <proper_name>. Planet: <body_name>.
    About the system: <gttr_hook>

    Style: British. Answer: Cooper's Creek
    Style: Dutch.   Answer: Meijer Beek
    ...

Real-mode smoke on 10 cases across 4 contrasting systems shows the
hook is doing exactly what it should. Sample output on the same
body_id / local_id pairs:

  Tau Ceti     (cosmopolitan hub)         → Oakham River, Riverwood, Bridle Way
  Ran          (old-family agricultural)  → Hart's Well, Blackwood Ridge
  ACB          (Lattice Commission seat)  → Greenhaven, Rudge Brook
  Posto Avançado (PT frontier dead-end)   → Rio Preto, Serra de Caxias, Cunha's Cove

Posto Avançado went from "likely-English under the old corridor-only
prompt" to actual Portuguese names with a real Brazilian place stem
(Caxias), because the hook explicitly mentions wave_5 Portuguese
founders and frontier dead-end context. The gttr cultural one-liner
is the single strongest lever available for per-system cohesion —
this was the mono-culture issue observed in the first run, now fixed.

Token cost: ~60-90 extra tokens per prompt (hook + ident line).
Inference slowdown: ~5-10% per call. Acceptable for the quality gain.

Also restores 10 markers.json files that were stale from the aborted
run just killed — they were all core bodies at hop 0-1 which benefit
most from the gttr-context upgrade, so re-running them with the new
prompt is worth the ~3 minutes of re-inference.
2026-04-15 12:37:52 +02:00