Unresolved contradiction — needs an experiment, not a fix. Do not change the code until this is decided; the reading and the observed behaviour disagree.
The reading
RemoteCam/SessionCoordinator.swift:936
case is UICmd.VideoResourceTransferCompleted, is UICmd.VideoResourceTransferFailed:
ctrl?.cameraViewModel.finishVideoTransfer()
This shadows handleRoot:1058-1066 — the only code that emits StopRecordingVideoResp after a successful resource transfer:
case let completed as UICmd.VideoResourceTransferCompleted:
monitor?.videoTransferFinished()
if completed.success {
await sendOrGoToScanning(RemoteCmd.StopRecordingVideoResp(sender: nil, pic: nil, error: nil))
}
The camera can only leave .cameraTransmittingVideo via :939-945 (on StopRecordingVideoResp). On the send-video path the pipeline never produces one itself — RecordingPipeline.swift:185-190 only sends it in the else (don't-send-to-peer) branch; the send branch calls sendVideoAsResource. So by this reading the camera wedges after every send-video recording, in both directions, and the next StartRecordingVideo gets an error ack from handleRoot:1034-1035.
The contradiction
Recording twice in a row with the iPhone as camera reportedly works fine. The monitor hides a camera-side wedge because it rescues itself locally via didFinishReceivingResource (:2076-2096) — but the second recording should still fail, and it doesn't.
Most likely explanation: "send media to remote" is off, so RecordingPipeline.swift:189 answers directly and :936 is never exercised.
The deciding experiment
Coordinator test: seed .cameraTransmittingVideo, deliver UICmd.VideoResourceTransferCompleted(success: true), assert the camera sends RemoteCmd.StopRecordingVideoResp and returns to .camera.
- Fails → real bug;
:936 must fall through to handleRoot (or emit the response itself).
- Passes → the reading is wrong and the model needs revisiting.
Manual counterpart: enable "send media to remote", record → stop → record again.
Context: RemoteCamTests/RemoteCamSessionTests.swift already seeds .cameraTransmittingVideo for the keyframe tests, so the harness exists.
Unresolved contradiction — needs an experiment, not a fix. Do not change the code until this is decided; the reading and the observed behaviour disagree.
The reading
RemoteCam/SessionCoordinator.swift:936This shadows
handleRoot:1058-1066— the only code that emitsStopRecordingVideoRespafter a successful resource transfer:The camera can only leave
.cameraTransmittingVideovia:939-945(onStopRecordingVideoResp). On the send-video path the pipeline never produces one itself —RecordingPipeline.swift:185-190only sends it in theelse(don't-send-to-peer) branch; the send branch callssendVideoAsResource. So by this reading the camera wedges after every send-video recording, in both directions, and the nextStartRecordingVideogets an error ack fromhandleRoot:1034-1035.The contradiction
Recording twice in a row with the iPhone as camera reportedly works fine. The monitor hides a camera-side wedge because it rescues itself locally via
didFinishReceivingResource(:2076-2096) — but the second recording should still fail, and it doesn't.Most likely explanation: "send media to remote" is off, so
RecordingPipeline.swift:189answers directly and:936is never exercised.The deciding experiment
Coordinator test: seed
.cameraTransmittingVideo, deliverUICmd.VideoResourceTransferCompleted(success: true), assert the camera sendsRemoteCmd.StopRecordingVideoRespand returns to.camera.:936must fall through tohandleRoot(or emit the response itself).Manual counterpart: enable "send media to remote", record → stop → record again.
Context:
RemoteCamTests/RemoteCamSessionTests.swiftalready seeds.cameraTransmittingVideofor the keyframe tests, so the harness exists.