Background grounding and recipe fix-up API #90

Member

Maestro task: 0cbaa5bf-8be4-4cbd-aab2-891e7f1bc2b5 (Feature 12 - Regular Dinners and Onboarding).

Done-condition

Creating a Regular enqueues a grounding job that runs the Feature 10 pipeline and sets grounding_status grounded (recipe, photo, method, minutes, difficulty attached) or failed with a reason; creation by recipe_url grounds that URL directly. GET /api/v1/dinners/{id}/recipe-candidates returns up to 3 candidates {candidate_id, title, site_name, photo_url, minutes}; POST /api/v1/dinners/{id}/ground accepts {candidate_id} | {recipe_url} | {manual: {ingredients[], steps[], minutes, method}} and sets grounded or manual accordingly. Tests with fake search/fetch/LLM cover successful background grounding, failure -> failed, fixing via candidate, via pasted URL and via manual entry, and that POST /dinners returns before grounding completes. Go quality floor passes.

Evidence

  • New async grounding job on dinner create (POST returns before grounding), direct GroundURL for recipe_url creates, recipe-candidates (up to 3, ranked) and the ground endpoint (candidate/URL/manual). New migration 0009; sqlc regenerated; the store's pinned migration list updated.
  • gofmt/vet/build/go test -race pass; make sqlc-check no drift.
  • Tests cover successful background grounding, failure -> failed, fix by candidate/URL/manual, a manual fix kept while a job is running, candidate capping/ranking, and validation/404/422.

Self-review fixes: 422 responses no longer echo internal/provider error text (fixed message + test); the background job logs only the reason code. Known small gap: if enqueuing the job fails after the dinner is saved, the dinner is marked failed but the API returns 500 without the dinner id.

Maestro task: 0cbaa5bf-8be4-4cbd-aab2-891e7f1bc2b5 (Feature 12 - Regular Dinners and Onboarding). ## Done-condition Creating a Regular enqueues a grounding job that runs the Feature 10 pipeline and sets grounding_status grounded (recipe, photo, method, minutes, difficulty attached) or failed with a reason; creation by recipe_url grounds that URL directly. GET /api/v1/dinners/{id}/recipe-candidates returns up to 3 candidates {candidate_id, title, site_name, photo_url, minutes}; POST /api/v1/dinners/{id}/ground accepts {candidate_id} | {recipe_url} | {manual: {ingredients[], steps[], minutes, method}} and sets grounded or manual accordingly. Tests with fake search/fetch/LLM cover successful background grounding, failure -> failed, fixing via candidate, via pasted URL and via manual entry, and that POST /dinners returns before grounding completes. Go quality floor passes. ## Evidence - New async grounding job on dinner create (POST returns before grounding), direct GroundURL for recipe_url creates, recipe-candidates (up to 3, ranked) and the ground endpoint (candidate/URL/manual). New migration 0009; sqlc regenerated; the store's pinned migration list updated. - gofmt/vet/build/go test -race pass; make sqlc-check no drift. - Tests cover successful background grounding, failure -> failed, fix by candidate/URL/manual, a manual fix kept while a job is running, candidate capping/ranking, and validation/404/422. Self-review fixes: 422 responses no longer echo internal/provider error text (fixed message + test); the background job logs only the reason code. Known small gap: if enqueuing the job fails after the dinner is saved, the dinner is marked failed but the API returns 500 without the dinner id.
dev_agent added 1 commit 2026-10-06 16:19:42 -04:00
Ground new Regulars in the background and add recipe fix-up API
CI / ci (push) Successful in 2m37s
CI / ci (pull_request) Successful in 2m18s
d6d82e8368
Creating a Regular now enqueues a ground_dinner job and returns at once
with its grounding_job_id. The job grounds the dinner's recipe_url with
GroundURL, else its name with Ground, and sets grounding_status grounded
(recipe, photo, method, minutes, difficulty) or failed with a
grounding_error reason code (migration 0009). It writes only a dinner
still pending, so a fix made meanwhile wins.

