Skip to content

fix(bin): preserve complete hold-to-speak recordings - #95

Merged
Amplify-Logic merged 1 commit into
mainfrom
fm/glasses-bridge-capture-truncation-c2
Aug 23, 2026
Merged

fix(bin): preserve complete hold-to-speak recordings#95
Amplify-Logic merged 1 commit into
mainfrom
fm/glasses-bridge-capture-truncation-c2

Conversation

@Amplify-Logic

Copy link
Copy Markdown
Owner

Intent

Fix the urgent field bug on the Starship bridge hold-to-speak control: the captain held the button and spoke full sentences, but the uploaded m4a files were 784 bytes and 11 KB (only the final instant of speech; transcripts "Bye." and "you"). A captain-side Sent must mean the entire press-to-release recording left the phone, not the last MediaRecorder chunk.

Required outcome:

  • Collect every dataavailable chunk into an array, build the blob in onstop after the last flush, then POST so the entire audio from press to release is one file.
  • Keep the PR feat: upgrade the captain bridge with photos and hold-to-speak #90 race protection: release during getUserMedia must still cancel cleanly with no infinite recording.
  • Client-side sanity guard: if the built blob is smaller than about 1KB per second held (with a floor), show the failure state instead of claiming Sent.
  • Server side: log received audio byte size per /speak request in the bridge log so field truncation is visible.
  • Tests: extend existing bridge tests for the upload path (full-blob assembly via unit-testable page JS; server-side size logging). Do not fake browser tests that prove nothing.
  • iPhone Safari is the only client that matters (audio/mp4). Do not restart or repoint launchd services.
  • Existing bridge behavior from feat: upgrade the captain bridge with photos and hold-to-speak #90/fix(bin): calm the phone glance with focused work groups #91 stays unchanged except this capture-integrity fix.

What Changed

  • Accumulate every iPhone Safari MediaRecorder timeslice and final flush into one audio file before uploading.
  • Reject undersized recordings client-side and log extracted audio byte counts for /speak requests.
  • Extend bridge tests and documentation for full-chunk assembly, truncation detection, and server-side size logging.

Risk Assessment

✅ Low: The change is well-bounded, satisfies the capture-integrity requirements, preserves the early-release race protection, and introduces no material issues found in review.

Testing

The full bridge suite passed, covering the #90 release-during-permission race, complete Safari m4a blob assembly, undersized-capture rejection, the real /speak forwarding path, and server byte-size logging. Focused evidence shows a 6,500-byte full capture reaching “Sent” while a 784-byte capture is rejected without POSTing. No screenshot was captured because meaningful verification requires iPhone Safari MediaRecorder events; a static rendered page would not demonstrate capture integrity.

Evidence: Capture-integrity end-user transcript

A 3-second press assembled all chunks into one 6,500-byte audio/mp4 upload and displayed “Sent”. An undersized 8-second capture displayed “Recording was too small to send.” and made no POST.

{
  "full_press_3s": {
    "listening": {
      "status": "Listening…",
      "button": "Release to send",
      "timeslice_ms": 1000
    },
    "final": {
      "status": "Sent",
      "state": "ok"
    },
    "final_flush_requested": true,
    "tracks_stopped": true,
    "posts": [
      {
        "field": "audio",
        "filename": "bridge.m4a",
        "bytes": 6500,
        "type": "audio/mp4"
      }
    ]
  },
  "truncated_press_8s": {
    "listening": {
      "status": "Listening…",
      "button": "Release to send",
      "timeslice_ms": 1000
    },
    "final": {
      "status": "Recording was too small to send.",
      "state": "warn"
    },
    "final_flush_requested": true,
    "tracks_stopped": true,
    "posts": []
  }
}

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • Inspected git diff --unified=80 3418df5656d8dc5a613319525b68a1a7e3cbf3c1..57edb04c3a54f1f29fde54c8f2ccf94a9ba11e7c against the authoritative intent
  • bash tests/fm-bridge-view.test.sh
  • Executed the actual PAGE_JS in a MediaRecorder harness simulating Safari timeslice chunks, final flush ordering, a valid 3-second capture, and a truncated 8-second capture; saved the resulting user-visible state and upload transcript
  • git status --short && git diff --exit-code
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

iPhone Safari flushes MediaRecorder in timeslice chunks and can fire
stop before the last flush, so a full sentence became a few hundred
bytes. Collect every chunk, assemble the file on stop, reject
undersized captures, and log received audio bytes.

Co-authored-by: Cursor <cursoragent@cursor.com>
@Amplify-Logic
Amplify-Logic merged commit 9344127 into main Aug 23, 2026
13 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