Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,33 @@ jobs:
python-version: ['3.10', '3.11']

steps:
# Both repositories go in named subdirectories rather than the workspace
# root. `ruff check .` below lints the whole working directory, so a
# second checkout beside this one would put openadapt-capture's source
# through this repository's lint configuration.
- name: Checkout code
uses: actions/checkout@v4
with:
path: openadapt-viewer

# The scanner reads what the recorder writes, so its tests read
# recordings the recorder actually wrote. openadapt-capture commits two
# under examples/captures, regenerated and byte-compared by its own CI.
# Reading those is the point: a recording.db written here to match this
# repository's idea of the schema would prove only that the reader agrees
# with the test author. That is how the format drifted unnoticed for six
# weeks -- the scanner still globbed the pre-2026-07-17 capture.db and
# every test that exercised it built its own capture.db to match.
#
# Only examples/captures is fetched. The rest of that repository is not
# read here and pulling it would slow every matrix leg.
- name: Checkout openadapt-capture example recordings
uses: actions/checkout@v4
with:
repository: OpenAdaptAI/openadapt-capture
path: openadapt-capture
sparse-checkout: examples/captures
sparse-checkout-cone-mode: false

- name: Install uv
uses: astral-sh/setup-uv@v4
Expand All @@ -29,6 +54,7 @@ jobs:
run: uv python install ${{ matrix.python-version }}

- name: Install dependencies
working-directory: openadapt-viewer
run: uv sync --all-extras

# This step used to read:
Expand All @@ -44,6 +70,7 @@ jobs:
# the ruff version is bounded to >=0.16,<0.17 in pyproject.toml so a new
# ruff release cannot turn this red without a person raising the ceiling.
- name: Run ruff linter (check)
working-directory: openadapt-viewer
run: uv run ruff check .

# The companion `ruff format --check src/openadapt_viewer/` step was
Expand All @@ -57,4 +84,11 @@ jobs:
# adds the step back.

- name: Run pytest
working-directory: openadapt-viewer
env:
# tests/test_scanner_recording_db.py reads the two recordings here and
# fails, rather than skips, if they are absent under GITHUB_ACTIONS.
OPENADAPT_CAPTURE_EXAMPLES: ${{ github.workspace }}/openadapt-capture/examples/captures
# tests/test_screenshot_generation.py takes the checkout root.
OPENADAPT_CAPTURE_DIR: ${{ github.workspace }}/openadapt-capture
run: uv run pytest tests/ -v
11 changes: 6 additions & 5 deletions CATALOG_IMPLEMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ An automated recording catalog system that makes all captured data automatically
- Singleton pattern via `get_catalog()`

2. **Scanner** (`scanner.py`)
- Automatic discovery of recordings (directories with `capture.db`)
- Automatic discovery of recordings (directories with `recording.db`)
- Indexing of segmentation results (`*_episodes.json` files)
- Metadata extraction (frames, events, duration, timestamps)
- Default path detection
Expand Down Expand Up @@ -72,9 +72,10 @@ openadapt-viewer/
### Key Algorithms

**Recording Discovery**:
1. Glob for `**/capture.db` files
2. Extract metadata from capture.db SQLite tables
3. Count screenshots in `screenshots/` directory
1. Glob for `**/recording.db` files
2. Read the `recording` row for the start timestamp, task description,
platform and display geometry
3. Count `action_event` rows for events and `screenshot` rows for frames
4. Register in catalog with `INSERT OR REPLACE`

**Segmentation Indexing**:
Expand Down Expand Up @@ -136,7 +137,7 @@ Generated: /path/to/viewer.html

### Integration Points Verified

✅ Scanner reads from openadapt-capture `capture.db` files
✅ Scanner reads from openadapt-capture `recording.db` files
✅ Scanner parses openadapt-ml segmentation JSON files
✅ Catalog API exports data as JavaScript
✅ Viewer generator injects dropdown into base HTML
Expand Down
7 changes: 3 additions & 4 deletions CATALOG_SYSTEM.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@ The **Recording Catalog System** provides automatic discovery and indexing of al
│ │
│ openadapt-capture/ │
│ ├── turn-off-nightshift/ │
│ │ ├── capture.db ←────┐ │
│ │ ├── screenshots/ │ │
│ │ ├── recording.db ←────┐ │
│ │ └── video.mp4 │ │
│ └── demo_new/ │ │
│ └── capture.db │ Scanner discovers │
│ └── recording.db │ Scanner discovers │
│ │ recordings │
│ openadapt-ml/ │ │
│ └── segmentation_output/ │ │
Expand Down Expand Up @@ -558,7 +557,7 @@ openadapt-viewer catalog stats
# Re-scan directories
openadapt-viewer catalog scan

# Check recording structure (must have capture.db)
# Check recording structure (must have recording.db)
ls -la /path/to/recording/
```

Expand Down
2 changes: 1 addition & 1 deletion docs/SCREENSHOT_SYSTEM.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ Install with: cd ../openadapt-capture && uv pip install -e .
### Capture Errors
```
Error: Capture not found: /path/to/capture
FileNotFoundError: [Errno 2] No such file or directory: '/path/to/capture/capture.db'
FileNotFoundError: [Errno 2] No such file or directory: '/path/to/capture/recording.db'
```

### HTML Generation Errors
Expand Down
8 changes: 4 additions & 4 deletions docs/SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,11 @@ uv run playwright install chromium
**Solution**: Verify capture paths
```bash
# Check captures exist
ls -la /path/to/openadapt-capture/turn-off-nightshift/
ls -la /path/to/openadapt-capture/demo_new/
ls -la /path/to/openadapt-capture/examples/captures/turn-off-nightshift/
ls -la /path/to/openadapt-capture/examples/captures/demo_new/

# Look for capture.db
ls -la /path/to/openadapt-capture/turn-off-nightshift/capture.db
# Look for recording.db
ls -la /path/to/openadapt-capture/examples/captures/turn-off-nightshift/recording.db
```

**Or use custom path**:
Expand Down
13 changes: 10 additions & 3 deletions src/openadapt_viewer/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,14 +538,21 @@ def run_catalog_command(args):
if args.name:
recording.name = args.name

catalog.register_recording(**recording.model_dump())
# Recording names the field `id`; register_recording takes it as
# `recording_id`. Splatting the model straight in raised TypeError,
# which this except clause does not catch, so `catalog register`
# ended in a traceback for every directory that got this far.
fields = recording.model_dump()
fields["recording_id"] = fields.pop("id")
catalog.register_recording(**fields)
print(f"Successfully registered: {recording.name}")
print(f" ID: {recording.id}")
print(f" Frames: {recording.frame_count}")
print(f" Events: {recording.event_count}")
except (OSError, sqlite3.Error, ValueError) as e:
# OSError: unreadable recording directory. sqlite3.Error: unreadable
# capture.db or a failed catalog write. ValueError: a row that does
# OSError: an unreadable recording directory, or one holding no
# recording.db. sqlite3.Error: a corrupt recording.db or a failed
# catalog write. ValueError: a row that does
# not validate as a Recording. Anything else is a bug in this
# package and should surface as a traceback rather than as a
# one-line "Error registering recording".
Expand Down
Loading
Loading