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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user