robotics-runtime-contracts 0.17.0__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 (209) hide show
  1. robotics_runtime_contracts-0.17.0/.gitignore +16 -0
  2. robotics_runtime_contracts-0.17.0/LICENSE +21 -0
  3. robotics_runtime_contracts-0.17.0/PKG-INFO +351 -0
  4. robotics_runtime_contracts-0.17.0/README.md +327 -0
  5. robotics_runtime_contracts-0.17.0/docs/schema-digests.json +34 -0
  6. robotics_runtime_contracts-0.17.0/pyproject.toml +50 -0
  7. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/__init__.py +281 -0
  8. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/_mcap_crc.py +101 -0
  9. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/_mcap_observations.py +91 -0
  10. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/_mcap_summary.py +118 -0
  11. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/_merge_patch.py +54 -0
  12. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/_qualification.py +1195 -0
  13. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/_qualification_checks.py +400 -0
  14. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/_qualification_files.py +102 -0
  15. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/_qualification_types.py +104 -0
  16. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/_resources.py +19 -0
  17. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/_timestamps.py +22 -0
  18. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/_writer_cli.py +179 -0
  19. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/canonical.py +180 -0
  20. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/catalog.py +54 -0
  21. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/cli.py +438 -0
  22. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/document_ops.py +187 -0
  23. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/errors.py +25 -0
  24. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/extensions.py +281 -0
  25. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/providers.py +66 -0
  26. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/py.typed +0 -0
  27. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/qualification.py +118 -0
  28. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/qualification_policy.py +178 -0
  29. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/receipts.py +59 -0
  30. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/recordings.py +26 -0
  31. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/__init__.py +0 -0
  32. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/acceptance-aggregate.v1.schema.json +157 -0
  33. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/acceptance-observation.v1.schema.json +38 -0
  34. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/acceptance-result-core.v1.schema.json +1027 -0
  35. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/acceptance-result.v1.schema.json +442 -0
  36. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/acceptance-run.v1.schema.json +98 -0
  37. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/acceptance-scenario-core.v1.schema.json +1202 -0
  38. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/acceptance-scenario.v1.schema.json +485 -0
  39. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/artifact-receipt.v1.schema.json +68 -0
  40. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/artifact-verification.v1.schema.json +92 -0
  41. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/campaign-summary.v1.schema.json +167 -0
  42. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/catalog.v1.json +38 -0
  43. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/causal-chain.v1.schema.json +70 -0
  44. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/clock-relation.v1.schema.json +204 -0
  45. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/common.v1.schema.json +243 -0
  46. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/conformance-result.v1.schema.json +117 -0
  47. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/dataset-manifest.v1.schema.json +340 -0
  48. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/evidence-index.v1.schema.json +257 -0
  49. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/execution-permit.v1.schema.json +226 -0
  50. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/execution-trust-policy.v1.schema.json +122 -0
  51. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/execution-verification.v1.schema.json +163 -0
  52. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/model-artifact-manifest.v1.schema.json +262 -0
  53. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/qualification-bundle.v1.schema.json +108 -0
  54. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/qualification-policy.v1.schema.json +94 -0
  55. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/qualification-profile.v1.schema.json +29 -0
  56. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/recording-summary.v1.schema.json +122 -0
  57. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/robot-description.v1.schema.json +212 -0
  58. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/runtime-manifest-core.v1.schema.json +808 -0
  59. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/runtime-manifest.v1.schema.json +126 -0
  60. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/transport-channel-observation.v1.schema.json +157 -0
  61. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/transport-channel.v1.schema.json +274 -0
  62. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/transport-qualification-result-core.v1.schema.json +484 -0
  63. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/schemas/transport-qualification-result.v1.schema.json +97 -0
  64. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/semantics.py +1274 -0
  65. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/serialization.py +244 -0
  66. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/statements.py +102 -0
  67. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/status.py +37 -0
  68. robotics_runtime_contracts-0.17.0/src/robotics_runtime_contracts/writers.py +298 -0
  69. robotics_runtime_contracts-0.17.0/tests/__init__.py +0 -0
  70. robotics_runtime_contracts-0.17.0/tests/fixtures/campaign/valid/legacy-shortfall.json +37 -0
  71. robotics_runtime_contracts-0.17.0/tests/fixtures/dataset/invalid/s3-without-version.yaml +34 -0
  72. robotics_runtime_contracts-0.17.0/tests/fixtures/dataset/valid/camera-mcap.yaml +41 -0
  73. robotics_runtime_contracts-0.17.0/tests/fixtures/evidence-index/invalid/unconfirmed-s3.yaml +27 -0
  74. robotics_runtime_contracts-0.17.0/tests/fixtures/evidence-index/valid/mixed.yaml +43 -0
  75. robotics_runtime_contracts-0.17.0/tests/fixtures/execution-trust-policy/invalid/no-approver.json +27 -0
  76. robotics_runtime_contracts-0.17.0/tests/fixtures/execution-trust-policy/invalid/overlong-lifetime.json +27 -0
  77. robotics_runtime_contracts-0.17.0/tests/fixtures/execution-trust-policy/invalid/unfilled-target.json +27 -0
  78. robotics_runtime_contracts-0.17.0/tests/fixtures/execution-trust-policy/valid/hil.json +27 -0
  79. robotics_runtime_contracts-0.17.0/tests/fixtures/execution-trust-policy/valid/infra-example.json +27 -0
  80. robotics_runtime_contracts-0.17.0/tests/fixtures/model-artifact/invalid/portable-tensorrt.yaml +48 -0
  81. robotics_runtime_contracts-0.17.0/tests/fixtures/model-artifact/valid/onnx.yaml +51 -0
  82. robotics_runtime_contracts-0.17.0/tests/fixtures/model-artifact/valid/tensorrt.yaml +57 -0
  83. robotics_runtime_contracts-0.17.0/tests/fixtures/physical/valid/hil-permit.yaml +26 -0
  84. robotics_runtime_contracts-0.17.0/tests/fixtures/physical/valid/hil-result.yaml +104 -0
  85. robotics_runtime_contracts-0.17.0/tests/fixtures/physical/valid/hil-runtime.yaml +81 -0
  86. robotics_runtime_contracts-0.17.0/tests/fixtures/physical/valid/hil-scenario.yaml +71 -0
  87. robotics_runtime_contracts-0.17.0/tests/fixtures/physical/valid/hil-verification.yaml +29 -0
  88. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/aggregate.json +1 -0
  89. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/artifacts.json +1 -0
  90. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/conformance.json +1 -0
  91. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/dataset.json +1 -0
  92. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/dataset.mcap +1 -0
  93. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/detector.onnx +1 -0
  94. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/evaluator-package.whl +1 -0
  95. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/evaluator-receipt.json +1 -0
  96. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/evaluator-statement.json +1 -0
  97. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/evaluator-trust.json +1 -0
  98. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/evaluator-verification.bundle +1 -0
  99. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/evaluator-verification.json +1 -0
  100. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/evidence-index.json +1 -0
  101. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/evidence-receipt.json +1 -0
  102. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/evidence-statement.json +1 -0
  103. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/evidence-verification.bundle +1 -0
  104. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/evidence-verification.json +1 -0
  105. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/model.json +1 -0
  106. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/output.mcap +1 -0
  107. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/provider-config.json +1 -0
  108. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/provider-conformance.json +1 -0
  109. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/provider-profile.json +1 -0
  110. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/qos-overrides.yaml +3 -0
  111. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/recording-summary.json +1 -0
  112. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/result.json +1 -0
  113. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/run.json +1 -0
  114. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/runtime.json +1 -0
  115. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/sample.bin +1 -0
  116. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/inference/scenario.json +1 -0
  117. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/aggregate.json +1 -0
  118. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/approver.bundle +1 -0
  119. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/artifacts.json +1 -0
  120. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/evidence-index.json +1 -0
  121. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/execution.rego +2 -0
  122. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/hardware-clock.json +1 -0
  123. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/observation.mcap +1 -0
  124. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/operator.bundle +1 -0
  125. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/permit.json +1 -0
  126. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/preflight.json +1 -0
  127. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/provider-config.json +1 -0
  128. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/provider-conformance.json +1 -0
  129. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/provider-profile.json +1 -0
  130. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/recording-summary.json +1 -0
  131. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/result.json +1 -0
  132. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/run.json +1 -0
  133. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/runtime.json +1 -0
  134. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/scenario.json +1 -0
  135. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/sros2-policy.xml +1 -0
  136. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/statement.json +1 -0
  137. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/trust-policy.json +1 -0
  138. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/physical/verification.json +1 -0
  139. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/aggregate.json +1 -0
  140. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/artifacts.json +1 -0
  141. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/bridge-config.json +1 -0
  142. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/causal-chain.json +1 -0
  143. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/channel-observation.json +1 -0
  144. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/channel.json +1 -0
  145. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/clock-relation.json +1 -0
  146. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/control-evidence-index.json +1 -0
  147. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/control-result.json +1 -0
  148. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/control-runtime.json +1 -0
  149. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/control-summary.json +1 -0
  150. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/control.mcap +1 -0
  151. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/control.otlp.jsonl +1 -0
  152. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/provider-config.json +1 -0
  153. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/provider-conformance.json +1 -0
  154. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/provider-profile.json +1 -0
  155. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/run.json +1 -0
  156. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/scenario.json +1 -0
  157. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/transport.json +1 -0
  158. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/worker-evidence-index.json +1 -0
  159. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/worker-result.json +1 -0
  160. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/worker-runtime.json +1 -0
  161. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/worker-summary.json +1 -0
  162. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/worker.mcap +1 -0
  163. robotics_runtime_contracts-0.17.0/tests/fixtures/qualification/transport/worker.otlp.jsonl +1 -0
  164. robotics_runtime_contracts-0.17.0/tests/fixtures/result/valid/passed.yaml +90 -0
  165. robotics_runtime_contracts-0.17.0/tests/fixtures/robot-description/invalid/escaping-path.json +44 -0
  166. robotics_runtime_contracts-0.17.0/tests/fixtures/robot-description/invalid/prefixed-source-hash.json +44 -0
  167. robotics_runtime_contracts-0.17.0/tests/fixtures/robot-description/invalid/unexpanded-xacro.json +44 -0
  168. robotics_runtime_contracts-0.17.0/tests/fixtures/robot-description/valid/sdf.json +39 -0
  169. robotics_runtime_contracts-0.17.0/tests/fixtures/robot-description/valid/urdf.json +44 -0
  170. robotics_runtime_contracts-0.17.0/tests/fixtures/run/valid/simulation.yaml +14 -0
  171. robotics_runtime_contracts-0.17.0/tests/fixtures/runtime/invalid/cuda-without-accelerator.yaml +80 -0
  172. robotics_runtime_contracts-0.17.0/tests/fixtures/runtime/invalid/none-with-model.yaml +61 -0
  173. robotics_runtime_contracts-0.17.0/tests/fixtures/runtime/valid/cpu-simulation.yaml +84 -0
  174. robotics_runtime_contracts-0.17.0/tests/fixtures/runtime/valid/no-inference-simulation.yaml +70 -0
  175. robotics_runtime_contracts-0.17.0/tests/fixtures/scenario/invalid/playback-without-dataset.yaml +64 -0
  176. robotics_runtime_contracts-0.17.0/tests/fixtures/scenario/valid/playback.yaml +65 -0
  177. robotics_runtime_contracts-0.17.0/tests/fixtures/scenario/valid/simulation-realtime.yaml +90 -0
  178. robotics_runtime_contracts-0.17.0/tests/support.py +17 -0
  179. robotics_runtime_contracts-0.17.0/tests/test_acceptance_result.py +213 -0
  180. robotics_runtime_contracts-0.17.0/tests/test_acceptance_run.py +23 -0
  181. robotics_runtime_contracts-0.17.0/tests/test_acceptance_scenario.py +79 -0
  182. robotics_runtime_contracts-0.17.0/tests/test_campaign_summary.py +104 -0
  183. robotics_runtime_contracts-0.17.0/tests/test_canonical.py +344 -0
  184. robotics_runtime_contracts-0.17.0/tests/test_canonical_fixtures.py +154 -0
  185. robotics_runtime_contracts-0.17.0/tests/test_cli.py +339 -0
  186. robotics_runtime_contracts-0.17.0/tests/test_consumer_examples.py +89 -0
  187. robotics_runtime_contracts-0.17.0/tests/test_contracts.py +183 -0
  188. robotics_runtime_contracts-0.17.0/tests/test_errors_and_resources.py +417 -0
  189. robotics_runtime_contracts-0.17.0/tests/test_evidence_index.py +77 -0
  190. robotics_runtime_contracts-0.17.0/tests/test_extensions.py +127 -0
  191. robotics_runtime_contracts-0.17.0/tests/test_fixtures.py +29 -0
  192. robotics_runtime_contracts-0.17.0/tests/test_mcap_validation.py +268 -0
  193. robotics_runtime_contracts-0.17.0/tests/test_merge_patch.py +183 -0
  194. robotics_runtime_contracts-0.17.0/tests/test_physical_contracts.py +165 -0
  195. robotics_runtime_contracts-0.17.0/tests/test_product_roles.py +353 -0
  196. robotics_runtime_contracts-0.17.0/tests/test_provider_receipt_api.py +80 -0
  197. robotics_runtime_contracts-0.17.0/tests/test_qualification.py +839 -0
  198. robotics_runtime_contracts-0.17.0/tests/test_qualification_api.py +270 -0
  199. robotics_runtime_contracts-0.17.0/tests/test_qualification_policy.py +81 -0
  200. robotics_runtime_contracts-0.17.0/tests/test_receipt_writer.py +168 -0
  201. robotics_runtime_contracts-0.17.0/tests/test_recording_writer.py +167 -0
  202. robotics_runtime_contracts-0.17.0/tests/test_schema_digests.py +26 -0
  203. robotics_runtime_contracts-0.17.0/tests/test_semantics.py +138 -0
  204. robotics_runtime_contracts-0.17.0/tests/test_serialization.py +255 -0
  205. robotics_runtime_contracts-0.17.0/tests/test_statement_matching.py +140 -0
  206. robotics_runtime_contracts-0.17.0/tests/test_statement_writer.py +137 -0
  207. robotics_runtime_contracts-0.17.0/tests/test_trace_contracts.py +803 -0
  208. robotics_runtime_contracts-0.17.0/tests/test_writer_input_aliases.py +93 -0
  209. robotics_runtime_contracts-0.17.0/tests/test_writers.py +227 -0
