Surface replenish failures, follow the active batch, scope deck keys, keep three deck depths
CI / ci (push) Successful in 3m2s
CI / ci (pull_request) Successful in 2m44s

Fixes the Feature 13 review findings on the Discover deck (Maestro task
4fc551f0-3c11-4c15-b638-f2c08a28eb29):

- F13-01: a batch failure (start, poll or job) is shown with its Retry
  whatever the deck has, so a replenish that fails while cards remain is
  no longer silent until the deck runs out.
- F13-02: GET /api/v1/suggestions/deck reports the batch pending or
  running (active_batch, read in the deck's snapshot), and a decision
  that calls for a replenish returns the job of the batch it started or
  joined. The page follows a newly reported active batch, so a reopened
  page or a second session shows skeleton cards while the batch runs
  instead of "All caught up".
- F13-03: ← / → leave the deck alone while it is inert behind a modal
  (the Quest log sheet or its confirmation).
- F13-04: a one- or two-card deck keeps all three depths: skeleton cards
  stand in for the missing ones while a batch finds more Side quests,
  blank stack-edge cards while none is coming.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 05:04:20 -04:00
co-authored by Claude Opus 5.5
parent 4d9d8afd8d
commit af58caac94
10 changed files with 424 additions and 89 deletions
+8 -6
View File
@@ -310,9 +310,11 @@ automatic** (D-021).
block the next.
`GET /api/v1/suggestions/deck` returns `{suggestions: [{id, dinner_id,
name, photo_url, difficulty, method, minutes_total, cuisine, reason,
cited_regular_ids, status, dinner_status, decided_at, created_at}]}`:
the `pending` suggestions whose dinner is still `suggested`, oldest
first. `POST /api/v1/suggestions/{id}/accept` (Try it) sets the
cited_regular_ids, status, dinner_status, decided_at, created_at}],
active_batch}`: the `pending` suggestions whose dinner is still
`suggested`, oldest first, and the batch `pending` or `running`
(`{batch_id, job_id, trigger, status}`, or null), read in one snapshot,
so a client that did not start the batch can follow its job. `POST /api/v1/suggestions/{id}/accept` (Try it) sets the
suggestion `accepted` and moves its dinner to `quest_log`; `POST
/api/v1/suggestions/{id}/decline` (Pass) sets it `declined` and archives
the dinner; every later batch, and the household context's passed list,
@@ -323,9 +325,9 @@ automatic** (D-021).
and answers 200; the opposite decision is 409 `suggestion_decided`, a
suggestion whose dinner left the deck some other way 409
`dinner_not_suggested`, and an unknown id 404. A decision that leaves
fewer than 5 in the deck starts a `replenish` batch, whose job id it
returns, unless a batch is already pending or running
(`replenish_job_id` is then null). The batch and its job are written in
fewer than 5 in the deck starts a `replenish` batch, or joins the batch
already pending or running, and returns that batch's job id either way
(`replenish_job_id` is null when the deck keeps 5 or more). The batch and its job are written in
the decision's own transaction, so a decision is never recorded without
the replenish it calls for; when they cannot be written, neither is the
decision, and a retry decides again.