Delete seeded scenarios no seed file claims any more
`previous_titles` stops a rename stranding the row it left behind, but the rows already stranded still had to be deleted by hand on every deployment. The seeder now removes them on the next boot, which retires the stale "Road to the Champion" demo without a database console. Only rows with a NULL owner and `is_public` are considered, and a player's own scenario is neither, so nothing anybody created is reachable. An adventure started from a deleted demo survives: `adventures.scenario_id` is `ON DELETE SET NULL`, and the adventure holds its own copies of the cards and scripts, so it loses only the inherited cover art. Two cases skip the sweep, because neither is an instruction to remove live content: a seed file that fails to parse claims no title, and an empty seed directory reads as a packaging failure. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PacdRuPXSkQQy4ZYdH32hF
This commit is contained in:
co-authored by
Claude Opus 5
parent
c2d3f0d8b9
commit
9398c13da5
+11
-2
@@ -237,11 +237,20 @@ first orphaned and public forever. This is the same failure this file already re
|
||||
"Road to the Champion". Seed files now carry `previous_titles`, and the rename lands on
|
||||
the existing row. Verified: the Pokemon demo kept its id.
|
||||
|
||||
**A seeded scenario nobody claims is now deleted on boot.** `previous_titles`
|
||||
stops a rename stranding a row; the sweep removes the ones already stranded, which
|
||||
retires "[Demo] Road to the Champion" without a console. Only rows with a NULL owner
|
||||
and `is_public` are reachable, and `adventures.scenario_id` is `ON DELETE SET NULL`, so
|
||||
an adventure started from a deleted demo keeps its story and loses only the cover art.
|
||||
A seed file that fails to parse, or an empty seed directory, skips the sweep.
|
||||
|
||||
**Every new guest is given a pre-played adventure.** `app/starter.py` copies a shipped
|
||||
export bundle into each new guest account. The point is the first screen: real turns with
|
||||
their world-state chips, including a refused change and a milestone, before spending any
|
||||
of the daily demo turns. The row building inside `POST /adventures/import` moved to
|
||||
`bundle.materialize` so both callers share one writer.
|
||||
`bundle.materialize` so both callers share one writer. The copy is linked back to its
|
||||
demo scenario by title, because an adventure has no art of its own and a bundle cannot
|
||||
carry an id that means anything in another database.
|
||||
|
||||
**An SVG data URI is not usable as scenario art.** `app/images.py` accepts raster formats
|
||||
only, deliberately, because SVG can carry script and the bytes are served from the app's
|
||||
@@ -944,7 +953,7 @@ the SQLite dev parity this codebase protects on purpose).
|
||||
|
||||
```
|
||||
cd backend
|
||||
.venv/Scripts/python.exe -m pytest tests/ # 539 tests (~180s)
|
||||
.venv/Scripts/python.exe -m pytest tests/ # 549 tests (~180s)
|
||||
.venv/Scripts/python.exe -m tools.stress_session # egress report (SQLite)
|
||||
|
||||
# Same harness against a real Postgres. The target must be a THROWAWAY database
|
||||
|
||||
Reference in New Issue
Block a user