Adv 2.0 L5e: death state migration off AdvCharacter

Eight player_meta columns: alive (default 1), dead_until,
death_reprieve_last, last_pardon_used (DATETIME), last_death_date,
grudge_location, death_source, death_location (TEXT).

DeathState struct + load/upsert/backfill/projection helpers. Dual-write
strategy switches: instead of per-site upserts, the dual-write rides
saveAdvCharacter itself (after the existing display_name dual-write).
Death-state mutation surface spans ~50 save sites; the saveAdvCharacter-
internal hook catches every one without scatter.

Backfill idempotent (only fills rows where every death field is still
default). Tests cover backfill, fallback, round-trip, and the
saveAdvCharacter dual-write.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
prosolis
2026-05-09 11:33:16 -07:00
parent 8fc8941cc9
commit 45586eb697
6 changed files with 388 additions and 1 deletions

View File

@@ -283,6 +283,23 @@ func runMigrations(d *sql.DB) error {
`ALTER TABLE player_meta ADD COLUMN harvest_actions_used INTEGER NOT NULL DEFAULT 0`,
`ALTER TABLE player_meta ADD COLUMN created_at DATETIME`,
`ALTER TABLE player_meta ADD COLUMN last_active_at DATETIME`,
// Adv 2.0 Phase L5e — Death state migration off AdvCharacter.
// Alive / DeadUntil / DeathReprieveLast / LastDeathDate /
// LastPardonUsed / GrudgeLocation / DeathSource / DeathLocation move
// to player_meta. Dual-write strategy switches to inside
// saveAdvCharacter (death state mutates at ~50 save sites; per-site
// upserts would be too noisy — gogobee_legacy_migration.md §7.3
// L5e). `Alive` defaults to 1 since legacy created characters are
// alive, and a never-migrated row should fall through to the legacy
// table via loadDeathState.
`ALTER TABLE player_meta ADD COLUMN alive INTEGER NOT NULL DEFAULT 1`,
`ALTER TABLE player_meta ADD COLUMN dead_until DATETIME`,
`ALTER TABLE player_meta ADD COLUMN death_reprieve_last DATETIME`,
`ALTER TABLE player_meta ADD COLUMN last_death_date TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE player_meta ADD COLUMN last_pardon_used DATETIME`,
`ALTER TABLE player_meta ADD COLUMN grudge_location TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE player_meta ADD COLUMN death_source TEXT NOT NULL DEFAULT ''`,
`ALTER TABLE player_meta ADD COLUMN death_location TEXT NOT NULL DEFAULT ''`,
}
for _, stmt := range columnMigrations {
if _, err := d.Exec(stmt); err != nil {