Skip to content

Give host vision a profile that does not switch motion on - #224

Merged
RobVanProd merged 1 commit into
mainfrom
agent/vision-profile-motion-off
Aug 12, 2026
Merged

Give host vision a profile that does not switch motion on#224
RobVanProd merged 1 commit into
mainfrom
agent/vision-profile-motion-off

Conversation

@RobVanProd

Copy link
Copy Markdown
Owner

Why

F3 in docs/BRIDGE_AI_HANDOFF.md is that vision delivers nothing — camera_face_batches,
camera_faces_observed and camera_events all zero. That starves face-follow, active-speaker
selection, the FaceLost path, and all of Part 3, which is the half of the vision about noticing
people
.

Two things blocked it, and neither was the code F3 points at.

The installed candidate has no camera at all. It reports compiled_enable_camera: 0 and
compiled_enable_camera_host_vision: 0, so no host worker could ever have received a frame from it
regardless of host state.

The only camera profile also turned motion on. stackchan_camera_probe sets
STACKCHAN_MOTION_ENABLED_AT_BOOT=1 and STACKCHAN_AUTONOMOUS_MOTION_AT_BOOT=1, so the only way to
get eyes was to accept autonomous actuator motion at boot as a side effect. Presence detection should
not carry that price.

The profile

stackchan_release_forensics_vision takes the camera and the authenticated host-vision endpoints and
leaves the inherited motion-off-at-boot posture untouched — no build_unflags, no motion markers.
tools/test_release_boot_motion_contract.ps1 asserts that directly, including the absence of
build_unflags, so it cannot quietly acquire motion later.

STACKCHAN_CAMERA_CAPTURE_PROBE_ONLY is deliberately not set: serveCameraGrayFrame() captures on
demand per authenticated request, so the periodic capture probe is a separate diagnostic rather than a
prerequisite for host vision.

A security hole this would have opened

platformio_apply_wifi_bridge_env.py recognised paired-camera environments by the literal prefix
stackchan_camera_probe. A camera image built from the new profile would therefore not have
required STACKCHAN_PAIRING_SHORT_CODE, and would have served its camera endpoints unauthenticated.

Rather than add one more name and leave the same trap for whoever adds the next camera profile, the
contract now derives every camera environment from platformio.ini — following extends inheritance —
and requires each to refuse to build without a pairing code. Adding a camera environment without the
guard now fails the contract.

stackchan_release_full is excluded on purpose: it is the public secret-free image, embeds no pairing
code by design, and owners provision pairing after flash. Requiring one at build time would make the
public release unbuildable.

Verification

  • Release boot-motion contract: passes, including the new motion-off assertions.
  • PlatformIO Wi-Fi environment contract: 7/7, including the new derived camera-environment check.
  • Building the profile without a pairing code fails at configure time in
    platformio_apply_wifi_bridge_env.py:78, which is the guard doing its job.
  • Full compilation of this exact profile therefore needs a pairing code and is not demonstrated here.
    The identical camera flags do compile: stackchan_release_full carries
    STACKCHAN_ENABLE_CAMERA=1 and STACKCHAN_ENABLE_CAMERA_HOST_VISION=1 and builds clean.

Host side, for the record

The host half was also missing and is now in place: C:\stackchan_vision_venv did not exist, so no
vision worker could have run on this host whatever the firmware did. It now has the pinned
numpy==2.2.6 and opencv-python-headless==4.13.0.92 from bridge/requirements-vision.txt, and
test_vision_service passes 8/8 in it.

Not claimed

No physical qualification. The profile still needs a private per-device build, a flash, and advancing
authenticated frame and target counters on the robot before F3 can be called closed. Nothing in Part 3
can be qualified until they advance.

F3 in docs/BRIDGE_AI_HANDOFF.md is that vision delivers nothing: camera_face_batches,
camera_faces_observed and camera_events are all zero, which starves face-follow, active-speaker
selection, the FaceLost path, and everything in Part 3 that depends on noticing people.

Two things blocked it, and neither was the code F3 points at.

The installed release candidate reports compiled_enable_camera: 0 and
compiled_enable_camera_host_vision: 0, so no host worker could ever have received a frame from it.
The only camera-enabled profile was stackchan_camera_probe, which also sets
STACKCHAN_MOTION_ENABLED_AT_BOOT=1 and STACKCHAN_AUTONOMOUS_MOTION_AT_BOOT=1. Getting eyes therefore
meant accepting autonomous actuator motion at boot as a side effect, which is not a trade presence
detection should have to make.

stackchan_release_forensics_vision takes the camera and the authenticated host-vision endpoints and
leaves the inherited motion-off-at-boot posture untouched: no build_unflags, no motion markers. The
boot-motion contract now asserts that directly, including the absence of build_unflags, so the
profile cannot quietly acquire motion later.

STACKCHAN_CAMERA_CAPTURE_PROBE_ONLY is deliberately not set. serveCameraGrayFrame() captures on
demand per authenticated request, so the periodic capture probe is a separate diagnostic rather than
a prerequisite for host vision.

The pairing guard needed widening to match. platformio_apply_wifi_bridge_env.py recognised paired
camera environments by the literal prefix "stackchan_camera_probe", so a camera image built from the
new profile would not have required STACKCHAN_PAIRING_SHORT_CODE and would have served its camera
endpoints unauthenticated. Rather than add one more name and leave the same trap for the next
profile, the contract now derives every camera environment from platformio.ini, following extends
inheritance, and requires each to refuse to build without a pairing code.

stackchan_release_full is excluded from that requirement on purpose: it is the public secret-free
image, it embeds no pairing code by design, and owners provision pairing after flash.

Verified: release boot-motion contract passes, and the PlatformIO Wi-Fi environment contract passes
7/7 including the new derived camera-environment check.

Physical qualification of the profile is not claimed here. It still needs a private per-device build,
a flash, and advancing authenticated frame and target counters on the robot.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@RobVanProd
RobVanProd merged commit 174fd0a into main Aug 12, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant