Maestro task: 9b4db226-9d8f-4251-a5de-adc45713c7bc (Feature 10 - Recipe Grounding and Photos).
Done-condition
internal/ai/skills implements normalize_recipe v1 (temperature 0): input title, raw ingredient lines, steps, JSON-LD times; output {ingredients:[{name,qty,unit,note}], method, difficulty, minutes_total}. Validators require exactly one output ingredient per input line, in order, non-empty name. Code-derived values win: minutes_total from JSON-LD when present; method crockpot on slow cooker/crock pot mentions; difficulty from step count and minutes when the model omits it. Golden Fake-provider tests: typical recipe, line-count mismatch repaired, slow-cooker forced to crockpot despite the model, JSON-LD minutes overriding the model. Go quality floor passes.
Evidence
New internal/ai/skills normalize_recipe + prompt template (checksum test passes); docs updated.
gofmt/vet/go test -race/build pass; no new dependency.
First concrete skill on the merged Feature 09 harness.
Maestro task: 9b4db226-9d8f-4251-a5de-adc45713c7bc (Feature 10 - Recipe Grounding and Photos).
## Done-condition
internal/ai/skills implements normalize_recipe v1 (temperature 0): input title, raw ingredient lines, steps, JSON-LD times; output {ingredients:[{name,qty,unit,note}], method, difficulty, minutes_total}. Validators require exactly one output ingredient per input line, in order, non-empty name. Code-derived values win: minutes_total from JSON-LD when present; method crockpot on slow cooker/crock pot mentions; difficulty from step count and minutes when the model omits it. Golden Fake-provider tests: typical recipe, line-count mismatch repaired, slow-cooker forced to crockpot despite the model, JSON-LD minutes overriding the model. Go quality floor passes.
## Evidence
- New internal/ai/skills normalize_recipe + prompt template (checksum test passes); docs updated.
- gofmt/vet/go test -race/build pass; no new dependency.
- First concrete skill on the merged Feature 09 harness.
normalize_recipe v1 turns a recipe page's title, raw ingredient lines,
steps and JSON-LD times into {ingredients: [{name, qty, unit, note}],
method, difficulty, minutes_total}. skills.NormalizeRecipe always runs it
at temperature 0. Validation requires one named ingredient per input line,
in order, so a mismatch gets the harness's repair turn. Code-derived
values win over the model's: JSON-LD total minutes, crockpot for a slow
cooker or crock pot mention, and a derived difficulty when the model gives
none. Golden tests with the Fake provider cover a typical recipe, a
repaired line-count mismatch, a slow-cooker recipe forced to crockpot and
JSON-LD minutes overriding the model.
Maestro task 9b4db226-9d8f-4251-a5de-adc45713c7bc
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Address review findings on the normalize_recipe skill:
- Ingredient order: an ingredient is out of order when its name has more
of its words in another line than in its own, not merely when it
shares no word with its own line. Swapping "olive oil" and
"sesame oil" now fails validation and triggers the repair turn.
- Required fields: Ingredient and NormalizedRecipe decode through
UnmarshalJSON that requires every schema field and rejects unknown
ones; qty, unit and note may not be omitted or null. Such a reply
fails to decode and triggers the repair turn.
- Zero total: a present JSON-LD TotalMinutes that is not positive is
rejected by PromptInput before any model call, instead of falling
back to the model's minutes.
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.
Maestro task: 9b4db226-9d8f-4251-a5de-adc45713c7bc (Feature 10 - Recipe Grounding and Photos).
Done-condition
internal/ai/skills implements normalize_recipe v1 (temperature 0): input title, raw ingredient lines, steps, JSON-LD times; output {ingredients:[{name,qty,unit,note}], method, difficulty, minutes_total}. Validators require exactly one output ingredient per input line, in order, non-empty name. Code-derived values win: minutes_total from JSON-LD when present; method crockpot on slow cooker/crock pot mentions; difficulty from step count and minutes when the model omits it. Golden Fake-provider tests: typical recipe, line-count mismatch repaired, slow-cooker forced to crockpot despite the model, JSON-LD minutes overriding the model. Go quality floor passes.
Evidence
normalize_recipe v1 turns a recipe page's title, raw ingredient lines, steps and JSON-LD times into {ingredients: [{name, qty, unit, note}], method, difficulty, minutes_total}. skills.NormalizeRecipe always runs it at temperature 0. Validation requires one named ingredient per input line, in order, so a mismatch gets the harness's repair turn. Code-derived values win over the model's: JSON-LD total minutes, crockpot for a slow cooker or crock pot mention, and a derived difficulty when the model gives none. Golden tests with the Fake provider cover a typical recipe, a repaired line-count mismatch, a slow-cooker recipe forced to crockpot and JSON-LD minutes overriding the model. Maestro task 9b4db226-9d8f-4251-a5de-adc45713c7bc Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>Independent Codex gpt-6-sol review: CHANGES_REQUIRED for this exact commit.
Independent Codex gpt-6-sol review: APPROVED for this exact commit.