Drop the eight legacy columns SP8 left behind

Migrations 66 to 73 drop `actions.index`, `variants`, `variant_index`,
`variant_count`, `state_before`, and `world_state_before`, plus
`adventures.memory_cursor` and `summary_cursor`. `index` is a keyword in
SQLite, so migration 71 quotes it.

Nothing outside the migrations read these. `models.py`, `schemas.py`, and
`ACTION_LIST_COLUMNS` lose the same eight fields, `Adventure.actions` orders
by `id`, and `attempts.renumber`, `context.history.max_action_index`, and
`nodes.next_index` are deleted.

Two changes keep the migration replayable on a `create_all` database:

- `_split_variants_into_siblings` wrote through the live ORM table, so it
  stopped compiling once migration 66 removed five of its columns. It now
  writes through `_ACTIONS_AT_60`, a frozen `Table` with its own `MetaData`.
- Five data passes read columns these migrations drop. Each now calls
  `_has_columns` and returns early when the columns are absent.

`bootstrap` takes a `through` version so a migration test can stop at the
schema it asserts on.

555 tests pass, up from 549. Eight of the new cases assert each column is
gone after a real schema-45 database migrates all the way.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0198qDK3gmgSo7EtQ4GTPqqK
This commit is contained in:
parththakkar106
2026-08-29 17:15:49 +05:30
committed by Parth
co-authored by Claude Opus 5
parent e0bf2b61d9
commit f1bebe18d0
41 changed files with 477 additions and 378 deletions
+1 -1
View File
@@ -99,7 +99,7 @@ adv = models.Adventure(
db.add(adv)
db.flush()
db.add(models.Action(
adventure_id=adv.id, index=0, type="start",
adventure_id=adv.id, type="start",
text="The cellar door has been shut since your grandmother died. "
"Tonight the lantern is lit and the key is in your hand."))
db.add(models.AdventureScript(
+1 -2
View File
@@ -396,7 +396,7 @@ def add_second_adventure(db, rng: random.Random, user) -> int:
db.flush()
for i in range(6):
action = models.Action(
adventure_id=other.id, index=i,
adventure_id=other.id,
type="ai" if i % 2 else "do",
text=f"[second adventure] turn {i}. {prose(rng, 200)}",
state_after=rich_script_state(i),
@@ -507,7 +507,6 @@ def build_fixture(args, rng: random.Random) -> tuple[int, int]:
for n, body in enumerate(texts):
action = models.Action(
adventure_id=adventure.id,
index=i,
type="ai" if is_ai else "do",
text=body,
# The turn's assembled prompt is stored once, on the
+1 -1
View File
@@ -86,7 +86,7 @@ adv = models.Adventure(
db.add(adv)
db.flush()
db.add(models.Action(
adventure_id=adv.id, index=0, type="start",
adventure_id=adv.id, type="start",
text="The cellar door has been shut since your grandmother died."))
db.commit()
adv_id = adv.id