ideas_from_ingredients skill and job (Feature 18, task 1)
Maestro task c3c5f98e-7f7d-4c6b-a1ab-d45bb8e497f9. The first idea generator: the household lists what it has, the skill asks for 8 ideas and keeps at most 5, and every idea is grounded before the household sees it — no placeholder ideas, ever.
What the code guarantees, not the model: a "uses" entry survives only if its normalized form matches an ingredient the household actually listed, and the summary line ("Uses all 5 · missing: 1 lime" / "Uses 3 of 5 · missing: 1 lime, cumin" / "Uses all 5 · nothing missing") is computed from the corrected sets. Every idea is grounded through Feature 10's pipeline and ungroundable ideas are dropped. quick_only is decided after grounding from the grounded recipe's method (crockpot) or minutes_total ≤ 30 — the model's est_minutes plays no part.
POST /api/v1/ideas/from-ingredients {ingredients[], quick_only} returns 202 {jobId}; polling GET /api/v1/jobs/{id} yields {id, kind: "ideas_from_ingredients", status, result, error} with result.stage of suggesting|grounding|done and ideas carrying {name, uses[], missing[], summary, method, minutes_total, difficulty, quick, recipe_id, photo_url, source_url, site_name}. A test observes progressive publishes of 0, 0, 1, 2, 3, 4, 5 ideas, each already grounded; a failed job publishes no ideas, with ai_failed | search_not_configured | search_failed | internal_error. Ideas are not stored as dinners — the later actions task uses recipe_id.
Built on the Feature 09 harness (layered prompts, one repair turn, single-flight per scope, ai_runs logging); a new prompt template is registered with its checksum and goldens. NewRouter now takes a non-nil *ideas.Service, which touches 12 existing server test files mechanically.
Checks: the developer reports gofmt -l . empty, go vet ./... clean, go test -race -count=1 ./... all packages ok, CGO_ENABLED=0 go build ./... ok. The repository guide also requires the web floor for every change; the orchestrator runs it separately at this head.
## ideas_from_ingredients skill and job (Feature 18, task 1)
Maestro task `c3c5f98e-7f7d-4c6b-a1ab-d45bb8e497f9`. The first idea generator: the household lists what it has, the skill asks for 8 ideas and keeps at most 5, and every idea is grounded before the household sees it — no placeholder ideas, ever.
**What the code guarantees, not the model:** a "uses" entry survives only if its normalized form matches an ingredient the household actually listed, and the summary line ("Uses all 5 · missing: 1 lime" / "Uses 3 of 5 · missing: 1 lime, cumin" / "Uses all 5 · nothing missing") is computed from the corrected sets. Every idea is grounded through Feature 10's pipeline and ungroundable ideas are dropped. `quick_only` is decided after grounding from the **grounded recipe's** method (`crockpot`) or `minutes_total ≤ 30` — the model's `est_minutes` plays no part.
`POST /api/v1/ideas/from-ingredients {ingredients[], quick_only}` returns 202 `{jobId}`; polling `GET /api/v1/jobs/{id}` yields `{id, kind: "ideas_from_ingredients", status, result, error}` with `result.stage` of `suggesting|grounding|done` and ideas carrying `{name, uses[], missing[], summary, method, minutes_total, difficulty, quick, recipe_id, photo_url, source_url, site_name}`. A test observes progressive publishes of 0, 0, 1, 2, 3, 4, 5 ideas, each already grounded; a failed job publishes no ideas, with `ai_failed | search_not_configured | search_failed | internal_error`. Ideas are not stored as dinners — the later actions task uses `recipe_id`.
Built on the Feature 09 harness (layered prompts, one repair turn, single-flight per scope, `ai_runs` logging); a new prompt template is registered with its checksum and goldens. `NewRouter` now takes a non-nil `*ideas.Service`, which touches 12 existing server test files mechanically.
**Checks:** the developer reports `gofmt -l .` empty, `go vet ./...` clean, `go test -race -count=1 ./...` all packages ok, `CGO_ENABLED=0 go build ./...` ok. The repository guide also requires the web floor for every change; the orchestrator runs it separately at this head.
Implement the ideas_from_ingredients v1 skill on the AI harness: it asks
for 8 ideas {name, uses[], missing[], est_minutes, method, difficulty,
search_query}, keeps only "uses" entries whose harness.Normalize form is
one of the household's listed ingredients (written as the household wrote
them, in its order), drops ideas using none or repeating another, and
computes the summary line from the corrected lists.
Add internal/ideas: an ideas_from_ingredients job that grounds the ideas
with Grounder.GroundMany in the model's order until 5 are kept, drops the
ungroundable ones and, for quick_only, those whose grounded recipe is not
a Quick dinner (crockpot or minutes_total <= 30), publishing the result
as each idea is kept. POST /api/v1/ideas/from-ingredients answers 202
{jobId}.
Maestro task c3c5f98e-7f7d-4c6b-a1ab-d45bb8e497f9.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A run that keeps no idea fails with no_ideas_found instead of ending
done with an empty list.
- Before an ideas job fails it republishes its result with no ideas, so
GET /api/v1/jobs/{id} never shows ideas on a failed job, even ones a
previous grounding round already published.
- Each idea is published as soon as its grounding finishes, placed in the
model's order. recipes.GroundEach reports items as they finish;
GroundMany is rebuilt on it with unchanged semantics.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A failed ideas_from_ingredients job could still show ideas through
GET /api/v1/jobs/{id}: a job failed at boot as interrupted by restart
keeps its last partial result, and when the write clearing the ideas
itself failed the runner recorded internal_error over the uncleared
result. Neither path can be fixed by a write.
The jobs package gains an opt-in per-kind hook, Kind.FailedResult,
which Runner.Get applies to a failed job's stored result on every read.
The ideas kind registers withoutIdeas, which empties the ideas and keeps
the rest of the result. Kinds that do not call FailedResult are
unchanged. The write-side clear stays as a tidy-up of what is stored.
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.
ideas_from_ingredients skill and job (Feature 18, task 1)
Maestro task
c3c5f98e-7f7d-4c6b-a1ab-d45bb8e497f9. The first idea generator: the household lists what it has, the skill asks for 8 ideas and keeps at most 5, and every idea is grounded before the household sees it — no placeholder ideas, ever.What the code guarantees, not the model: a "uses" entry survives only if its normalized form matches an ingredient the household actually listed, and the summary line ("Uses all 5 · missing: 1 lime" / "Uses 3 of 5 · missing: 1 lime, cumin" / "Uses all 5 · nothing missing") is computed from the corrected sets. Every idea is grounded through Feature 10's pipeline and ungroundable ideas are dropped.
quick_onlyis decided after grounding from the grounded recipe's method (crockpot) orminutes_total ≤ 30— the model'sest_minutesplays no part.POST /api/v1/ideas/from-ingredients {ingredients[], quick_only}returns 202{jobId}; pollingGET /api/v1/jobs/{id}yields{id, kind: "ideas_from_ingredients", status, result, error}withresult.stageofsuggesting|grounding|doneand ideas carrying{name, uses[], missing[], summary, method, minutes_total, difficulty, quick, recipe_id, photo_url, source_url, site_name}. A test observes progressive publishes of 0, 0, 1, 2, 3, 4, 5 ideas, each already grounded; a failed job publishes no ideas, withai_failed | search_not_configured | search_failed | internal_error. Ideas are not stored as dinners — the later actions task usesrecipe_id.Built on the Feature 09 harness (layered prompts, one repair turn, single-flight per scope,
ai_runslogging); a new prompt template is registered with its checksum and goldens.NewRouternow takes a non-nil*ideas.Service, which touches 12 existing server test files mechanically.Checks: the developer reports
gofmt -l .empty,go vet ./...clean,go test -race -count=1 ./...all packages ok,CGO_ENABLED=0 go build ./...ok. The repository guide also requires the web floor for every change; the orchestrator runs it separately at this head.Implement the ideas_from_ingredients v1 skill on the AI harness: it asks for 8 ideas {name, uses[], missing[], est_minutes, method, difficulty, search_query}, keeps only "uses" entries whose harness.Normalize form is one of the household's listed ingredients (written as the household wrote them, in its order), drops ideas using none or repeating another, and computes the summary line from the corrected lists. Add internal/ideas: an ideas_from_ingredients job that grounds the ideas with Grounder.GroundMany in the model's order until 5 are kept, drops the ungroundable ones and, for quick_only, those whose grounded recipe is not a Quick dinner (crockpot or minutes_total <= 30), publishing the result as each idea is kept. POST /api/v1/ideas/from-ingredients answers 202 {jobId}. Maestro task c3c5f98e-7f7d-4c6b-a1ab-d45bb8e497f9. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>Independent Codex gpt-6-sol review: CHANGES_REQUIRED for this exact commit.
- A run that keeps no idea fails with no_ideas_found instead of ending done with an empty list. - Before an ideas job fails it republishes its result with no ideas, so GET /api/v1/jobs/{id} never shows ideas on a failed job, even ones a previous grounding round already published. - Each idea is published as soon as its grounding finishes, placed in the model's order. recipes.GroundEach reports items as they finish; GroundMany is rebuilt on it with unchanged semantics. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>Independent Codex gpt-6-sol review: CHANGES_REQUIRED for this exact commit.
A failed ideas_from_ingredients job could still show ideas through GET /api/v1/jobs/{id}: a job failed at boot as interrupted by restart keeps its last partial result, and when the write clearing the ideas itself failed the runner recorded internal_error over the uncleared result. Neither path can be fixed by a write. The jobs package gains an opt-in per-kind hook, Kind.FailedResult, which Runner.Get applies to a failed job's stored result on every read. The ideas kind registers withoutIdeas, which empties the ideas and keeps the rest of the result. Kinds that do not call FailedResult are unchanged. The write-side clear stays as a tidy-up of what is stored. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>Independent Codex gpt-6-sol review: APPROVED for this exact commit.