Skip to content

Commit 44a82ba

Browse files
author
semantic-release
committed
chore: release 0.3.0
1 parent 11eafca commit 44a82ba

1 file changed

Lines changed: 259 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,265 @@
11
# CHANGELOG
22

33

4+
## v0.3.0 (2026-02-18)
5+
6+
### Bug Fixes
7+
8+
- Resolve all ruff lint errors ([#7](https://github.com/OpenAdaptAI/openadapt-capture/pull/7),
9+
[`de00dab`](https://github.com/OpenAdaptAI/openadapt-capture/commit/de00dab66724eb786dafb80ddfc860c51be13877))
10+
11+
* fix: resolve all ruff lint errors
12+
13+
- Remove unused variable assignments (share.py, browser_bridge.py, windows.py, test_highlevel.py) -
14+
Add noqa comment for Quartz import needed by ApplicationServices (darwin.py) - Remove unused
15+
TYPE_CHECKING import (storage/__init__.py) - Add proper TYPE_CHECKING import for CaptureStats
16+
annotation (generate_real_capture_plot.py) - Auto-fix import sorting across multiple files
17+
18+
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
19+
20+
* docs: update README with share command and ecosystem links
21+
22+
- Uncomment PyPI badges (package now published as 0.3.0) - Add "Sharing Recordings" section with
23+
Magic Wormhole usage - Update openadapt-privacy from "Coming soon" to GitHub link - Add share
24+
extra to optional extras table - Add openadapt-privacy and openadapt-evals to Related Projects
25+
26+
* docs: remove redundant openadapt-ml training section
27+
28+
The detailed training workflow belongs in openadapt-ml's README. This keeps openadapt-capture
29+
focused on its core functionality. Users can find training info via the Related Projects link.
30+
31+
---------
32+
33+
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
34+
35+
- Throttle screen capture to reduce system lag during recording
36+
([#11](https://github.com/OpenAdaptAI/openadapt-capture/pull/11),
37+
[`d7134a8`](https://github.com/OpenAdaptAI/openadapt-capture/commit/d7134a83921a551cd8e91ae127f63f0759a146fe))
38+
39+
The screen reader thread was capturing screenshots in a tight loop with no frame rate limit, causing
40+
high CPU and memory pressure. With action-gated video, only the most recent screenshot matters
41+
when an action occurs, so capturing at 100+ fps was pure waste.
42+
43+
Add SCREEN_CAPTURE_FPS config (default: 10 fps). The throttle sleeps for the remainder of the frame
44+
interval after each capture. Set to 0 for unlimited (legacy behavior). Also available as
45+
screen_capture_fps param on Recorder constructor and RecordingConfig.
46+
47+
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
48+
49+
- **ci**: Fix release automation — use ADMIN_TOKEN for protected branches
50+
([#8](https://github.com/OpenAdaptAI/openadapt-capture/pull/8),
51+
[`4205cd5`](https://github.com/OpenAdaptAI/openadapt-capture/commit/4205cd5d2c6fd86eff4fd1e3bcd93a59aae03416))
52+
53+
* fix: resolve all ruff lint errors
54+
55+
- Remove unused variable assignments (share.py, browser_bridge.py, windows.py, test_highlevel.py) -
56+
Add noqa comment for Quartz import needed by ApplicationServices (darwin.py) - Remove unused
57+
TYPE_CHECKING import (storage/__init__.py) - Add proper TYPE_CHECKING import for CaptureStats
58+
annotation (generate_real_capture_plot.py) - Auto-fix import sorting across multiple files
59+
60+
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
61+
62+
* docs: update README with share command and ecosystem links
63+
64+
- Uncomment PyPI badges (package now published as 0.3.0) - Add "Sharing Recordings" section with
65+
Magic Wormhole usage - Update openadapt-privacy from "Coming soon" to GitHub link - Add share
66+
extra to optional extras table - Add openadapt-privacy and openadapt-evals to Related Projects
67+
68+
* docs: remove redundant openadapt-ml training section
69+
70+
The detailed training workflow belongs in openadapt-ml's README. This keeps openadapt-capture
71+
focused on its core functionality. Users can find training info via the Related Projects link.
72+
73+
* fix(ci): fix release automation — use ADMIN_TOKEN to push to protected branches
74+
75+
Root cause: GITHUB_TOKEN cannot push commits to protected branches. Semantic-release created the
76+
v0.3.0 tag (tags bypass protection) but the "chore: release 0.3.0" commit that bumps
77+
pyproject.toml was orphaned.
78+
79+
- Use ADMIN_TOKEN for checkout and semantic-release (can push to main) - Add skip-check to prevent
80+
infinite loops on release commits - Sync pyproject.toml version to 0.3.0 (matches latest tag)
81+
82+
Prerequisite: Add ADMIN_TOKEN secret (GitHub PAT with repo scope) to
83+
84+
repository settings.
85+
86+
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
87+
88+
---------
89+
90+
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
91+
92+
- **ci**: Use v9 branch config for python-semantic-release
93+
([#13](https://github.com/OpenAdaptAI/openadapt-capture/pull/13),
94+
[`11eafca`](https://github.com/OpenAdaptAI/openadapt-capture/commit/11eafcaac1cab88dde4e861e93553fdef4b4ac1b))
95+
96+
* feat: disable window capture by default, add recording profiling with auto-wormhole
97+
98+
- Make window reader/writer conditional on RECORD_WINDOW_DATA (defaults to False), eliminating
99+
unnecessary thread + process + expensive platform API calls - Add throttle to read_window_events
100+
(0.1s) and memory_writer (1s) loops - Add profiling summary at end of record() with duration,
101+
event counts/rates, config flags, main thread check, and thread count - Auto-send profiling.json
102+
via Magic Wormhole after recording stops
103+
104+
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
105+
106+
* fix: skip window requirement when RECORD_WINDOW_DATA=False, set log level to WARNING
107+
108+
- When window capture is disabled, skip the window timestamp requirement in process_events instead
109+
of discarding all action events - Set loguru log level to WARNING by default (was DEBUG) to reduce
110+
noise during recording
111+
112+
* fix: set log level to INFO not WARNING
113+
114+
* fix: handle missing video frames on early Ctrl+C
115+
116+
video_post_callback crashes with KeyError 'last_frame' when recording stops before any action
117+
triggers a video frame write. Guard against missing state keys and close the container gracefully.
118+
119+
* fix: guard window event save when capture disabled, fix PyAV pict_type compat
120+
121+
- Second reference to prev_window_event in process_events was unguarded, causing AttributeError when
122+
RECORD_WINDOW_DATA=False - PyAV pict_type="I" raises TypeError on newer versions; fall back to
123+
integer constant
124+
125+
* fix: use PictureType.I enum for PyAV pict_type, add video tests
126+
127+
- Use av.video.frame.PictureType.I instead of string "I" which is unsupported in current PyAV
128+
versions - Add test_video.py with tests for frame writing, key frames, and PictureType enum
129+
compatibility
130+
131+
* fix: use Agg backend for matplotlib, improve wormhole-not-found message
132+
133+
- Set matplotlib to non-interactive Agg backend so plotting works from background threads (fixes
134+
RuntimeError when Recorder runs record() in a non-main thread) - Improve wormhole-not-found
135+
message with install instructions
136+
137+
* fix: reset stop sequence index after match to prevent IndexError
138+
139+
When the stop sequence was fully matched, the index wasn't reset. Extra keypresses after the match
140+
would index past the end of the sequence list, causing IndexError.
141+
142+
* feat: add per-screenshot timing to profiling, fix stop sequence IndexError
143+
144+
- Track screenshot duration (avg/max/min ms) and total iteration duration per screen reader loop
145+
iteration in profiling.json - Reset stop sequence index after match to prevent IndexError on extra
146+
keypresses
147+
148+
* feat: make send_profile opt-in CLI flag, add magic-wormhole as regular dep
149+
150+
Profiling data is no longer auto-sent via wormhole after every recording. Use --send_profile flag to
151+
opt in. Also promotes magic-wormhole from optional [share] extra to a regular dependency since
152+
sharing is core functionality.
153+
154+
* fix: add pixel_ratio and audio_start_time to CaptureSession
155+
156+
HTML visualizer referenced these attributes which didn't exist on CaptureSession. Added properties
157+
with safe fallbacks and updated html.py to use getattr with defaults.
158+
159+
* fix(ci): use v9 branch config for python-semantic-release
160+
161+
The `branch = "main"` key is from v7/v8 and is silently ignored by v9, causing "No release will be
162+
made, 0.3.0 has already been released!" on every push. Use the v9 `[branches.main]` table.
163+
164+
---------
165+
166+
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
167+
168+
### Features
169+
170+
- Copy legacy OpenAdapt recording system into openadapt-capture
171+
([#9](https://github.com/OpenAdaptAI/openadapt-capture/pull/9),
172+
[`d359011`](https://github.com/OpenAdaptAI/openadapt-capture/commit/d3590118edad60171c8c2ca47cee181f05d590e2))
173+
174+
* fix: match legacy OpenAdapt recording architecture
175+
176+
- Action-gated video capture: only encode frames when actions occur (~1-5 fps) instead of every
177+
screenshot (24fps). This is the core reason legacy OpenAdapt was smooth — not just separate
178+
processes. Matches legacy RECORD_FULL_VIDEO=False default behavior. - Video encoding in separate
179+
multiprocessing.Process (avoids GIL) - Screenshots via mss (2-4x faster than PIL.ImageGrab on
180+
Windows) - SIGINT ignored in worker process (main handles Ctrl+C) - Non-daemon process ensures
181+
video finalization on shutdown - First frame forced as key frame for seekability - Fix wormhole
182+
FileNotFoundError on Windows (searches Scripts/ dir)
183+
184+
Legacy patterns matched: - prev_screen_event buffering → _prev_screen_frame -
185+
prev_saved_screen_timestamp dedup → _prev_saved_screen_timestamp - RECORD_FULL_VIDEO option →
186+
record_full_video parameter - SIG_IGN in worker processes - mss with CAPTUREBLT=0 on Windows
187+
188+
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
189+
190+
* feat: copy legacy OpenAdapt recording system into openadapt-capture
191+
192+
Replace vibe-coded recording internals with proven legacy OpenAdapt code, adapted only for
193+
per-capture databases and import paths.
194+
195+
New modules (copied from legacy): - db/models.py: SQLAlchemy models (Recording, ActionEvent,
196+
Screenshot, WindowEvent, PerformanceStat, MemoryStat) - db/crud.py: batch insert functions,
197+
post_process_events - extensions/synchronized_queue.py: multiprocessing queue wrapper - utils.py:
198+
timestamps, screenshots, monitor dims - window/: platform-specific active window capture -
199+
plotting.py: performance stat visualization
200+
201+
Updated modules: - recorder.py: full legacy record() with multi-process writers, action-gated video,
202+
stop sequences, SIGINT handling - capture.py: reads from SQLAlchemy DB, fixes session leak,
203+
mouse_pressed=None handling, disabled event filtering, adds dx/dy/button properties to Action -
204+
config.py: all legacy recording config values - video.py: legacy functional API wrappers - cli.py:
205+
wired to new recorder - pyproject.toml: added sqlalchemy, loguru, psutil, tqdm deps
206+
207+
Bug fixes: - Reset stop_sequence_detected on re-entry (Recorder reuse) - Close session on error in
208+
CaptureSession.load() - Skip click events with mouse_pressed=None - Filter disabled events in
209+
raw_events()
210+
211+
Tests: 118 passed + 6 performance tests (Windows-only)
212+
213+
Docs: updated README.md and CLAUDE.md to match new architecture
214+
215+
* fix: make pynput import conditional for headless CI
216+
217+
- Wrap Recorder import in try/except in __init__.py and test files - Skip Recorder tests when pynput
218+
unavailable (no display server) - Fix all ruff I001 import sorting violations - Remove unused
219+
imports and variables
220+
221+
* fix(ci): exclude browser bridge tests and add timeout
222+
223+
Browser bridge tests hang indefinitely on headless CI due to async websocket fixtures. Add
224+
pytest-timeout and a 10-minute job timeout.
225+
226+
---------
227+
228+
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
229+
230+
- Unified Recorder API with config overrides and runtime properties
231+
([#10](https://github.com/OpenAdaptAI/openadapt-capture/pull/10),
232+
[`d840e81`](https://github.com/OpenAdaptAI/openadapt-capture/commit/d840e8107d7d45347201f04958c53293f08902e6))
233+
234+
Restore the clean Python API from the pre-legacy design on top of the proven legacy multi-process
235+
recording internals.
236+
237+
Recorder constructor now accepts capture_video, capture_audio, and other recording options as
238+
keyword params that override config defaults. Adds event_count, is_recording, stats,
239+
wait_for_ready(), and capture properties for runtime introspection.
240+
241+
Changes: - config.py: Add RecordingConfig dataclass + config_override() context manager for
242+
temporary config patching - recorder.py: Add shared counter params to record(), fix module-level
243+
config reads (STOP_SEQUENCES, PLOT_PERFORMANCE), rewrite Recorder class with full API (~120 lines
244+
replacing ~36) - cli.py: Forward --video/--audio/--images flags to Recorder - __init__.py: Export
245+
RecordingConfig - tests: 11 new tests (Recorder API + config_override)
246+
247+
Fixes compatibility with record_waa_demos.py which passes capture_video/capture_audio and reads
248+
recorder.event_count.
249+
250+
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
251+
252+
- **share**: Add Magic Wormhole sharing for recordings
253+
([`e7cfb1e`](https://github.com/OpenAdaptAI/openadapt-capture/commit/e7cfb1ec84999184a96682ebf74c08929485fe63))
254+
255+
- Add share.py module with send/receive via wormhole - Add 'capture share send/receive' CLI commands
256+
- Add magic-wormhole as optional [share] dependency - Auto-installs wormhole if missing
257+
258+
Usage: capture share send ./my_recording capture share receive 7-guitarist-revenge
259+
260+
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
261+
262+
4263
## v0.2.0 (2026-01-29)
5264

6265
### Bug Fixes

0 commit comments

Comments
 (0)