metrifid 0.2.1__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 (200) hide show
  1. metrifid-0.2.1/.github/quality-constraints.txt +11 -0
  2. metrifid-0.2.1/.gitignore +13 -0
  3. metrifid-0.2.1/.pre-commit-config.yaml +23 -0
  4. metrifid-0.2.1/CHANGELOG.md +269 -0
  5. metrifid-0.2.1/CODE_OF_CONDUCT.md +106 -0
  6. metrifid-0.2.1/CONTRIBUTING.md +105 -0
  7. metrifid-0.2.1/DCO +33 -0
  8. metrifid-0.2.1/LICENSE +201 -0
  9. metrifid-0.2.1/NOTICE +7 -0
  10. metrifid-0.2.1/PKG-INFO +213 -0
  11. metrifid-0.2.1/README.md +169 -0
  12. metrifid-0.2.1/SECURITY.md +60 -0
  13. metrifid-0.2.1/docs/canonicalization.md +155 -0
  14. metrifid-0.2.1/docs/capabilities_and_use_cases.md +1280 -0
  15. metrifid-0.2.1/docs/comparison.md +107 -0
  16. metrifid-0.2.1/docs/compiled_certification.md +160 -0
  17. metrifid-0.2.1/docs/getting_started.md +762 -0
  18. metrifid-0.2.1/docs/licensing_and_contributions.md +67 -0
  19. metrifid-0.2.1/docs/menagerie_formatter_case.md +98 -0
  20. metrifid-0.2.1/docs/model_closure.md +87 -0
  21. metrifid-0.2.1/docs/reference.md +179 -0
  22. metrifid-0.2.1/docs/sdk.md +213 -0
  23. metrifid-0.2.1/docs/timestep_audit.md +226 -0
  24. metrifid-0.2.1/docs/workloads.md +65 -0
  25. metrifid-0.2.1/examples/certify/README.md +65 -0
  26. metrifid-0.2.1/examples/certify/changed.xml +14 -0
  27. metrifid-0.2.1/examples/certify/equivalent/baseline.xml +12 -0
  28. metrifid-0.2.1/examples/certify/equivalent/candidate.xml +17 -0
  29. metrifid-0.2.1/examples/certify/run_example.py +114 -0
  30. metrifid-0.2.1/examples/compare/README.md +56 -0
  31. metrifid-0.2.1/examples/compare/baseline/model.xml +12 -0
  32. metrifid-0.2.1/examples/compare/candidate/model.xml +12 -0
  33. metrifid-0.2.1/examples/compare/comparison.json +26 -0
  34. metrifid-0.2.1/examples/compare/prepare_workload.py +91 -0
  35. metrifid-0.2.1/examples/sdk/_shared.py +111 -0
  36. metrifid-0.2.1/examples/sdk/audit_api.py +78 -0
  37. metrifid-0.2.1/examples/sdk/certify_api.py +66 -0
  38. metrifid-0.2.1/examples/sdk/compare_api.py +79 -0
  39. metrifid-0.2.1/pyproject.toml +150 -0
  40. metrifid-0.2.1/src/metrifid/__init__.py +102 -0
  41. metrifid-0.2.1/src/metrifid/_alignment.py +298 -0
  42. metrifid-0.2.1/src/metrifid/_artifact_schemas.py +423 -0
  43. metrifid-0.2.1/src/metrifid/_atomic_output.py +416 -0
  44. metrifid-0.2.1/src/metrifid/_audit_artifacts.py +364 -0
  45. metrifid-0.2.1/src/metrifid/_audit_config.py +370 -0
  46. metrifid-0.2.1/src/metrifid/_audit_execution.py +535 -0
  47. metrifid-0.2.1/src/metrifid/_audit_reporting.py +408 -0
  48. metrifid-0.2.1/src/metrifid/_closure_schemas.py +206 -0
  49. metrifid-0.2.1/src/metrifid/_comparison_schemas.py +29 -0
  50. metrifid-0.2.1/src/metrifid/_composite_dependencies.py +321 -0
  51. metrifid-0.2.1/src/metrifid/_configuration_schemas.py +217 -0
  52. metrifid-0.2.1/src/metrifid/_contract_schemas.py +182 -0
  53. metrifid-0.2.1/src/metrifid/_dependency_reader.py +384 -0
  54. metrifid-0.2.1/src/metrifid/_distribution_constants.py +6 -0
  55. metrifid-0.2.1/src/metrifid/_distribution_manifest.py +352 -0
  56. metrifid-0.2.1/src/metrifid/_distribution_members.py +262 -0
  57. metrifid-0.2.1/src/metrifid/_distribution_types.py +91 -0
  58. metrifid-0.2.1/src/metrifid/_identity_schemas.py +26 -0
  59. metrifid-0.2.1/src/metrifid/_json_admission.py +254 -0
  60. metrifid-0.2.1/src/metrifid/_model_admission.py +37 -0
  61. metrifid-0.2.1/src/metrifid/_model_alignment.py +380 -0
  62. metrifid-0.2.1/src/metrifid/_model_closure.py +821 -0
  63. metrifid-0.2.1/src/metrifid/_model_compile.py +349 -0
  64. metrifid-0.2.1/src/metrifid/_model_dependencies.py +71 -0
  65. metrifid-0.2.1/src/metrifid/_model_descriptor_builders.py +268 -0
  66. metrifid-0.2.1/src/metrifid/_model_descriptor_types.py +306 -0
  67. metrifid-0.2.1/src/metrifid/_model_descriptors.py +39 -0
  68. metrifid-0.2.1/src/metrifid/_model_identity.py +116 -0
  69. metrifid-0.2.1/src/metrifid/_model_identity_types.py +318 -0
  70. metrifid-0.2.1/src/metrifid/_model_identity_validation.py +283 -0
  71. metrifid-0.2.1/src/metrifid/_model_refusal.py +57 -0
  72. metrifid-0.2.1/src/metrifid/_npz.py +274 -0
  73. metrifid-0.2.1/src/metrifid/_operational_registry.py +298 -0
  74. metrifid-0.2.1/src/metrifid/_owned_artifacts.py +388 -0
  75. metrifid-0.2.1/src/metrifid/_receipt_schemas.py +477 -0
  76. metrifid-0.2.1/src/metrifid/_runtime_identity.py +64 -0
  77. metrifid-0.2.1/src/metrifid/_runtime_schemas.py +332 -0
  78. metrifid-0.2.1/src/metrifid/_schema_constants.py +35 -0
  79. metrifid-0.2.1/src/metrifid/_schema_primitives.py +248 -0
  80. metrifid-0.2.1/src/metrifid/_timegrid.py +265 -0
  81. metrifid-0.2.1/src/metrifid/_workload.py +389 -0
  82. metrifid-0.2.1/src/metrifid/_workload_validation.py +216 -0
  83. metrifid-0.2.1/src/metrifid/certify/__init__.py +63 -0
  84. metrifid-0.2.1/src/metrifid/certify/_artifact.py +308 -0
  85. metrifid-0.2.1/src/metrifid/certify/_bytes.py +192 -0
  86. metrifid-0.2.1/src/metrifid/certify/_entrypoint.py +113 -0
  87. metrifid-0.2.1/src/metrifid/certify/_field_schema.py +94 -0
  88. metrifid-0.2.1/src/metrifid/certify/_fields.py +414 -0
  89. metrifid-0.2.1/src/metrifid/certify/_markdown.py +243 -0
  90. metrifid-0.2.1/src/metrifid/certify/_receipt.py +301 -0
  91. metrifid-0.2.1/src/metrifid/certify/_receipt_contract.py +121 -0
  92. metrifid-0.2.1/src/metrifid/certify/_receipt_validation.py +413 -0
  93. metrifid-0.2.1/src/metrifid/certify/_run.py +264 -0
  94. metrifid-0.2.1/src/metrifid/certify/_runtime_schema.py +191 -0
  95. metrifid-0.2.1/src/metrifid/certify/_status.py +37 -0
  96. metrifid-0.2.1/src/metrifid/cli.py +254 -0
  97. metrifid-0.2.1/src/metrifid/compare/__init__.py +34 -0
  98. metrifid-0.2.1/src/metrifid/compare/_budget.py +202 -0
  99. metrifid-0.2.1/src/metrifid/compare/_environment.py +169 -0
  100. metrifid-0.2.1/src/metrifid/compare/_failure.py +87 -0
  101. metrifid-0.2.1/src/metrifid/compare/_markdown.py +339 -0
  102. metrifid-0.2.1/src/metrifid/compare/_metric_math.py +132 -0
  103. metrifid-0.2.1/src/metrifid/compare/_metrics.py +465 -0
  104. metrifid-0.2.1/src/metrifid/compare/_model_pair.py +140 -0
  105. metrifid-0.2.1/src/metrifid/compare/_monitoring.py +48 -0
  106. metrifid-0.2.1/src/metrifid/compare/_mujoco_backend.py +71 -0
  107. metrifid-0.2.1/src/metrifid/compare/_orchestration_receipt.py +225 -0
  108. metrifid-0.2.1/src/metrifid/compare/_orchestrator.py +599 -0
  109. metrifid-0.2.1/src/metrifid/compare/_output.py +126 -0
  110. metrifid-0.2.1/src/metrifid/compare/_runner.py +476 -0
  111. metrifid-0.2.1/src/metrifid/compare/_trace.py +226 -0
  112. metrifid-0.2.1/src/metrifid/demo.py +143 -0
  113. metrifid-0.2.1/src/metrifid/distribution.py +225 -0
  114. metrifid-0.2.1/src/metrifid/errors.py +460 -0
  115. metrifid-0.2.1/src/metrifid/json_values.py +397 -0
  116. metrifid-0.2.1/src/metrifid/operational.py +475 -0
  117. metrifid-0.2.1/src/metrifid/py.typed +0 -0
  118. metrifid-0.2.1/src/metrifid/schemas.py +85 -0
  119. metrifid-0.2.1/src/metrifid/timestep_audit.py +61 -0
  120. metrifid-0.2.1/src/metrifid/version.py +3 -0
  121. metrifid-0.2.1/src/metrifid/workload_writers.py +317 -0
  122. metrifid-0.2.1/tests/__init__.py +1 -0
  123. metrifid-0.2.1/tests/_support/__init__.py +1 -0
  124. metrifid-0.2.1/tests/_support/constructed_models.py +174 -0
  125. metrifid-0.2.1/tests/conftest.py +259 -0
  126. metrifid-0.2.1/tests/contract/test_certify_admission.py +439 -0
  127. metrifid-0.2.1/tests/contract/test_certify_receipt.py +582 -0
  128. metrifid-0.2.1/tests/contract/test_certify_receipt_evidence.py +605 -0
  129. metrifid-0.2.1/tests/contract/test_certify_receipt_validation.py +644 -0
  130. metrifid-0.2.1/tests/contract/test_ci_quality_environment.py +61 -0
  131. metrifid-0.2.1/tests/contract/test_completed_artifact_lifecycle.py +143 -0
  132. metrifid-0.2.1/tests/contract/test_contribution_policy.py +58 -0
  133. metrifid-0.2.1/tests/contract/test_distribution_artifacts.py +213 -0
  134. metrifid-0.2.1/tests/contract/test_limitations.py +140 -0
  135. metrifid-0.2.1/tests/contract/test_model_identity_contract.py +764 -0
  136. metrifid-0.2.1/tests/contract/test_operational_failure.py +413 -0
  137. metrifid-0.2.1/tests/contract/test_operational_identity_binding.py +249 -0
  138. metrifid-0.2.1/tests/contract/test_public_api.py +226 -0
  139. metrifid-0.2.1/tests/contract/test_pure_receipt_validation.py +156 -0
  140. metrifid-0.2.1/tests/contract/test_reason_registry.py +471 -0
  141. metrifid-0.2.1/tests/contract/test_reason_role_binding.py +189 -0
  142. metrifid-0.2.1/tests/contract/test_receipt_cross_invariants.py +241 -0
  143. metrifid-0.2.1/tests/contract/test_receipt_hash.py +549 -0
  144. metrifid-0.2.1/tests/contract/test_strict_receipt_schemas.py +446 -0
  145. metrifid-0.2.1/tests/contract/test_strict_schemas.py +403 -0
  146. metrifid-0.2.1/tests/contract/test_workload_contract.py +33 -0
  147. metrifid-0.2.1/tests/fixtures/canonical_vectors.json +1039 -0
  148. metrifid-0.2.1/tests/integration/test_certify_cli.py +354 -0
  149. metrifid-0.2.1/tests/integration/test_examples.py +80 -0
  150. metrifid-0.2.1/tests/integration/test_execution_identity_attacks.py +334 -0
  151. metrifid-0.2.1/tests/integration/test_installed_demo.py +73 -0
  152. metrifid-0.2.1/tests/integration/test_installed_distribution.py +134 -0
  153. metrifid-0.2.1/tests/integration/test_mujoco_model_identity.py +448 -0
  154. metrifid-0.2.1/tests/integration/test_mujoco_model_identity_native.py +517 -0
  155. metrifid-0.2.1/tests/integration/test_operation_labels_and_config_admission.py +149 -0
  156. metrifid-0.2.1/tests/integration/test_sdk_examples.py +120 -0
  157. metrifid-0.2.1/tests/integration/test_timestep_audit_native.py +766 -0
  158. metrifid-0.2.1/tests/integration/test_workload_identity_binding.py +209 -0
  159. metrifid-0.2.1/tests/security/test_model_closure_read_bounds.py +259 -0
  160. metrifid-0.2.1/tests/security/test_model_path_confinement.py +615 -0
  161. metrifid-0.2.1/tests/security/test_model_path_races.py +537 -0
  162. metrifid-0.2.1/tests/security/test_mujoco_callback_surface.py +251 -0
  163. metrifid-0.2.1/tests/security/test_npz_safety.py +323 -0
  164. metrifid-0.2.1/tests/security/test_output_ownership.py +833 -0
  165. metrifid-0.2.1/tests/unit/test_activation_layout_registry.py +295 -0
  166. metrifid-0.2.1/tests/unit/test_binary64.py +149 -0
  167. metrifid-0.2.1/tests/unit/test_canonical_json.py +349 -0
  168. metrifid-0.2.1/tests/unit/test_certify_artifact.py +287 -0
  169. metrifid-0.2.1/tests/unit/test_certify_entrypoint.py +244 -0
  170. metrifid-0.2.1/tests/unit/test_certify_fields.py +629 -0
  171. metrifid-0.2.1/tests/unit/test_cli.py +132 -0
  172. metrifid-0.2.1/tests/unit/test_compare_budget.py +604 -0
  173. metrifid-0.2.1/tests/unit/test_compare_environment.py +258 -0
  174. metrifid-0.2.1/tests/unit/test_compare_markdown.py +548 -0
  175. metrifid-0.2.1/tests/unit/test_compare_metrics.py +202 -0
  176. metrifid-0.2.1/tests/unit/test_compare_orchestration.py +706 -0
  177. metrifid-0.2.1/tests/unit/test_compare_output.py +90 -0
  178. metrifid-0.2.1/tests/unit/test_compare_runner.py +176 -0
  179. metrifid-0.2.1/tests/unit/test_distribution_identity.py +637 -0
  180. metrifid-0.2.1/tests/unit/test_distribution_members.py +668 -0
  181. metrifid-0.2.1/tests/unit/test_exact_rational.py +160 -0
  182. metrifid-0.2.1/tests/unit/test_json_admission.py +212 -0
  183. metrifid-0.2.1/tests/unit/test_model_alignment.py +447 -0
  184. metrifid-0.2.1/tests/unit/test_model_closure.py +335 -0
  185. metrifid-0.2.1/tests/unit/test_model_dependencies.py +546 -0
  186. metrifid-0.2.1/tests/unit/test_model_dependency_resolution.py +554 -0
  187. metrifid-0.2.1/tests/unit/test_model_identity.py +447 -0
  188. metrifid-0.2.1/tests/unit/test_model_identity_validation.py +622 -0
  189. metrifid-0.2.1/tests/unit/test_npz_loader.py +180 -0
  190. metrifid-0.2.1/tests/unit/test_operational_failure_delivery.py +161 -0
  191. metrifid-0.2.1/tests/unit/test_operational_registry.py +305 -0
  192. metrifid-0.2.1/tests/unit/test_output.py +345 -0
  193. metrifid-0.2.1/tests/unit/test_public_mapping_validation.py +118 -0
  194. metrifid-0.2.1/tests/unit/test_timegrid.py +329 -0
  195. metrifid-0.2.1/tests/unit/test_timestep_audit.py +625 -0
  196. metrifid-0.2.1/tests/unit/test_timestep_audit_execution.py +646 -0
  197. metrifid-0.2.1/tests/unit/test_timestep_audit_reporting.py +620 -0
  198. metrifid-0.2.1/tests/unit/test_workload.py +635 -0
  199. metrifid-0.2.1/tests/unit/test_workload_writers.py +501 -0
  200. metrifid-0.2.1/tools/mjb_characterization.py +381 -0
