Maestro task d076480c-6c59-4c57-9023-6941badb4520 — "Shopping API and item toggles" (Feature 17, task 2 of 7).
Done-condition
GET /api/v1/shopping/{weekStart} returns {weekStart, label, title, status, sent_to_chat_at, needed_count, total_count, groups:[{dinner {id, name}, day label, items:[{id, name, qty, needed}]}]} or 404. PATCH /api/v1/shopping/items/{id} {needed} updates the flag and returns new counts; it returns 409 when the list is archived. POST /api/v1/shopping/{weekStart}/generate (re)generates via the generator. Pushing a plan to Calendar calls generation for that week. API tests cover counts after toggles, 409 on archived, regeneration and the push hook.
Scope
The HTTP API, the item toggle and the push hook. No archive_title skill (fa4b94c9), no freeze/archive API (7ac36526), no UI.
Points for review
The push hook decision (the developer's, stated in NOTES): the hook runs in postPlanPush right after plan.Service.Push returns successfully — the seam Feature 16 left. If generation fails after the push, the push is not rolled back and the response stays 200 with supply_run: {status, error}, where status is generated, archived or failed (error code supply_run_failed, retryable: true, logged at ERROR), and nothing claims a list exists; Generate rolls its own transaction back and POST /generate retries. Generation runs with context.WithoutCancel so a client disconnect cannot cancel it. Judge that decision against the fail-fast/no-silent-fallback rules.
The response shape exactly as specified, including needed_count (items with needed=true) vs total_count (all), the group day label, and qty null when unknown. The developer added date beside the weekday day, and skipped on the generate response — say if either is out of scope or confusing.
PATCH validates the body, returns the new counts, 409 on an archived list (flag unchanged), 404 for an unknown item and 400 for a bad body.
POST /generate goes through the same Generate; 404 for a week with no plan and 409 for an archived list.
JSON naming consistency: the developer used weekStart because the done-condition writes it so (following the jobId precedent), while the plan API returns week_start. Judge whether that inconsistency is acceptable or worth flagging.
internal/server/plans.go changed (the push hook) and NewRouter gained a parameter with all test call sites updated: confirm no push behaviour regressed and no test was weakened.
New sqlc queries (ListShoppingGroupDinners, GetShoppingItemList, SetShoppingItemNeeded) committed and not hand-edited; no migration added.
Scope, test adequacy (the developer reports 7 mutations each caught), maintainability, error handling.
## Task
Maestro task `d076480c-6c59-4c57-9023-6941badb4520` — "Shopping API and item toggles" (Feature 17, task 2 of 7).
## Done-condition
`GET /api/v1/shopping/{weekStart}` returns `{weekStart, label, title, status, sent_to_chat_at, needed_count, total_count, groups:[{dinner {id, name}, day label, items:[{id, name, qty, needed}]}]}` or 404. `PATCH /api/v1/shopping/items/{id} {needed}` updates the flag and returns new counts; it returns 409 when the list is archived. `POST /api/v1/shopping/{weekStart}/generate` (re)generates via the generator. Pushing a plan to Calendar calls generation for that week. API tests cover counts after toggles, 409 on archived, regeneration and the push hook.
## Scope
The HTTP API, the item toggle and the push hook. No `archive_title` skill (`fa4b94c9`), no freeze/archive API (`7ac36526`), no UI.
## Points for review
- **The push hook decision** (the developer's, stated in NOTES): the hook runs in `postPlanPush` right after `plan.Service.Push` returns successfully — the seam Feature 16 left. If generation fails **after** the push, the push is not rolled back and the response stays 200 with `supply_run: {status, error}`, where status is `generated`, `archived` or `failed` (`error` code `supply_run_failed`, `retryable: true`, logged at ERROR), and nothing claims a list exists; `Generate` rolls its own transaction back and `POST /generate` retries. Generation runs with `context.WithoutCancel` so a client disconnect cannot cancel it. Judge that decision against the fail-fast/no-silent-fallback rules.
- The response shape exactly as specified, including `needed_count` (items with `needed=true`) vs `total_count` (all), the group day label, and `qty` null when unknown. The developer added `date` beside the weekday `day`, and `skipped` on the generate response — say if either is out of scope or confusing.
- `PATCH` validates the body, returns the **new** counts, 409 on an archived list (flag unchanged), 404 for an unknown item and 400 for a bad body.
- `POST /generate` goes through the same `Generate`; 404 for a week with no plan and 409 for an archived list.
- **JSON naming consistency:** the developer used `weekStart` because the done-condition writes it so (following the `jobId` precedent), while the plan API returns `week_start`. Judge whether that inconsistency is acceptable or worth flagging.
- `internal/server/plans.go` changed (the push hook) and `NewRouter` gained a parameter with all test call sites updated: confirm no push behaviour regressed and no test was weakened.
- New sqlc queries (`ListShoppingGroupDinners`, `GetShoppingItemList`, `SetShoppingItemNeeded`) committed and not hand-edited; no migration added.
- Scope, test adequacy (the developer reports 7 mutations each caught), maintainability, error handling.
## Evidence (orchestrator-run gate at 6aa511348818d0ad776819a02260df054624e7ba)
- `gofmt -l .` — empty; `go vet ./...` — clean
- `go test -race -count=1 ./...` — 27 packages ok, 0 failures (server 193.8s)
- `CGO_ENABLED=0 go build ./...` — ok
- `make sqlc-check SQLC=$(go env GOPATH)/bin/sqlc` — no drift
- `cd web && npm run typecheck && npm test && npm run build` — PASS (no web change)
Implementation commit: `6aa511348818d0ad776819a02260df054624e7ba`
GET /api/v1/shopping/{weekStart} reads the week's Supply run with its
week label, counts and groups by plan day; POST
/api/v1/shopping/{weekStart}/generate makes or remakes it through
shopping.Generate; PATCH /api/v1/shopping/items/{id} sets an item's
needed flag and answers with the list's new counts, 409 archived once
the list is in the Supply archive and 404 for an unknown item.
A successful Push to Calendar now makes the pushed week's Supply run.
Generation runs after the push is recorded and never fails or undoes
it: the 200 answer reports supply_run generated, archived or failed,
and a failure is logged as an error.
Maestro task d076480c-6c59-4c57-9023-6941badb4520.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A plan edit landing between a successful Push and the Generate that
followed it made the Supply run from the newer plan while the push answer
reported supply_run generated, so the list could hold a dinner Calendar
never showed (MQ-133-01).
Push now returns the revision it pushed, and the push hook calls
shopping.GeneratePushed, which checks inside its transaction that the
week's plan is still at that revision (week_plans.revision, as the draft
path does) and otherwise fails with ErrPlanChanged, leaving the Supply run
as it was. The push answer then reports supply_run failed with error
plan_changed (retryable: push again), logged as a warning.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Task
Maestro task
d076480c-6c59-4c57-9023-6941badb4520— "Shopping API and item toggles" (Feature 17, task 2 of 7).Done-condition
GET /api/v1/shopping/{weekStart}returns{weekStart, label, title, status, sent_to_chat_at, needed_count, total_count, groups:[{dinner {id, name}, day label, items:[{id, name, qty, needed}]}]}or 404.PATCH /api/v1/shopping/items/{id} {needed}updates the flag and returns new counts; it returns 409 when the list is archived.POST /api/v1/shopping/{weekStart}/generate(re)generates via the generator. Pushing a plan to Calendar calls generation for that week. API tests cover counts after toggles, 409 on archived, regeneration and the push hook.Scope
The HTTP API, the item toggle and the push hook. No
archive_titleskill (fa4b94c9), no freeze/archive API (7ac36526), no UI.Points for review
postPlanPushright afterplan.Service.Pushreturns successfully — the seam Feature 16 left. If generation fails after the push, the push is not rolled back and the response stays 200 withsupply_run: {status, error}, where status isgenerated,archivedorfailed(errorcodesupply_run_failed,retryable: true, logged at ERROR), and nothing claims a list exists;Generaterolls its own transaction back andPOST /generateretries. Generation runs withcontext.WithoutCancelso a client disconnect cannot cancel it. Judge that decision against the fail-fast/no-silent-fallback rules.needed_count(items withneeded=true) vstotal_count(all), the group day label, andqtynull when unknown. The developer addeddatebeside the weekdayday, andskippedon the generate response — say if either is out of scope or confusing.PATCHvalidates the body, returns the new counts, 409 on an archived list (flag unchanged), 404 for an unknown item and 400 for a bad body.POST /generategoes through the sameGenerate; 404 for a week with no plan and 409 for an archived list.weekStartbecause the done-condition writes it so (following thejobIdprecedent), while the plan API returnsweek_start. Judge whether that inconsistency is acceptable or worth flagging.internal/server/plans.gochanged (the push hook) andNewRoutergained a parameter with all test call sites updated: confirm no push behaviour regressed and no test was weakened.ListShoppingGroupDinners,GetShoppingItemList,SetShoppingItemNeeded) committed and not hand-edited; no migration added.Evidence (orchestrator-run gate at
6aa5113488)gofmt -l .— empty;go vet ./...— cleango test -race -count=1 ./...— 27 packages ok, 0 failures (server 193.8s)CGO_ENABLED=0 go build ./...— okmake sqlc-check SQLC=$(go env GOPATH)/bin/sqlc— no driftcd web && npm run typecheck && npm test && npm run build— PASS (no web change)Implementation commit:
6aa511348818d0ad776819a02260df054624e7baGET /api/v1/shopping/{weekStart} reads the week's Supply run with its week label, counts and groups by plan day; POST /api/v1/shopping/{weekStart}/generate makes or remakes it through shopping.Generate; PATCH /api/v1/shopping/items/{id} sets an item's needed flag and answers with the list's new counts, 409 archived once the list is in the Supply archive and 404 for an unknown item. A successful Push to Calendar now makes the pushed week's Supply run. Generation runs after the push is recorded and never fails or undoes it: the 200 answer reports supply_run generated, archived or failed, and a failure is logged as an error. Maestro task d076480c-6c59-4c57-9023-6941badb4520. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>Independent Codex gpt-6-sol review: APPROVED for this exact commit.
Independent Codex gpt-6-sol review: APPROVED for this exact commit.