Problem
After import_lerobot_dataset finishes, a recipient of the delivery (landing MCAPs + prepared-manifest.json) cannot ask HFlow whether that delivery is still intact.
Schema-3 manifests already carry per-episode receipts (uri, content_id, size_bytes). The receipt docstring and docs/how-to/import-lerobot-v3.md say a delivery can be checked against the manifest without re-running import. There is no public library or CLI reader that performs that check:
hasattr(hflow, "verify_prepared_manifest") -> False
Truncation, same-path byte replacement, or a missing landing object stay silent until some later consumer fails for unrelated reasons. Hand checks exist only inside tests (test_manifest_content_id_detects_a_truncated_episode).
This is the LeRobot twin of the snapshot receipt/verify split (#397/#401 writer, #428 reader). Writer landed in #389; verify was deferred there. Verified against current main (c6d6d3729d7d7107c72fe7de4a7caf11ee549167).
Proposed behavior
Add a first-party verification path that reads an existing schema-3 prepared-manifest.json and checks every listed episode against the landing files — without re-running conversion or touching the Hugging Face cache.
Smallest useful outcome: given a data root that already contains prepared-manifest.json and landing MCAPs, the caller learns pass/fail (and which episode failed) from the receipts HFlow already wrote (uri, content_id, size_bytes).
Suggested API (names flexible):
from hflow import verify_prepared_manifest
report = verify_prepared_manifest("file:///path/to/data-root")
# report.ok is True when every episode matches
# on failure: which uri, and whether missing / size mismatch / content_id mismatch
Suggested CLI (pick one shape):
hflow verify lerobot-import file:///path/to/data-root
Behavior contract:
| Delivery state |
Result |
| Unchanged after publish |
Pass |
| Landing file missing |
Fail, name the episode uri |
Truncated / wrong size_bytes |
Fail |
Same-length byte replacement (content_id disagrees) |
Fail |
Extra files under landing/ not listed in the manifest |
Ignore (or warn — confirm with maintainers) |
Default verification must work offline against local roots and must not re-encode video or rewrite the manifest. Bucket roots should use the existing StorageRoot read path (same as import), without publishing new episodes.
Update docs/how-to/import-lerobot-v3.md so “can be checked against the manifest” points at this API/CLI.
Out of scope for the same change: snapshot verify (#428), resume CRC (#426), schema bumps, and adding source_episode_index unless maintainers want that as a tiny additive follow-up.
Alternatives considered
Compatibility and data-format impact
- No change to MCAP layout, episode bytes, catalog schema, or Airflow bundles.
- No prepared-manifest schema bump required unless maintainers later want additive fields (e.g.
source_episode_index).
- Reader-only: consumes existing
uri / content_id / size_bytes receipts.
- Unlisted extra files under
landing/ should be ignored or warned (policy to confirm); verification must not rewrite the manifest or landing objects.
- Bucket roots: verification may read remote objects (same as other StorageRoot consumers); should not mutate the catalog or publish new episodes.
Contribution
Yes
Problem
After
import_lerobot_datasetfinishes, a recipient of the delivery (landing MCAPs +prepared-manifest.json) cannot ask HFlow whether that delivery is still intact.Schema-3 manifests already carry per-episode receipts (
uri,content_id,size_bytes). The receipt docstring anddocs/how-to/import-lerobot-v3.mdsay a delivery can be checked against the manifest without re-running import. There is no public library or CLI reader that performs that check:Truncation, same-path byte replacement, or a missing landing object stay silent until some later consumer fails for unrelated reasons. Hand checks exist only inside tests (
test_manifest_content_id_detects_a_truncated_episode).This is the LeRobot twin of the snapshot receipt/verify split (#397/#401 writer, #428 reader). Writer landed in #389; verify was deferred there. Verified against current
main(c6d6d3729d7d7107c72fe7de4a7caf11ee549167).Proposed behavior
Add a first-party verification path that reads an existing schema-3
prepared-manifest.jsonand checks every listed episode against the landing files — without re-running conversion or touching the Hugging Face cache.Smallest useful outcome: given a data root that already contains
prepared-manifest.jsonand landing MCAPs, the caller learns pass/fail (and which episode failed) from the receipts HFlow already wrote (uri,content_id,size_bytes).Suggested API (names flexible):
Suggested CLI (pick one shape):
Behavior contract:
urisize_bytescontent_iddisagrees)landing/not listed in the manifestDefault verification must work offline against local roots and must not re-encode video or rewrite the manifest. Bucket roots should use the existing StorageRoot read path (same as import), without publishing new episodes.
Update
docs/how-to/import-lerobot-v3.mdso “can be checked against the manifest” points at this API/CLI.Out of scope for the same change: snapshot verify (#428), resume CRC (#426), schema bumps, and adding
source_episode_indexunless maintainers want that as a tiny additive follow-up.Alternatives considered
test_manifest_content_id_detects_a_truncated_episode); not a product surface for recipients of a bucket prefix or copied directory.format.json/ snapshot tables vs LeRobot landing + prepared-manifest); does not cover import deliveries that never become a snapshot.Compatibility and data-format impact
source_episode_index).uri/content_id/size_bytesreceipts.landing/should be ignored or warned (policy to confirm); verification must not rewrite the manifest or landing objects.Contribution
Yes