@@ -0,0 +1,11 @@
1
+ # CI-only quality toolchain. Public runtime and development dependency metadata remain minimum-only.
2
+ build==1.5.0
3
+ editables==0.6
4
+ hatchling==1.31.0
5
+ hypothesis==6.165.2
6
+ mypy==1.20.2
7
+ numpy==2.3.5
8
+ pytest==9.1.1
9
+ pytest-randomly==4.1.0
10
+ ruff==0.16.2
11
+ twine==7.0.0
@@ -0,0 +1,13 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .pytest_cache/
4
+ .mypy_cache/
5
+ .ruff_cache/
6
+ .coverage
7
+ coverage.xml
8
+ htmlcov/
9
+ build/
10
+ dist/
11
+ *.egg-info/
12
+ *.dist-info/
13
+ .venv/
@@ -0,0 +1,23 @@
1
+ repos:
2
+ - repo: local
3
+ hooks:
4
+ - id: ruff-check
5
+ name: ruff check
6
+ entry: python -m ruff check
7
+ language: system
8
+ types: [python]
9
+ pass_filenames: false
10
+
11
+ - id: ruff-format
12
+ name: ruff format --check
13
+ entry: python -m ruff format --check
14
+ language: system
15
+ types: [python]
16
+ pass_filenames: false
17
+
18
+ - id: mypy
19
+ name: mypy --strict src/metrifid
20
+ entry: python -m mypy --strict src/metrifid
21
+ language: system
22
+ types: [python]
23
+ pass_filenames: false
@@ -0,0 +1,269 @@
1
+ # Changelog
2
+
3
+ Notable changes to `metrifid`. Starting with `0.2.0`, release identifiers use exactly three
4
+ dot-separated integer components: `MAJOR.MINOR.PATCH`. Historical development entries below
5
+ remain as an audit trail and do not define the current release version.
6
+
7
+ ## 0.2.1
8
+
9
+ - Keep Apache License 2.0 as the controlling license for the open-source Metrifid repository.
10
+ - Add project attribution through `NOTICE`.
11
+ - Add the unmodified Developer Certificate of Origin 1.1 and require signed-off contributed commits.
12
+ - Clarify that DCO sign-off is contribution provenance, not copyright assignment.
13
+ - Package `LICENSE` and `NOTICE` as PEP 639 legal files and carry `DCO` in the source distribution.
14
+ - Identify the copyright holder in package metadata and remove the deprecated Apache license Trove
15
+ classifier.
16
+
17
+ ## 0.2.0
18
+
19
+ - Add `python -m metrifid.demo`, a self-contained first-use demonstration that runs from a wheel
20
+ installation alone with no checkout, arguments, network access, or packaged assets.
21
+ - Add `docs/sdk.md` documenting the supported programmatic execution surface — `certify_models`,
22
+ `compare_configuration_file`, and `audit_configuration_file` — with signatures, return types, the
23
+ completed-decision versus refusal distinction, output ownership, the native runtime requirement,
24
+ and an explicit statement that native execution is neither thread-safe nor reentrant.
25
+ - Add four runnable SDK example scripts under `examples/sdk/` that use only public APIs and run
26
+ from any directory against an installed wheel.
27
+ - Add a complete, runnable comparison example under `examples/compare/` with all ten configuration
28
+ fields, both models, and a workload preparation script that never overwrites an existing artifact.
29
+ - Make the README first-use path wheel-only, and use inline code instead of relative Markdown links
30
+ so the PyPI description has no broken links before owner-bound URLs exist.
31
+ - State in `docs/model_closure.md` and `docs/capabilities_and_use_cases.md` that closure content is
32
+ bounded by the documented byte limit, that file-count, directory-count, and traversal-depth limits
33
+ are not separately guaranteed in this pre-alpha release, and that this package targets local
34
+ trusted-input workflows rather than hosted untrusted uploads.
35
+ - Replace hand-maintained test-count claims with a statement that release evidence is generated by
36
+ CI, and remove stale `0.2.0a13` version text.
37
+ - Ship `SECURITY.md`, `CODE_OF_CONDUCT.md`, `.pre-commit-config.yaml`, and
38
+ `.github/quality-constraints.txt` in the source distribution so it contains everything its own
39
+ contributor and security documentation references.
40
+ - Build release artifacts through isolated PEP 517, install and test the direct sdist in a separate
41
+ clean environment, rebuild a wheel from the extracted sdist, and check distribution equivalence
42
+ semantically in CI.
43
+
44
+ ## 0.2.0a14
45
+
46
+ - Add one bounded strict JSON admission module and apply it to comparison configurations, alias
47
+ files, and timestep-audit configurations. Duplicate member names, raw float tokens, `NaN`,
48
+ `Infinity`, malformed UTF-8, and oversized, over-deep, over-wide, or over-long documents are now
49
+ refused at every file-based trust boundary, and audit configurations no longer use permissive
50
+ JSON parsing.
51
+ - Read configuration and alias files through a single no-follow descriptor confirmed regular by
52
+ `fstat`, with the byte ceiling applied before parsing.
53
+ - Add `metrifid.certify.load_and_validate_certification_receipt` for receipt files and untrusted
54
+ bytes. It rejects duplicate names and noncanonical numeric tokens before the semantic validator
55
+ runs. `validate_receipt` is unchanged for callers holding a parsed mapping.
56
+ - Make certification receipt parsing and validation importable without MuJoCo or NumPy by moving
57
+ the runtime-identity schema to `certify/_runtime_schema.py` and the field-report schema to
58
+ `certify/_field_schema.py`, and by deferring native imports in `certify/_artifact.py` and
59
+ `certify/_bytes.py` to their producer functions.
60
+ - Report the real operation on distribution-identity failures, so a `certify` refusal says
61
+ `certify` and an `audit-timestep` refusal says `audit-timestep`.
62
+ - Restore normal Python submodule attribute behavior, so `import metrifid.errors` then
63
+ `metrifid.errors` works.
64
+ - Install MuJoCo in the CI quality environment so strict MyPy passes on a first push.
65
+
66
+ ## 0.2.0a13
67
+
68
+ - Add a human-friendly getting-started guide and a faithful capabilities/use-cases reference.
69
+ - Make source-checkout installation the primary pre-publication path in README and examples.
70
+ - Remove stale release numbers and avoid promising a vulnerability-reporting channel before it is enabled.
71
+ - Preserve the open-ended CPython and NumPy compatibility policy introduced in 0.2.0a12.
72
+ - Make release quality checks reproducible with CI-only constraints that do not narrow public
73
+ runtime or development dependencies.
74
+ - Correct three cross-version/platform test assumptions and the Audit retained-evidence expectation.
75
+ - Keep runtime admission capability-based and architecture-neutral.
76
+
77
+ ## [0.2.0a12]
78
+
79
+ ### Changed
80
+
81
+ - Python metadata is `>=3.11` with no upper bound, and the classifiers list 3.11 through 3.14.
82
+ - One shared native-runtime gate now admits Certify, Compare, Audit Timestep, and compiled model
83
+ identity. The separate, narrower Certify envelope is removed.
84
+ - The gate rejects only Python below 3.11. It never inspects the interpreter implementation name,
85
+ uses no finite Python-minor allowlist or upper bound, and never rejects an architecture; the
86
+ machine string remains receipt evidence only.
87
+ - Platform admission is capability-based: a POSIX operating system reporting `Linux` or `Darwin`
88
+ plus the exact `dir_fd`, `follow_symlinks`, `fd`, callable, and open-flag facilities the confined
89
+ filesystem work requires. Native Windows remains unsupported; WSL is the documented route.
90
+ - The MuJoCo runtime dependency is `mujoco==3.10.0.*`, so binding-only `3.10.0.postN` packages that
91
+ target the same native engine are accepted. Prerelease, development, `3.10.1`, and `3.11`-or-later
92
+ package versions still refuse, and the native engine must remain 3.10.0 / 3010000 exactly.
93
+ - NumPy is `>=1.26` with no runtime upper bound and no runtime version gate.
94
+ - The development extra keeps its package names, drops NumPy, and uses minimum-only specifiers.
95
+ - The build-system requirement is `hatchling>=1.27` with no upper bound.
96
+ - CI builds one wheel and one sdist once and installs those exact wheel bytes noneditably in every
97
+ compatibility lane. MJB digests are never compared across lanes.
98
+ - `tools/mjb_characterization.py` is included in the sdist and runs in every blocking lane. It stays
99
+ outside the public import package.
100
+
101
+ ### Unchanged
102
+
103
+ - Public APIs, schemas, statuses, reason codes, exit codes, numerical methods, output names, receipt
104
+ bytes, output ownership, source-closure behavior, and the complete-MJB identity rule.
105
+ - The workload artifact writers, canonical JSON and exact-number helpers, and receipt parsing and
106
+ validation remain outside the native gate and require no MuJoCo admission.
107
+
108
+ ## [0.2.0a11]
109
+
110
+ ### Fixed
111
+
112
+ - Certify and Compare perform their final public-path and exact-byte verification after the retained source contexts close, so replacing the public output pathname during final source cleanup causes refusal instead of returning paths to unrelated bytes.
113
+ - Timestep Audit verifies the aggregate pair before making the public path and registered output tree its final success boundary, closing the same path-replacement window for aggregate results.
114
+ - Private temporary names are relinquished permanently after finalization or cleanup. Reusing an old random temporary name later can no longer cause Metrifid cleanup to remove the caller's new directory entry.
115
+ - Comparison and Audit tests now assert the no-clobber preservation contract instead of the obsolete replace-and-delete behavior.
116
+
117
+ ### Unchanged
118
+
119
+ - Public APIs, schemas, statuses, reason codes, exit codes, numerical methods, output names, receipt bytes for successful unaffected runs, and the complete-MJB identity rule.
120
+
121
+ ## [0.2.0a10]
122
+
123
+ ### Fixed
124
+
125
+ - Public output ownership is recorded only after a descriptor-relative no-clobber hard link exists
126
+ and still identifies the retained sealed bytes. A conflicting hardlink can no longer be mistaken
127
+ for product-owned output and deleted during failure cleanup.
128
+ - Generic paired-result and workload-writer cleanup removes only retained private temporaries.
129
+ Already-linked public evidence is preserved on every later failure, while timestep-audit cleanup
130
+ still removes exact private workspace artifacts and never deletes registered public evidence.
131
+
132
+ ### Unchanged
133
+
134
+ - Successful Compare, Certify, workload-writer, and timestep-audit bytes; public APIs; schemas;
135
+ statuses; reason codes; exits; numerical methods; and output names.
136
+
137
+ ## [0.2.0a8]
138
+
139
+ ### Fixed
140
+
141
+ - A timestep audit freezes one model-closure snapshot and one bounded state/actions byte set for
142
+ the entire campaign. Every candidate consumes those inputs, the aggregate derives identities
143
+ from them, and final live-input divergence removes all audit output and refuses publication.
144
+ - Model traversal, paired-result publication, audit cleanup, and workload writers are confined to
145
+ retained directory descriptors. NPZ size limits are enforced during the read, Certify retains and
146
+ reverifies both source snapshots, and Certify/Compare refuse output at or below either model root.
147
+ - Source-closure documentation now matches execution: every admitted regular file under the model
148
+ root affects source identity, while separate dependency discovery identifies files MuJoCo reaches.
149
+ An unused regular file does not affect compiled-MJB bytes unless MuJoCo resolves it.
150
+
151
+ ### Unchanged
152
+
153
+ - Public APIs, schemas, statuses, exit codes, output names, receipt meanings, numerical methods,
154
+ exact-time behavior, and the package architecture.
155
+
156
+ ## [0.2.0a7]
157
+
158
+ ### Changed
159
+
160
+ - The project adopts its public name. The distribution, import package, console
161
+ command, repository slug, schema prefix and runtime key prefix are all `metrifid`, and the
162
+ display name is `Metrifid`. This is a pre-public namespace reset, so no alias for the former
163
+ internal name is shipped in any form.
164
+ - The model-closure documentation states the part it previously left out: a substitution that is
165
+ visible in file metadata refuses before the member is read at all. The admitted-replacement,
166
+ final-divergence and byte-identical cases are unchanged and the content-addressed claim is not
167
+ broadened.
168
+
169
+ ### Unchanged
170
+
171
+ - Every command, decision, status, exit code, refusal, metric, tolerance, time-grid rule,
172
+ source-closure algorithm, receipt hashing rule, canonical encoding, output filename, supported
173
+ platform and public Python export. Only the namespace and the version moved.
174
+
175
+ ## [0.2.0a6]
176
+
177
+ ### Changed
178
+
179
+ - The source-closure contract is documented as what it computes: content addressing. A member is
180
+ named by its relative path, its exact byte count and the SHA-256 of the exact bytes read. Those
181
+ bytes are the ones hashed, copied into the private immutable snapshot and compiled, and the
182
+ source is re-measured against that snapshot before publication. The documentation no longer
183
+ implies that a byte-identical replacement of a member's underlying file object is detected; no
184
+ published identity depends on distinguishing it.
185
+
186
+ ### Unchanged
187
+
188
+ - Every command, status, exit code, schema identifier, canonical encoding, output filename,
189
+ supported platform and public Python export. Symlink, path-escape, non-regular-member,
190
+ unreadable-member and byte-budget refusals remain fail-closed, and source content that differs
191
+ from the snapshot at final verification still refuses with `MODEL_CLOSURE_MUTATED`.
192
+
193
+ ## [0.2.0a5]
194
+
195
+ ### Added
196
+
197
+ - `certify` is validated on Linux x86_64 as well as Darwin x86_64, both with CPython 3.12 and
198
+ MuJoCo Python and native `3.10.0` exactly. The supported set is explicit; every other
199
+ environment still refuses rather than guessing, and the refusal now names the complete
200
+ supported set.
201
+ - Continuous integration runs the bundled `examples/certify/run_example.py` against the installed
202
+ wheel, so the documented example is exercised on every change.
203
+
204
+ ### Changed
205
+
206
+ - Continuous integration installs the built wheel with its bounded `[dev]` extra instead of
207
+ installing validation tools separately, and verifies that both the import and the console
208
+ script resolve from the installed environment.
209
+ - Documentation states plainly that a complete-MJB certificate is bound to the runtime identity
210
+ recorded in the receipt. Support statements name the two measured platforms.
211
+
212
+ ### Unchanged
213
+
214
+ - Every command, status, exit code, schema identifier, canonical encoding, output filename,
215
+ atomic publication rule, closure and snapshot behavior, installed-distribution identity check,
216
+ top-level Python export and runtime dependency. `compare` and `audit-timestep` keep the
217
+ environment envelope they already had.
218
+
219
+ ## [0.2.0a4]
220
+
221
+ ### Changed
222
+
223
+ - The repository is shaped for outside contributors: development-history artifacts and the tests
224
+ that asserted file inventories, source line counts and documentation prose are gone. Every
225
+ behavior, security, receipt, closure, path-confinement, workload, comparison, audit and
226
+ certification test is retained.
227
+ - Two long modules were split along their real seams with no import path changed:
228
+ `_model_admission` is a facade over `_model_compile` and `_model_descriptors`;
229
+ `timestep_audit` is a facade over `_audit_config`, `_audit_execution` and `_audit_reporting`.
230
+ - Documentation is organized around the three decisions a user makes, with an API reference, a
231
+ model-closure guide, a workload guide and a public case study. A runnable example ships in
232
+ `examples/certify/`.
233
+
234
+ ### Fixed
235
+
236
+ - Descriptive field evidence is bounded. A changed field larger than 64 MiB per side keeps its
237
+ path, types, dtypes, shapes and digests but reports no element count and no witnesses, and the
238
+ report's `truncated` flag records it. Changed fields are described in sorted path order and no
239
+ two fields' copied arrays are ever held at the same time.
240
+ - Receipt revalidation completes its descriptive type checks: a present field side must name a
241
+ nonempty type and a null-or-nonempty dtype, an absent side must be null throughout, and a
242
+ witness value may only be one of the canonical forms the reporter emits.
243
+
244
+ ## [0.2.0a3]
245
+
246
+ ### Added
247
+
248
+ - `metrifid certify`: compile two MuJoCo source closures and state, over every byte of the
249
+ serialized compiled model, whether they are identical. Exit `0` certifies; exit `40` does not.
250
+ It runs no workload and never steps the simulation. On a difference the receipt reports the
251
+ first differing byte offset, the differing byte count, and a bounded descriptive report naming
252
+ the changed public fields with sorted index and value witnesses.
253
+ - Receipt revalidation for an unsigned certification receipt: exact member sets, frozen claim and
254
+ limitation text, the nested runtime identity and its own hash, both role identities, each
255
+ artifact's binding to the recorded runtime, and the byte comparison against the two artifacts.
256
+
257
+ ### Fixed
258
+
259
+ - Test isolation no longer depends on suite order: helpers that swap modules record and restore
260
+ every `sys.modules` entry and parent-package attribute they change.
261
+
262
+ ## Earlier development
263
+
264
+ `0.1.x` through `0.2.0a2` established the foundations the shipped decisions rest on: canonical
265
+ JSON with exact rationals and IEEE-754 bit-exact doubles, self-hashed receipts, measured model
266
+ closures with bounded no-follow reads and mutation detection, snapshot compilation, semantic
267
+ joint and actuator alignment, strict workload artifacts with an exact time grid, the `compare`
268
+ decision and its four statuses, the `audit-timestep` decision, and the installed-distribution
269
+ identity check. None of it was published.
@@ -0,0 +1,106 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our community a
6
+ harassment-free experience for everyone, regardless of age, body size, visible or invisible
7
+ disability, ethnicity, sex characteristics, gender identity and expression, level of experience,
8
+ education, socio-economic status, nationality, personal appearance, race, caste, color, religion,
9
+ or sexual identity and orientation.
10
+
11
+ We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive,
12
+ and healthy community.
13
+
14
+ ## Our Standards
15
+
16
+ Examples of behavior that contributes to a positive environment include:
17
+
18
+ - Demonstrating empathy and kindness toward other people.
19
+ - Being respectful of differing opinions, viewpoints, and experiences.
20
+ - Giving and gracefully accepting constructive feedback.
21
+ - Accepting responsibility and apologizing to those affected by our mistakes, and learning from the
22
+ experience.
23
+ - Focusing on what is best not just for us as individuals, but for the overall community.
24
+
25
+ Examples of unacceptable behavior include:
26
+
27
+ - The use of sexualized language or imagery, and sexual attention or advances of any kind.
28
+ - Trolling, insulting or derogatory comments, and personal or political attacks.
29
+ - Public or private harassment.
30
+ - Publishing others' private information, such as a physical or electronic address, without
31
+ explicit permission.
32
+ - Other conduct which could reasonably be considered inappropriate in a professional setting.
33
+
34
+ ## Enforcement Responsibilities
35
+
36
+ Community leaders are responsible for clarifying and enforcing our standards of acceptable
37
+ behavior and will take appropriate and fair corrective action in response to behavior they deem
38
+ inappropriate, threatening, offensive, or harmful.
39
+
40
+ Community leaders have the right and responsibility to remove, edit, or reject comments, commits,
41
+ code, wiki edits, issues, and other contributions that are not aligned with this Code of Conduct,
42
+ and will communicate reasons for moderation decisions when appropriate.
43
+
44
+ ## Scope
45
+
46
+ This Code of Conduct applies within all community spaces, and also applies when an individual is
47
+ officially representing the community in public spaces. Examples include using an official account,
48
+ posting through an official social media account, or acting as an appointed representative at an
49
+ online or offline event.
50
+
51
+ ## Enforcement
52
+
53
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to repository
54
+ maintainers through private repository channels made available by the hosting platform. All
55
+ complaints will be reviewed and investigated promptly and fairly.
56
+
57
+ All community leaders are obligated to respect the privacy and security of the reporter of any
58
+ incident.
59
+
60
+ ## Enforcement Guidelines
61
+
62
+ Community leaders will follow these Community Impact Guidelines in determining the consequences for
63
+ any action they deem in violation of this Code of Conduct.
64
+
65
+ ### 1. Correction
66
+
67
+ **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or
68
+ unwelcome in the community.
69
+
70
+ **Consequence**: A private, written warning from community leaders, providing clarity around the
71
+ nature of the violation and an explanation of why the behavior was inappropriate. A public apology
72
+ may be requested.
73
+
74
+ ### 2. Warning
75
+
76
+ **Community Impact**: A violation through a single incident or series of actions.
77
+
78
+ **Consequence**: A warning with consequences for continued behavior. No interaction with the people
79
+ involved, including unsolicited interaction with those enforcing the Code of Conduct, for a
80
+ specified period of time. This includes avoiding interactions in community spaces as well as
81
+ external channels like social media. Violating these terms may lead to a temporary or permanent ban.
82
+
83
+ ### 3. Temporary Ban
84
+
85
+ **Community Impact**: A serious violation of community standards, including sustained inappropriate
86
+ behavior.
87
+
88
+ **Consequence**: A temporary ban from any sort of interaction or public communication with the
89
+ community for a specified period of time. No public or private interaction with the people involved,
90
+ including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this
91
+ period. Violating these terms may lead to a permanent ban.
92
+
93
+ ### 4. Permanent Ban
94
+
95
+ **Community Impact**: Demonstrating a pattern of violation of community standards, including
96
+ sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement
97
+ of classes of individuals.
98
+
99
+ **Consequence**: A permanent ban from any sort of public interaction within the community.
100
+
101
+ ## Attribution
102
+
103
+ This Code of Conduct is adapted from the Contributor Covenant, version 2.1, available at
104
+ https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
105
+
106
+ Community Impact Guidelines were inspired by Mozilla's code of conduct enforcement ladder.
@@ -0,0 +1,105 @@
1
+ # Contributing
2
+
3
+ Thanks for looking. This is a small, deliberately narrow tool, and the bar for changes is
4
+ "a user can tell the difference".
5
+
6
+ ## Contribution license and DCO sign-off
7
+
8
+ Metrifid is licensed under Apache License 2.0. Contributions intentionally submitted for inclusion
9
+ are accepted under that license. Every commit in a pull request must certify the Developer
10
+ Certificate of Origin 1.1 in [`DCO`](DCO).
11
+
12
+ Use `git commit -s` to add this line to each commit message:
13
+
14
+ ```text
15
+ Signed-off-by: Your Name <you@example.com>
16
+ ```
17
+
18
+ The sign-off certifies that you have the right to submit the contribution under Apache-2.0. It is
19
+ not a copyright assignment or a contributor license agreement. Contributors retain copyright in
20
+ their contributions. Do not submit material you do not have the right to contribute. A pull request
21
+ with an unsigned commit will not be merged. The DCO also explains that the public sign-off record is
22
+ retained and may be redistributed with the project.
23
+
24
+ Read [`docs/licensing_and_contributions.md`](docs/licensing_and_contributions.md) before opening a
25
+ pull request.
26
+
27
+ ## Set up
28
+
29
+ ```bash
30
+ python -m venv .venv && source .venv/bin/activate
31
+ python -m pip install -e ".[dev]"
32
+ ```
33
+
34
+ The editable install above is for editing, linting, typing, and pure/unit work only. Integration,
35
+ security, receipt, command, and release evidence must run against a noneditable wheel, because the
36
+ product is the installed distribution rather than the source tree.
37
+
38
+ The MuJoCo native engine `3.10.0` exactly is a hard requirement — the compiled-artifact identity is
39
+ only meaningful against a fixed engine build. A binding-only `3.10.0.postN` package targets that
40
+ same engine and is accepted; any other engine version refuses rather than guessing.
41
+
42
+ Python 3.11 or newer is supported, with no upper bound and no runtime rejection based on the
43
+ interpreter name. Release evidence currently uses CPython because the MuJoCo binary wheels exercised
44
+ by CI target CPython. The package metadata has no artificial upper bound. CI is configured for
45
+ CPython 3.11–3.14 on Linux x86_64, CPython 3.12 and 3.14 on macOS arm64, and CPython 3.12 on
46
+ macOS x86_64. Linux and macOS are admitted when the shared POSIX capability gate passes, with no
47
+ architecture whitelist. Native Windows is unsupported; use WSL.
48
+
49
+ ## Before you open a pull request
50
+
51
+ Use the editable development environment for static quality gates:
52
+
53
+ ```bash
54
+ python -m ruff check .
55
+ python -m ruff format --check .
56
+ python -m mypy --strict src/metrifid
57
+ ```
58
+
59
+ Run product, integration, security, receipt, command, and release tests from a separate noneditable
60
+ wheel environment:
61
+
62
+ ```bash
63
+ python -m build --no-isolation
64
+ python -m venv .wheel-test-venv
65
+ source .wheel-test-venv/bin/activate
66
+ python -m pip install dist/metrifid-*.whl
67
+ python -m pip install -c .github/quality-constraints.txt editables hatchling hypothesis mypy pytest pytest-randomly
68
+ python -m pytest -q tests
69
+ ```
70
+
71
+ CI follows the same separation: it builds one wheel and one sdist once, then installs those exact
72
+ wheel bytes noneditably in every compatibility lane. Decision-bearing release evidence never comes
73
+ from the editable source tree.
74
+
75
+ ## What the tests are for
76
+
77
+ Tests here assert *behavior*: statuses, exit codes, refusal reasons, published bytes, hash
78
+ stability, path confinement, read bounds and receipt validation. Please add tests of that kind.
79
+
80
+ Please do not add tests that assert source line counts, repository file inventories,
81
+ documentation wording, or frozen distribution hashes. Those pin the shape of the repository
82
+ rather than the behavior of the product, and they were removed for that reason.
83
+
84
+ ## Things that are deliberately frozen
85
+
86
+ Changing any of these is a breaking change and needs its own discussion first:
87
+
88
+ - the three command shapes and their exit codes;
89
+ - the completed statuses;
90
+ - the complete-MJB identity method;
91
+ - the published schema identifiers;
92
+ - canonical JSON encoding, exact-number forms and self-hashing;
93
+ - output filenames and atomic publication;
94
+ - the top-level `metrifid` exports.
95
+
96
+ ## Style
97
+
98
+ Ruff decides formatting and lint; there is no separate style guide to read. Keep functions small
99
+ enough to read in one screen — nothing in `src/metrifid` exceeds 80 lines. Prefer a named helper
100
+ over a comment explaining a long block, and prefer a comment explaining *why* over one restating
101
+ *what*.
102
+
103
+ ## Reporting a security issue
104
+
105
+ See [`SECURITY.md`](SECURITY.md). Please do not open a public issue for a vulnerability.
metrifid-0.2.1/DCO ADDED
@@ -0,0 +1,33 @@
1
+ Developer Certificate of Origin
2
+ Version 1.1
3
+
4
+ Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
5
+
6
+ Everyone is permitted to copy and distribute verbatim copies of this
7
+ license document, but changing it is not allowed.
8
+
9
+ Developer's Certificate of Origin 1.1
10
+
11
+ By making a contribution to this project, I certify that:
12
+
13
+ (a) The contribution was created in whole or in part by me and I
14
+ have the right to submit it under the open source license
15
+ indicated in the file; or
16
+
17
+ (b) The contribution is based upon previous work that, to the best
18
+ of my knowledge, is covered under an appropriate open source
19
+ license and I have the right under that license to submit that
20
+ work with modifications, whether created in whole or in part
21
+ by me, under the same open source license (unless I am
22
+ permitted to submit under a different license), as indicated
23
+ in the file; or
24
+
25
+ (c) The contribution was provided directly to me by some other
26
+ person who certified (a), (b) or (c) and I have not modified
27
+ it.
28
+
29
+ (d) I understand and agree that this project and the contribution
30
+ are public and that a record of the contribution (including all
31
+ personal information I submit with it, including my sign-off) is
32
+ maintained indefinitely and may be redistributed consistent with
33
+ this project or the open source license(s) involved.