Secret Scan / scan (push) Successful in 11s
Build App (Preview) / compute-version (pull_request) Successful in 11s
Secret Scan / scan (pull_request) Successful in 8s
Build App (Preview) / create-release (pull_request) Successful in 8s
Build App (Preview) / build-macos (pull_request) Successful in 2m44s
Build App (Preview) / build-windows (pull_request) Successful in 5m35s
Build App (Preview) / build-linux (pull_request) Successful in 7m17s
Build App (Preview) / prune-previews (pull_request) Successful in 4s
Review of this branch found the first cut made every probe error fatal, including one that is usually irrelevant. `snapshot_exists` is consulted only when there is no container, or when a stopped container coincides with a busy project -- `pick_probe_source` discards it outright for a running one. So a daemon hiccup between the four sequential readings turned a full report into a bare "could not be checked" with Update disabled, in a change whose whole purpose is handling exactly that hiccup better. It is now carried as a `Result` to the points that consult it and surfaced only there. `stopped_probe_policy` carries its own message, because "try again once it finishes" claims waiting is the only obstacle, which a failed `image_exists` has not established. `base_image_id` stays fatal, deliberately: it is the right-hand side of the comparison, and `image_id` already distinguishes "not pulled locally" (`Ok(None)`, a legitimate not-stale) from "could not ask". Letting an `Err` through as `None` would report a project up to date on a reading nobody got -- #56 one field over. The message no longer blames the daemon. Three of the four callees can `Err` from a daemon that answered perfectly: `image_id` maps only 404 to `Ok(None)`, and the base image name is user-supplied, so a malformed reference told the user to go fix a daemon that was running fine. That is the same category of error as #56 itself. `ContainerState` makes "running is known but no container was found" unrepresentable rather than merely unreached, so the downstream match has no impossible arm and the invariant is enforced where it is established. Finally, the tests covered the new function but not the line the bug was on: a partial revert to `.unwrap_or(None)` kept them all green. The readings now travel as a named struct of `Result`s, so that revert is a compile error -- verified by performing it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>