Make the vision preflight detect a camera-less image - #225
Merged
RobVanProd merged 1 commit intoAug 12, 2026
Conversation
The preflight reported `"ready": true` unconditionally. It never contacted the robot, so it could not distinguish a working setup from one that would never produce a detection, and `tools/start_local_vision.ps1` would happily launch a worker against firmware with the camera compiled out. That is F3's signature failure and why it stayed undiagnosed: the host polls forever and returns zero faces, which looks exactly like a detector that simply sees nobody. The reference robot has `compiled_enable_camera: 0` and `compiled_enable_camera_host_vision: 0`, and the old preflight still called it ready. Preflight now reads the unauthenticated /debug surface and refuses when either compiled flag is explicitly disabled, when the robot is unreachable, or when /debug is unparsable, reporting the distinguishing reason and exiting 2 so the launcher stops instead of starting a doomed worker. An absent flag is treated as unknown rather than disabled: /debug truncates by omitting fields, and reading omission as "camera off" would turn a large snapshot into a false negative. Verified against the live robot: preflight now returns `ready: false, reason: "firmware-camera-disabled: compiled_enable_camera,compiled_enable_camera_host_vision"` with exit 2, and start_local_vision.ps1 stops with "Local vision preflight failed with exit 2." It previously printed `preflight-ready` for that same robot. The pairing code is still never fetched into the payload; /debug needs no pairing, so the check adds no new secret handling. bridge/test_vision_service.py: 11/11. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The preflight could not fail
bridge/vision_service.py --preflightreported"ready": trueunconditionally. It never contactedthe robot, so it could not distinguish a working setup from one that would never produce a single
detection — and
tools/start_local_vision.ps1gates on that result, so it would happily launch aworker doomed to return nothing.
That is exactly F3's signature failure, and a large part of why it stayed undiagnosed. F3 reads
"the camera works and the robot is serving frames; the host has never returned a single detection."
A worker polling a camera-less image looks identical to a detector that simply sees nobody: zero
faces, no errors, forever.
The reference robot reports
compiled_enable_camera: 0andcompiled_enable_camera_host_vision: 0.The old preflight still called it ready.
Change
Preflight now reads the unauthenticated
/debugsurface and refuses when:firmware-camera-disabled: <flags>robot-unreachable: <error type>/debugis unparsable or not an objectIt reports the distinguishing reason and exits 2, so the launcher stops rather than starting a
worker that cannot work.
An absent flag is treated as unknown rather than disabled.
/debugtruncates by omitting fields(
debug_response_truncated: trueis observable on the live robot), so reading omission as "cameraoff" would turn a large snapshot into a false negative.
Verified against the live robot
Before — same robot, camera compiled out:
After:
and
tools/start_local_vision.ps1stops withLocal vision preflight failed with exit 2.Notes
/debugneeds no pairing code, and the pairing code is still neverfetched into the payload. The existing no-leak assertion is retained.
bridge/test_vision_service.py: 11/11, covering ready, camera-disabled, unreachable, and thetruncated-response case.
contract is replaced rather than worked around.
Pairs with #224, which supplies a camera profile that does not also switch motion on. Neither is
physical qualification of F3.