feat(webapp): copies of a creature on the shelf, "Add another" (#1321) #1323

Merged
claude-bot merged 7 commits from feat/1321-shelf-copies into main 2026-11-03 02:25:19 +00:00
Collaborator

Closes #1321 (D318, the owner's answer to Q209).

Server

  • Migration d1321c0e5a7b, which revises b1242c0d1e2f:
    • adds shelf_cards.copy_number, backfilled to 1;
    • the unique index becomes (session_id, reference_entry_id, copy_number);
    • the downgrade deletes copies above 1 and restores the old index, and its docstring says so.
  • POST /api/sessions/{id}/shelf with "another": true creates the next copy. Its number is the highest so far, removed copies included, plus 1. Without another, the request behaves as today.
  • Every card carries copy_number. Rule cards also carry copies, the count of live copies.
  • Carry-forward and by_rule use the lowest copy number, removed copies included. A pin carries one card forward, and copies stay with their session.
  • Stored titles are unchanged. The bot is unaffected, so the contract isn't bumped.

Screen

  • displayTitle reads "Goblin 2" for copy 2 and up. It flows to the table, the shelf lists, Find, reveal and the phone. The shown strip now uses it too.
  • Preview keeps the "On the shelf" chip and adds "Add another" (aria-label "Add another
Closes #1321 (D318, the owner's answer to Q209). **Server** - Migration `d1321c0e5a7b`, which revises `b1242c0d1e2f`: - adds `shelf_cards.copy_number`, backfilled to 1; - the unique index becomes `(session_id, reference_entry_id, copy_number)`; - the downgrade deletes copies above 1 and restores the old index, and its docstring says so. - `POST /api/sessions/{id}/shelf` with `"another": true` creates the next copy. Its number is the highest so far, removed copies included, plus 1. Without `another`, the request behaves as today. - Every card carries `copy_number`. Rule cards also carry `copies`, the count of live copies. - Carry-forward and `by_rule` use the lowest copy number, removed copies included. A pin carries one card forward, and copies stay with their session. - Stored titles are unchanged. The bot is unaffected, so the contract isn't bumped. **Screen** - `displayTitle` reads "Goblin 2" for copy 2 and up. It flows to the table, the shelf lists, Find, reveal and the phone. The shown strip now uses it too. - Preview keeps the "On the shelf" chip and adds **"Add another"** (`aria-label` "Add another <title>"). A polite status line announces "<title> <n> added to the shelf." **Checked** - Backend: - lint and checks are clean; - a targeted run of shelf, table, prep and planning tests gave 409 passed and 1 failed, a case-sensitive docstring check in the new tests that was then fixed. The 15 new tests then passed alone; - alembic upgrade, downgrade and upgrade all run clean; - the full suite didn't finish on the loaded host. - Frontend: - lint has 0 errors; - `src/pages/table` and `src/pages/prep`: 19 files passed, on a re-run with a 60-second timeout because the host was loaded; - the whole suite wasn't completed. - **Not yet:** CI and the render check, which is running. **Not covered, as today:** - exporting and re-importing a campaign doesn't keep copies; - copying a shelf from another session carries one card per creature. Wording for review: "Add another", and "<title> <n> added to the shelf." 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Merge branch 'feat/1321-fe' into feat/1321-shelf-copies
All checks were successful
CI / Backend lint (ruff) (pull_request) Successful in 36s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m13s
CI / Bot/backend version sync (pull_request) Successful in 26s
CI / Feedback site tests (pull_request) Successful in 59s
CI / Does this change touch the recording path? (pull_request) Successful in 17s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Which journeys does this change need? (pull_request) Successful in 22s
CI / Bot tests and audit (pull_request) Successful in 2m25s
CI / Docker image build (pull_request) Successful in 4m58s
CI / Frontend (shard 2/2) (pull_request) Successful in 15m41s
CI / Frontend (shard 1/2) (pull_request) Successful in 19m28s
CI / End-to-end journeys (desktop) (pull_request) Successful in 24m53s
CI / Backend migration, tests, and audit (pull_request) Successful in 1h12m8s
265baba486
Author
Collaborator

Render check: the built stack, dark theme, 1280×800, signed in as dana. The migration ran up to d1321c0e5a7b on a fresh stack.

  • "Add to the shelf" became "On the shelf" with "Add another" beside it.
  • Two presses of "Add another" made "Goblin Warrior 2" and "Goblin Warrior 3". The POSTs returned copy_number 1, 2, 3 and copies 1, 2, 3.
  • Lowering HP on card 2 left cards 1 and 3 at 6/6.
  • Showing card 3 read "Show Goblin Warrior 3 to the table" in the dialog, on the shown strip and in the spotlight.
  • Find lists all three cards under "On the shelf".
  • axe found no violations, and the console had 0 errors.

Two things the check saw that this PR didn't cause:

  • A rules card with no player text can't be shown (422). The dialog already warns "Nothing here for the players yet".
  • A creature card shows its HP row only after its HP has changed.

Wording r-001 to r-003 is approved on the Wording Review page. This PR is set to merge when CI passes.

**Render check:** the built stack, dark theme, 1280×800, signed in as dana. The migration ran up to `d1321c0e5a7b` on a fresh stack. - "Add to the shelf" became "On the shelf" with "Add another" beside it. - Two presses of "Add another" made "Goblin Warrior 2" and "Goblin Warrior 3". The POSTs returned `copy_number` 1, 2, 3 and `copies` 1, 2, 3. - Lowering HP on card 2 left cards 1 and 3 at 6/6. - Showing card 3 read "Show Goblin Warrior 3 to the table" in the dialog, on the shown strip and in the spotlight. - Find lists all three cards under "On the shelf". - axe found no violations, and the console had 0 errors. **Two things the check saw that this PR didn't cause:** - A rules card with no player text can't be shown (422). The dialog already warns "Nothing here for the players yet". - A creature card shows its HP row only after its HP has changed. Wording r-001 to r-003 is approved on the Wording Review page. This PR is set to merge when CI passes.
Merge remote-tracking branch 'origin/main' into feat/1321-shelf-copies
All checks were successful
CI / Bot/backend version sync (pull_request) Successful in 34s
CI / Backend lint (ruff) (pull_request) Successful in 41s
CI / Feedback site tests (pull_request) Successful in 58s
CI / Does this change touch the recording path? (pull_request) Successful in 20s
CI / Synthetic session harness (no GPU, no LLM) (pull_request) Has been skipped
CI / Which journeys does this change need? (pull_request) Successful in 20s
CI / Summarisation accuracy eval harness (stub provider) (pull_request) Successful in 1m58s
CI / Bot tests and audit (pull_request) Successful in 4m6s
CI / Docker image build (pull_request) Successful in 5m28s
CI / Frontend (shard 2/2) (pull_request) Successful in 9m36s
CI / Frontend (shard 1/2) (pull_request) Successful in 11m14s
CI / End-to-end journeys (desktop) (pull_request) Successful in 13m11s
CI / Backend migration, tests, and audit (pull_request) Successful in 57m9s
43aa6d24c2
Sign in to join this conversation.
No description provided.