hflow 0.2.0__tar.gz → 0.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. {hflow-0.2.0 → hflow-0.2.2}/PKG-INFO +57 -42
  2. {hflow-0.2.0 → hflow-0.2.2}/README.md +52 -41
  3. {hflow-0.2.0 → hflow-0.2.2}/pyproject.toml +17 -2
  4. {hflow-0.2.0 → hflow-0.2.2}/pyproject.toml.orig +29 -2
  5. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/__init__.py +52 -4
  6. hflow-0.2.2/src/hflow/_grouped_mcap_writer/__init__.py +19 -0
  7. hflow-0.2.0/src/hflow/mcap_writer.py → hflow-0.2.2/src/hflow/_grouped_mcap_writer/_writer.py +94 -58
  8. hflow-0.2.2/src/hflow/_pinned_asset.py +80 -0
  9. hflow-0.2.2/src/hflow/_video_measurement_toolchain.py +56 -0
  10. hflow-0.2.2/src/hflow/_video_measurements/__init__.py +54 -0
  11. hflow-0.2.2/src/hflow/_video_measurements/_camera_motion.py +319 -0
  12. hflow-0.2.2/src/hflow/_video_measurements/_frame_statistics.py +714 -0
  13. hflow-0.2.2/src/hflow/_video_measurements/_raw_frames.py +168 -0
  14. hflow-0.2.2/src/hflow/_video_measurements/_toolchain.py +30 -0
  15. hflow-0.2.2/src/hflow/app.py +2262 -0
  16. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/batching.py +7 -5
  17. hflow-0.2.2/src/hflow/behavior.py +73 -0
  18. hflow-0.2.2/src/hflow/catalog.py +902 -0
  19. hflow-0.2.2/src/hflow/checks.py +1556 -0
  20. hflow-0.2.2/src/hflow/cli.py +1256 -0
  21. hflow-0.2.2/src/hflow/curation.py +630 -0
  22. hflow-0.2.2/src/hflow/dataset.py +327 -0
  23. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/episode.py +23 -20
  24. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/ffmpeg/__init__.py +1 -6
  25. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/ffmpeg/_binary.py +16 -35
  26. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/ffmpeg/_contact_sheet.py +26 -6
  27. hflow-0.2.2/src/hflow/format.py +197 -0
  28. hflow-0.2.2/src/hflow/ingest_ledger.py +192 -0
  29. hflow-0.2.2/src/hflow/manifest.py +147 -0
  30. hflow-0.2.2/src/hflow/mediapipe_hands.py +492 -0
  31. hflow-0.2.2/src/hflow/project.py +182 -0
  32. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/resample.py +96 -11
  33. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/__init__.py +30 -0
  34. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/_bundle.py +403 -41
  35. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/_client.py +131 -22
  36. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/_deploy.py +75 -22
  37. hflow-0.2.2/src/hflow/runtime/_endpoint.py +128 -0
  38. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/_lifecycle.py +4 -1
  39. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/_templates.py +156 -161
  40. hflow-0.2.2/src/hflow/runtime/_topology.py +201 -0
  41. hflow-0.2.2/src/hflow/snapshot.py +689 -0
  42. hflow-0.2.2/src/hflow/stage_execution.py +481 -0
  43. hflow-0.2.2/src/hflow/stage_planning.py +269 -0
  44. hflow-0.2.2/src/hflow/steps.py +425 -0
  45. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/storage.py +39 -4
  46. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/testing.py +36 -12
  47. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/transform.py +255 -31
  48. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/video.py +38 -0
  49. hflow-0.2.2/src/hflow/workspace.py +166 -0
  50. hflow-0.2.0/src/hflow/app.py +0 -1109
  51. hflow-0.2.0/src/hflow/catalog.py +0 -476
  52. hflow-0.2.0/src/hflow/checks.py +0 -400
  53. hflow-0.2.0/src/hflow/cli.py +0 -523
  54. hflow-0.2.0/src/hflow/curation.py +0 -385
  55. hflow-0.2.0/src/hflow/ffmpeg/_instrument.py +0 -239
  56. hflow-0.2.0/src/hflow/format.py +0 -106
  57. hflow-0.2.0/src/hflow/steps.py +0 -364
  58. {hflow-0.2.0 → hflow-0.2.2}/LICENSE +0 -0
  59. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/doctor.py +0 -0
  60. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/providers.py +0 -0
  61. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/py.typed +0 -0
  62. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/reader.py +0 -0
  63. {hflow-0.2.0 → hflow-0.2.2}/src/hflow/runtime/_compose.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hflow
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Open source SDK for building Physical AI data pipelines
5
5
  Keywords: airflow,data-pipeline,data-quality,dataset-curation,mcap,physical-ai,robotics
6
6
  Author: Hebbian Robotics, Kingston Kuan, Brandon Ong
@@ -15,6 +15,8 @@ Requires-Dist: numpy>=2.4.6
15
15
  Requires-Dist: zstandard>=0.25.0
16
16
  Requires-Dist: pyarrow>=25.0.1 ; extra == 'arrow'
17
17
  Requires-Dist: obstore>=0.10.0 ; extra == 'bucket'