@@ -0,0 +1,16 @@
1
+ .venv/
2
+ .wheel-venv/
3
+ build/
4
+ dist/
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ .coverage
8
+ htmlcov/
9
+ __pycache__/
10
+ *.py[cod]
11
+ artifacts/
12
+ tmp/
13
+ .env
14
+ .env.*
15
+ !.env.example
16
+ *.egg-info/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Maxim Kolpakov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,351 @@
1
+ Metadata-Version: 2.4
2
+ Name: robotics-runtime-contracts
3
+ Version: 0.17.0
4
+ Summary: Canonical acceptance and evidence contracts for robotics runtimes.
5
+ Project-URL: Homepage, https://github.com/mmkolpakov/robotics-runtime/tree/main/packages/contracts
6
+ Project-URL: Repository, https://github.com/mmkolpakov/robotics-runtime
7
+ Project-URL: Issues, https://github.com/mmkolpakov/robotics-runtime/issues
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: acceptance-testing,json-schema,robotics,ros2,simulation
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Topic :: Scientific/Engineering
17
+ Requires-Python: <3.15,>=3.12
18
+ Requires-Dist: jsonschema[format-nongpl]<5,>=4.26
19
+ Requires-Dist: pyyaml<7,>=6.0.3
20
+ Requires-Dist: referencing<1,>=0.37
21
+ Provides-Extra: mcap
22
+ Requires-Dist: mcap<2,>=1.4; extra == 'mcap'
23
+ Description-Content-Type: text/markdown
24
+
25
+ # Robotics Runtime Contracts
26
+
27
+ [![CI](https://github.com/mmkolpakov/robotics-runtime-contracts/actions/workflows/ci.yml/badge.svg)](https://github.com/mmkolpakov/robotics-runtime-contracts/actions/workflows/ci.yml)
28
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
29
+
30
+ Canonical, machine-verifiable contracts for portable robotics executions.
31
+
32
+ This package defines the boundary shared by product repositories, runtime
33
+ infrastructure, and acceptance tooling. It validates requested scenarios,
34
+ observed runtimes, evidence, qualification inputs, and verdicts. It does not
35
+ launch ROS 2, choose a simulator, collect telemetry, or contain product logic.
36
+
37
+ ## Architecture
38
+
39
+ ```mermaid
40
+ flowchart LR
41
+ product["Product repository"] --> infra["Runtime infrastructure"]
42
+ infra --> execution["ROS 2 execution"]
43
+ execution --> harness["Acceptance harness"]
44
+ harness --> evidence["Evidence and verdict"]
45
+ contracts["Runtime contracts"] -. validates .-> product
46
+ contracts -. validates .-> infra
47
+ contracts -. validates .-> harness
48
+ ```
49
+
50
+ The contracts are independent of a particular robot or product. They describe
51
+ ROS 2 execution, security and timing concepts, including implementation-specific
52
+ constraints. Provider identities are recorded as data or namespaced extensions;
53
+ they do not select a schema.
54
+
55
+ ## Install
56
+
57
+ Python 3.12 through 3.14 is supported. Install a wheel from a tagged
58
+ [GitHub Release](https://github.com/mmkolpakov/robotics-runtime-contracts/releases),
59
+ or create a development environment:
60
+
61
+ ```bash
62
+ uv sync --locked --all-groups
63
+ ```
64
+
65
+ Release assets include build-provenance attestations. See
66
+ [SUPPLY_CHAIN.md](SUPPLY_CHAIN.md).
67
+
68
+ ## CLI
69
+
70
+ Validate JSON or YAML using its declared `schema_version`:
71
+
72
+ ```bash
73
+ robotics-contracts validate scenario.yaml
74
+ ```
75
+
76
+ Resolve reviewed RFC 7396 overlays and retain their origin trace:
77
+
78
+ ```bash
79
+ robotics-contracts scenario resolve base.yaml \
80
+ --overlay camera.yaml \
81
+ --overlay limits.yaml \
82
+ --output resolved.yaml \
83
+ --trace-output resolution-trace.json
84
+ ```
85
+
86
+ Qualification subjects use the following naming pattern. Add the evidence index,
87
+ retained raw artifacts, and other bindings required by the scenario to make the set
88
+ complete; see [qualification validation](docs/qualification.md).
89
+
90
+ ```bash
91
+ robotics-contracts validate-qualification \
92
+ --artifact scenario:scenario.json=scenario.json \
93
+ --artifact acceptance_run:acceptance-run.json=run.json \
94
+ --artifact runtime_manifest:runtime-manifests/main.json=runtime.json \
95
+ --artifact domain_result:results/main.json=result.json \
96
+ --artifact acceptance_aggregate:acceptance-aggregate.json=aggregate.json
97
+ ```
98
+
99
+ Use `--quiet` for gates and `--format json` for stable machine-readable
100
+ diagnostics. `describe` reports a schema identifier and digest, `diff` emits an
101
+ RFC 7396 merge patch, and `permit init --subject-digest ...` creates an unsigned
102
+ physical-execution permit for an external signing workflow.
103
+
104
+ ## Python API
105
+
106
+ ```python
107
+ from robotics_runtime_contracts import (
108
+ schema_for_role,
109
+ schema_registry,
110
+ validate_document,
111
+ validate_role,
112
+ )
113
+
114
+ validate_document(document)
115
+ validate_role(document, "acceptance_scenario")
116
+ print(schema_for_role("runtime_manifest"))
117
+ registry = schema_registry()
118
+ ```
119
+
120
+ Validation is offline, does not mutate inputs, and rejects non-finite numbers.
121
+ Individual document validation reports its first failure; structural and semantic
122
+ errors normally include a JSON path. The public `qualification` module accumulates
123
+ independent document and link failures in `QualificationReport`, with explicit
124
+ blocked checks when prerequisites are invalid. Link errors can have no JSON path.
125
+ The package exports `worst_status()` for consumers to share status-folding
126
+ rules; this does not mean every consumer already uses it.
127
+
128
+ ## Contract Set
129
+
130
+ Release 0.16 publishes one catalogued `v1` contract set. These identifiers are
131
+ not compatible with every historical `v1` document. The
132
+ machine-readable source of truth is
133
+ [`catalog.v1.json`](src/robotics_runtime_contracts/schemas/catalog.v1.json).
134
+
135
+ | Area | Public roles |
136
+ | --- | --- |
137
+ | Execution | scenario, run, observation, result, aggregate, campaign |
138
+ | Runtime | runtime manifest, model manifest, dataset manifest, robot description |
139
+ | Evidence | evidence index, recording summary, artifact receipt |
140
+ | Qualification | profile, conformance result, bundle, policy |
141
+ | Physical safety | execution permit, verification, trust policy |
142
+ | Cross-domain transport | channel, observation, clock relation, causal chain, qualification result |
143
+
144
+ Every public document uses JSON Schema Draft 2020-12, declares a
145
+ `schema_version` ending in `.v1`, rejects unknown root fields, and has an ID in
146
+ the `urn:robotics-runtime-contracts:v1:*` namespace. Internal schema resources
147
+ exist only to remove duplication and are not document roles.
148
+
149
+ The working catalog adds `execution_trust_policy` and `robot_description` for
150
+ the next release; these roles were not published in 0.16. See
151
+ [product artifact roles](docs/product-artifact-roles.md) for their field and
152
+ path conventions and [consumer examples](consumer-examples/README.md) for
153
+ complete documents with real artifact byte digests.
154
+
155
+ ## Extensions
156
+
157
+ Scenario extensions can use digest-pinned schemas without changing the common
158
+ contract. This validation currently applies only to acceptance scenarios;
159
+ `extensions` in other document roles do not receive the same schema checks.
160
+ Extension schemas are interpreted as Draft 2020-12. Extension keys use
161
+ reverse-domain namespaces such as
162
+ `org.example.sorting`; schema bytes are supplied by the caller and are never
163
+ fetched from the network.
164
+
165
+ ```python
166
+ validate_document(
167
+ scenario,
168
+ extension_schemas={
169
+ "https://schemas.example.org/sorting.v1.schema.json": schema_bytes,
170
+ },
171
+ )
172
+ ```
173
+
174
+ Promote an extension into the common catalog only after it has reusable
175
+ semantics and evidence from more than one domain.
176
+
177
+ ## Merge patches and semantic diff
178
+
179
+ Scenario overlays use the native, typed implementation of
180
+ [RFC 7396 section 2](https://www.rfc-editor.org/rfc/rfc7396#section-2).
181
+ Object members merge recursively, `null` removes a member, and arrays replace
182
+ as a whole. Inputs and outputs do not share mutable containers. Overlays apply
183
+ in the given order, followed by contract validation.
184
+
185
+ `semantic_diff` compares parsed values recursively without Python's scalar
186
+ coercions: booleans differ from numbers, and integer/float representations such
187
+ as `1` and `1.0` also produce a patch. Object key order and source formatting are
188
+ ignored. A round-trip check rejects targets that require introducing an object
189
+ member with value `null`, using `diff.unrepresentable`; an unchanged existing
190
+ `null` and nulls inside replaced arrays are representable. This distinction is
191
+ part of the diff API; RFC 7396 specifies patch application, not diff generation.
192
+ The implementation is checked against the RFC's 15 Appendix A vectors and
193
+ generated round-trip cases. It has no third-party merge-patch dependency.
194
+
195
+ ## JSON and YAML input
196
+
197
+ Documents are UTF-8 mappings with string keys and finite JSON values. Files
198
+ ending in `.json` are parsed strictly as JSON, without a YAML fallback;
199
+ `.yaml`/`.yml` select YAML. For unnamed input, standard input, and other suffixes,
200
+ a leading `{` or `[` selects strict JSON and other input selects YAML. Pass a
201
+ YAML `source_name` to `loads_mapping` when using YAML flow syntax such as
202
+ `{key: value}`. Duplicate keys are rejected in both formats, including nested
203
+ objects and escaped spellings of the same JSON key. Digest-pinned extension
204
+ schemas use the same strict JSON parser.
205
+
206
+ The YAML loader uses the [YAML 1.2 core scalar rules](https://yaml.org/spec/1.2.2/#1032-tag-resolution):
207
+ dates and timestamps stay strings; `yes`, `no`, `on`, `off`, `1:30`, `0b10` and
208
+ `1_000` stay strings; only the core `true`/`false` spellings become booleans.
209
+ `010` is decimal 10; `0o10` is octal 8 and `0x10` is hexadecimal 16. `1.10` and
210
+ `1e2` are numbers; quote them when they represent textual versions or IDs.
211
+ Non-finite numbers, non-string keys, non-core tags, aliases (including recursive
212
+ and merge aliases), and multiple YAML documents are rejected. `<<` has no merge
213
+ semantics. YAML output quotes strings using the same scalar rules and emits no
214
+ aliases, so reading a written document preserves its JSON values.
215
+
216
+ Each contract document or extension schema is limited to 8 MiB of UTF-8 input,
217
+ 64 node levels (root at level 1), and 100,000 nodes, counting mapping keys and
218
+ values. File and stdin reads stop at the byte limit plus one sentinel byte.
219
+ These bounds apply to document loaders, not retained raw evidence files.
220
+ Limit failures use `input.limit_exceeded`, duplicates use `input.duplicate_key`
221
+ with the member path, and aliases use `input.yaml_alias`. Other malformed input
222
+ uses `input.parse_failed`; non-finite values use `input.non_finite_number`.
223
+
224
+ ## Deterministic JSON and artifact hashes
225
+
226
+ `dumps_canonical(document) -> bytes` implements this project's deterministic
227
+ JSON profile. **It is not RFC 8785/JCS.** Existing contract integers, including
228
+ nanoseconds beyond 2**53, remain exact JSON number tokens. No schemas or wire
229
+ types change to satisfy JCS's binary64 domain. This is an explicit compatibility
230
+ choice, not a fallback from a strict JCS implementation.
231
+
232
+ The profile accepts built-in `dict`, `list`, `str`, `int`, `float`, `bool` and
233
+ `None` values. Object keys must be strings. It emits UTF-8 without a BOM or
234
+ trailing newline, with compact `,`/`:` separators. Object keys sort recursively
235
+ by Unicode code point, which differs from JCS's UTF-16 ordering; array order
236
+ is preserved. Unicode is not normalized, non-ASCII characters remain UTF-8,
237
+ and JSON control/quote/backslash escaping uses the native Python JSON encoder.
238
+ Surrogate code points in Python strings are rejected. A valid JSON surrogate
239
+ escape pair parsed into a Unicode scalar is supported.
240
+
241
+ Integers have no 53-bit or 64-bit cap and are never converted to float or string
242
+ values. Booleans stay distinct from integers. Finite floats use native Python
243
+ JSON spelling: `1.0`, `1e-06`, and `-0.0` remain those spellings, including the
244
+ negative-zero sign. This preserves the supplied float; it cannot recover
245
+ decimal precision already lost before the call. Tuples, sets, bytes, Decimal,
246
+ custom objects and subclasses of the accepted built-ins are not coerced.
247
+
248
+ The input tree uses the same 64-level and 100,000-node limits as the loaders,
249
+ counting keys and values with the root at level 1. Encoded output is limited to
250
+ 8 MiB, including escaping and UTF-8 expansion. Individual oversized strings
251
+ and integers are rejected before assembling output. The interpreter's integer
252
+ decimal-conversion limit also applies and is never changed process-wide.
253
+ Shared containers are expanded within the node budget; cycles fail the depth
254
+ limit. Errors inherit `ContractError`: `input.invalid_type`,
255
+ `input.invalid_unicode`, `input.non_finite_number`, or `input.limit_exceeded`.
256
+ Paths identify the invalid value, the object containing a non-string or oversized
257
+ key, or `$` for the total output-byte limit. Diagnostic paths also have an 8 MiB
258
+ UTF-8 budget: when a member or index would exceed it, errors in that subtree use
259
+ the nearest enclosing path that fits. Key sizes are checked before constructing
260
+ their paths, and diagnostic escaping uses bounded chunks. This does not narrow
261
+ the accepted keys or change serialized bytes. Serialization does not mutate the
262
+ input.
263
+
264
+ ```python
265
+ from robotics_runtime_contracts import dumps_canonical, file_sha256
266
+
267
+ encoded = dumps_canonical({"ns": 1785067200123456789, "ready": True})
268
+ assert encoded == b'{"ns":1785067200123456789,"ready":true}'
269
+ digest = file_sha256("existing-evidence.bin")
270
+ ```
271
+
272
+ `file_sha256(path) -> str` returns the lowercase SHA-256 hex digest of the
273
+ **original file bytes**, read in 1 MiB chunks. It expands home paths, propagates
274
+ normal file I/O errors and does not apply the document-size limit to artifacts.
275
+ It never parses or serializes the file, even for JSON, and works on binary data.
276
+ There is no `document_digest` API. Existing receipts and signatures continue
277
+ to refer to original bytes. Re-serializing a separate copy can change its hash;
278
+ replacing an existing artifact requires rebuilding its dependent hash/signature
279
+ chain. Hash new files only after their exact bytes have been written.
280
+
281
+ ## Errors and resource paths
282
+
283
+ Expected validation and document-operation failures inherit from the public
284
+ `ContractError`, which remains a `ValueError`. Existing specialized exception
285
+ classes and their constructor signatures remain available. Every contract
286
+ error has an `error_id` and a `json_path` (`None` when no document location
287
+ applies). The CLI keeps its JSON diagnostic envelope
288
+ `{"error": {"error_id": "...", "message": "...", "path": "..."}}`; `path` is
289
+ omitted when unavailable. Schema diagnostics use jsonschema's `best_match`,
290
+ including nested `anyOf`/`oneOf` errors, so the chosen message can change. See
291
+ [jsonschema's selection rules](https://python-jsonschema.readthedocs.io/en/stable/errors/#best-match-and-relevance).
292
+
293
+ CLI exit codes are 0 for success, 1 for invalid input, I/O failures or internal
294
+ errors, and 2 for invalid arguments (including conflicting paths and malformed
295
+ artifact/extension options). I/O errors use `input.io_error`; unexpected
296
+ exceptions use `internal.error` without a traceback. Python I/O APIs retain
297
+ their normal `OSError` behavior. Library programming errors are not converted
298
+ to validation failures. `--help` and process interrupts retain normal behavior.
299
+ All CLI file inputs and outputs expand `~` before accessing the filesystem.
300
+
301
+ Error families include `schema.validation_failed`, `schema.unknown`,
302
+ `schema.role_unknown`, `schema.reference_invalid`, `semantic.validation_failed`,
303
+ `extension.validation_failed`, `qualification.invalid`,
304
+ `qualification.unknown_domain`, `qualification.unknown_channel`,
305
+ `provider.requirements_unsatisfied`, `receipt.validation_failed`,
306
+ `clock.evidence_invalid`, `status.invalid`, `input.parse_failed`,
307
+ `input.non_finite_number`, `input.invalid_timestamp`, `input.invalid`,
308
+ and `cli.arguments_invalid`. Extension references resolve offline; dangling or
309
+ non-terminating references encountered during validation are extension errors.
310
+ Timestamp comparisons share one offset-aware parser; timestamp format
311
+ validation remains the responsibility of the contract schema.
312
+
313
+ `schema_dir()` and `schema_path()` still return `pathlib.Path` objects. For
314
+ zip imports, `importlib.resources.as_file` extracts the schema directory once
315
+ and its context stays open until process exit; an `atexit` handler removes the
316
+ temporary directory, following the
317
+ [resource context lifetime](https://docs.python.org/3/library/importlib.resources.html#importlib.resources.as_file).
318
+ Callers can retain these paths within the process without
319
+ adopting a context-manager API. Paths must not be persisted for another process.
320
+
321
+ ## Version Policy
322
+
323
+ Known consumers include the acceptance harness and runtime infra. They use
324
+ different contract generations; see the dated consumer table in
325
+ [COMPATIBILITY.md](COMPATIBILITY.md) and the
326
+ [0.15 to 0.16 migration guide](docs/migrations/0.15-to-0.16.md).
327
+ Published schema names now permit only additive changes; breaking changes
328
+ require a new schema major and migration notes. The structural compatibility
329
+ gate is planned, so published schema changes remain deferred. Released tags
330
+ and artifacts remain immutable. See [CHANGELOG.md](CHANGELOG.md).
331
+
332
+ HIL and real-target contracts are observation-only. A valid document is not an
333
+ authorization to actuate hardware and is not proof that a device or accelerator
334
+ has been qualified.
335
+
336
+ ## Development
337
+
338
+ ```bash
339
+ uv sync --locked --all-groups
340
+ uv run pre-commit run --all-files --show-diff-on-failure
341
+ uv run pytest
342
+ uv build --no-sources
343
+ ```
344
+
345
+ Consumer examples live in [`consumer-examples/`](consumer-examples/).
346
+ Contributions must follow [CONTRIBUTING.md](CONTRIBUTING.md), and security
347
+ reports must follow [SECURITY.md](SECURITY.md).
348
+
349
+ ## License
350
+
351
+ [MIT](LICENSE)