One command. Every artefact's shape.
Six steps.
The lines they printed.
Every line below is the standard output of one make demo run on 2026-10-18 (exit code 0), copied unchanged. The recording is simulated and the consent record synthetic; the sync error is the simulator's detector floor, not a measurement of a device. The card this run wrote is the one rendered on the datasets page.
Record a kit session on the simulator
cr4dle-capture record-kit puts a simulated Lens on a synthetic consent record for two epochs of two seconds: the episode directory, a raw area that never leaves the device, the MCAP source of record and a recording_ref identity for each. It prints the measured sync error, the discard counts and the regime, gaze and bystander facts of the recording.
stdoutSynthetic · one run · 2026-10-18 · tree 052c6fe0 record-kit (simulated Lens, synthetic consent) -> /tmp/cr4dle-demo/ (+ raw area /tmp/cr4dle-demo-raw/, + /tmp/cr4dle-demo.mcap)consent: SYNTHETIC record consent-synthetic-45486bbf-25b1-5b04-8589-b7ae5b898127 (jurisdiction ZZ; sim backend only; granted at the sim clock origin) regime=by-hand (default on --backend sim; --regime is required for hardware and replay); gaze role natural by default for regime by-hand: by-hand demonstrators look at the task; --gaze-role overrides kit=kit-sim-0001 units=dev-sim-glasses-0001:pupil-labs-neon,dev-sim-headcam-0001:uvc-head-camera,dev-sim-band-0001:mindrove-armband-2,dev-sim-exo-0001:exo-rgbd-camera,dev-sim-force-0001:fingertip-force,dev-sim-flash-0001:led-flash-sync recorded episode ep-lens-sim-0 of lens (sim) -> /tmp/cr4dle-demo/ kit kit-sim-0001: primary=dev-sim-glasses-0001 (pupil-labs-neon; hw_rev=simulated fw_ver=simulated) frames=240 streamKinds=hand_pose,head_pose,gaze_target,demonstrator_state videos=0 cameras=- redaction=drop-all-frames-v1 sync_error_us p50=5000 p95=5000 max=5000 [led_flash+imu_tap; 3 events; measured] clock_model sync_error_us p50=53 p95=133 [fit residual without the detection floor of 5000 us; 2 of 2 stream fit(s) have 2 or more events] discardCounts={'sync_skew': 0, 'missing_consent': 0, 'redaction_failed': 0, 'low_quality': 0, 'calibration_invalid': 0} demonstrationRegime=DEMONSTRATION_REGIME_BY_HAND gazeRole=GAZE_ROLE_NATURAL gazePresent=True bystanderCount=0 raw (on-device only; never exported): /tmp/cr4dle-demo-raw/ -- replay with `cr4dle replay --device lens --session /tmp/cr4dle-demo` mcap (on-device only; never exported): /tmp/cr4dle-demo.mcap -- chunk groups cameras,state,biosignal, gop_preset=vla; inspect with `cr4dle-capture mcap-info /tmp/cr4dle-demo.mcap` recording_ref (T4-R identity; ADR-0107): /tmp/cr4dle-demo.recording_ref.json -- rec-a740349ccfcd6b43 kind=episode_mcap bytes=151846 hub_id=hub-simulated; purge with `cr4dle-capture purge --sha256 a740349ccfcd6b43e90126b51e23848152c946595bccc942df0157d0d5382107` recording_ref (T4-R identity; ADR-0107): /tmp/cr4dle-demo-raw.recording_ref.json -- rec-313e607d1087113a kind=raw_area bytes=300013 hub_id=hub-simulated; purge with `cr4dle-capture purge --sha256 313e607d1087113a8d5a551aad5ebb381eee05b70247d98333aa81bc1495b652`
Measure the clocks again from the raw area
cr4dle-capture sync-report --recompute re-runs the LED-flash and tap detectors on the raw area and compares the offsets with the ones recorded at capture. The residual per stream is the sync error; a stream with a single event is marked unverified (an offset with no residual), and an episode with fewer than three events on a contributing stream is reported as not measured and discarded under sync skew.
stdoutSynthetic · one run · 2026-10-18 · tree 052c6fe0 sync-report --recompute (the detectors re-run on the raw area)sync report of /tmp/cr4dle-demo sync_error_us p50=5000 p95=5000 max=5000 [led_flash+imu_tap; 3 events; measured] clock_model sync_error_us p50=53 p95=133 [fit residual without the detection floor of 5000 us; 2 of 2 stream fit(s) have 2 or more events] enough_events=True (min 3) floor_us=5000 reference=hub imu imu_tap offset_us=-102 drift_ppm=+27.857 resolution_us=5000 events=3 residual_us=[-15, 30, -15] [measured] video led_flash offset_us=+0 drift_ppm=-0.000 resolution_us=4167 events=3 residual_us=[0, 0, 0] [measured] note: imu_tap is the trigger surrogate for a band without a trigger input; its residual spread includes the operator's tap-to-flash error note: drop-frames fallback: RedactorUnavailable: FaceBlurRedactor needs opencv (uv sync --extra vision) recomputed from the raw area /tmp/cr4dle-demo-raw/ sync_error_us p50=5000 p95=5000 max=5000 [led_flash+imu_tap; 3 events; measured] clock_model sync_error_us p50=53 p95=133 [fit residual without the detection floor of 5000 us; 2 of 2 stream fit(s) have 2 or more events] imu offset_us=-102 vs recorded -102 (delta +0 us) video offset_us=+0 vs recorded +0 (delta +0 us) largest offset delta: 0 us
Inspect the MCAP source of record
cr4dle-capture mcap-info lists the chunk groups, message counts and the three metadata records (consent, episode, provenance), checks that messages of different groups never share a chunk, and prints the recording_ref identity the file's bytes hash to.
stdoutSynthetic · one run · 2026-10-18 · tree 052c6fe0 mcap-info (chunk groups, counts, metadata; the never-share-a-chunk invariant; the recording_ref identity, ADR-0107)/tmp/cr4dle-demo.mcap (151846 B; library 'cr4dle-capture 0.0.1'; compression {'zstd': 8}) chunk groups: cameras, state, biosignal chunks=8 log time 0..7966667 us (hub clock) cameras channels=0 messages=0 chunks=0 topics=[] state channels=1 messages=240 chunks=4 topics=['/state/demonstration_frame'] biosignal channels=2 messages=8 chunks=4 topics=['/biosignal/gaze', '/biosignal/imu'] invariant (messages of different groups never share a chunk): holds metadata cr4dle.consent/v1: 9 field(s) consent_id = consent-synthetic-45486bbf-25b1-5b04-8589-b7ae5b898127 consent_ver = synthetic-1 granted_at = 2026-09-13T00:00:00.000000Z jurisdiction = ZZ purposes = ["PURPOSE_ROBOT_TRAINING_DATA"] revocation_checked_at = 2026-09-13T00:00:00.000000Z revocation_note = re-checked at export against the consent record (ADR-0049); this file records the status at the i... revocation_status = not_revoked_at_capture synthetic = true metadata cr4dle.episode/v1: 33 field(s) bystander_count = 0 chunk_groups = ["cameras","state","biosignal"] clock_model = {"floor_us":5000,"log_time":"hub receive clock of the window (ns); state messages log at the hub-... demonstration_regime = DEMONSTRATION_REGIME_BY_HAND discard_counts = {"calibration_invalid":0,"low_quality":0,"missing_consent":0,"redaction_failed":0,"sync_skew":0} egress = on-device / private store only; the exporter reads the episode directory, never this file ended_at = 2026-09-13T00:00:08.000000Z episode_dir = cr4dle-demo episode_id = ep-lens-sim-0 flush_interval_s = 2.0 gaze_present = true gaze_role = GAZE_ROLE_NATURAL gop = {"b_frames":0,"buyer":"policy (VLA) training: single-frame random access, a keyframe every second... gop_preset = vla manifest_sha256 = e5850bdaab31cb74584a1f5f50cc356f495e9bcf51c9ea40566e8d1257345164 n_frames = 240 participant_pseudonym = psn_synthetic_0000 persons_seen_max = {} session_id = ep-lens-sim-0 started_at = 2026-09-13T00:00:00.000000Z status = complete stream_kinds = ["hand_pose","head_pose","gaze_target","demonstrator_state"] sync_enough_events = true sync_error_us = {"max":5000,"p50":5000,"p95":5000} sync_error_us_frames = {"max":5000,"p50":5000,"p95":5000} sync_measured = true sync_n_events = 3 sync_notes = ["imu_tap is the trigger surrogate for a band without a trigger input; its residual spread includ... sync_report_sha256 = f1ed6e185a26d24b981cfa9c6fd503bc52ab9a720382a3270038bf8657418dd6 t_end_us = 8000000 t_start_us = 0 task_id = videos = [] metadata cr4dle.provenance/v1: 21 field(s) adapters = ["SimulatedSignalSource"] backend = simulated cal_id = camera_message_format = ref device_family = lens device_id = dev-sim-glasses-0001 devices = [{"device_id":"dev-sim-glasses-0001","equipment_id":"pupil-labs-neon","fw_ver":"simulated","hw_re... dsp_code_hash = sha256:036329d68dfd9314 feat_schema_ver = 1 force_model_id = form = eye-tracking-glasses fw_ver = simulated hw_rev = simulated kit_id = kit-sim-0001 redaction_policy_ver = drop-all-frames-v1 redactor_code_hash = sha256:84ba19e6abb7b4a65a8861e63415c114 sdk_versions = {"cr4dle-capture":"0.0.1","cr4dle-common":"30.0.0","cr4dle-runtime":"0.0.1","mcap":"1.4.0","numpy... state_model_id = demonstrator-state-stub-0 tier = TIER_L0_GLASSES vendor = pupil-labs-neon video_codec = recording_ref (cr4dle-demo.recording_ref.json; T4-R identity, never a location): recording_id=rec-a740349ccfcd6b43 kind=episode_mcap bytes=151846 hub_id=hub-simulated consent_id=consent-synthetic-45486bbf-25b1-5b04-8589-b7ae5b898127 sha256 a740349ccfcd6b43e90126b51e23848152c946595bccc942df0157d0d5382107 -- the file's bytes hash to this identity
Export through the consent gate
cr4dle-dataset-export reads the episode directory and first prints which record decides consent. The demo names --consent manifest: the manifest's own consent record, the simulation-only mode, so a withdrawal recorded elsewhere is invisible to this run. A person's data is exported against a consent store instead (--consent <directory of consent records>), where the gate re-checks consent at the instant of export and a withdrawal recorded after capture refuses the episode. The exporter then lays the LeRobot v2.1 files down with the finger_keypoints_v1 action space, writes the card with every unmeasured block as not run, and prints the identity posture from a synthetic re-identification report.
stdoutSynthetic · one run · 2026-10-18 · tree 052c6fe0 cr4dle-dataset-export --consent manifest --format lerobot_v21 --action-space finger_keypoints_v1 --reid-report benchmarks/fixtures/loso-report.reid.json -> /tmp/cr4dle-demo-lerobot/ (cr4dle-quality signal-qc first writes the signal QC verdict that the export admits)cr4dle-quality: signal QC ep-lens-sim-0: pass (no failed check; required streams imu, video) -> /tmp/cr4dle-demo/signal_qc.json cr4dle-dataset-export: consent lookup: manifest record (consent at capture; a withdrawal recorded elsewhere is invisible -- synthetic sessions only) cr4dle-dataset-export: wrote 1 episode(s), 240 frame(s), 0 video(s) to /tmp/cr4dle-demo-lerobot (lerobot v2.1 via --format lerobot_v21, video codec none, action space finger_keypoints_v1 v1, card schema_version 4, source simulation); sync error us p50/p95/max 5000/5000/5000; discards {'sync_skew': 0, 'missing_consent': 0, 'redaction_failed': 0, 'low_quality': 0, 'calibration_invalid': 0}; card meta/dataset_card.json; gate cr4dle-export 0.0.1 (consent: manifest); study CR4-DEMO-2026-10 (resolved) cr4dle-dataset-export: identity posture: rank-1 62.0% (chance 20.0%), EER 18.0%, n=5 x 2 sessions on observation.hand_pose, observation.head_pose; no eye image egress is a redaction fact, not an anonymity claim; literature [REPORTED]: pose rank-1 94.0% among 55,541 · gaze EER 6.2%-8.8% at 125-250 Hz · sEMG rank-1 98.5% cross-day; benchmarks/fixtures/loso-report.reid.json; reid_audit@2; synthetic evidence; representation no_video (not_applicable); linkability not applicable cr4dle-dataset-export: episode audit: regimes {'by_hand': 1, 'leader_follower': 0, 'vr_teleop': 0, 'exoskeleton': 0, 'walking': 0}; gaze present/labelled 1/1 (control-monitoring gaze excluded 0, scripted gaze excluded 0); hand lost % mean/p95/max 0.0/0.0/0.0 over 1 episode(s) with hand pose; bystanders max 0; rows meta/episodes_audit.jsonl
Validate the card
The stdlib validator of the data platform checks meta/dataset_card.json against the card schema and prints the one line that the counsel of a dataset user can look for.
stdoutSynthetic · one run · 2026-10-18 · tree 052c6fe0 the card validates against the schemacard validates: /tmp/cr4dle-demo-lerobot/meta/dataset_card.jsonMeasure quality beside the export
cr4dle-quality detects contact events on the force trace (none here: the simulated Lens recording carries no force stream) and appends its rows to the append-only quality catalog. Its labels are measurements, never a verdict about the episode or the person.
stdoutSynthetic · one run · 2026-10-18 · tree 052c6fe0 cr4dle-quality contact-events + catalog-append (measurements beside the export, ADR-0056)cr4dle-quality: contact events on 1 episode(s): contacts 0, slips 0, drops 0 (0 event rows) -> meta/contact_events.parquet + meta/contact_events_summary.json; no contact_force stream in this export, so every count is 0 cr4dle-quality: thresholds: CONTACT_ON_N=0.5 N, CONTACT_OFF_N=0.3 N, POOLED_ON_N=1.0 N, POOLED_OFF_N=0.6 N, DEBOUNCE_S=0.05 s, SLIP_DROP_N=1.0 N, SLIP_WINDOW_S=0.1 s, RELEASE_WINDOW_S=0.1 s, ABRUPT_RELEASE_N=1.0 N, PLACE_MAX_WRIST_SPEED_MPS=0.15 m/s cr4dle-quality: advantage_proxy: 1 / (1 + max(0, incidents - median_incidents)) with incidents = n_slips + n_drops and the median over the collection's episodes with a force stream; bounded (0, 1]; a relative ranking measurement for curation, never a task-completion label and never a verdict (median incidents None) cr4dle-quality: labels are measurements of the force trace; never a verdict about the episode or the person cr4dle-quality: appended 47 row(s) for 1 episode(s) to /tmp/cr4dle-demo-lerobot/meta/quality_catalog/20261018T064238Z-5bbb45.parquet (run 20261018T064238Z-5bbb45; 1 file(s) in the catalog now; nothing rewritten) cr4dle-quality: participant key: consent_id
What the run warned
The face-blur redactor needs the optional vision extra; without it the redaction stage drops every frame rather than export one it could not blur. The card records the fallback as its redaction policy.
face-blur redactor unavailable, falling back to drop-frames: RedactorUnavailable: FaceBlurRedactor needs opencv (uv sync --extra vision)
Recorded when the kit
is on a person.
This slot holds a ninety-second recording of the kit on a person demonstrating a task: the band, the head camera, the flash, the sync report and the card. No such recording exists yet; it is made at the gate that puts the kit on a person, dated . Until then the slot stays empty rather than hold a staged frame.
From the repository root.
make bootstrap make demo
The chain needs no hardware, no account and no data: the capture root, the data platform and the export gate run on synthetic input. The card it writes is cr4dle-demo-b030d2ed16f8 with source: simulation; a card from a person carries the same fields with its numbers measured.