18
+ Requires-Dist: mediapipe>=1.0.0 ; extra == 'mediapipe'
19
+ Requires-Dist: opencv-python-headless>=4.10 ; extra == 'motion'
18
20
  Requires-Dist: openai>=3.0.0 ; extra == 'openai'
19
21
  Requires-Python: >=3.11
20
22
  Project-URL: Repository, https://github.com/Hebbian-Robotics/hflow
@@ -22,6 +24,8 @@ Project-URL: Documentation, https://github.com/Hebbian-Robotics/hflow/tree/main/
22
24
  Project-URL: Issues, https://github.com/Hebbian-Robotics/hflow/issues
23
25
  Provides-Extra: arrow
24
26
  Provides-Extra: bucket
27
+ Provides-Extra: mediapipe
28
+ Provides-Extra: motion
25
29
  Provides-Extra: openai
26
30
  Description-Content-Type: text/markdown
27
31
 
@@ -35,7 +39,7 @@ Description-Content-Type: text/markdown
35
39
 
36
40
  <h1 align="center">HFlow</h1>
37
41
 
38
- <p align="center"><strong>Open source SDK for building Physical AI data pipelines</strong></p>
42
+ <p align="center"><strong>Open source SDK for scalable multimodal data pipelines in robotics and physical AI</strong></p>
39
43
 
40
44
  <p align="center">
41
45
  <a href="https://www.ycombinator.com/companies/hebbian-robotics">
@@ -49,25 +53,27 @@ Description-Content-Type: text/markdown
49
53
  </a>
50
54
  </p>
51
55
 
52
- HFlow provides reusable infrastructure for physical AI data pipelines. Add your
53
- existing Python transformations, quality checks, labels, and enrichments; HFlow
54
- handles the orchestration, storage, versioning, and curation around them.
56
+ Hebbian Robotics (YC S26) is building HFlow, an open source SDK for scalable
57
+ multimodal data pipelines in robotics and physical AI. It makes data tooling and
58
+ practices typically developed inside large robotics teams accessible to teams of
59
+ any size.
60
+
61
+ We believe processing data is a major bottleneck in robotics. A corpus can combine
62
+ video, state, actions, timestamps, and metadata from many recording systems. Teams
63
+ often feel the problem first in quality control: determining whether cameras froze,
64
+ streams drifted out of sync, required topics disappeared, or duplicate recordings
65
+ entered the corpus. As the corpus grows, fragmented scripts make it difficult to
66
+ know what ran, audit the results, or reproduce a dataset.
67
+
68
+ Teams can start with HFlow's built-in checks, write new transformations, checks,
69
+ labels, and enrichments, or connect processing code they already use. HFlow handles
70
+ the orchestration, storage, versioning, and curation around those steps.
55
71
 
56
72
  HFlow stamps each processed episode with its provenance, renders the pipeline
57
73
  as a graph, and records metadata and quality evidence in a queryable catalog.
58
74
  You can trace how outputs were produced, monitor every stage, and
59
75
  investigate a corpus without loading the underlying recordings.
60
76
 
