Repository navigation
Conversation
The tray only mirrored OpenAdapt Desktop, so a recording started with `openadapt-flow record` or `capture record` gave no cue in the menu bar. - Watch local Capture recorders through openadapt-capture's authenticated control client (discover_recorders/status_recording). "Recording" comes from the recorder's `ready` flag. The end comes from capture-state.json, and only a complete, verified session for that exact session counts as saved. - On macOS, Start Recording without Desktop runs `openadapt-flow record --backend macos`; Stop sends it Ctrl-C. A recording started elsewhere is stopped through its control channel. - Stop announcing "Capture saved" when a start never reached recording, and let Start work again after an error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
Why
The tray only mirrored OpenAdapt Desktop. Desktop has no signed build, so on a Mac without it, a recording started with
openadapt-flow recordgave no cue in the menu bar. The person teaching could not tell when the recorder was actually capturing.openadapt-flow recordprints "Perform your workflow on the target desktop now" before the recorder has started (packages/flow/openadapt_flow/desktop_record.py, theannounceblock runs beforewith factory(...), and the result ofwait_for_readyis ignored). So the terminal text is not a readiness signal.What changes
capture_watch.py: a polling watcher (0.5 s) over openadapt-capture's public client contract:discover_recorders()andstatus_recording(). Stages:starting→ready(only when the recorder reportsphase == "recording"andready: true) →stopping(stopping/finalizing) →ended. When the recorder's descriptor goes away, the outcome comes fromcapture-state.json. Only a file for that exact session that iscompleteandintegrity_verifiedcounts as saved. A missing or mismatched file is reported as "result could not be read", never as saved.local_record.py(macOS only): when Desktop is not reachable, Start Recording runsopenadapt-flow record --backend macos --out <captures_directory>/<name> --task <name>in its own session, with output going to<name>.record.log. Stop Recording sends SIGINT, the Ctrl-C the command documents. A recording started in a terminal is stopped throughstop_recording()on its control channel.app.py: the watcher drives the icon, tooltip and notifications only while Desktop is not connected, so Desktop's recordings are not shown twice. While the tray runs its ownopenadapt-flow record, it ignores other recorders. If flow exits non-zero after the capture was saved, the tray says the capture was saved but conversion failed, with the log path.can_start_recording()was IDLE-only, so after any ERROR, Start stayed disabled until the tray restarted. ERROR is terminal, so Start now works from it.watch_local_recorders(defaulttrue). README section "Recording without OpenAdapt Desktop". CAPABILITIES row.Evidence (one Mac, macOS 15, real recorder, real menu-bar icon)
Scratch env with this branch's
packages/capture,packages/flow[macos]andpackages/trayinstalled editable.Real tray app (pystray icon and real notifications), Desktop launch disabled, Start and Stop driven through
start_recording()/stop_recording(), window-scoped to Calculator:The recorder was ready 6.6 s after the command started. The conversion error is expected: no clicks were made, and flow refuses a capture with no actions.
Watcher alone vs. a terminal-style
openadapt-flow record:starting3.6 s →stopping34.5 s →ended failed (recording_failed). Neverreadyvideo_writerreadiness timeout at 30 s, the same failure seen in the sign-in spike--macos-app Finderstarting→ended failed (window_target_ambiguous)--macos-app Calculator --macos-window-title Calculatorstarting3.4 s →ready9.1 s → SIGINT →stopping→ended completephase: complete, complete: true, integrity_verified: trueIn the full-desktop case, flow had already told the person to perform the workflow, but the recorder never became ready. The tray stayed amber ("starting the recorder") and then showed the failure.
Tests:
uv run pytest -q→ 373 passed, 2 skipped.ruff check src testsis clean (the new files areruff formatclean; the package as a whole is not yet).Open questions
openadapt-flow[capture]still allows>=1.2.0, and an env with capture 1.2.2 silently gets no watcher (the tray prints one line at start). Should flow'scaptureextra require>=1.3.0? And should the tray get acaptureextra (openadapt-capture>=1.3.0)? I left both out to avoid a largeuv.lockchange in this PR.open -b ai.openadapt.desktoplaunched a local development build of Desktop. The tray prefers Desktop when it can launch it, so Start went to that build (which then failed on Input Monitoring) instead of toopenadapt-flow. Should the tray preferopenadapt-flowwhen Desktop isn't already running, or offer a setting?openadapt-flow recordfrom the tray. The control-channel stop finalizes the capture, but flow's_wait_for_stoponly returns on Ctrl-C or--until-cmd. So flow keeps waiting until Ctrl-C in its terminal, and only then converts. A small flow change (return when the recorder stops) would fix it. Follow-up PR?failed-finalization) was visible. The tray shows the first one it sees, or only its own while it runsopenadapt-flow record. Should test recorders use their ownOPENADAPT_CAPTURE_RUNTIME_DIRso they never reach a person's tray?sayon ready/stop (macOS), or is the icon plus notification enough?--linux-allow-physical-input. Worth doing, and how should the tray stop the recorder there (control channel plus the flow fix from question 3)?tray.json?Nothing is released. Releases go only through the reviewed workflow.
🤖 Generated with Claude Code