On Windows, cook shopping-list and cook doctor validate report the same broken recipe reference differently.
Given @./absent{} in a recipe:
cook doctor validate → ❌ Missing reference: ./absent
cook shopping-list … → Recipe not found: .\absent
On Unix both report absent / ./absent consistently.
Cause
doctor builds the reference path with an explicit forward slash (reference.path("/")), while the shopping-list expansion joins with std::path::MAIN_SEPARATOR_STR. On Windows that yields .\absent, and the ./-stripping in find::get_recipe only matches the forward-slash form — so the prefix survives into the reported name.
This contradicts an explicit contract in the code, which says the ./ "must not survive into the reported name, or the message names something the caller never asked for".
Scope
Cosmetic only. Resolution is unaffected — Utf8Path::join handles .\sauce natively on Windows — so only the text of the error message differs. The affected surfaces are the RecipeNotFound name, the reference name in errors, and the display path used for a referenced recipe's parse diagnostics.
Suggested direction
Join with a literal "/" in the shopping-list reference builders, matching what doctor already does. Windows accepts forward slashes in join, so resolution is unchanged.
Notes
Found while making cookcli-core's tests portable for the cross-platform CI matrix (#434) — these unit tests had never run on Windows before, because CI only recently began testing the whole workspace. Reported rather than fixed, since that branch is at its merge gate and a behaviour change there wants a deliberate decision.
On Windows,
cook shopping-listandcook doctor validatereport the same broken recipe reference differently.Given
@./absent{}in a recipe:On Unix both report
absent/./absentconsistently.Cause
doctorbuilds the reference path with an explicit forward slash (reference.path("/")), while the shopping-list expansion joins withstd::path::MAIN_SEPARATOR_STR. On Windows that yields.\absent, and the./-stripping infind::get_recipeonly matches the forward-slash form — so the prefix survives into the reported name.This contradicts an explicit contract in the code, which says the
./"must not survive into the reported name, or the message names something the caller never asked for".Scope
Cosmetic only. Resolution is unaffected —
Utf8Path::joinhandles.\saucenatively on Windows — so only the text of the error message differs. The affected surfaces are theRecipeNotFoundname, the reference name in errors, and the display path used for a referenced recipe's parse diagnostics.Suggested direction
Join with a literal
"/"in the shopping-list reference builders, matching whatdoctoralready does. Windows accepts forward slashes injoin, so resolution is unchanged.Notes
Found while making
cookcli-core's tests portable for the cross-platform CI matrix (#434) — these unit tests had never run on Windows before, because CI only recently began testing the whole workspace. Reported rather than fixed, since that branch is at its merge gate and a behaviour change there wants a deliberate decision.