Add Side quest suggestion batches, deck and Try it / Pass API
CI / ci (push) Successful in 2m52s
CI / ci (pull_request) Successful in 2m46s

POST /api/v1/suggestions/batches enqueues a suggestion_batch job that runs
suggest_side_quests through the harness, grounds the survivors with
recipes.Grounder.GroundMany (dropping those no recipe grounds) and stores
each as a dinner (status suggested, origin side_quest) with a pending
suggestion holding its reason and cited_regular_ids. Only one batch is
pending or running at a time; a POST while one is active returns it.

GET /api/v1/suggestions/deck lists pending suggestions oldest first with
the dinner's name, photo, difficulty and the reason. POST
/api/v1/suggestions/{id}/accept moves the dinner to the Quest log; /decline
records the Pass and archives the dinner, whose name every later batch
reads as declined. Both are idempotent and 409 on the opposite decision.
A decision leaving fewer than 5 in the deck starts a replenish batch
unless one is already pending or running. Batches left unfinished by a
restart are failed at boot so they never block the next.

Task: b4f2558c-227f-4627-852b-be5aa190242a

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-06 23:28:11 -04:00
co-authored by Claude Opus 5.5
parent 7d1e983fc8
commit 50399b6329
19 changed files with 2420 additions and 18 deletions
+1 -1
View File
@@ -45,7 +45,7 @@ func newOriginRouter(t *testing.T, logs io.Writer) http.Handler {
}
logger := slog.New(forwarded.LogHandler(slog.NewJSONHandler(logs, nil)))
r, err := NewRouter(logger, "dev", trusted, probeAuth{}, stubSessions{}, newTestSettings(t),
newTestSearch(t), newTestAI(t), newTestDinners(t), newTestRunner(t), newTestPhotos(t), fstest.MapFS{"index.html": {Data: []byte(fixtureIndex)}})
newTestSearch(t), newTestAI(t), newTestDinners(t), newTestSuggest(t), newTestRunner(t), newTestPhotos(t), fstest.MapFS{"index.html": {Data: []byte(fixtureIndex)}})
if err != nil {
t.Fatal(err)
}