physlint 0.2.0a2__tar.gz → 0.3.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.
- physlint-0.3.2/.github/ISSUE_TEMPLATE/evidence-submission.yml +59 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/CHANGELOG.md +27 -4
- {physlint-0.2.0a2 → physlint-0.3.2}/CONTRIBUTING.md +3 -1
- {physlint-0.2.0a2 → physlint-0.3.2}/PKG-INFO +49 -15
- {physlint-0.2.0a2 → physlint-0.3.2}/README.md +48 -14
- physlint-0.3.2/docs/assets/launch/exports/evidence-index.png +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/metrics/downloads.json +2 -2
- physlint-0.3.2/docs/plugins.md +44 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/rules/mvp-rules.md +1 -0
- physlint-0.3.2/docs/validation/compatibility-survey.md +84 -0
- physlint-0.3.2/examples/plugins/idle_prefix.py +79 -0
- physlint-0.3.2/observatory/README.md +23 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/app/ObservatoryTable.tsx +10 -9
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/app/globals.css +35 -3
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/app/layout.tsx +11 -0
- physlint-0.3.2/observatory/app/page.tsx +168 -0
- physlint-0.3.2/observatory/data/comparisons.json +64 -0
- physlint-0.3.2/observatory/data/observations.json +365 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/tests/rendered-html.test.mjs +5 -3
- {physlint-0.2.0a2 → physlint-0.3.2}/pyproject.toml +1 -1
- physlint-0.3.2/src/physlint/__init__.py +6 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/_version.py +1 -1
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/adapters/lerobot.py +24 -9
- physlint-0.3.2/src/physlint/api.py +81 -0
- physlint-0.3.2/src/physlint/cli.py +304 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/config.py +29 -0
- physlint-0.3.2/src/physlint/engine/baseline.py +103 -0
- physlint-0.3.2/src/physlint/engine/cache.py +73 -0
- physlint-0.3.2/src/physlint/engine/compare.py +111 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/engine/planner.py +12 -3
- physlint-0.3.2/src/physlint/engine/runner.py +204 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/models/__init__.py +6 -1
- physlint-0.3.2/src/physlint/models/baseline.py +50 -0
- physlint-0.3.2/src/physlint/models/comparison.py +53 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/models/finding.py +41 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/models/rule.py +1 -0
- physlint-0.3.2/src/physlint/plugins.py +83 -0
- physlint-0.3.2/src/physlint/reporters/__init__.py +42 -0
- physlint-0.2.0a2/src/physlint/reporters/json.py → physlint-0.3.2/src/physlint/reporters/atomic.py +2 -5
- physlint-0.3.2/src/physlint/reporters/html.py +113 -0
- physlint-0.3.2/src/physlint/reporters/json.py +12 -0
- physlint-0.3.2/src/physlint/reporters/junit.py +60 -0
- physlint-0.3.2/src/physlint/reporters/sarif.py +81 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/reporters/terminal.py +55 -0
- physlint-0.3.2/src/physlint/rules/__init__.py +32 -0
- physlint-0.3.2/src/physlint/rules/duplication.py +76 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/tests/test_adapter.py +10 -0
- physlint-0.3.2/tests/test_baseline.py +55 -0
- physlint-0.3.2/tests/test_cache.py +37 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/tests/test_cli.py +47 -2
- physlint-0.3.2/tests/test_compare.py +44 -0
- physlint-0.3.2/tests/test_observatory_data.py +17 -0
- physlint-0.3.2/tests/test_plugins.py +27 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/tests/test_release_metadata.py +3 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/tests/test_report.py +3 -1
- physlint-0.3.2/tests/test_reporters.py +29 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/tests/test_rules.py +9 -0
- physlint-0.3.2/tests/test_survey_harness.py +105 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/uv.lock +1 -1
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/README.md +10 -0
- physlint-0.3.2/validation/build_observatory.py +232 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/manifest.yaml +1 -1
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/mcap_manifest.yaml +1 -1
- physlint-0.3.2/validation/reports/lerobot-survey-2026-08-30/check-aloha-battery.json +239 -0
- physlint-0.3.2/validation/reports/lerobot-survey-2026-08-30/check-lekiwi-go2.json +236 -0
- physlint-0.3.2/validation/reports/lerobot-survey-2026-08-30/check-libero-spatial.json +273 -0
- physlint-0.3.2/validation/reports/lerobot-survey-2026-08-30/check-pusht.json +1589 -0
- physlint-0.3.2/validation/reports/lerobot-survey-2026-08-30/check-reachy-head.json +308 -0
- physlint-0.3.2/validation/reports/lerobot-survey-2026-08-30/check-so100-pickplace.json +236 -0
- physlint-0.3.2/validation/reports/lerobot-survey-2026-08-30/check-so101-teleop.json +1587 -0
- physlint-0.3.2/validation/reports/lerobot-survey-2026-08-30/check-unitree-h1-greet.json +237 -0
- physlint-0.3.2/validation/reports/lerobot-survey-2026-08-30/check-ur10e-robotiq.json +345 -0
- physlint-0.3.2/validation/reports/lerobot-survey-2026-08-30/check-xarm-lift.json +237 -0
- physlint-0.3.2/validation/reports/lerobot-survey-2026-08-30/summary.csv +16 -0
- physlint-0.3.2/validation/reports/lerobot-survey-2026-08-30/summary.json +360 -0
- physlint-0.3.2/validation/reports/lerobot-survey-2026-08-30/summary.sha256 +1 -0
- physlint-0.3.2/validation/survey_harness.py +364 -0
- physlint-0.3.2/validation/survey_manifest.yaml +181 -0
- physlint-0.2.0a2/observatory/README.md +0 -15
- physlint-0.2.0a2/observatory/app/page.tsx +0 -71
- physlint-0.2.0a2/observatory/data/observations.json +0 -129
- physlint-0.2.0a2/src/physlint/__init__.py +0 -6
- physlint-0.2.0a2/src/physlint/api.py +0 -29
- physlint-0.2.0a2/src/physlint/cli.py +0 -184
- physlint-0.2.0a2/src/physlint/engine/runner.py +0 -149
- physlint-0.2.0a2/src/physlint/reporters/__init__.py +0 -1
- physlint-0.2.0a2/src/physlint/rules/__init__.py +0 -22
- physlint-0.2.0a2/tests/test_observatory_data.py +0 -11
- physlint-0.2.0a2/validation/build_observatory.py +0 -85
- {physlint-0.2.0a2 → physlint-0.3.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/.github/ISSUE_TEMPLATE/false-positive.yml +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/.github/ISSUE_TEMPLATE/format-request.yml +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/.github/scripts/update_download_metrics.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/.github/workflows/ci.yml +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/.github/workflows/download-metrics.yml +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/.github/workflows/publish-testpypi.yml +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/.github/workflows/publish.yml +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/.github/workflows/real-data-validation.yml +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/.gitignore +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/LICENSE +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/SECURITY.md +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/adapters/lerobot.md +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/adapters/mcap-ros2.md +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/assets/launch/exports/clean-validation.png +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/assets/launch/exports/controlled-nan-failure.png +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/assets/launch/exports/format-compatibility.png +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/assets/launch/exports/validation-summary.png +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/assets/launch/validation-summary.png +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/assets/launch/validation-summary.svg +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/design/mcap-ros.md +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/launch/README.md +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/launch/capture-assets.md +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/launch/post-templates.md +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/roadmap.md +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/rules/mcap-ros2-rules.md +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/validation/mcap-ros2-2026-08-27.md +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/docs/validation/real-data-2026-08-23.md +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/.gitignore +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/.openai/hosting.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/app/chatgpt-auth.ts +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/db/index.ts +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/db/schema.ts +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/drizzle/meta/_journal.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/drizzle.config.ts +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/eslint.config.mjs +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/examples/d1/app/api/notes/route.ts +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/examples/d1/db/schema.ts +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/next-env.d.ts +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/next.config.ts +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/package-lock.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/package.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/postcss.config.mjs +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/public/favicon.png +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/public/favicon.svg +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/public/file.svg +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/public/globe.svg +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/public/physlint-observatory-social.png +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/public/window.svg +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/tsconfig.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/vite.config.ts +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/observatory/worker/index.ts +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/adapters/__init__.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/adapters/base.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/adapters/mcap.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/corruptions.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/engine/__init__.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/engine/discovery.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/models/dataset.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/models/mcap.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/py.typed +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/rules/common.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/rules/manifest.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/rules/mcap.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/rules/numeric.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/rules/temporal.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/src/physlint/rules/video.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/tests/conftest.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/tests/test_config.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/tests/test_corruptions.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/tests/test_mcap_adapter.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/tests/test_mcap_rules.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/tests/test_mcap_validation_harness.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/tests/test_prepare_demo.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/tests/test_validation_harness.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/__init__.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/harness.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/mcap_harness.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/prepare_demo.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/render_assets.py +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/mcap-ros2-2026-08-26/foxglove-ten-messages.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/mcap-ros2-2026-08-26/robotis-arx5-button.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/mcap-ros2-2026-08-26/ros2-joint-state-clean.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/mcap-ros2-2026-08-26/ros2-joint-state-corrupt.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/mcap-ros2-2026-08-26/summary.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/real-data-2026-08-24/clean-panda.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/real-data-2026-08-24/clean-rover.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/real-data-2026-08-24/clean-sentinel.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/real-data-2026-08-24/clean-so101.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/real-data-2026-08-24/corruption-nan.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/real-data-2026-08-24/corruption-reordered.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/real-data-2026-08-24/corruption-truncated.json +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/real-data-2026-08-24/summary.csv +0 -0
- {physlint-0.2.0a2 → physlint-0.3.2}/validation/reports/real-data-2026-08-24/summary.json +0 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
name: Community evidence submission
|
|
2
|
+
description: Put a public robot dataset or recording on the Physlint Community Evidence Atlas.
|
|
3
|
+
title: "[evidence]: "
|
|
4
|
+
labels: ["evidence", "community"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for contributing to the public map of robot data health. Submit only public, non-sensitive sources that can be revision-pinned. Do not attach private datasets, credentials, or reports containing private paths.
|
|
10
|
+
- type: input
|
|
11
|
+
id: source
|
|
12
|
+
attributes:
|
|
13
|
+
label: Public dataset or recording
|
|
14
|
+
description: Link the public repository, dataset, or recording.
|
|
15
|
+
placeholder: https://huggingface.co/datasets/owner/dataset
|
|
16
|
+
validations:
|
|
17
|
+
required: true
|
|
18
|
+
- type: input
|
|
19
|
+
id: revision
|
|
20
|
+
attributes:
|
|
21
|
+
label: Immutable revision
|
|
22
|
+
description: Provide a commit, tag, release, checksum, or other stable revision when available.
|
|
23
|
+
placeholder: Commit SHA, tag, or release identifier
|
|
24
|
+
validations:
|
|
25
|
+
required: true
|
|
26
|
+
- type: dropdown
|
|
27
|
+
id: profile
|
|
28
|
+
attributes:
|
|
29
|
+
label: Data profile
|
|
30
|
+
options:
|
|
31
|
+
- LeRobot
|
|
32
|
+
- Generic MCAP
|
|
33
|
+
- ROS 2 over MCAP
|
|
34
|
+
- Another format
|
|
35
|
+
validations:
|
|
36
|
+
required: true
|
|
37
|
+
- type: textarea
|
|
38
|
+
id: context
|
|
39
|
+
attributes:
|
|
40
|
+
label: Robot and collection context
|
|
41
|
+
description: Tell the community what robot, task, sensors, and collection setup this evidence represents.
|
|
42
|
+
validations:
|
|
43
|
+
required: true
|
|
44
|
+
- type: textarea
|
|
45
|
+
id: expectation
|
|
46
|
+
attributes:
|
|
47
|
+
label: What should we learn from it?
|
|
48
|
+
description: Describe whether you expect a healthy result, a known defect, or a finding that needs review.
|
|
49
|
+
validations:
|
|
50
|
+
required: true
|
|
51
|
+
- type: checkboxes
|
|
52
|
+
id: consent
|
|
53
|
+
attributes:
|
|
54
|
+
label: Publication agreement
|
|
55
|
+
options:
|
|
56
|
+
- label: I confirm this source is public and may be referenced by name in the Community Evidence Atlas.
|
|
57
|
+
required: true
|
|
58
|
+
- label: I understand Physlint will publish scoped validation evidence, not a safety certification or universal quality score.
|
|
59
|
+
required: true
|
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.2 — 2026-09-06
|
|
4
|
+
|
|
5
|
+
- Launch the Physlint Community Evidence Atlas with 23 published observations, community survey context, real defect stories, and stable evidence links.
|
|
6
|
+
- Add a public evidence-submission workflow for dataset and recording maintainers.
|
|
7
|
+
- Replace the public regressions section with a clearer community narrative while retaining the generated comparison catalog for reproducibility.
|
|
8
|
+
- Refresh the PyPI monthly download snapshot to 289 downloads.
|
|
9
|
+
|
|
10
|
+
## 0.3.1 — 2026-08-30
|
|
11
|
+
|
|
12
|
+
- Add a stratified LeRobot compatibility survey, kept separate from the four-snapshot release gate.
|
|
13
|
+
- Accept Hub feature `names` stored as a single string instead of crashing discovery.
|
|
14
|
+
|
|
15
|
+
## 0.3.0 — 2026-08-30
|
|
16
|
+
|
|
17
|
+
- Add `physlint compare` for dataset and report regression diffs, including coverage drift without a quality score.
|
|
18
|
+
- Add reviewed baselines via `physlint baseline` and `--baseline`; suppressions require fingerprint, rule ID, author, reason, and optional expiry.
|
|
19
|
+
- Add JUnit, SARIF, and local HTML reporters alongside versioned JSON.
|
|
20
|
+
- Add a plugin loader for `module:Class` specs and `physlint.rules` entry points, plus an example idle-prefix rule.
|
|
21
|
+
- Cache expensive video rule results on disk, keyed by source fingerprint and rule options.
|
|
22
|
+
- Detect exact duplicate numeric episodes with `duplication.exact_episodes`.
|
|
23
|
+
- Publish Observatory regression evidence generated from committed clean-versus-corruption reports.
|
|
24
|
+
|
|
25
|
+
## 0.2.0a2
|
|
26
|
+
|
|
27
|
+
- Refined the Physlint Observatory launch experience and branding.
|
|
28
|
+
- Continued validation coverage for LeRobot, MCAP, and ROS 2 workflows.
|
|
29
|
+
|
|
3
30
|
## 0.2.0a1 — development
|
|
4
31
|
|
|
5
32
|
- Add standalone generic MCAP discovery, content fingerprints, CRC-aware scanning, and seven container rules.
|
|
@@ -21,7 +48,3 @@
|
|
|
21
48
|
- Add a reproducible four-dataset and three-corruption release gate.
|
|
22
49
|
|
|
23
50
|
This alpha supports local LeRobot v3.x directories. MCAP/ROS 2 and Robomimic are roadmap items, not implemented adapters.
|
|
24
|
-
## 0.2.0a2
|
|
25
|
-
|
|
26
|
-
- Refined the Physlint Observatory launch experience and branding.
|
|
27
|
-
- Continued validation coverage for LeRobot, MCAP, and ROS 2 workflows.
|
|
@@ -9,10 +9,12 @@ mypy
|
|
|
9
9
|
pytest
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
Rules must include positive and negative fixtures, a controlled corruption test where applicable, stable evidence and remediation, documented limitations, and a characterized cost. Adapters must remain read-only, metadata-first, lazy over samples, and explicit about capabilities.
|
|
12
|
+
Rules must include positive and negative fixtures, a controlled corruption test where applicable, stable evidence and remediation, documented limitations, and a characterized cost. Adapters must remain read-only, metadata-first, lazy over samples, and explicit about capabilities. External rules should follow [docs/plugins.md](docs/plugins.md).
|
|
13
13
|
|
|
14
14
|
New adapter proposals should start with the format-request issue template and include immutable public healthy examples, controlled defects, stream/episode semantics, and the real failure modes the adapter should catch. See `docs/roadmap.md` for the acceptance gate.
|
|
15
15
|
|
|
16
16
|
The pinned public release gate is intentionally separate from normal CI because it downloads hundreds of MiB. Maintainers can run it locally with `python -m validation.harness` or trigger the manual real-data workflow.
|
|
17
17
|
|
|
18
|
+
The compatibility survey is also separate from CI and from the release gate. It downloads a stratified public corpus and records outcomes without requiring a pass. Run `python -m validation.survey_harness` and read `docs/validation/compatibility-survey.md` before adding Hub datasets. Do not promote a survey row into the release gate until every finding has been classified by hand.
|
|
19
|
+
|
|
18
20
|
Do not add network access, telemetry, source-data mutation, large fixtures, or a new default dependency without an issue describing the measured requirement.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: physlint
|
|
3
|
-
Version: 0.2
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Local-first integrity validation for physical-AI and robot-learning data
|
|
5
5
|
Project-URL: Homepage, https://github.com/pranayjoshi/physlint
|
|
6
6
|
Project-URL: Documentation, https://github.com/pranayjoshi/physlint#readme
|
|
@@ -54,17 +54,19 @@ Local-first, deterministic validation for physical-AI recordings and robot-learn
|
|
|
54
54
|
[](https://pypistats.org/packages/physlint)
|
|
55
55
|

|
|
56
56
|
[](LICENSE)
|
|
57
|
-

|
|
58
58
|
|
|
59
59
|
[Quickstart](#quickstart) · [Demo](#see-it-catch-a-real-defect) · [Rules](#what-physlint-checks) · [Evidence](#reproducible-public-data-evidence) · [Observatory](#physlint-observatory) · [Roadmap](#format-roadmap) · [Contributing](#contributing)
|
|
60
60
|
|
|
61
|
-
<img src="docs/assets/launch/exports/
|
|
61
|
+
<img src="docs/assets/launch/exports/evidence-index.png" alt="Physlint evidence index showing robot dataset and recording health checks across LeRobot, MCAP, and ROS 2 data." width="100%">
|
|
62
62
|
|
|
63
63
|
</div>
|
|
64
64
|
|
|
65
65
|
Physlint finds concrete integrity defects before robot data reaches training. It explains the impact, identifies the affected episode and stream, recommends remediation, writes a stable JSON report, and returns a CI-safe exit code.
|
|
66
66
|
|
|
67
|
-
The released `0.
|
|
67
|
+
The released `0.3.2` supports **LeRobot Dataset v3.x**, generic **MCAP** container validation, and a **ROS 2-over-MCAP** semantic profile, plus dataset comparison, reviewed baselines, CI report formats, and a plugin SDK. It also launches the [Community Evidence Atlas](https://physlint.com), where maintainers can explore reproducible findings and submit public robot data for inclusion. Claims stay scoped to pinned conformance data and controlled evidence. Native rosbag2 SQLite remains a conversion workflow.
|
|
68
|
+
|
|
69
|
+
At the `0.3.2` release snapshot, PyPI Stats reported **289 downloads in the preceding month**.
|
|
68
70
|
|
|
69
71
|
> [!IMPORTANT]
|
|
70
72
|
> Physlint validates configured data-integrity contracts. A pass does not certify policy quality, task success, or robot safety.
|
|
@@ -84,13 +86,13 @@ Physlint requires Python 3.11 or newer.
|
|
|
84
86
|
### Install from PyPI
|
|
85
87
|
|
|
86
88
|
```bash
|
|
87
|
-
python -m pip install "physlint[video]==0.
|
|
89
|
+
python -m pip install "physlint[video]==0.3.2"
|
|
88
90
|
```
|
|
89
91
|
|
|
90
92
|
To test the exact tagged source instead of the PyPI distribution, install the GitHub release directly:
|
|
91
93
|
|
|
92
94
|
```bash
|
|
93
|
-
python -m pip install "physlint[video] @ git+https://github.com/pranayjoshi/physlint.git@v0.
|
|
95
|
+
python -m pip install "physlint[video] @ git+https://github.com/pranayjoshi/physlint.git@v0.3.2"
|
|
94
96
|
```
|
|
95
97
|
|
|
96
98
|
### Check a LeRobot dataset or MCAP recording
|
|
@@ -106,12 +108,29 @@ physlint check /path/to/recording.mcap
|
|
|
106
108
|
physlint inspect /path/to/recording.mcap --profile ros2
|
|
107
109
|
```
|
|
108
110
|
|
|
109
|
-
Write JSON to
|
|
111
|
+
Write JSON, JUnit, SARIF, or HTML to exact destinations:
|
|
110
112
|
|
|
111
113
|
```bash
|
|
112
114
|
physlint check /path/to/lerobot-dataset \
|
|
113
115
|
--output json \
|
|
114
|
-
--json-output artifacts/physlint-report.json
|
|
116
|
+
--json-output artifacts/physlint-report.json \
|
|
117
|
+
--junit-output artifacts/physlint.junit.xml \
|
|
118
|
+
--sarif-output artifacts/physlint.sarif \
|
|
119
|
+
--html-output artifacts/physlint.html
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Compare two dataset versions or previously written reports:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
physlint compare /path/to/previous /path/to/current
|
|
126
|
+
physlint compare artifacts/previous.json artifacts/current.json --output json
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Accept known findings into a reviewed baseline. New fingerprints of the same rule still fail:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
physlint baseline /path/to/dataset --author ada --reason "station clock offset" --output .physlint/baseline.yaml
|
|
133
|
+
physlint check /path/to/dataset --baseline .physlint/baseline.yaml
|
|
115
134
|
```
|
|
116
135
|
|
|
117
136
|
The source remains untouched. Exit code `0` means the configured contract passed; `1` means validation completed with a blocking finding.
|
|
@@ -135,7 +154,7 @@ Physlint owns NaN and infinity semantics in `numeric.finite_values`; the same sa
|
|
|
135
154
|
|
|
136
155
|
## What Physlint checks
|
|
137
156
|
|
|
138
|
-
Thirty-
|
|
157
|
+
Thirty-two deterministic rules are installed. Physlint plans only the rules for the detected adapter and profile:
|
|
139
158
|
|
|
140
159
|
| Area | Checks |
|
|
141
160
|
|---|---|
|
|
@@ -144,6 +163,7 @@ Thirty-one deterministic rules are installed. Physlint plans only the rules for
|
|
|
144
163
|
| **Temporal** | Strictly monotonic timestamps, FPS cadence, FPS-aware maximum gaps, complete stream overlap, and observation/action delay when independently timestamped |
|
|
145
164
|
| **Numeric** | NaN/Inf, configured physical bounds, and configured discontinuity limits |
|
|
146
165
|
| **Video** | Complete decode, motion-aware frozen-frame runs, and grouped black/near-empty frames |
|
|
166
|
+
| **Duplication** | Exact numeric episode copies |
|
|
147
167
|
| **MCAP** | Record/CRC readability, summary consistency, index coverage, channel/schema coherence, timestamp order, duplicate timestamps, and sequence continuity |
|
|
148
168
|
| **ROS 2** | Portable CDR schemas, full decode, required topics, cadence gaps, configured header/log skew, known message invariants, and TF parent consistency |
|
|
149
169
|
|
|
@@ -158,7 +178,7 @@ physlint explain video.frozen_frames
|
|
|
158
178
|
|
|
159
179
|
Rules whose required inputs are unavailable return `not_run` with a reason; they are never misreported as passed. Robot-specific bounds and discontinuity checks stay `not_run` until the user supplies meaningful thresholds.
|
|
160
180
|
|
|
161
|
-
Read the complete [LeRobot MVP rules](docs/rules/mvp-rules.md)
|
|
181
|
+
Read the complete [LeRobot MVP rules](docs/rules/mvp-rules.md), [MCAP/ROS 2 rules](docs/rules/mcap-ros2-rules.md), and [plugin SDK](docs/plugins.md). Task-specific checks stay out of the default contract; load them with `plugins:` or a `physlint.rules` entry point.
|
|
162
182
|
|
|
163
183
|
For ROS 2 contracts, configure the topics and timing assumptions that Physlint cannot infer honestly:
|
|
164
184
|
|
|
@@ -220,7 +240,16 @@ rules:
|
|
|
220
240
|
|
|
221
241
|
reports:
|
|
222
242
|
json: true
|
|
243
|
+
junit: false
|
|
244
|
+
sarif: false
|
|
245
|
+
html: false
|
|
223
246
|
output_dir: .physlint/reports
|
|
247
|
+
cache:
|
|
248
|
+
enabled: true
|
|
249
|
+
directory: .physlint/cache
|
|
250
|
+
# baseline: .physlint/baseline.yaml
|
|
251
|
+
# plugins:
|
|
252
|
+
# - ./rules/idle_prefix.py:IdlePrefixRule
|
|
224
253
|
```
|
|
225
254
|
|
|
226
255
|
Use it explicitly when needed:
|
|
@@ -237,12 +266,14 @@ The CLI has stable exit codes and writes reports atomically, so a basic GitHub A
|
|
|
237
266
|
|
|
238
267
|
```yaml
|
|
239
268
|
- name: Install Physlint
|
|
240
|
-
run: python -m pip install "physlint[video]==0.
|
|
269
|
+
run: python -m pip install "physlint[video]==0.3.2"
|
|
241
270
|
|
|
242
271
|
- name: Validate robot dataset
|
|
243
272
|
run: |
|
|
244
273
|
physlint check "$DATASET_PATH" \
|
|
245
|
-
--json-output artifacts/physlint-report.json
|
|
274
|
+
--json-output artifacts/physlint-report.json \
|
|
275
|
+
--junit-output artifacts/physlint.junit.xml \
|
|
276
|
+
--sarif-output artifacts/physlint.sarif
|
|
246
277
|
|
|
247
278
|
- uses: actions/upload-artifact@v4
|
|
248
279
|
if: always()
|
|
@@ -254,7 +285,7 @@ The CLI has stable exit codes and writes reports atomically, so a basic GitHub A
|
|
|
254
285
|
| Exit code | Meaning |
|
|
255
286
|
|---:|---|
|
|
256
287
|
| `0` | Validation completed and the configured contract passed |
|
|
257
|
-
| `1` | Validation completed and the contract failed |
|
|
288
|
+
| `1` | Validation completed and the contract failed, or `compare` found a regression |
|
|
258
289
|
| `2` | Invalid command or configuration |
|
|
259
290
|
| `3` | Dataset or adapter failure |
|
|
260
291
|
| `4` | Internal Physlint error |
|
|
@@ -284,6 +315,8 @@ Everything needed to audit or rerun those claims is versioned:
|
|
|
284
315
|
|
|
285
316
|
Runtime measurements are observations from the documented machine and run—not universal performance guarantees.
|
|
286
317
|
|
|
318
|
+
A larger [compatibility survey](docs/validation/compatibility-survey.md) adds ten revision-pinned public LeRobot v3 snapshots (1,678 episodes, 182,128 frames) plus five fail-closed v2 screens. Five of the ten v3 snapshots passed the default contract; the rest are classified in that report. Those rows are Observatory survey evidence. They do not expand the four-snapshot release claim and they are not a Hugging Face quality score.
|
|
319
|
+
|
|
287
320
|
The MCAP/ROS 2 release gate additionally verifies an exact Foxglove conformance fixture, a public robot-captured RobotisAI episode, and two deterministic ROS 2 recordings:
|
|
288
321
|
|
|
289
322
|
| Recording | Profile | Provenance | Checks | Expected outcome |
|
|
@@ -297,7 +330,7 @@ See the [MCAP/ROS 2 manifest](validation/mcap_manifest.yaml), [reproduction harn
|
|
|
297
330
|
|
|
298
331
|
## Physlint Observatory
|
|
299
332
|
|
|
300
|
-
The repository now includes the
|
|
333
|
+
The repository now includes the [Physlint Community Evidence Atlas](observatory/): a profile-aware public map spanning LeRobot, MCAP, and ROS 2, with real defect stories and a contribution path for dataset maintainers. It deliberately does not collapse unlike contracts into one universal quality score. Every row exposes provenance, applicable checks, findings, a stable share link, and a sanitized report.
|
|
301
334
|
|
|
302
335
|
## Format roadmap
|
|
303
336
|
|
|
@@ -389,6 +422,7 @@ Contributions are welcome, particularly:
|
|
|
389
422
|
- False-positive reproductions
|
|
390
423
|
- MCAP/ROS recording schemas and failure modes
|
|
391
424
|
- New deterministic rules with controlled corruptions
|
|
425
|
+
- Plugin rules that follow the [plugin SDK](docs/plugins.md)
|
|
392
426
|
- Documentation, performance characterization, and privacy reviews
|
|
393
427
|
|
|
394
428
|
Development setup:
|
|
@@ -410,7 +444,7 @@ Read [CONTRIBUTING.md](CONTRIBUTING.md), open a format request, or join [GitHub
|
|
|
410
444
|
|
|
411
445
|
## Project status
|
|
412
446
|
|
|
413
|
-
Physlint is
|
|
447
|
+
Physlint is released. Its claims are deliberately limited to the documented LeRobot, generic MCAP, and ROS 2-over-MCAP boundaries and their committed evidence. The project does not train policies, repair data, host datasets, infer task success, produce an opaque quality score, or certify that a robot or policy is safe.
|
|
414
448
|
|
|
415
449
|
See [CHANGELOG.md](CHANGELOG.md) for release notes.
|
|
416
450
|
|
|
@@ -11,17 +11,19 @@ Local-first, deterministic validation for physical-AI recordings and robot-learn
|
|
|
11
11
|
[](https://pypistats.org/packages/physlint)
|
|
12
12
|

|
|
13
13
|
[](LICENSE)
|
|
14
|
-

|
|
15
15
|
|
|
16
16
|
[Quickstart](#quickstart) · [Demo](#see-it-catch-a-real-defect) · [Rules](#what-physlint-checks) · [Evidence](#reproducible-public-data-evidence) · [Observatory](#physlint-observatory) · [Roadmap](#format-roadmap) · [Contributing](#contributing)
|
|
17
17
|
|
|
18
|
-
<img src="docs/assets/launch/exports/
|
|
18
|
+
<img src="docs/assets/launch/exports/evidence-index.png" alt="Physlint evidence index showing robot dataset and recording health checks across LeRobot, MCAP, and ROS 2 data." width="100%">
|
|
19
19
|
|
|
20
20
|
</div>
|
|
21
21
|
|
|
22
22
|
Physlint finds concrete integrity defects before robot data reaches training. It explains the impact, identifies the affected episode and stream, recommends remediation, writes a stable JSON report, and returns a CI-safe exit code.
|
|
23
23
|
|
|
24
|
-
The released `0.
|
|
24
|
+
The released `0.3.2` supports **LeRobot Dataset v3.x**, generic **MCAP** container validation, and a **ROS 2-over-MCAP** semantic profile, plus dataset comparison, reviewed baselines, CI report formats, and a plugin SDK. It also launches the [Community Evidence Atlas](https://physlint.com), where maintainers can explore reproducible findings and submit public robot data for inclusion. Claims stay scoped to pinned conformance data and controlled evidence. Native rosbag2 SQLite remains a conversion workflow.
|
|
25
|
+
|
|
26
|
+
At the `0.3.2` release snapshot, PyPI Stats reported **289 downloads in the preceding month**.
|
|
25
27
|
|
|
26
28
|
> [!IMPORTANT]
|
|
27
29
|
> Physlint validates configured data-integrity contracts. A pass does not certify policy quality, task success, or robot safety.
|
|
@@ -41,13 +43,13 @@ Physlint requires Python 3.11 or newer.
|
|
|
41
43
|
### Install from PyPI
|
|
42
44
|
|
|
43
45
|
```bash
|
|
44
|
-
python -m pip install "physlint[video]==0.
|
|
46
|
+
python -m pip install "physlint[video]==0.3.2"
|
|
45
47
|
```
|
|
46
48
|
|
|
47
49
|
To test the exact tagged source instead of the PyPI distribution, install the GitHub release directly:
|
|
48
50
|
|
|
49
51
|
```bash
|
|
50
|
-
python -m pip install "physlint[video] @ git+https://github.com/pranayjoshi/physlint.git@v0.
|
|
52
|
+
python -m pip install "physlint[video] @ git+https://github.com/pranayjoshi/physlint.git@v0.3.2"
|
|
51
53
|
```
|
|
52
54
|
|
|
53
55
|
### Check a LeRobot dataset or MCAP recording
|
|
@@ -63,12 +65,29 @@ physlint check /path/to/recording.mcap
|
|
|
63
65
|
physlint inspect /path/to/recording.mcap --profile ros2
|
|
64
66
|
```
|
|
65
67
|
|
|
66
|
-
Write JSON to
|
|
68
|
+
Write JSON, JUnit, SARIF, or HTML to exact destinations:
|
|
67
69
|
|
|
68
70
|
```bash
|
|
69
71
|
physlint check /path/to/lerobot-dataset \
|
|
70
72
|
--output json \
|
|
71
|
-
--json-output artifacts/physlint-report.json
|
|
73
|
+
--json-output artifacts/physlint-report.json \
|
|
74
|
+
--junit-output artifacts/physlint.junit.xml \
|
|
75
|
+
--sarif-output artifacts/physlint.sarif \
|
|
76
|
+
--html-output artifacts/physlint.html
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Compare two dataset versions or previously written reports:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
physlint compare /path/to/previous /path/to/current
|
|
83
|
+
physlint compare artifacts/previous.json artifacts/current.json --output json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Accept known findings into a reviewed baseline. New fingerprints of the same rule still fail:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
physlint baseline /path/to/dataset --author ada --reason "station clock offset" --output .physlint/baseline.yaml
|
|
90
|
+
physlint check /path/to/dataset --baseline .physlint/baseline.yaml
|
|
72
91
|
```
|
|
73
92
|
|
|
74
93
|
The source remains untouched. Exit code `0` means the configured contract passed; `1` means validation completed with a blocking finding.
|
|
@@ -92,7 +111,7 @@ Physlint owns NaN and infinity semantics in `numeric.finite_values`; the same sa
|
|
|
92
111
|
|
|
93
112
|
## What Physlint checks
|
|
94
113
|
|
|
95
|
-
Thirty-
|
|
114
|
+
Thirty-two deterministic rules are installed. Physlint plans only the rules for the detected adapter and profile:
|
|
96
115
|
|
|
97
116
|
| Area | Checks |
|
|
98
117
|
|---|---|
|
|
@@ -101,6 +120,7 @@ Thirty-one deterministic rules are installed. Physlint plans only the rules for
|
|
|
101
120
|
| **Temporal** | Strictly monotonic timestamps, FPS cadence, FPS-aware maximum gaps, complete stream overlap, and observation/action delay when independently timestamped |
|
|
102
121
|
| **Numeric** | NaN/Inf, configured physical bounds, and configured discontinuity limits |
|
|
103
122
|
| **Video** | Complete decode, motion-aware frozen-frame runs, and grouped black/near-empty frames |
|
|
123
|
+
| **Duplication** | Exact numeric episode copies |
|
|
104
124
|
| **MCAP** | Record/CRC readability, summary consistency, index coverage, channel/schema coherence, timestamp order, duplicate timestamps, and sequence continuity |
|
|
105
125
|
| **ROS 2** | Portable CDR schemas, full decode, required topics, cadence gaps, configured header/log skew, known message invariants, and TF parent consistency |
|
|
106
126
|
|
|
@@ -115,7 +135,7 @@ physlint explain video.frozen_frames
|
|
|
115
135
|
|
|
116
136
|
Rules whose required inputs are unavailable return `not_run` with a reason; they are never misreported as passed. Robot-specific bounds and discontinuity checks stay `not_run` until the user supplies meaningful thresholds.
|
|
117
137
|
|
|
118
|
-
Read the complete [LeRobot MVP rules](docs/rules/mvp-rules.md)
|
|
138
|
+
Read the complete [LeRobot MVP rules](docs/rules/mvp-rules.md), [MCAP/ROS 2 rules](docs/rules/mcap-ros2-rules.md), and [plugin SDK](docs/plugins.md). Task-specific checks stay out of the default contract; load them with `plugins:` or a `physlint.rules` entry point.
|
|
119
139
|
|
|
120
140
|
For ROS 2 contracts, configure the topics and timing assumptions that Physlint cannot infer honestly:
|
|
121
141
|
|
|
@@ -177,7 +197,16 @@ rules:
|
|
|
177
197
|
|
|
178
198
|
reports:
|
|
179
199
|
json: true
|
|
200
|
+
junit: false
|
|
201
|
+
sarif: false
|
|
202
|
+
html: false
|
|
180
203
|
output_dir: .physlint/reports
|
|
204
|
+
cache:
|
|
205
|
+
enabled: true
|
|
206
|
+
directory: .physlint/cache
|
|
207
|
+
# baseline: .physlint/baseline.yaml
|
|
208
|
+
# plugins:
|
|
209
|
+
# - ./rules/idle_prefix.py:IdlePrefixRule
|
|
181
210
|
```
|
|
182
211
|
|
|
183
212
|
Use it explicitly when needed:
|
|
@@ -194,12 +223,14 @@ The CLI has stable exit codes and writes reports atomically, so a basic GitHub A
|
|
|
194
223
|
|
|
195
224
|
```yaml
|
|
196
225
|
- name: Install Physlint
|
|
197
|
-
run: python -m pip install "physlint[video]==0.
|
|
226
|
+
run: python -m pip install "physlint[video]==0.3.2"
|
|
198
227
|
|
|
199
228
|
- name: Validate robot dataset
|
|
200
229
|
run: |
|
|
201
230
|
physlint check "$DATASET_PATH" \
|
|
202
|
-
--json-output artifacts/physlint-report.json
|
|
231
|
+
--json-output artifacts/physlint-report.json \
|
|
232
|
+
--junit-output artifacts/physlint.junit.xml \
|
|
233
|
+
--sarif-output artifacts/physlint.sarif
|
|
203
234
|
|
|
204
235
|
- uses: actions/upload-artifact@v4
|
|
205
236
|
if: always()
|
|
@@ -211,7 +242,7 @@ The CLI has stable exit codes and writes reports atomically, so a basic GitHub A
|
|
|
211
242
|
| Exit code | Meaning |
|
|
212
243
|
|---:|---|
|
|
213
244
|
| `0` | Validation completed and the configured contract passed |
|
|
214
|
-
| `1` | Validation completed and the contract failed |
|
|
245
|
+
| `1` | Validation completed and the contract failed, or `compare` found a regression |
|
|
215
246
|
| `2` | Invalid command or configuration |
|
|
216
247
|
| `3` | Dataset or adapter failure |
|
|
217
248
|
| `4` | Internal Physlint error |
|
|
@@ -241,6 +272,8 @@ Everything needed to audit or rerun those claims is versioned:
|
|
|
241
272
|
|
|
242
273
|
Runtime measurements are observations from the documented machine and run—not universal performance guarantees.
|
|
243
274
|
|
|
275
|
+
A larger [compatibility survey](docs/validation/compatibility-survey.md) adds ten revision-pinned public LeRobot v3 snapshots (1,678 episodes, 182,128 frames) plus five fail-closed v2 screens. Five of the ten v3 snapshots passed the default contract; the rest are classified in that report. Those rows are Observatory survey evidence. They do not expand the four-snapshot release claim and they are not a Hugging Face quality score.
|
|
276
|
+
|
|
244
277
|
The MCAP/ROS 2 release gate additionally verifies an exact Foxglove conformance fixture, a public robot-captured RobotisAI episode, and two deterministic ROS 2 recordings:
|
|
245
278
|
|
|
246
279
|
| Recording | Profile | Provenance | Checks | Expected outcome |
|
|
@@ -254,7 +287,7 @@ See the [MCAP/ROS 2 manifest](validation/mcap_manifest.yaml), [reproduction harn
|
|
|
254
287
|
|
|
255
288
|
## Physlint Observatory
|
|
256
289
|
|
|
257
|
-
The repository now includes the
|
|
290
|
+
The repository now includes the [Physlint Community Evidence Atlas](observatory/): a profile-aware public map spanning LeRobot, MCAP, and ROS 2, with real defect stories and a contribution path for dataset maintainers. It deliberately does not collapse unlike contracts into one universal quality score. Every row exposes provenance, applicable checks, findings, a stable share link, and a sanitized report.
|
|
258
291
|
|
|
259
292
|
## Format roadmap
|
|
260
293
|
|
|
@@ -346,6 +379,7 @@ Contributions are welcome, particularly:
|
|
|
346
379
|
- False-positive reproductions
|
|
347
380
|
- MCAP/ROS recording schemas and failure modes
|
|
348
381
|
- New deterministic rules with controlled corruptions
|
|
382
|
+
- Plugin rules that follow the [plugin SDK](docs/plugins.md)
|
|
349
383
|
- Documentation, performance characterization, and privacy reviews
|
|
350
384
|
|
|
351
385
|
Development setup:
|
|
@@ -367,7 +401,7 @@ Read [CONTRIBUTING.md](CONTRIBUTING.md), open a format request, or join [GitHub
|
|
|
367
401
|
|
|
368
402
|
## Project status
|
|
369
403
|
|
|
370
|
-
Physlint is
|
|
404
|
+
Physlint is released. Its claims are deliberately limited to the documented LeRobot, generic MCAP, and ROS 2-over-MCAP boundaries and their committed evidence. The project does not train policies, repair data, host datasets, infer task success, produce an opaque quality score, or certify that a robot or policy is safe.
|
|
371
405
|
|
|
372
406
|
See [CHANGELOG.md](CHANGELOG.md) for release notes.
|
|
373
407
|
|
|
Binary file
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"label": "downloads/month",
|
|
4
|
-
"message": "
|
|
4
|
+
"message": "289",
|
|
5
5
|
"color": "brightgreen",
|
|
6
6
|
"cacheSeconds": 86400,
|
|
7
|
-
"updated_at": "2026-
|
|
7
|
+
"updated_at": "2026-09-07T02:45:03.175664+00:00",
|
|
8
8
|
"source": "https://pypistats.org/api/packages/physlint/recent?period=month"
|
|
9
9
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Plugin SDK
|
|
2
|
+
|
|
3
|
+
Physlint loads extra rules without putting task-specific heuristics into the default contract. A plugin is a class with `metadata: RuleMetadata` and `run(dataset, options, severity) -> list[Finding]`.
|
|
4
|
+
|
|
5
|
+
## Load from a quality contract
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
config_version: 1
|
|
9
|
+
plugins:
|
|
10
|
+
- ./rules/idle_prefix.py:IdlePrefixRule
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The spec is `module:Class` or `path.py:Class`. Unknown option keys are rejected. Plugin rule IDs must not collide with built-ins.
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
physlint rules --config physlint.yaml
|
|
17
|
+
physlint explain example.idle_prefix --config physlint.yaml
|
|
18
|
+
physlint check /path/to/dataset --config physlint.yaml
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Install via entry points
|
|
22
|
+
|
|
23
|
+
Packaged plugins can register:
|
|
24
|
+
|
|
25
|
+
```toml
|
|
26
|
+
[project.entry-points."physlint.rules"]
|
|
27
|
+
idle_prefix = "my_org_rules:IdlePrefixRule"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Installed entry points are loaded on every run, then config `plugins:` are appended.
|
|
31
|
+
|
|
32
|
+
## Contract
|
|
33
|
+
|
|
34
|
+
- Read-only. Never mutate source data.
|
|
35
|
+
- Deterministic. The same dataset, options, and Physlint version must produce the same fingerprints.
|
|
36
|
+
- Bounded. Honor `max_findings` and avoid embedding images or full samples.
|
|
37
|
+
- Honest. If required capabilities are missing, the engine records `not_run`; do not pass.
|
|
38
|
+
- Documented. Include remediation, limitations, and option defaults.
|
|
39
|
+
|
|
40
|
+
Set `metadata.adapters` to restrict a plugin to `lerobot` or `mcap`. Leave it empty to participate on every adapter that satisfies the required capabilities.
|
|
41
|
+
|
|
42
|
+
## Example
|
|
43
|
+
|
|
44
|
+
`examples/plugins/idle_prefix.py` flags long zero-action prefixes. It is a warning, not a built-in, because idle length is a collection policy rather than a universal integrity failure.
|
|
@@ -36,3 +36,4 @@ Fails for non-positive episode lengths, reversed ranges, a mismatch between decl
|
|
|
36
36
|
- `numeric.discontinuity`: adjacent values respect configured maximum absolute deltas.
|
|
37
37
|
- `video.decode`: decoded frame count matches episode length within tolerance.
|
|
38
38
|
- `video.black_frames`: frame mean and standard deviation are not both near zero; adjacent bad frames are grouped.
|
|
39
|
+
- `duplication.exact_episodes`: numeric observation/action trajectories are unique across episodes.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# LeRobot compatibility survey
|
|
2
|
+
|
|
3
|
+
Status: first wave, 2026-08-30
|
|
4
|
+
Tier: compatibility observations — **not the public release gate**
|
|
5
|
+
|
|
6
|
+
The release gate remains the four pinned snapshots in [`validation/manifest.yaml`](../../validation/manifest.yaml). This survey asks a different question: does the LeRobot v3 adapter stay honest across embodiments, producers, and cadences that those four rows do not cover?
|
|
7
|
+
|
|
8
|
+
It does not attempt to validate Hugging Face robotics data. Hub-scale crawls measure repository hygiene, not Physlint trust.
|
|
9
|
+
|
|
10
|
+
## Method
|
|
11
|
+
|
|
12
|
+
1. Screen Hub candidates from metadata only (`meta/info.json`, size, version, robot, FPS, license/gate).
|
|
13
|
+
2. Keep a snapshot only when it fills an empty diversity cell and is small enough to review findings by hand.
|
|
14
|
+
3. Pin the exact revision. Download into `validation/.work/survey/`, which is gitignored.
|
|
15
|
+
4. Run the default `physlint check`. Record sanitized reports. Do not require a pass.
|
|
16
|
+
5. For published v2.x layouts, download only `meta/info.json` and prove discovery fails closed.
|
|
17
|
+
6. Classify findings against source values before promoting any row into the release gate.
|
|
18
|
+
|
|
19
|
+
## First-wave cells
|
|
20
|
+
|
|
21
|
+
| Cell | Snapshot |
|
|
22
|
+
|---|---|
|
|
23
|
+
| Official 10 FPS / 2D | `lerobot/pusht` |
|
|
24
|
+
| Official xArm / 15 FPS | `lerobot/xarm_lift_medium` |
|
|
25
|
+
| Official humanoid / 50 FPS | `lerobot/unitreeh1_two_robot_greeting` |
|
|
26
|
+
| Official SO-100 / 30 FPS | `lerobot/svla_so100_pickplace` |
|
|
27
|
+
| Community bimanual / 50 FPS | `macrodata/aloha_static_battery_ep000_004` |
|
|
28
|
+
| Industrial arm / 6 FPS | `wenyixu101/ur10e-robotiq-2f85` |
|
|
29
|
+
| Community SO-101 / 25 FPS | `wenyixu101/so101-pick-and-place` |
|
|
30
|
+
| Reachy / 60 FPS | `tavis-benchmark/tavis-head-sample-reachy2` |
|
|
31
|
+
| Mobile base / 30 FPS | `vietnguyen28/lekiwi_go2` |
|
|
32
|
+
| NVIDIA Franka suite | `nvidia/LIBERO_LeRobot_v3` (`libero_spatial`) |
|
|
33
|
+
| Fail-closed v2.0 / v2.1 | Koch, Reachy kitchen, RoboTwin, large SO-101 |
|
|
34
|
+
|
|
35
|
+
Deferred on purpose: official mobile Aloha with `observation.effort` (8.6 GB), 1080p LeKiwi (3.9 GB), 10 GB SO-101 sim, 60 GB BridgeData V2, and multi-terabyte Hub dumps. Those belong in a later size/memory wave, not this survey.
|
|
36
|
+
|
|
37
|
+
## Claims that stay false
|
|
38
|
+
|
|
39
|
+
- “Physlint validated Hugging Face robotics datasets.”
|
|
40
|
+
- “N / M Hub datasets pass.”
|
|
41
|
+
- “N terabytes scanned.”
|
|
42
|
+
|
|
43
|
+
After this wave the honest statement is: the release gate is unchanged; a stratified public survey of N revision-pinned v3 snapshots plus M version-edge screens is committed under `validation/reports/lerobot-survey-2026-08-30/`.
|
|
44
|
+
|
|
45
|
+
## Reproduce
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
python -m pip install -e '.[video,dev]'
|
|
49
|
+
python -m pip install huggingface_hub
|
|
50
|
+
python -m validation.survey_harness
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Use `--only pusht --only koch-v21` to rerun one cell. Pass `--dataset-root ID=PATH` for an offline snapshot. The survey writes sanitized JSON next to `summary.json`; it does not update README release-gate counts.
|
|
54
|
+
|
|
55
|
+
## Results
|
|
56
|
+
|
|
57
|
+
First wave, Physlint `0.3.0`, run `lerobot-survey-2026-08-30`.
|
|
58
|
+
|
|
59
|
+
Checked snapshots: **5 passed, 5 failed, 0 errored** after the string-`names` adapter fix. Version-edge screens: **5/5 rejected**. Coverage: 1,678 episodes and 182,128 frames. The four-snapshot release gate is unchanged.
|
|
60
|
+
|
|
61
|
+
| Snapshot | Result | Applicable | Findings | Classification |
|
|
62
|
+
|---|---|---:|---:|---|
|
|
63
|
+
| `lerobot/pusht` | Fail | 15 | 50 (capped) | Likely false positive. 2D low-texture sim; 6–8 frame freezes with `motion_fraction` 1.0 against a 0.5 pixel MAD. |
|
|
64
|
+
| `lerobot/xarm_lift_medium` | Pass | 15 | 0 | Clean official xArm / 15 FPS. |
|
|
65
|
+
| `lerobot/unitreeh1_two_robot_greeting` | Pass | 15 | 0 | Clean official humanoid / 50 FPS. |
|
|
66
|
+
| `lerobot/svla_so100_pickplace` | Pass | 15 | 0 | Clean official SO-100 / 30 FPS. |
|
|
67
|
+
| `macrodata/aloha_static_battery_ep000_004` | Pass | 15 | 0 | Clean community bimanual / 50 FPS. |
|
|
68
|
+
| `wenyixu101/ur10e-robotiq-2f85` | Fail | 15 | 4 | Review. Four 6-frame holds at 6 FPS (~1 s) during motion; possible sim hold. |
|
|
69
|
+
| `wenyixu101/so101-pick-and-place` | Fail | 15 | 50 (capped) | Likely false positive. All cited ranges are the wrist camera, often 40+ frames, `motion_fraction` ~0.4. |
|
|
70
|
+
| `tavis-benchmark/tavis-head-sample-reachy2` | Fail | 5 | 3 | Confirmed defect. Episode metadata names `file-001/002/004.parquet`; the Hub tree only publishes `file-000.parquet`. |
|
|
71
|
+
| `vietnguyen28/lekiwi_go2` | Pass | 15 | 0 | Clean community mobile base. |
|
|
72
|
+
| `nvidia/LIBERO_LeRobot_v3` `libero_spatial` | Fail | 15 | 1 | Review. One 6-frame freeze at an episode start, `motion_fraction` 0.4. |
|
|
73
|
+
|
|
74
|
+
### Version-edge screens
|
|
75
|
+
|
|
76
|
+
Discovery rejected `v2.0` and `v2.1` metadata for Koch, Reachy kitchen, RoboTwin, and the large SO-101 pi0.5 corpus. That is the required fail-closed behavior.
|
|
77
|
+
|
|
78
|
+
### Product issues
|
|
79
|
+
|
|
80
|
+
1. **Fixed — string feature names.** Reachy stores `action.names` as `"env actions"`. Discovery previously raised a Pydantic `ValidationError`. The adapter now coerces a string name to a one-element list and wraps other invalid feature declarations as `AdapterError`.
|
|
81
|
+
2. **Open — frozen-frame defaults on 2D / wrist / episode-start holds.** Motion correlation is not enough when pixel MAD stays below 0.5. Do not change the default contract from this wave alone; gather more wrist-camera and 2D-sim cases first.
|
|
82
|
+
3. **Open — 50-finding cap.** PushT and the SO-101 teleop set both hit the cap, so the true freeze count is unknown.
|
|
83
|
+
|
|
84
|
+
No failing survey row is promoted into the release gate. Sanitized reports are in [`validation/reports/lerobot-survey-2026-08-30/`](../../validation/reports/lerobot-survey-2026-08-30/).
|