game kit: free a deposited trinket 7d after it goes in-use; retire COIN's room cooldown — TDD

A deposited trinket binds `Token.current_room` (the 'In-Use: <room>' Game Kit
label), set on deposit + cleared only on MANUAL return. Once a seat's token cost
lapsed (7d → GATE VIEW returns to prompt re-deposit) nothing freed the binding —
`cost_current` is a render-time prop, so no 7d mutation — leaving e.g. a CARTE
used a week prior stuck 'In-Use' (staging, 2026-06-08).

Fix — a uniform, type-agnostic in-use clock:
- New `Token.in_use_since`, stamped when `current_room` is set (`debit_token`
  COIN, `drop_token` CARTE). `release_lapsed_trinkets(tokens)` frees
  `current_room` + `in_use_since` + `slots_claimed` once held >= the room's
  `renewal_period` (7d). The SEAT is untouched — renewal grace (to 2xspan) +
  auto-BYE stay `_expire_lapsed_seats`'s job (a separate, later threshold).
- PASS/BAND never bind (reusable keys) -> no-op; COIN + CARTE covered by the one
  rule. Fires on the gameboard / `_game_kit_context` render (the gamer sees it
  freed immediately) + the cron backstop (`expire_lapsed_room_seats`).
- Migration 0018 backfills `in_use_since` from the earliest backing-slot
  `filled_at` so existing staging bindings release on accurate timing (old free
  on next sweep, recent keep grace) instead of every legacy NULL releasing early.

Retired COIN's bespoke ROOM cooldown: `debit_token` no longer sets
`next_ready_at` + `return_token` no longer clears it. `next_ready_at` is now
My-Sea-exclusive (the 24h DRAW cooldown, no room context) — the two clocks no
longer share a meaning + can't clash (user-spec 2026-06-08).

TDD: ReleaseLapsedTrinketsTest (6) + cron release + 2 gameboard-immediacy tests +
updated return/tooltip/bind assertions; 1124 lyric+epic+gameboard ITs green.

[[feedback-equip-slot-gates-trinket-use]] [[feedback-my-sea-cooldown-design]]

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Disco DeDisco
2026-06-08 16:35:35 -04:00
parent d50645b216
commit dcfa54f522
10 changed files with 264 additions and 10 deletions

View File

@@ -222,8 +222,7 @@ def debit_token(user, slot, token):
slot.debited_token_type = token.token_type
if token.token_type == Token.COIN:
token.current_room = slot.room
period = slot.room.renewal_period or timedelta(days=7)
token.next_ready_at = timezone.now() + period
token.in_use_since = timezone.now() # room in-use clock (7d release)
token.save()
# Parity w. CARTE's drop_token unequip: a deposited COIN is committed
# elsewhere & can't be re-used as the active trinket until the deposit