GET /api/v1/dinners/{id}/recipe-candidates returns up to 3 ranked
candidates {candidate_id, title, site_name, photo_url, minutes} without
downloading photos or running the model. POST /api/v1/dinners/{id}/ground
takes exactly one of {candidate_id}, {recipe_url} or {manual: {...}} and
sets grounded or manual.

PhotoCache takes an ImageFetcher interface and recipestest provides fakes
so other packages can test grounding with fake search, fetch and model.
main wires the Grounder with normalize_recipe over the AI settings.

Maestro task: 0cbaa5bf-8be4-4cbd-aab2-891e7f1bc2b5

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
overseer added 1 commit 2026-10-06 16:19:42 -04:00
Ground new Regulars in the background and add recipe fix-up API
CI / ci (push) Successful in 2m37s
CI / ci (pull_request) Successful in 2m18s
d6d82e8368
Creating a Regular now enqueues a ground_dinner job and returns at once
with its grounding_job_id. The job grounds the dinner's recipe_url with
GroundURL, else its name with Ground, and sets grounding_status grounded
(recipe, photo, method, minutes, difficulty) or failed with a
grounding_error reason code (migration 0009). It writes only a dinner
still pending, so a fix made meanwhile wins.

GET /api/v1/dinners/{id}/recipe-candidates returns up to 3 ranked
candidates {candidate_id, title, site_name, photo_url, minutes} without
downloading photos or running the model. POST /api/v1/dinners/{id}/ground
takes exactly one of {candidate_id}, {recipe_url} or {manual: {...}} and
sets grounded or manual.

PhotoCache takes an ImageFetcher interface and recipestest provides fakes
so other packages can test grounding with fake search, fetch and model.
main wires the Grounder with normalize_recipe over the AI settings.

Maestro task: 0cbaa5bf-8be4-4cbd-aab2-891e7f1bc2b5

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
review_agent requested changes 2026-10-06 16:23:11 -04:00
Dismissed
review_agent left a comment
Member

Independent Codex gpt-6-sol review: CHANGES_REQUIRED for this exact commit.

Independent Codex gpt-6-sol review: CHANGES_REQUIRED for this exact commit.
overseer added 1 commit 2026-10-06 16:32:43 -04:00
Fail interrupted groundings at boot and bound hand grounding
CI / ci (push) Successful in 2m25s
CI / ci (pull_request) Successful in 2m20s
f4bed5d82d
At boot, after the job runner fails the jobs a previous process left
running, FailInterruptedGroundings sets every dinner still pending with
no ground_dinner job queued or running to failed (interrupted). A crash
mid-job, or between saving a dinner and enqueuing its job, no longer
leaves the dinner pending forever.

A search failure on recipe-candidates or ground now logs only the reason
code search_failed, never the wrapped error, which may quote the
provider; the response stays redacted.

When the grounding job cannot be enqueued, POST /dinners answers 201
with the saved dinner failed (grounding_error) and grounding_job_id
null, instead of a 500 that hid the dinner it had created.

Grounding a candidate or link by hand runs under a 90-second deadline
(fetch, photo, normalize_recipe); past it the request answers 504
ground_timeout and the dinner is unchanged.

Maestro task: 0cbaa5bf-8be4-4cbd-aab2-891e7f1bc2b5

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
review_agent left a comment
Member

Independent Codex gpt-6-sol review: APPROVED for this exact commit.

Independent Codex gpt-6-sol review: APPROVED for this exact commit.
approver_agent merged commit 423b898f54 into feature/2066f34b-5804-410a-859b-f87021a8ae6c-regular-dinners-onboarding 2026-10-06 16:39:11 -04:00
Sign in to join this conversation.
No Reviewers
No labels
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Maniacs_Mansion/MealQuest#90