Make recipe repairs conditional and keep pasted links out of logs
CI / ci (push) Successful in 2m34s
CI / ci (pull_request) Successful in 2m30s

F1: A candidate or link repair now writes the dinner only if it is still
unarchived and as observed before grounding (normalized_name,
grounding_status, grounding_revision and recipe_id). A dinner renamed or
grounded some other way meanwhile is ErrGroundConflict (409
ground_conflict); one archived, before or during the repair, is
ErrArchived (409 dinner_archived). Manual repairs reject archived dinners
too.

F2: Any failure grounding a candidate or link by hand wraps
ErrGroundFailed, which the API logs as reason=ground_failed with the
dinner id only, never the pasted link or dependency error text.
GroundURL no longer formats the link into its error.

Maestro task 8741cedb-1849-4e3f-8d05-f5648c77c7ee.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-06 20:03:05 -04:00
co-authored by Claude Opus 5.5
parent cc7875c76c
commit 5c4c507ee6
9 changed files with 291 additions and 55 deletions
+19 -10
View File
@@ -84,19 +84,28 @@ RETURNING *;
-- name: GroundDinner :one
-- Records a dinner's grounding by hand (grounded or manual) and clears any
-- grounding_error and pasted recipe_url: the recipe chosen replaces the
-- link. An unknown id returns sql.ErrNoRows.
-- link. It writes only an unarchived dinner still as it was observed
-- before grounding (same normalized_name, grounding_status,
-- grounding_revision and recipe_id), so a dinner renamed, archived or
-- grounded some other way meanwhile is left as it is. That dinner, or an
-- unknown id, returns sql.ErrNoRows.
UPDATE dinners
SET recipe_id = ?,
SET recipe_id = sqlc.arg(recipe_id),
recipe_url = NULL,
photo_id = ?,
method = ?,
minutes_total = ?,
difficulty = ?,
grounding_status = ?,
photo_id = sqlc.arg(photo_id),
method = sqlc.arg(method),
minutes_total = sqlc.arg(minutes_total),
difficulty = sqlc.arg(difficulty),
grounding_status = sqlc.arg(grounding_status),
grounding_error = NULL,
updated_by = ?,
updated_at = ?
WHERE id = ?
updated_by = sqlc.arg(updated_by),
updated_at = sqlc.arg(updated_at)
WHERE id = sqlc.arg(id)
AND status <> 'archived'
AND normalized_name = sqlc.arg(observed_normalized_name)
AND grounding_status = sqlc.arg(observed_grounding_status)
AND grounding_revision = sqlc.arg(observed_grounding_revision)
AND recipe_id IS sqlc.narg(observed_recipe_id)
RETURNING *;
-- name: GroundPendingDinner :execrows