chore(db): backfill founding_age_years for inhabited bodies (#1000) #144

Closed
jpmschweitzer wants to merge 0 commits from founding-age-backfill into main
Owner

#1000 — Backfill founding_age_years for inhabited bodies

founding_age_years was NULL on all 273 inhabited bodies; it gates ConstructionEra (D-229) and block irregularity (D-216). Source-canonical fix: an idempotent MIGRATION_SQL UPDATE in import_economics.py + make regen-db. No hand-edit of systems.db.

Derivation (per D-216 amendment)

founding_age_years = COALESCE(colonial_charter event age_years, settlement_wave fallback)

  • Events-first: colonial_charter authored age (the real founding event — the named founding/first_settlement/colonization types match zero rows; civilizational_origin @ 12900yr correctly excluded).
  • Wave fallback: wave_1=600, wave_2=500, wave_3=300, wave_4=100, wave_5=40.
  • Excluded (stays NULL): settlement_wave IN ('origin','unsettled') — Sol is out of player scope (D-236).

Result (QA-verified, Hoshe APPROVE — 7/7 checks pass)

  • 269/273 inhabited bodies populated; 4 NULL = Sol bodies (Earth/Luna/Mars/Europa), correct.
  • 11 charter-sourced bodies match authored ages exactly; 258 from wave fallback; 0 wave mismatches.
  • Idempotent (WHERE founding_age_years IS NULL); range sane (40–600); check-systems-db stamp fresh.

🤖 Generated with Claude Code

## #1000 — Backfill founding_age_years for inhabited bodies `founding_age_years` was NULL on all 273 inhabited bodies; it gates `ConstructionEra` (D-229) and block irregularity (D-216). Source-canonical fix: an idempotent `MIGRATION_SQL` UPDATE in `import_economics.py` + `make regen-db`. No hand-edit of `systems.db`. ### Derivation (per D-216 amendment) `founding_age_years = COALESCE(colonial_charter event age_years, settlement_wave fallback)` - **Events-first:** `colonial_charter` authored age (the real founding event — the named `founding`/`first_settlement`/`colonization` types match zero rows; `civilizational_origin` @ 12900yr correctly excluded). - **Wave fallback:** wave_1=600, wave_2=500, wave_3=300, wave_4=100, wave_5=40. - **Excluded** (stays NULL): `settlement_wave IN ('origin','unsettled')` — Sol is out of player scope (D-236). ### Result (QA-verified, Hoshe APPROVE — 7/7 checks pass) - **269/273** inhabited bodies populated; **4** NULL = Sol bodies (Earth/Luna/Mars/Europa), correct. - 11 charter-sourced bodies match authored ages exactly; 258 from wave fallback; 0 wave mismatches. - Idempotent (`WHERE founding_age_years IS NULL`); range sane (40–600); `check-systems-db` stamp fresh. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
jpmschweitzer added 1 commit 2026-05-30 19:17:06 +02:00
Add idempotent MIGRATION_SQL UPDATE to import_economics.py deriving
bodies.founding_age_years via COALESCE(colonial_charter event age,
settlement_wave fallback) per the D-216 amendment.

- Events-first: colonial_charter age_years (authored; 11 bodies).
- Wave fallback: wave_1=600/wave_2=500/wave_3=300/wave_4=100/wave_5=40
  (258 bodies).
- Exclude settlement_wave in (origin, unsettled) -> stays NULL: 4 Sol
  bodies remain NULL (out of player scope, D-236).

Source-canonical via regen-db; 269/273 inhabited bodies now populated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Owner

Review: founding-age-backfill → main (code) — CHANGES REQUESTED

Reviewers: Hoshe (data QA), Tyre (pipeline integrity). Both REQUEST_CHANGES.

The data is numerically perfect — 273 inhabited bodies, 269 set / 4 NULL (all Sol/origin, correct per D-236), 11 charter-sourced bodies (charter age wins over wave in every divergent case), 258 wave-fallback with zero mismatches across all five waves, range 40–600, idempotent (WHERE founding_age_years IS NULL makes re-run a no-op), source-canonical (only import_economics.py + regen'd systems.db), stamp fresh. The MIGRATION_SQL placement is the sanctioned escape-hatch path and the system_history PK guarantees the wave subquery is single-row.

One blocker (a decision-record consistency fix) + two low suggestions:

# File Issue By
1 decisions/architecture.md — D-216 amendment (~L1208) The decision text is stale vs the implemented behavior. It states events-first matches event_type ∈ {founding, first_settlement, colonization} and is "currently empty in the live DB, scaffolding only." Both are false: the SQL correctly uses event_type = 'colonial_charter' (9 authored systems, 11 inhabited bodies, 5 diverging from wave fallback — e.g. GJ 144=580, GJ 338B=590, GJ 380=480). The SQL is correct; the decision record is wrong. Update the amendment to colonial_charter and the real counts so the load-bearing D-record matches the implementation. Hoshe + Tyre
2 tooling/economy-db/import_economics.py:~383 LIMIT 1 on the colonial_charter subquery has no ORDER BY — non-deterministic if a system ever gets two charter rows (none today). Add ORDER BY sort_order ASC LIMIT 1 to make the pick explicit. Tyre
3 tooling/economy-db/import_economics.py:~386 Wave-fallback CASE has no ELSE — a future wave_6 (which passes the EXISTS guard) would silently yield NULL. Add ELSE NULL -- unexpected wave marker, or a post-update assert counting founding_age_years IS NULL AND inhabited=1 in non-excluded scope. Tyre

Recommend folding the D-216 doc fix into this branch so the decision record and its implementation merge together.

🤖 review via /pr-review

## Review: founding-age-backfill → main (code) — **CHANGES REQUESTED** Reviewers: **Hoshe** (data QA), **Tyre** (pipeline integrity). Both REQUEST_CHANGES. The data is **numerically perfect** — 273 inhabited bodies, 269 set / 4 NULL (all Sol/`origin`, correct per D-236), 11 charter-sourced bodies (charter age wins over wave in every divergent case), 258 wave-fallback with **zero mismatches** across all five waves, range 40–600, idempotent (`WHERE founding_age_years IS NULL` makes re-run a no-op), source-canonical (only `import_economics.py` + regen'd `systems.db`), stamp fresh. The MIGRATION_SQL placement is the sanctioned escape-hatch path and the `system_history` PK guarantees the wave subquery is single-row. One blocker (a decision-record consistency fix) + two low suggestions: | # | File | Issue | By | |---|------|-------|----| | 1 | `decisions/architecture.md` — D-216 amendment (~L1208) | **The decision text is stale vs the implemented behavior.** It states events-first matches `event_type ∈ {founding, first_settlement, colonization}` and is "currently empty in the live DB, scaffolding only." Both are false: the SQL correctly uses `event_type = 'colonial_charter'` (9 authored systems, 11 inhabited bodies, 5 diverging from wave fallback — e.g. GJ 144=580, GJ 338B=590, GJ 380=480). **The SQL is correct; the decision record is wrong.** Update the amendment to `colonial_charter` and the real counts so the load-bearing D-record matches the implementation. | Hoshe + Tyre | | 2 | `tooling/economy-db/import_economics.py:~383` | `LIMIT 1` on the `colonial_charter` subquery has no `ORDER BY` — non-deterministic if a system ever gets two charter rows (none today). Add `ORDER BY sort_order ASC LIMIT 1` to make the pick explicit. | Tyre | | 3 | `tooling/economy-db/import_economics.py:~386` | Wave-fallback `CASE` has no `ELSE` — a future `wave_6` (which passes the EXISTS guard) would silently yield NULL. Add `ELSE NULL -- unexpected wave` marker, or a post-update assert counting `founding_age_years IS NULL AND inhabited=1` in non-excluded scope. | Tyre | Recommend folding the D-216 doc fix into this branch so the decision record and its implementation merge together. 🤖 review via /pr-review
jpmschweitzer added 1 commit 2026-05-30 22:07:19 +02:00
- Update D-216 amendment text to match the implemented decision:
  events-first uses event_type='colonial_charter' (9 systems, 11 bodies,
  5 diverging from wave) — not the stale founding/first_settlement/
  colonization scaffolding vocabulary.
- Add ORDER BY sort_order ASC to the colonial_charter subquery for a
  deterministic pick if a system ever has two charter rows.
- Add explicit ELSE NULL to the wave-fallback CASE so an unexpected
  settlement_wave leaves a trace instead of silently nulling.

Data unchanged: 269/273 set, 4 Sol NULL; stamp fresh.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Owner

Re-review (commit 9f4b1bf02) — APPROVED

Both reviewers re-verified against the follow-up commit.

Hoshe (data QA): APPROVE — D-216 amendment now reads event_type = 'colonial_charter' with accurate counts (9 systems / 11 bodies / 5 diverging, with examples), stale "empty/scaffolding" claim gone; ORDER BY sort_order ASC + ELSE NULL present; counts unchanged (273 / 269 set / 4 Sol NULL), 0 charter mismatches, 0 wave mismatches; stamp fresh; source-canonical path only.

Tyre (pipeline): APPROVE — D-record now matches implementation; deterministic charter pick and explicit CASE fallthrough in place; import_economics meta stamp fresh (generated_at post-dates the source edit), source + DB committed together — no binary-merge-conflict risk. "Surgical patch, no scope creep. Ship it."

No remaining items. Clean to merge.

🤖 re-review via /pr-review

## Re-review (commit `9f4b1bf02`) — **APPROVED** Both reviewers re-verified against the follow-up commit. **Hoshe (data QA): APPROVE** — D-216 amendment now reads `event_type = 'colonial_charter'` with accurate counts (9 systems / 11 bodies / 5 diverging, with examples), stale "empty/scaffolding" claim gone; `ORDER BY sort_order ASC` + `ELSE NULL` present; counts unchanged (273 / 269 set / 4 Sol NULL), 0 charter mismatches, 0 wave mismatches; stamp fresh; source-canonical path only. **Tyre (pipeline): APPROVE** — D-record now matches implementation; deterministic charter pick and explicit CASE fallthrough in place; `import_economics` meta stamp fresh (`generated_at` post-dates the source edit), source + DB committed together — no binary-merge-conflict risk. "Surgical patch, no scope creep. Ship it." No remaining items. Clean to merge. 🤖 re-review via /pr-review
jpmschweitzer closed this pull request 2026-05-30 22:50:30 +02:00

Pull request closed

This pull request cannot be reopened because the branch was deleted.
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jpmschweitzer/settled-reach#144