noteflowai/robot-reel · 0.19.0 · 2026-10-04

seal one frame/channel finding into a LeRobot replay bundle

Adds a --mark option to the existing robot-reel lerobot command: robot-reel lerobot EXPORT_DIR --mark FRAME --signal KEY/NAME [--signal ...] --note TEXT. It runs verify() on the export first. It then writes one finding.json containing: the episode, the zero-based frame, timestamps[frame], 1 to 8 key/name/value signals read from episode.json, the note, the manifest hash of episode.json, the package version (or null) and a fixed limitations statement. The sha256 of finding.json is added to manifest.json, and every other manifest entry stays the same. With --verify, alone or with --check-media / --check-source, the JSON result includes the sealed finding. An unmarked export gives the same result as before. Verify exits 2 with a named error if finding.json was edited without re-hashing, if finding.json is present but not listed in the manifest, if a listed finding.json is missing, if episode.json or a clip changed, or if a re-hashed finding disagrees with episode.json or breaks the input rules. Invalid --mark arguments, an already-marked export and any verify failure exit 2 and write nothing. If the manifest replacement fails, --mark removes the finding.json it placed in that run. Controller-executed checks: on base commit 4ed6d4b, the new feature test exited 1 with 'unrecognized arguments: --mark', so the test exercises the new option. On candidate commit 6f393b3, the controller ran robot_reel.pages --write, tests/test_feature_11ffe2c50b07.py, npm run check:js, the full Python unittest suite and node --test. All exited 0, and node --test reported 53/53 passed. My own action was writing this metadata; I ran no commands.

Use it

Prerequisites: Linux or macOS shell, Python, a checkout of this commit, and the package installed from it with its LeRobot extra: pip install '.[lerobot]' (the docs pin the planned release robot-reel[lerobot]==0.19.0). --check-media needs the ffmpeg provided by that extra.

Sample input: docs/lerobot ships in the repository. It is a real recorded episode from lerobot/svla_so101_pickplace at a pinned revision, not synthetic data. The note text below is a manual example.

1. Sender: create the input copy, then mark it (the original docs/lerobot stays unchanged):
cp -r docs/lerobot /tmp/so101
robot-reel lerobot /tmp/so101 --mark 239 --signal action/shoulder_pan.pos --signal observation.state/shoulder_pan.pos --note "Command and measurement diverge while the gripper approaches the box"
This exits 0 and prints JSON with episode 0, frame 239, its timestamp, the values 45.14706 and 61.75649, and the finding.json path.

2. Recipient: simulate another machine by moving the bundle to another path:
mkdir -p /tmp/received && cp -r /tmp/so101 /tmp/received/so101
robot-reel lerobot /tmp/received/so101 --verify --check-media
The result includes the finding object. To view it, open /tmp/received/so101/index.html and step to frame 239 with the existing frame controls.

3. Optional tamper demo (GNU sed). This exits 2 with 'Hash mismatch: finding.json':
sed -i 's/diverge/agree/' /tmp/received/so101/finding.json
robot-reel lerobot /tmp/received/so101 --verify

If verify reports that finding.json is present but not listed in manifest.json, delete finding.json and mark a fresh copy.

Scope

CLI only. The viewer and its embedded data are unchanged and do not highlight the finding. The controller's node --test run (53/53 passed) included the existing LeRobot replay browser regression checks at desktop and mobile widths. Those checks cover the unchanged viewer, not this feature. No one visually reviewed this feature, and no screenshots were provided. Scope: one finding per bundle, one frame and 1 to 8 channels. There are no frame ranges and no command to edit or remove a finding. Integrity: sha256 hashes, not a signature, and verify does not check who wrote the finding. A re-hashed rewrite that stays consistent with episode.json is not detected. Examples are a different valid note, a different robot_reel string, or another frame with its matching recorded values. A finding records an observation. It is not a failure label or a calibrated threshold. Test coverage: the passing tests cover the specified cases on the published SO-101 episode and on copies made by the tests. They do not show compatibility across other LeRobot datasets. Writes: the two renames are not one atomic operation. A crash between them can leave an unlisted finding.json, which verify reports. Compatibility: robot-reel versions without --mark reject a marked bundle as 'Incomplete LeRobot replay manifest'. The docs pin 0.19.0, so if the release ships under another version, both doc pins must be updated.

Upgrade and rollback

Upgrade both sender and recipient to the release that contains --mark (the docs pin robot-reel[lerobot]==0.19.0). Existing exports need no migration and give the same verify result as before. --mark edits the folder in place, so mark a copy if older versions must still read the original. To roll back a bundle, delete finding.json and remove its single entry from manifest.json. All other hashes are untouched, so the folder then verifies with both old and new versions. If only one of the two is removed, verify reports it. To roll back the package, reinstall the previous version. It will reject marked bundles until they are reverted as described above.

Source commit: c4bbdbb2ee7749971cbe40f8db7f828b7f3782ab