61
- The design is an open source implementation of Dyna Robotics'
62
- ["Training Dyna-2 at million-hour scale, repeatably"](https://www.dyna.co/research/dyna-2-infrastructure) article,
63
- published August 2026. Dyna-2 was trained on more than one million hours of
64
- egocentric video data, and the post describes the reusable infrastructure that
65
- made processing and experimenting with that data repeatable. You can think of
66
- HFlow as an independent, open-source implementation of those public ideas,
67
- adapted for people who need the same foundation without Dyna's million-hour
68
- production stack. It is not Dyna's private source code or an undisclosed
69
- wire-compatible production system.
70
-
71
77
  MCAP is HFlow's v1 input and output boundary because it efficiently stores
72
78
  and serves synchronized video, state, action, and other time-series streams.
73
79
  That format requirement does not define where the data comes from: human-worn
@@ -75,13 +81,13 @@ cameras, teleoperated robots, autonomous policies, and other collection systems
75
81
  can all feed the pipeline once their data is represented as a supported MCAP
76
82
  episode.
77
83
 
78
- > **Status: pre-v1, with the core lifecycle working end to end.** HFlow is ready to try locally. See [what is implemented](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md#what-is-different-from-dyna) and [open issues](https://github.com/Hebbian-Robotics/hflow/issues) for current details and remaining work.
84
+ > **Status: pre-v1, with the core lifecycle working end to end.** HFlow is ready to try locally. See [what is implemented](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md#implementation-status) and [open issues](https://github.com/Hebbian-Robotics/hflow/issues) for current details and remaining work.
79
85
 
80
- **Help advance open robotics and Physical AI.** [Contributors are welcome](https://github.com/Hebbian-Robotics/hflow/blob/main/CONTRIBUTING.md), and no robot hardware is required.
86
+ **Help grow the open robotics community.** [Star the repository](https://github.com/Hebbian-Robotics/hflow), share it with your network, or [contribute](https://github.com/Hebbian-Robotics/hflow/blob/main/CONTRIBUTING.md). Our goal is an open source community where anyone can participate in building the future of robotics. No robot hardware is required to contribute.
81
87
 
82
88
  | | HFlow's boundary |
83
89
  | --- | --- |
84
- | **Input** | One multimodal episode per standard MCAP file |
90
+ | **Input** | One multimodal episode per standard MCAP file (`hflow doctor` says whether yours qualifies) |
85
91
  | **Processing** | Your Python transforms, checks, labels, and enrichments |
86
92
  | **Execution** | In-process for development; generated Airflow 3 DAGs for scheduled runs |
87
93
  | **Durable output** | Canonical MCAP episodes, provenance, artifacts, and a Parquet catalog |
@@ -89,7 +95,7 @@ episode.
89
95
 
90
96
  ## What you get
91
97
 
92
- Human and robot data move through the same four-stage lifecycle Dyna describes:
98
+ Human and robot data move through a four-stage lifecycle:
93
99
 
94
100
  ```
95
101
  collection --> ingestion ---------------> curation ------> delivery
@@ -103,7 +109,7 @@ collection --> ingestion ---------------> curation ------> delivery
103
109
  </p>
104
110
 
105
111
  - **Your processing code stays yours.** Transformations, quality checks, labels, and enrichments are plain Python functions in your own environment. Existing code plugs in through small adapters instead of being rewritten for a proprietary framework.
106
- - **Episodes are MCAP**, the container that ROS 2 records natively and [Foxglove](https://foxglove.dev/)/[Rerun](https://rerun.io/) open directly, written with the two tuning ideas from Dyna's post: in-band H.264 with GOP length matched to how the data is read, and **topic-group chunking** (camera streams and state streams never share a chunk, so a training sample costs one read per group instead of one per topic).
112
+ - **Episodes are MCAP**, the container that ROS 2 records natively and [Foxglove](https://foxglove.dev/)/[Rerun](https://rerun.io/) open directly, written with two tunings described in Dyna's article: in-band H.264 with GOP length matched to how the data is read, and **topic-group chunking** (camera streams and state streams never share a chunk, so a training sample costs one read per group instead of one per topic).
107
113
  - **Processed episodes carry their provenance.** The file itself records the schema, pipeline, and tool versions that produced it, plus its source URI when available. Catalog records connect measurements and outcomes to step versions, making it easier to trace a bad result back to its origin.
108
114
  - **The pipeline is visible as a graph.** HFlow renders Airflow DAGs so you can see how stages connect and monitor task status, logs, retries, and reruns.
109
115
  - **Quality checks produce reusable evidence.** Accessors extract the inputs existing processing code expects (numpy arrays, MP4 paths, JPEG frames), and results land as queryable measurements rather than hardcoded verdicts. Different datasets can apply different thresholds without processing the media again.
@@ -121,6 +127,11 @@ same engine can be scaled as multiple isolated workspaces (for example, one
121
127
  per team or customer) behind an external control plane. That is the intended
122
128
  path to a future hosted version, but the hosted control plane is not
123
129
  implemented in this repository and is not a pre-v1 release commitment.
130
+ [docs/HOSTING.md](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/HOSTING.md)
131
+ documents the data-plane contract that makes such a control plane an
132
+ addition rather than a rearchitecture: the workspace unit, the seams a
133
+ service drives (manifests, remote runtime addressing, credential injection),
134
+ the trust model, and the current limits.
124
135
 
125
136
  ## Community and hosted interest
126
137
 
@@ -149,7 +160,7 @@ To run the repository's bundled quickstart:
149
160
  ```bash
150
161
  git clone https://github.com/Hebbian-Robotics/hflow.git
151
162
  cd hflow
152
- uv sync --locked --all-extras
163
+ uv sync --locked
153
164
  uv run python examples/quickstart.py
154
165
  ```
155
166
 
@@ -176,24 +187,28 @@ and other physical-AI recordings.
176
187
 
177
188
  ```python
178
189
  import hflow
190
+ from hflow.checks import camera_frame_stats
179
191
  from your_existing_qc import check_joint_smoothness # use your existing checks
180
192
 
181
- app = hflow.App("kitchen-pipeline", data_root="./data")
193
+ app = hflow.App("kitchen-pipeline") # data root: $HFLOW_DATA_ROOT, hflow.toml, else ./data
182
194
 
183
195
 
184
- @app.check()
196
+ @app.check(version="1")
185
197
  def joint_smoothness(ep: hflow.Episode) -> hflow.CheckResult:
186
198
  joints = ep.channel("/joint_states").to_numpy() # our line: extract
187
199
  result = check_joint_smoothness(joints, rate_hz=100) # your line: unchanged
188
200
  return hflow.CheckResult(measurements=result) # our line: record
189
201
 
190
202
 
191
- @app.check(critical=True)
203
+ @app.check(version="1", critical=True)
192
204
  def camera_blackout(ep: hflow.Episode) -> hflow.CheckResult:
193
- stats = hflow.ffmpeg.frame_stats(ep.video("wrist_cam")) # one decode pass
205
+ camera_topic = next(topic for topic in ep.cameras if "wrist_cam" in topic)
206
+ evidence = camera_frame_stats(ep, cameras=[camera_topic])
207
+ black_frame_percent = evidence.measurements[f"{camera_topic}/black_frame_pct"]
208
+ assert isinstance(black_frame_percent, float)
194
209
  return hflow.CheckResult(
195
- measurements={"black_pct": stats.black_frame_pct},
196
- verdict=stats.black_frame_pct < 0.5, # your threshold
210
+ measurements={"black_pct": black_frame_percent},
211
+ verdict=black_frame_percent < 50.0, # percent; your threshold
197
212
  )
198
213
 
199
214
 
@@ -202,6 +217,10 @@ if __name__ == "__main__":
202
217
  # Or call app.run() here to start the Compose runtime, then use `hflow ingest`.
203
218
  ```
204
219
 
220
+ Every check, enrichment, and derived channel declares a version. HFlow stores
221
+ that value exactly as written: keep it for behavior-preserving refactors, and
222
+ bump it when old and new results should no longer be treated as comparable.
223
+
205
224
  Curation comes afterwards, via `hflow.curate(data_root / "catalog", sql, output="manifest.parquet")`
206
225
  or `hflow curate "<sql>"` on the command line, either way reporting coverage
207
226
  denominators alongside the manifest:
@@ -209,7 +228,7 @@ denominators alongside the manifest:
209
228
  ```sql
210
229
  SELECT episode_id, uri FROM episodes
211
230
  WHERE task = 'fold_napkin'
212
- AND status != 'quarantined'
231
+ AND status = 'ok'
213
232
  AND black_pct < 1.0 -- percent, user-owned threshold
214
233
  AND pipeline_version = 'a41c9f27b3d8' -- pin one reprocessing generation
215
234
  ```
@@ -220,7 +239,6 @@ WHERE task = 'fold_napkin'
220
239
  2. **Evidence, not verdicts.** Checks record measurements with coverage; pass/fail policy belongs to the consumer, at curation time. Quality tags route episodes; they never delete data.
221
240
  3. **Standard formats at every boundary.** MCAP episodes, Parquet catalogs, Airflow DAGs. Our code exists only where the format forces bridging or a pitfall is genuinely non-obvious.
222
241
  4. **Your code stays your code.** Existing transforms, checks, and enrichments plug in through small adapters instead of being rewritten.
223
- 5. **Transparent provenance.** The docs mark every design element as *Dyna says* (from the blog) or *HFlow chooses* (our engineering judgment, with the evidence behind it).
224
242
 
225
243
  ## Non-goals
226
244
 
@@ -243,28 +261,25 @@ WHERE task = 'fold_napkin'
243
261
  - [Frequently asked questions](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/FAQ.md): formats, infrastructure, scale, project scope, and current release status
244
262
  - [How HFlow fits the robotics data stack](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/INTEGRATIONS.md): MCAP, Airflow, Foxglove, Rerun, DuckDB, object storage, and training formats
245
263
  - [Runnable examples](https://github.com/Hebbian-Robotics/hflow/blob/main/examples/README.md): exact commands, prerequisites, expected output, and links to the relevant guides
246
- - [Architecture and differences from Dyna](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md): the implemented, simplified, deferred, and out-of-scope matrix
264
+ - [Architecture and implementation status](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md): the implemented, simplified, deferred, and out-of-scope matrix
247
265
  - [Call OpenAI vision from a step](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/how-to/call-openai-vision.md): a focused guide linked to a complete executable pipeline
248
266
  - [Contributing](https://github.com/Hebbian-Robotics/hflow/blob/main/CONTRIBUTING.md): development setup, validation commands, test gates, and pull-request expectations
249
267
  - [Security policy](https://github.com/Hebbian-Robotics/hflow/blob/main/SECURITY.md): supported versions and private vulnerability reporting
250
268
 
251
269
  ## References
252
270
 
253
- Primary source:
254
-
255
- - Dyna Robotics, [Training Dyna-2 at million-hour scale, repeatably](https://www.dyna.co/research/dyna-2-infrastructure) (Aug 2026)
256
-
257
- Formats and tooling this project builds on:
258
271
 
272
+ - Dyna Robotics, [Training Dyna-2 at million-hour scale, repeatably](https://www.dyna.co/research/dyna-2-infrastructure)
259
273
  - [MCAP specification](https://mcap.dev/spec) and [Python libraries](https://mcap.dev/docs/python/) (Foxglove)
260
274
  - [foxglove.CompressedVideo schema](https://docs.foxglove.dev/docs/sdk/schemas/compressed-video): in-band H.264/H.265/VP9/AV1 video in MCAP
261
- - [Apache Airflow 3](https://airflow.apache.org/): ingestion DAG orchestration
262
- - [DuckDB](https://duckdb.org/): curation queries over the Parquet catalog
263
- - [Foxglove](https://foxglove.dev/) and [Rerun](https://rerun.io/): episode inspection
264
- - [FFmpeg](https://ffmpeg.org/): video processing and the deterministic frame instrument
265
-
266
- Parts of the durability and measurement design draw on production experience from [Pareto](https://github.com/Hebbian-Robotics/pareto), Hebbian Robotics' robotics data curation platform.
275
+ - [Apache Airflow](https://airflow.apache.org/)
276
+ - [DuckDB](https://duckdb.org/)
277
+ - [Foxglove](https://foxglove.dev/) and [Rerun](https://rerun.io/)
278
+ - [FFmpeg](https://ffmpeg.org/)
279
+ - [Pareto](https://github.com/Hebbian-Robotics/pareto), Hebbian Robotics' robotics data curation platform.
267
280
 
268
281
  ## License
269
282
 
270
- [Apache-2.0](https://github.com/Hebbian-Robotics/hflow/blob/main/LICENSE)
283
+ [Apache-2.0](https://github.com/Hebbian-Robotics/hflow/blob/main/LICENSE).
284
+ The license covers the code, not the names: see the
285
+ [trademark policy](https://github.com/Hebbian-Robotics/hflow/blob/main/TRADEMARKS.md).
@@ -8,7 +8,7 @@
8
8
 
9
9
  <h1 align="center">HFlow</h1>
10
10
 
11
- <p align="center"><strong>Open source SDK for building Physical AI data pipelines</strong></p>
11
+ <p align="center"><strong>Open source SDK for scalable multimodal data pipelines in robotics and physical AI</strong></p>
12
12
 
13
13
  <p align="center">
14
14
  <a href="https://www.ycombinator.com/companies/hebbian-robotics">
@@ -22,25 +22,27 @@
22
22
  </a>
23
23
  </p>
24
24
 
25
- HFlow provides reusable infrastructure for physical AI data pipelines. Add your
26
- existing Python transformations, quality checks, labels, and enrichments; HFlow
27
- handles the orchestration, storage, versioning, and curation around them.
25
+ Hebbian Robotics (YC S26) is building HFlow, an open source SDK for scalable
26
+ multimodal data pipelines in robotics and physical AI. It makes data tooling and
27
+ practices typically developed inside large robotics teams accessible to teams of
28
+ any size.
29
+
30
+ We believe processing data is a major bottleneck in robotics. A corpus can combine
31
+ video, state, actions, timestamps, and metadata from many recording systems. Teams
32
+ often feel the problem first in quality control: determining whether cameras froze,
33
+ streams drifted out of sync, required topics disappeared, or duplicate recordings
34
+ entered the corpus. As the corpus grows, fragmented scripts make it difficult to
35
+ know what ran, audit the results, or reproduce a dataset.
36
+
37
+ Teams can start with HFlow's built-in checks, write new transformations, checks,
38
+ labels, and enrichments, or connect processing code they already use. HFlow handles
39
+ the orchestration, storage, versioning, and curation around those steps.
28
40
 
29
41
  HFlow stamps each processed episode with its provenance, renders the pipeline
30
42
  as a graph, and records metadata and quality evidence in a queryable catalog.
31
43
  You can trace how outputs were produced, monitor every stage, and
32
44
  investigate a corpus without loading the underlying recordings.
33
45
 
34
- The design is an open source implementation of Dyna Robotics'
35
- ["Training Dyna-2 at million-hour scale, repeatably"](https://www.dyna.co/research/dyna-2-infrastructure) article,
36
- published August 2026. Dyna-2 was trained on more than one million hours of
37
- egocentric video data, and the post describes the reusable infrastructure that
38
- made processing and experimenting with that data repeatable. You can think of
39
- HFlow as an independent, open-source implementation of those public ideas,
40
- adapted for people who need the same foundation without Dyna's million-hour
41
- production stack. It is not Dyna's private source code or an undisclosed
42
- wire-compatible production system.
43
-
44
46
  MCAP is HFlow's v1 input and output boundary because it efficiently stores
45
47
  and serves synchronized video, state, action, and other time-series streams.
46
48
  That format requirement does not define where the data comes from: human-worn
@@ -48,13 +50,13 @@ cameras, teleoperated robots, autonomous policies, and other collection systems
48
50
  can all feed the pipeline once their data is represented as a supported MCAP
49
51
  episode.
50
52
 
51
- > **Status: pre-v1, with the core lifecycle working end to end.** HFlow is ready to try locally. See [what is implemented](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md#what-is-different-from-dyna) and [open issues](https://github.com/Hebbian-Robotics/hflow/issues) for current details and remaining work.
53
+ > **Status: pre-v1, with the core lifecycle working end to end.** HFlow is ready to try locally. See [what is implemented](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md#implementation-status) and [open issues](https://github.com/Hebbian-Robotics/hflow/issues) for current details and remaining work.
52
54
 
53
- **Help advance open robotics and Physical AI.** [Contributors are welcome](https://github.com/Hebbian-Robotics/hflow/blob/main/CONTRIBUTING.md), and no robot hardware is required.
55
+ **Help grow the open robotics community.** [Star the repository](https://github.com/Hebbian-Robotics/hflow), share it with your network, or [contribute](https://github.com/Hebbian-Robotics/hflow/blob/main/CONTRIBUTING.md). Our goal is an open source community where anyone can participate in building the future of robotics. No robot hardware is required to contribute.
54
56
 
55
57
  | | HFlow's boundary |
56
58
  | --- | --- |
57
- | **Input** | One multimodal episode per standard MCAP file |
59
+ | **Input** | One multimodal episode per standard MCAP file (`hflow doctor` says whether yours qualifies) |
58
60
  | **Processing** | Your Python transforms, checks, labels, and enrichments |
59
61
  | **Execution** | In-process for development; generated Airflow 3 DAGs for scheduled runs |
60
62
  | **Durable output** | Canonical MCAP episodes, provenance, artifacts, and a Parquet catalog |
@@ -62,7 +64,7 @@ episode.
62
64
 
63
65
  ## What you get
64
66
 
65
- Human and robot data move through the same four-stage lifecycle Dyna describes:
67
+ Human and robot data move through a four-stage lifecycle:
66
68
 
67
69
  ```
68
70
  collection --> ingestion ---------------> curation ------> delivery
@@ -76,7 +78,7 @@ collection --> ingestion ---------------> curation ------> delivery
76
78
  </p>
77
79
 
78
80
  - **Your processing code stays yours.** Transformations, quality checks, labels, and enrichments are plain Python functions in your own environment. Existing code plugs in through small adapters instead of being rewritten for a proprietary framework.
79
- - **Episodes are MCAP**, the container that ROS 2 records natively and [Foxglove](https://foxglove.dev/)/[Rerun](https://rerun.io/) open directly, written with the two tuning ideas from Dyna's post: in-band H.264 with GOP length matched to how the data is read, and **topic-group chunking** (camera streams and state streams never share a chunk, so a training sample costs one read per group instead of one per topic).
81
+ - **Episodes are MCAP**, the container that ROS 2 records natively and [Foxglove](https://foxglove.dev/)/[Rerun](https://rerun.io/) open directly, written with two tunings described in Dyna's article: in-band H.264 with GOP length matched to how the data is read, and **topic-group chunking** (camera streams and state streams never share a chunk, so a training sample costs one read per group instead of one per topic).
80
82
  - **Processed episodes carry their provenance.** The file itself records the schema, pipeline, and tool versions that produced it, plus its source URI when available. Catalog records connect measurements and outcomes to step versions, making it easier to trace a bad result back to its origin.
81
83
  - **The pipeline is visible as a graph.** HFlow renders Airflow DAGs so you can see how stages connect and monitor task status, logs, retries, and reruns.
82
84
  - **Quality checks produce reusable evidence.** Accessors extract the inputs existing processing code expects (numpy arrays, MP4 paths, JPEG frames), and results land as queryable measurements rather than hardcoded verdicts. Different datasets can apply different thresholds without processing the media again.
@@ -94,6 +96,11 @@ same engine can be scaled as multiple isolated workspaces (for example, one
94
96
  per team or customer) behind an external control plane. That is the intended
95
97
  path to a future hosted version, but the hosted control plane is not
96
98
  implemented in this repository and is not a pre-v1 release commitment.
99
+ [docs/HOSTING.md](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/HOSTING.md)
100
+ documents the data-plane contract that makes such a control plane an
101
+ addition rather than a rearchitecture: the workspace unit, the seams a
102
+ service drives (manifests, remote runtime addressing, credential injection),
103
+ the trust model, and the current limits.
97
104
 
98
105
  ## Community and hosted interest
99
106
 
@@ -122,7 +129,7 @@ To run the repository's bundled quickstart:
122
129
  ```bash
123
130
  git clone https://github.com/Hebbian-Robotics/hflow.git
124
131
  cd hflow
125
- uv sync --locked --all-extras
132
+ uv sync --locked
126
133
  uv run python examples/quickstart.py
127
134
  ```
128
135
 
@@ -149,24 +156,28 @@ and other physical-AI recordings.
149
156
 
150
157
  ```python
151
158
  import hflow
159
+ from hflow.checks import camera_frame_stats
152
160
  from your_existing_qc import check_joint_smoothness # use your existing checks
153
161
 
154
- app = hflow.App("kitchen-pipeline", data_root="./data")
162
+ app = hflow.App("kitchen-pipeline") # data root: $HFLOW_DATA_ROOT, hflow.toml, else ./data
155
163
 
156
164
 
157
- @app.check()
165
+ @app.check(version="1")
158
166
  def joint_smoothness(ep: hflow.Episode) -> hflow.CheckResult:
159
167
  joints = ep.channel("/joint_states").to_numpy() # our line: extract
160
168
  result = check_joint_smoothness(joints, rate_hz=100) # your line: unchanged
161
169
  return hflow.CheckResult(measurements=result) # our line: record
162
170
 
163
171
 
164
- @app.check(critical=True)
172
+ @app.check(version="1", critical=True)
165
173
  def camera_blackout(ep: hflow.Episode) -> hflow.CheckResult:
166
- stats = hflow.ffmpeg.frame_stats(ep.video("wrist_cam")) # one decode pass
174
+ camera_topic = next(topic for topic in ep.cameras if "wrist_cam" in topic)
175
+ evidence = camera_frame_stats(ep, cameras=[camera_topic])
176
+ black_frame_percent = evidence.measurements[f"{camera_topic}/black_frame_pct"]
177
+ assert isinstance(black_frame_percent, float)
167
178
  return hflow.CheckResult(
168
- measurements={"black_pct": stats.black_frame_pct},
169
- verdict=stats.black_frame_pct < 0.5, # your threshold
179
+ measurements={"black_pct": black_frame_percent},
180
+ verdict=black_frame_percent < 50.0, # percent; your threshold
170
181
  )
171
182
 
172
183
 
@@ -175,6 +186,10 @@ if __name__ == "__main__":
175
186
  # Or call app.run() here to start the Compose runtime, then use `hflow ingest`.
176
187
  ```
177
188
 
189
+ Every check, enrichment, and derived channel declares a version. HFlow stores
190
+ that value exactly as written: keep it for behavior-preserving refactors, and
191
+ bump it when old and new results should no longer be treated as comparable.
192
+
178
193
  Curation comes afterwards, via `hflow.curate(data_root / "catalog", sql, output="manifest.parquet")`
179
194
  or `hflow curate "<sql>"` on the command line, either way reporting coverage
180
195
  denominators alongside the manifest:
@@ -182,7 +197,7 @@ denominators alongside the manifest:
182
197
  ```sql
183
198
  SELECT episode_id, uri FROM episodes
184
199
  WHERE task = 'fold_napkin'
185
- AND status != 'quarantined'
200
+ AND status = 'ok'
186
201
  AND black_pct < 1.0 -- percent, user-owned threshold
187
202
  AND pipeline_version = 'a41c9f27b3d8' -- pin one reprocessing generation
188
203
  ```
@@ -193,7 +208,6 @@ WHERE task = 'fold_napkin'
193
208
  2. **Evidence, not verdicts.** Checks record measurements with coverage; pass/fail policy belongs to the consumer, at curation time. Quality tags route episodes; they never delete data.
194
209
  3. **Standard formats at every boundary.** MCAP episodes, Parquet catalogs, Airflow DAGs. Our code exists only where the format forces bridging or a pitfall is genuinely non-obvious.
195
210
  4. **Your code stays your code.** Existing transforms, checks, and enrichments plug in through small adapters instead of being rewritten.
196
- 5. **Transparent provenance.** The docs mark every design element as *Dyna says* (from the blog) or *HFlow chooses* (our engineering judgment, with the evidence behind it).
197
211
 
198
212
  ## Non-goals
199
213
 
@@ -216,28 +230,25 @@ WHERE task = 'fold_napkin'
216
230
  - [Frequently asked questions](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/FAQ.md): formats, infrastructure, scale, project scope, and current release status
217
231
  - [How HFlow fits the robotics data stack](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/INTEGRATIONS.md): MCAP, Airflow, Foxglove, Rerun, DuckDB, object storage, and training formats
218
232
  - [Runnable examples](https://github.com/Hebbian-Robotics/hflow/blob/main/examples/README.md): exact commands, prerequisites, expected output, and links to the relevant guides
219
- - [Architecture and differences from Dyna](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md): the implemented, simplified, deferred, and out-of-scope matrix
233
+ - [Architecture and implementation status](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/ARCHITECTURE.md): the implemented, simplified, deferred, and out-of-scope matrix
220
234
  - [Call OpenAI vision from a step](https://github.com/Hebbian-Robotics/hflow/blob/main/docs/how-to/call-openai-vision.md): a focused guide linked to a complete executable pipeline
221
235
  - [Contributing](https://github.com/Hebbian-Robotics/hflow/blob/main/CONTRIBUTING.md): development setup, validation commands, test gates, and pull-request expectations
222
236
  - [Security policy](https://github.com/Hebbian-Robotics/hflow/blob/main/SECURITY.md): supported versions and private vulnerability reporting
223
237
 
224
238
  ## References
225
239
 
226
- Primary source:
227
-
228
- - Dyna Robotics, [Training Dyna-2 at million-hour scale, repeatably](https://www.dyna.co/research/dyna-2-infrastructure) (Aug 2026)
229
-
230
- Formats and tooling this project builds on:
231
240
 
241
+ - Dyna Robotics, [Training Dyna-2 at million-hour scale, repeatably](https://www.dyna.co/research/dyna-2-infrastructure)
232
242
  - [MCAP specification](https://mcap.dev/spec) and [Python libraries](https://mcap.dev/docs/python/) (Foxglove)
233
243
  - [foxglove.CompressedVideo schema](https://docs.foxglove.dev/docs/sdk/schemas/compressed-video): in-band H.264/H.265/VP9/AV1 video in MCAP
234
- - [Apache Airflow 3](https://airflow.apache.org/): ingestion DAG orchestration
235
- - [DuckDB](https://duckdb.org/): curation queries over the Parquet catalog
236
- - [Foxglove](https://foxglove.dev/) and [Rerun](https://rerun.io/): episode inspection
237
- - [FFmpeg](https://ffmpeg.org/): video processing and the deterministic frame instrument
238
-
239
- Parts of the durability and measurement design draw on production experience from [Pareto](https://github.com/Hebbian-Robotics/pareto), Hebbian Robotics' robotics data curation platform.
244
+ - [Apache Airflow](https://airflow.apache.org/)
245
+ - [DuckDB](https://duckdb.org/)
246
+ - [Foxglove](https://foxglove.dev/) and [Rerun](https://rerun.io/)
247
+ - [FFmpeg](https://ffmpeg.org/)
248
+ - [Pareto](https://github.com/Hebbian-Robotics/pareto), Hebbian Robotics' robotics data curation platform.
240
249
 
241
250
  ## License
242
251
 
243
- [Apache-2.0](https://github.com/Hebbian-Robotics/hflow/blob/main/LICENSE)
252
+ [Apache-2.0](https://github.com/Hebbian-Robotics/hflow/blob/main/LICENSE).
253
+ The license covers the code, not the names: see the
254
+ [trademark policy](https://github.com/Hebbian-Robotics/hflow/blob/main/TRADEMARKS.md).
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hflow"
3
- version = "0.2.0"
3
+ version = "0.2.2"
4
4
  description = "Open source SDK for building Physical AI data pipelines"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -37,6 +37,8 @@ name = "Brandon Ong"
37
37
  [project.optional-dependencies]
38
38
  arrow = ["pyarrow>=25.0.1"]
39
39
  bucket = ["obstore>=0.10.0"]
40
+ mediapipe = ["mediapipe>=1.0.0"]
41
+ motion = ["opencv-python-headless>=4.10"]
40
42
  openai = ["openai>=3.0.0"]
41
43
 
42
44
  [project.urls]
@@ -49,7 +51,11 @@ hflow = "hflow.cli:main"
49
51
 
50
52
  [dependency-groups]
51
53
  dev = [
54
+ "hflow-server",
55
+ "httpx2>=2.10",
52
56
  "obstore>=0.10.0",
57
+ "opencv-python-headless>=4.10",
58
+ "pyarrow>=25.0.1",
53
59
  "pytest>=9.1.1",
54
60
  "pyyaml>=6.0.3",
55
61
  "ruff>=0.16.2",
@@ -63,8 +69,17 @@ build-backend = "uv_build"
63
69
  [tool.uv]
64
70
  exclude-newer = "5 days"
65
71
 
72
+ [tool.uv.workspace]
73
+ members = ["packages/*"]
74
+
75
+ [tool.uv.sources.hflow-server]
76
+ workspace = true
77
+
66
78
  [tool.pytest.ini_options]
67
- testpaths = ["tests"]
79
+ testpaths = [
80
+ "tests",
81
+ "packages/hflow-server/tests",
82
+ ]
68
83
 
69
84
  [tool.ruff]
70
85
  line-length = 100
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hflow"
3
- version = "0.2.0"
3
+ version = "0.2.2"
4
4
  description = "Open source SDK for building Physical AI data pipelines"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -36,6 +36,19 @@ arrow = ["pyarrow>=25.0.1"]
36
36
  # object_store crate as a single dependency-free wheel; local-path roots
37
37
  # never import it.
38
38
  bucket = ["obstore>=0.10.0"]
39
+ # Hand detection with MediaPipe's Hand Landmarker (hflow.mediapipe_hands).
40
+ # A MODEL, not a signal statistic, so it is opt-in twice over: outside the core
41
+ # install, and outside the dev group as well (unlike motion and bucket, which
42
+ # are mirrored into dev so the suite exercises them). It adds ~430 MB and its
43
+ # own OpenCV; a dev environment opts in with `--extra mediapipe`, exactly as
44
+ # the openai example does.
45
+ mediapipe = ["mediapipe>=1.0.0"]
46
+ # Camera-shake measurement: pyramidal Lucas-Kanade optical flow and a RANSAC
47
+ # similarity fit. No numpy-only equivalent preserves the instrument, and
48
+ # reimplementing them would make it a different, unvalidated one -- so the
49
+ # dependency is real, and confined to the one check that needs it. Headless
50
+ # because a data pipeline runs where there is no display.
51
+ motion = ["opencv-python-headless>=4.10"]
39
52
  openai = ["openai>=3.0.0"]
40
53
 
41
54
  [project.urls]
@@ -48,7 +61,15 @@ hflow = "hflow.cli:main"
48
61
 
49
62
  [dependency-groups]
50
63
  dev = [
64
+ "hflow-server", # the workspace API package, present in dev so the suite tests it
65
+ # Starlette's TestClient transport for the hflow-server suite. httpx2, not
66
+ # httpx: starlette 1.6 deprecates the httpx transport in its favour.
67
+ "httpx2>=2.10",
51
68
  "obstore>=0.10.0", # the bucket extra, present in dev so the suite tests it
69
+ # the motion extra, present in dev so the suite tests it rather than
70
+ # skipping the one check that cannot be verified any other way
71
+ "opencv-python-headless>=4.10",
72
+ "pyarrow>=25.0.1", # the arrow extra, present in dev so the suite tests it
52
73
  "pytest>=9.1.1",
53
74
  "pyyaml>=6.0.3",
54
75
  "ruff>=0.16.2",
@@ -65,8 +86,14 @@ build-backend = "uv_build"
65
86
  # trusted first-party packages.
66
87
  exclude-newer = "5 days"
67
88
 
89
+ [tool.uv.workspace]
90
+ members = ["packages/*"]
91
+
92
+ [tool.uv.sources]
93
+ hflow-server = { workspace = true }
94
+
68
95
  [tool.pytest.ini_options]
69
- testpaths = ["tests"]
96
+ testpaths = ["tests", "packages/hflow-server/tests"]
70
97
 
71
98
  [tool.ruff]
72
99
  line-length = 100