mostlyright-data 0.17.3__tar.gz → 0.17.5__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 (557) hide show
  1. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/PKG-INFO +1 -1
  2. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/pyproject.toml +1 -1
  3. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/skills/mr-data-build/SKILL.md +64 -11
  4. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/acquisition/http.py +4 -0
  5. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/acquisition/sandbox.py +301 -43
  6. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/cli.py +21 -0
  7. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/compact_worker.py +13 -4
  8. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/formats.py +18 -1
  9. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_deploy.py +2 -1
  10. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_run_worker.py +420 -42
  11. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/inprocess_acquisition.py +811 -67
  12. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/key_seam.py +2 -1
  13. mostlyright_data-0.17.5/src/mostlyright/data_harness/legacy_table_recovery.py +281 -0
  14. mostlyright_data-0.17.5/src/mostlyright/data_harness/legacy_table_recovery_contract.py +74 -0
  15. mostlyright_data-0.17.5/src/mostlyright/data_harness/page_coverage.py +92 -0
  16. mostlyright_data-0.17.5/src/mostlyright/data_harness/readers/configurable_delimited.py +284 -0
  17. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/html_web_extract.py +203 -72
  18. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/registry.py +35 -0
  19. mostlyright_data-0.17.5/src/mostlyright/data_harness/readers/samples/delimited_text/2.0.0/publisher_preamble/expected.json +41 -0
  20. mostlyright_data-0.17.5/src/mostlyright/data_harness/readers/samples/delimited_text/2.0.0/publisher_preamble/indices.csv +5 -0
  21. mostlyright_data-0.17.5/src/mostlyright/data_harness/readers/samples/html.web_extract/1.1.0/article_text_order/article.html +3 -0
  22. mostlyright_data-0.17.5/src/mostlyright/data_harness/readers/samples/html.web_extract/1.1.0/article_text_order/expected.json +28 -0
  23. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/tabular.py +2 -2
  24. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/run_execution_v4.py +127 -3
  25. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/authenticated_https_v2.py +9 -3
  26. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/authenticated_https_v3.py +14 -3
  27. mostlyright_data-0.17.5/src/mostlyright/data_harness/sources/page_collections.py +2198 -0
  28. mostlyright_data-0.17.5/src/mostlyright/data_harness/thin/collection_plan.py +211 -0
  29. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/transport.py +4 -2
  30. mostlyright_data-0.17.5/src/mostlyright/data_harness/thin/user_agent.py +74 -0
  31. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/v4_runs.py +29 -0
  32. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/cloud_auth.py +3 -1
  33. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/remediation.py +1 -1
  34. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/render.py +6 -0
  35. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/v4_acquisition.py +142 -1
  36. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/v4_recipe.py +184 -3
  37. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/v4_required_controls.py +13 -0
  38. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/.gitignore +0 -0
  39. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/README.md +0 -0
  40. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/scripts/hatch_build.py +0 -0
  41. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/skills/mr-data-build/agents/openai.yaml +0 -0
  42. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/skills/mr-data-build/scripts/write_research_notebook.py +0 -0
  43. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/skills/mr-data-build/scripts/write_visual_run.py +0 -0
  44. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/__init__.py +0 -0
  45. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/LICENSE +0 -0
  46. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/PROVENANCE.json +0 -0
  47. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/__init__.py +0 -0
  48. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/__init__.pyi +0 -0
  49. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/_version.py +0 -0
  50. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/cal_rec_boxes/__init__.py +0 -0
  51. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/cal_rec_boxes/main.py +0 -0
  52. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/ch_ppocr_cls/__init__.py +0 -0
  53. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/ch_ppocr_cls/main.py +0 -0
  54. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/ch_ppocr_cls/utils.py +0 -0
  55. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/ch_ppocr_det/__init__.py +0 -0
  56. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/ch_ppocr_det/main.py +0 -0
  57. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/ch_ppocr_det/utils.py +0 -0
  58. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/ch_ppocr_rec/__init__.py +0 -0
  59. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/ch_ppocr_rec/main.py +0 -0
  60. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/ch_ppocr_rec/typings.py +0 -0
  61. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/ch_ppocr_rec/utils.py +0 -0
  62. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/config.yaml +0 -0
  63. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/inference_engine/__init__.py +0 -0
  64. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/inference_engine/base.py +0 -0
  65. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/inference_engine/onnxruntime/__init__.py +0 -0
  66. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/inference_engine/onnxruntime/main.py +0 -0
  67. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/inference_engine/onnxruntime/provider_config.py +0 -0
  68. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/main.py +0 -0
  69. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/models/PP-OCRv6_det_small.onnx +0 -0
  70. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/models/PP-OCRv6_rec_small.onnx +0 -0
  71. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/models/ch_ppocr_mobile_v2.0_cls_mobile.onnx +0 -0
  72. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/py.typed +0 -0
  73. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/utils/__init__.py +0 -0
  74. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/utils/load_image.py +0 -0
  75. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/utils/log.py +0 -0
  76. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/utils/model_resolver.py +0 -0
  77. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/utils/output.py +0 -0
  78. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/utils/parse_parameters.py +0 -0
  79. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/utils/process_img.py +0 -0
  80. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/utils/typings.py +0 -0
  81. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/_vendor/rapidocr/utils/utils.py +0 -0
  82. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/__init__.py +0 -0
  83. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/acquisition/__init__.py +0 -0
  84. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/acquisition/derived_credentials.py +0 -0
  85. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/acquisition/parsing.py +0 -0
  86. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/acquisition/ranges.py +0 -0
  87. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/acquisition/result_download.py +0 -0
  88. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/acquisition/retention_admission.py +0 -0
  89. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/acquisition/sandbox_bootstrap.py +0 -0
  90. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/acquisition/url_policy.py +0 -0
  91. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/agent_runtime.py +0 -0
  92. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/assets/logo-ink.svg +0 -0
  93. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/backends/__init__.py +0 -0
  94. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/backends/pandas_backend.py +0 -0
  95. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/backends/polars_backend.py +0 -0
  96. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/backends/protocol.py +0 -0
  97. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/backends/reference.py +0 -0
  98. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/backends/registry.py +0 -0
  99. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/backends/restrictions.py +0 -0
  100. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/bounded_query.py +0 -0
  101. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/bounded_scratch_sink.py +0 -0
  102. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/canonical.py +0 -0
  103. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/catalog_job.py +0 -0
  104. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/contracts.py +0 -0
  105. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/coordinator.py +0 -0
  106. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/crosswalks.py +0 -0
  107. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/declared_checks.py +0 -0
  108. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/delta.py +0 -0
  109. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/delta_checks.py +0 -0
  110. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/delta_classifier.py +0 -0
  111. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/delta_persist.py +0 -0
  112. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/delta_recompute.py +0 -0
  113. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/delta_rows.py +0 -0
  114. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/deploy.py +0 -0
  115. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/deploy_target.py +0 -0
  116. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/deployment_evidence.py +0 -0
  117. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/documents/__init__.py +0 -0
  118. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/documents/_worker_capability.py +0 -0
  119. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/documents/capture.py +0 -0
  120. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/documents/contracts.py +0 -0
  121. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/documents/lane.py +0 -0
  122. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/documents/ocr.py +0 -0
  123. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/documents/pdf.py +0 -0
  124. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/documents/registry.py +0 -0
  125. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/documents/sandbox.py +0 -0
  126. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/documents/selections.py +0 -0
  127. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/documents/tables.py +0 -0
  128. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/documents/vendor_rapidocr.py +0 -0
  129. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/events.py +0 -0
  130. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/fast_delimited.py +0 -0
  131. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/fetch_egress_smoke.py +0 -0
  132. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/governors.py +0 -0
  133. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_bootstrap.py +0 -0
  134. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_crawler.py +0 -0
  135. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_crawler_container_smoke.py +0 -0
  136. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_crawler_fetch.py +0 -0
  137. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_crawler_job.py +0 -0
  138. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_crawler_protocol.py +0 -0
  139. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_ingestion_contract.py +0 -0
  140. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_ingestion_job.py +0 -0
  141. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_ingestion_job_smoke.py +0 -0
  142. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_ingestion_worker.py +0 -0
  143. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_rlimit_as_container_smoke.py +0 -0
  144. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_session_container_smoke.py +0 -0
  145. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_session_worker.py +0 -0
  146. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_session_worker_job_smoke.py +0 -0
  147. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_stream_recorder_container_smoke.py +0 -0
  148. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_stream_recorder_job.py +0 -0
  149. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_stream_subscription_container_smoke.py +0 -0
  150. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_stream_subscription_worker.py +0 -0
  151. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/hosted_worker.py +0 -0
  152. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/incremental_slice_executor.py +0 -0
  153. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/incremental_worker.py +0 -0
  154. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ingestion/__init__.py +0 -0
  155. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ingestion/contracts.py +0 -0
  156. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ingestion/faults.py +0 -0
  157. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ingestion/gcs_store.py +0 -0
  158. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ingestion/spool.py +0 -0
  159. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ingestion/store.py +0 -0
  160. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/linux_process_boundary.py +0 -0
  161. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/local_contracts.py +0 -0
  162. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/CONTRACT.md +0 -0
  163. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/__init__.py +0 -0
  164. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/chrome.py +0 -0
  165. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/code_body.py +0 -0
  166. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/document.py +0 -0
  167. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/frame.py +0 -0
  168. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/interactive.py +0 -0
  169. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/markdown_body.py +0 -0
  170. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/mr_components.py +0 -0
  171. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/outputs_data.py +0 -0
  172. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/outputs_rich.py +0 -0
  173. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/outputs_source.py +0 -0
  174. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/outputs_stage.py +0 -0
  175. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/outputs_text.py +0 -0
  176. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/parse.py +0 -0
  177. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/status.py +0 -0
  178. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/nbrender/tokens.py +0 -0
  179. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/notebook.py +0 -0
  180. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/offline.py +0 -0
  181. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/operation_registry.py +0 -0
  182. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/operator_setup.py +0 -0
  183. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/part_check_evidence.py +0 -0
  184. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/pipeline.py +0 -0
  185. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/plan_graph.py +0 -0
  186. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/preparation/__init__.py +0 -0
  187. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/preparation/contracts.py +0 -0
  188. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/preparation/engine.py +0 -0
  189. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/preparation/errors.py +0 -0
  190. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/preparation/gates.py +0 -0
  191. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/preparation/joins.py +0 -0
  192. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/preparation/profile.py +0 -0
  193. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/preparation/table.py +0 -0
  194. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/preparation/transforms.py +0 -0
  195. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/progress_events.py +0 -0
  196. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/__init__.py +0 -0
  197. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/_openpyxl.py +0 -0
  198. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/budgets.py +0 -0
  199. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/containers.py +0 -0
  200. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/contracts.py +0 -0
  201. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/delimited.py +0 -0
  202. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/geojson_vector.py +0 -0
  203. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/geopackage.py +0 -0
  204. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/geoparquet.py +0 -0
  205. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/grib2/__init__.py +0 -0
  206. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/grib2/admission.py +0 -0
  207. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/grib2/collection.py +0 -0
  208. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/grib2/collection_reader.py +0 -0
  209. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/grib2/decode.py +0 -0
  210. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/grib2/geometry.py +0 -0
  211. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/grib2/portable_math.py +0 -0
  212. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/grib_eccodes.py +0 -0
  213. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/html_tabular.py +0 -0
  214. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/json_tabular.py +0 -0
  215. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/parquet_tabular.py +0 -0
  216. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/pcaxis_px.py +0 -0
  217. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/protobuf_tabular.py +0 -0
  218. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/raster/__init__.py +0 -0
  219. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/raster/_bytes.py +0 -0
  220. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/raster/decode.py +0 -0
  221. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/raster/family.py +0 -0
  222. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/raster/jpeg2000.py +0 -0
  223. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/raster/profiles.py +0 -0
  224. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/raster/rendered.py +0 -0
  225. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/raster/safe.py +0 -0
  226. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/raster/sentinel_safe.py +0 -0
  227. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/raster/tiff.py +0 -0
  228. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/README.md +0 -0
  229. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.gzip/1.0.0/cities_one_stream/cities.csv.gz +0 -0
  230. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.gzip/1.0.0/cities_one_stream/expected.json +0 -0
  231. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.gzip/1.1.0/cities_one_stream/cities.csv.gz +0 -0
  232. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.gzip/1.1.0/cities_one_stream/expected.json +0 -0
  233. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.tar/1.0.0/cities_beside_a_directory_entry/cities.tar +0 -0
  234. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.tar/1.0.0/cities_beside_a_directory_entry/expected.json +0 -0
  235. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.tar/1.1.0/cities_beside_a_directory_entry/cities.tar +0 -0
  236. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.tar/1.1.0/cities_beside_a_directory_entry/expected.json +0 -0
  237. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.zip/1.0.0/cities_beside_a_second_member/cities.zip +0 -0
  238. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.zip/1.0.0/cities_beside_a_second_member/expected.json +0 -0
  239. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.zip/1.1.0/dwd_semicolon_station_member/dwd-station.zip +0 -0
  240. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.zip/1.1.0/dwd_semicolon_station_member/expected.json +0 -0
  241. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.zip/1.2.0/dwd_semicolon_station_member/dwd-station.zip +0 -0
  242. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/archive.zip/1.2.0/dwd_semicolon_station_member/expected.json +0 -0
  243. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/delimited_text/1.0.0/an_ordinary_comma_separated_table/cities.csv +0 -0
  244. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/delimited_text/1.0.0/an_ordinary_comma_separated_table/expected.json +0 -0
  245. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/delimited_text/1.0.0/quoted_fields_holding_the_delimiter/cities.tsv +0 -0
  246. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/delimited_text/1.0.0/quoted_fields_holding_the_delimiter/expected.json +0 -0
  247. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/delimited_text/1.1.0/an_hourly_observation_table_served_as_plain_text/expected.json +0 -0
  248. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/delimited_text/1.1.0/an_hourly_observation_table_served_as_plain_text/observations.csv +0 -0
  249. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/geojson.vector/1.0.0/czech_capital/expected.json +0 -0
  250. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/geojson.vector/1.0.0/czech_capital/places.geojson +0 -0
  251. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/geopackage.vector/1.0.0/epsg_4326_feature/expected.json +0 -0
  252. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/geopackage.vector/1.0.0/epsg_4326_feature/places.gpkg +0 -0
  253. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/geoparquet.vector/1.0.0/primary_wkb_point/expected.json +0 -0
  254. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/geoparquet.vector/1.0.0/primary_wkb_point/places.parquet +0 -0
  255. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/html.tabular/1.0.0/sanitized_table/expected.json +0 -0
  256. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/html.tabular/1.0.0/sanitized_table/table.html +0 -0
  257. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/html.web_extract/1.0.0/json_ld_scorecards/expected.json +0 -0
  258. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/html.web_extract/1.0.0/json_ld_scorecards/scorecards.html +0 -0
  259. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/image.rendered/1.0.0/tiny_png/expected.json +0 -0
  260. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/image.rendered/1.0.0/tiny_png/tiny-rendered.png +0 -0
  261. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/json.tabular/1.0.0/nested_hourly_observations/expected.json +0 -0
  262. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/json.tabular/1.0.0/nested_hourly_observations/stations.json +0 -0
  263. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/json.tabular/1.1.0/an_observation_stream_served_as_plain_text/expected.json +0 -0
  264. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/json.tabular/1.1.0/an_observation_stream_served_as_plain_text/observations.ndjson +0 -0
  265. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/meteorology.bufr/1.0.0/eccodes_bufr4_subset/eccodes-bufr4.bufr +0 -0
  266. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/meteorology.bufr/1.0.0/eccodes_bufr4_subset/expected.json +0 -0
  267. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/meteorology.grib/1.0.0/eccodes_grib1_origin/expected.json +0 -0
  268. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/meteorology.grib/1.0.0/eccodes_grib1_origin/regular-ll-surface.grib1 +0 -0
  269. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/microdata.sas_xpt/1.0.0/two_raw_columns/expected.json +0 -0
  270. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/microdata.sas_xpt/1.0.0/two_raw_columns/survey.xpt +0 -0
  271. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/microdata.spss_sav/1.0.0/two_raw_columns/expected.json +0 -0
  272. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/microdata.spss_sav/1.0.0/two_raw_columns/survey.sav +0 -0
  273. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/microdata.stata_dta/1.0.0/two_raw_columns/expected.json +0 -0
  274. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/microdata.stata_dta/1.0.0/two_raw_columns/stata.dta +0 -0
  275. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/official.pcaxis_px/1.0.0/population_by_region_and_year/expected.json +0 -0
  276. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/official.pcaxis_px/1.0.0/population_by_region_and_year/population.px +0 -0
  277. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/official.sdmx_json/1.0.0/compact_population_series/expected.json +0 -0
  278. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/official.sdmx_json/1.0.0/compact_population_series/population.json +0 -0
  279. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/parquet.tabular/1.0.0/two_columns/expected.json +0 -0
  280. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/parquet.tabular/1.0.0/two_columns/prices.parquet +0 -0
  281. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/protobuf.tabular/1.0.0/gtfs_realtime_trip_updates/expected.json +0 -0
  282. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/protobuf.tabular/1.0.0/gtfs_realtime_trip_updates/gtfs-realtime.desc +0 -0
  283. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/protobuf.tabular/1.0.0/gtfs_realtime_trip_updates/trip-updates.pb +0 -0
  284. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/raster.geospatial/1.0.0/tiny_geotiff/expected.json +0 -0
  285. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/raster.geospatial/1.0.0/tiny_geotiff/tiny-geospatial.tif +0 -0
  286. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/satellite.goes_abi_l2/1.0.0/authored_cmi_window/expected.json +0 -0
  287. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/satellite.goes_abi_l2/1.0.0/authored_cmi_window/goes-abi-l2-cmi-window.nc +0 -0
  288. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/satellite.himawari_hsd/1.0.0/authored_b13_single_bzip2/expected.json +0 -0
  289. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/satellite.himawari_hsd/1.0.0/authored_b13_single_bzip2/himawari-b13-0101-bzip2.dat +0 -0
  290. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/satellite.himawari_hsd_complete/1.0.0/authored_b13_three_segment_scan/expected.json +0 -0
  291. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/satellite.himawari_hsd_complete/1.0.0/authored_b13_three_segment_scan/himawari-hsd-b13-complete.zip +0 -0
  292. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/satellite.msg_seviri_l15/1.0.0/authored_calibrated_complete_visir/expected.json +0 -0
  293. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/satellite.msg_seviri_l15/1.0.0/authored_calibrated_complete_visir/msg-seviri-l15.zip +0 -0
  294. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/satellite.sentinel_safe/1.0.0/authored_b02_scl_window/expected.json +0 -0
  295. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/satellite.sentinel_safe/1.0.0/authored_b02_scl_window/sentinel-safe-b02-scl.zip +0 -0
  296. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/satellite.xrit_image/1.0.0/authored_complete_raw_counts/expected.json +0 -0
  297. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/satellite.xrit_image/1.0.0/authored_complete_raw_counts/xrit-complete-image.zip +0 -0
  298. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.fits/1.0.0/tiny_primary_window/expected.json +0 -0
  299. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.fits/1.0.0/tiny_primary_window/tiny-primary.fits +0 -0
  300. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.hdf4/1.0.0/authored_temperature_window/expected.json +0 -0
  301. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.hdf4/1.0.0/authored_temperature_window/temperature.hdf +0 -0
  302. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.hdf5/1.0.0/authored_temperature_window/expected.json +0 -0
  303. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.hdf5/1.0.0/authored_temperature_window/temperature.h5 +0 -0
  304. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.hdf_eos2/1.0.0/authored_grid_temperature_window/expected.json +0 -0
  305. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.hdf_eos2/1.0.0/authored_grid_temperature_window/nasa-hdfeos2-grid.hdf +0 -0
  306. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.hdf_eos2/1.0.0/authored_swath_temperature_window/expected.json +0 -0
  307. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.hdf_eos2/1.0.0/authored_swath_temperature_window/nasa-hdfeos2-swath.hdf +0 -0
  308. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.netcdf/1.0.0/authored_classic_temperature_window/expected.json +0 -0
  309. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.netcdf/1.0.0/authored_classic_temperature_window/temperature-classic.nc +0 -0
  310. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.zarr/1.0.0/authored_v3_temperature_window/expected.json +0 -0
  311. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/scientific.zarr/1.0.0/authored_v3_temperature_window/temperature-zarr-v3.zip +0 -0
  312. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/an_ordinary_table_beside_a_second_sheet/cities.xlsx +0 -0
  313. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/an_ordinary_table_beside_a_second_sheet/expected.json +0 -0
  314. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/shares_the_workbook_had_already_computed/expected.json +0 -0
  315. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/shares_the_workbook_had_already_computed/shares.xlsx +0 -0
  316. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.1.0/shares_the_workbook_had_already_computed/expected.json +0 -0
  317. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.1.0/shares_the_workbook_had_already_computed/shares.xlsx +0 -0
  318. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/README.md +0 -0
  319. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/gfs_2m_temperature/expected.json +0 -0
  320. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/gfs_2m_temperature/gfs-2m-temperature.grib2 +0 -0
  321. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_2m_temperature/expected.json +0 -0
  322. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_2m_temperature/hrrr-2m-temperature.grib2 +0 -0
  323. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_categorical_rain/expected.json +0 -0
  324. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_categorical_rain/hrrr-categorical-rain.grib2 +0 -0
  325. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/weather.grib2/2.0.0/hrrr_2m_temperature/expected.json +0 -0
  326. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/weather.grib2/2.0.0/hrrr_2m_temperature/hrrr-2m-temperature.grib2 +0 -0
  327. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/weather.grib2/3.0.0/gfs_and_hrrr_categorical_rain/expected.json +0 -0
  328. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/weather.grib2/3.0.0/gfs_and_hrrr_categorical_rain/gfs-and-hrrr-categorical-rain.grib2 +0 -0
  329. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/xbrl.facts/1.0.0/plain_filing_fact/expected.json +0 -0
  330. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/xbrl.facts/1.0.0/plain_filing_fact/filing.xml +0 -0
  331. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/xbrl.facts/1.0.0/xml_inline_fact/expected.json +0 -0
  332. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/xbrl.facts/1.0.0/xml_inline_fact/filing.xhtml +0 -0
  333. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/xml.tabular/1.0.0/pacer_rss_feed/expected.json +0 -0
  334. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/xml.tabular/1.0.0/pacer_rss_feed/feed.xml +0 -0
  335. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/xml.tabular/1.0.0/sec_form_d_filing/expected.json +0 -0
  336. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/xml.tabular/1.0.0/sec_form_d_filing/filing.xml +0 -0
  337. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/xml.tabular/1.0.0/unified_agenda_extract/agenda.xml +0 -0
  338. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples/xml.tabular/1.0.0/unified_agenda_extract/expected.json +0 -0
  339. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/samples.py +0 -0
  340. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific.py +0 -0
  341. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_arrays/__init__.py +0 -0
  342. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_arrays/container.py +0 -0
  343. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_arrays/goes.py +0 -0
  344. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_arrays/hdf4.py +0 -0
  345. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_arrays/hdf4_bridge.py +0 -0
  346. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_arrays/hdf5.py +0 -0
  347. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_arrays/native.py +0 -0
  348. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_arrays/netcdf.py +0 -0
  349. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_arrays/profiles.py +0 -0
  350. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_arrays/raw.py +0 -0
  351. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_arrays/zarr.py +0 -0
  352. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_catalog.py +0 -0
  353. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_segmented/__init__.py +0 -0
  354. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_segmented/asset_sets.py +0 -0
  355. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_segmented/formats.py +0 -0
  356. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_segmented/hsd.py +0 -0
  357. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_segmented/native.py +0 -0
  358. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_segmented/profiles.py +0 -0
  359. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_segmented/reader.py +0 -0
  360. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/scientific_segmented/xrit.py +0 -0
  361. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/sdmx_json.py +0 -0
  362. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/spreadsheet.py +0 -0
  363. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/statistical_microdata.py +0 -0
  364. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/vector.py +0 -0
  365. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/vector_wkb.py +0 -0
  366. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/xbrl_facts.py +0 -0
  367. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/readers/xml_tabular.py +0 -0
  368. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/recipe.py +0 -0
  369. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/review.py +0 -0
  370. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/rowset.py +0 -0
  371. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/run_phase_timing.py +0 -0
  372. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/session_probes.py +0 -0
  373. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/signing.py +0 -0
  374. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/skill_assets.py +0 -0
  375. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/source_bootstrap.py +0 -0
  376. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/source_bundle_writer.py +0 -0
  377. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/source_discovery.py +0 -0
  378. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/source_history_candidate_child.py +0 -0
  379. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/source_history_transform_child.py +0 -0
  380. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/source_inventory.py +0 -0
  381. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/source_partition.py +0 -0
  382. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/source_raw_inventory.py +0 -0
  383. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/source_state_index.py +0 -0
  384. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/__init__.py +0 -0
  385. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/_adapter_steps.py +0 -0
  386. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/adapters.py +0 -0
  387. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/authenticated_https.py +0 -0
  388. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/cadence.py +0 -0
  389. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/cadence_emission.py +0 -0
  390. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/cadence_history.py +0 -0
  391. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/__init__.py +0 -0
  392. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/admission.py +0 -0
  393. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/authoring.py +0 -0
  394. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/authoring_policy.py +0 -0
  395. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/authoring_shards.py +0 -0
  396. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/bounded_io.py +0 -0
  397. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/channel.py +0 -0
  398. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/channel_client.py +0 -0
  399. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/contracts.py +0 -0
  400. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/coverage.py +0 -0
  401. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/embedding.py +0 -0
  402. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/entry_v2.py +0 -0
  403. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/fill.py +0 -0
  404. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/fill_partitions.py +0 -0
  405. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/fill_staging.py +0 -0
  406. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/gating.py +0 -0
  407. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/generation_receipt.py +0 -0
  408. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/harvest/__init__.py +0 -0
  409. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/harvest/ckan.py +0 -0
  410. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/harvest/datagov_v4.py +0 -0
  411. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/harvest/protocol.py +0 -0
  412. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/harvest/sdmx.py +0 -0
  413. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/harvest/stac.py +0 -0
  414. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/hosted_catalog.py +0 -0
  415. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/identity_history.py +0 -0
  416. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/neural.py +0 -0
  417. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/packed_catalog.py +0 -0
  418. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/packed_retrieval.py +0 -0
  419. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/packed_writer.py +0 -0
  420. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/query_trace.py +0 -0
  421. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/recommend.py +0 -0
  422. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/retrieval.py +0 -0
  423. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/retrieval_manifest.py +0 -0
  424. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/sealed.py +0 -0
  425. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/search.py +0 -0
  426. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/streaming_delta.py +0 -0
  427. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/catalog/update.py +0 -0
  428. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/collections.py +0 -0
  429. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/contracts.py +0 -0
  430. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/dataset.py +0 -0
  431. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/deletion.py +0 -0
  432. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/document_projection.py +0 -0
  433. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/fitness.py +0 -0
  434. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/governance.py +0 -0
  435. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/hosted.py +0 -0
  436. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/integration.py +0 -0
  437. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/range_reader.py +0 -0
  438. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/registry.py +0 -0
  439. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/rights_rule.py +0 -0
  440. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/source_cadence_vectors.v1.json +0 -0
  441. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/sports.py +0 -0
  442. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream.py +0 -0
  443. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_capture_session.py +0 -0
  444. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connector.py +0 -0
  445. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.cursor-resume.v3.json +0 -0
  446. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-frame-ed25519.v2.json +0 -0
  447. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-frame-hmac.v2.json +0 -0
  448. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-frame-hmac384.v2.json +0 -0
  449. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-frame-hmac512.v2.json +0 -0
  450. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-frame.v2.json +0 -0
  451. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-header-rsa.v2.json +0 -0
  452. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-header.v2.json +0 -0
  453. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-permessage-jwt.v2.json +0 -0
  454. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-permessage.v2.json +0 -0
  455. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-prelude.v2.json +0 -0
  456. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-query.v2.json +0 -0
  457. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-subprotocol.v2.json +0 -0
  458. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-subscribe.v2.json +0 -0
  459. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/fixture.keyed-urlpath.v2.json +0 -0
  460. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_connectors/polymarket.clob-market.v1.json +0 -0
  461. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_credential.py +0 -0
  462. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_prelude.py +0 -0
  463. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_recorder.py +0 -0
  464. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_registry.py +0 -0
  465. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_rotation.py +0 -0
  466. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_segment_recorder.py +0 -0
  467. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_series.py +0 -0
  468. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_signing.py +0 -0
  469. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sources/stream_transport.py +0 -0
  470. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/sql_transform_engine.py +0 -0
  471. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/stream_order_vector.py +0 -0
  472. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/stream_recovery_objects.py +0 -0
  473. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/stream_segment_spill.py +0 -0
  474. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/stream_subscription_feed.py +0 -0
  475. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/stream_subscription_sealer.py +0 -0
  476. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/stream_subscription_worker.py +0 -0
  477. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/stream_venue.py +0 -0
  478. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/stream_venue_staging.py +0 -0
  479. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/studio_boundary.py +0 -0
  480. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/studio_subscription_control.py +0 -0
  481. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/table_manifest.py +0 -0
  482. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/table_parts.py +0 -0
  483. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/table_profile.py +0 -0
  484. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/__init__.py +0 -0
  485. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/acquire.py +0 -0
  486. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/acquire_cancel.py +0 -0
  487. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/activity.py +0 -0
  488. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/approvals.py +0 -0
  489. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/commands.py +0 -0
  490. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/download.py +0 -0
  491. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/narrative.py +0 -0
  492. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/parity.py +0 -0
  493. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/probe.py +0 -0
  494. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/propose.py +0 -0
  495. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/recipe.py +0 -0
  496. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/research.py +0 -0
  497. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/router.py +0 -0
  498. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/runs.py +0 -0
  499. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/session.py +0 -0
  500. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/stream.py +0 -0
  501. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/stream_venue.py +0 -0
  502. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/v4.py +0 -0
  503. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/v4_artifacts.py +0 -0
  504. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/v4_connections.py +0 -0
  505. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/v4_dataset_covers.py +0 -0
  506. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/v4_datasets.py +0 -0
  507. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/v4_handoff.py +0 -0
  508. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/v4_narrative.py +0 -0
  509. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/v4_query.py +0 -0
  510. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/v4_secrets.py +0 -0
  511. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/v4_stream.py +0 -0
  512. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/v4_tables.py +0 -0
  513. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/vocabulary.py +0 -0
  514. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/thin/workers.py +0 -0
  515. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ucum/TABLE-PIN.json +0 -0
  516. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ucum/ucum-subset.v1.json +0 -0
  517. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/unit_flow.py +0 -0
  518. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/units.py +0 -0
  519. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/__init__.py +0 -0
  520. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/attendance.py +0 -0
  521. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/clarification.py +0 -0
  522. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/commands/__init__.py +0 -0
  523. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/commands/auth.py +0 -0
  524. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/commands/catalog_author.py +0 -0
  525. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/commands/catalog_harvest.py +0 -0
  526. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/commands/catalog_publish.py +0 -0
  527. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/commands/clarify.py +0 -0
  528. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/commands/login.py +0 -0
  529. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/commands/record.py +0 -0
  530. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/commands/whoami.py +0 -0
  531. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/credential_native.py +0 -0
  532. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/credential_store.py +0 -0
  533. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/credentials.py +0 -0
  534. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/headline.py +0 -0
  535. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/hosted_acquisition.py +0 -0
  536. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/local_review.py +0 -0
  537. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/login.py +0 -0
  538. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/path_kind.py +0 -0
  539. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/plain_file.py +0 -0
  540. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/ux/readers.py +0 -0
  541. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/v4_check_dialect.py +0 -0
  542. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/v4_closed_source.py +0 -0
  543. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/v4_document_pin.py +0 -0
  544. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/v4_reader_pin.py +0 -0
  545. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/v4_snapshot_artifact.py +0 -0
  546. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/v4_stream_recording.py +0 -0
  547. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/v4_transform.py +0 -0
  548. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/v4_window.py +0 -0
  549. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/visual_run/__init__.py +0 -0
  550. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/visual_run/authoring.py +0 -0
  551. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/visual_run/contracts.py +0 -0
  552. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/visual_run/materialize.py +0 -0
  553. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/visual_run/observations.py +0 -0
  554. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/visual_run/reducer.py +0 -0
  555. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/visual_run/sdk.py +0 -0
  556. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/visual_run/store.py +0 -0
  557. {mostlyright_data-0.17.3 → mostlyright_data-0.17.5}/src/mostlyright/data_harness/visual_run/transport.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mostlyright-data
3
- Version: 0.17.3
3
+ Version: 0.17.5
4
4
  Summary: Mostly Right CLI for reproducible, reviewed Parquet datasets
5
5
  Project-URL: Homepage, https://mostlyright.md/
6
6
  Project-URL: Documentation, https://mostlyright.md/docs/guides/cli/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mostlyright-data"
3
- version = "0.17.3"
3
+ version = "0.17.5"
4
4
  description = "Mostly Right CLI for reproducible, reviewed Parquet datasets"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13,<3.14"
@@ -389,10 +389,10 @@ around a probe from an hour ago still being warm.
389
389
 
390
390
  Where a source needs a credential, enrol it by name first — see
391
391
  [Source credentials](#source-credentials) — and reference the name from the recipe document. Where
392
- neither a probe nor a run can reach the bytes, because the source is a bounded collection or is
393
- not registered in the workspace, establish shape from the provider's own documentation and
394
- published schema, say plainly that the shape is documented rather than observed, and let the hosted
395
- Clean room be the first thing that opens the bytes. Named messages out of one large object are
392
+ neither a probe nor a run can reach the bytes, because the source is not registered in the
393
+ workspace, establish shape from the provider's own documentation and published schema, say
394
+ plainly that the shape is documented rather than observed, and let the hosted Clean room be the
395
+ first thing that opens the bytes. Named messages out of one large object are
396
396
  [`acquire-slices`](#not-hosted-yet), which is not hosted yet.
397
397
 
398
398
  Hold the comparison in the shape [Narrating the run](#narrating-the-run) takes: one `source` block
@@ -799,9 +799,12 @@ one", not as a failure: a document declaring 8 MiB over a feed that answers 40 K
799
799
  **If a source really does deliver more than the Reader holds, do not answer it by lowering the
800
800
  ceiling on that source:** that does not fetch less data, it truncates the sample or refuses the
801
801
  full run. Split the window across several sources — one per month, per region, or per whatever the
802
- publisher paginates on — and union them in a first transform step. A recipe names up to 64 sources,
803
- which is a great many windows. [The recipe document](../../docs/RECIPE-DOCUMENT.md) carries the
804
- measured numbers behind the ceiling.
802
+ publisher paginates on — and union them in a first transform step. A recipe names up to 256
803
+ sources, which is a great many windows. [The recipe document](../../docs/RECIPE-DOCUMENT.md)
804
+ carries the measured numbers behind the ceiling.
805
+
806
+ **A corpus of many pages behind one index is a COLLECTION, not many sources.** See
807
+ [Authoring a collection source](#authoring-a-collection-source).
805
808
 
806
809
  **The dataset's record is the primary one; a run's own record is for what happened inside that
807
810
  run.** The sources, the decisions and the questions went onto the dataset in stage 3, where they
@@ -1570,6 +1573,53 @@ What it costs the protocol, and what to do instead:
1570
1573
  - Preserve event time, available time, acquisition time, source revision, and timezone. Do not use
1571
1574
  post-cutoff information in targets, labels, features, joins, or validation decisions.
1572
1575
 
1576
+ ### Authoring a collection source
1577
+
1578
+ A corpus published as an index plus many detail pages is **one** source through
1579
+ `public.https.collection@2.0.0`, not one source per page. Source count and publisher count are
1580
+ unaffected by how many pages sit behind it: 2,819 pages is one source, one publisher, one line on
1581
+ the dataset's sources card.
1582
+
1583
+ Write it as a source whose connector is that coordinate plus a `collection` member:
1584
+
1585
+ - `collection.discovery` says how the corpus is LISTED — `json_api` with RFC 6901 pointers,
1586
+ `html_index` with the reader's closed selectors, `sitemap`, or an `explicit` member list — and
1587
+ which pagination grammar the listing uses. The run follows only that grammar and never a link
1588
+ found inside a detail page.
1589
+ - `collection.pages` says what may be fetched and how much: `allowed_origins` (which must include
1590
+ the discovery address's own origin), `max_pages`, `max_fetches_per_run`, `concurrency` (1 or 2),
1591
+ `min_interval_seconds` as a whole number of seconds (one or more), `request_timeout_seconds`,
1592
+ `retries`, and a `revisit` rule. Only `allowed_origins` is required; every other member has a
1593
+ stated meaning when it is left out.
1594
+ - `limits.max_requests` is REQUIRED and bounds every request the run makes, discovery and detail
1595
+ pages together. `limits.max_source_bytes` bounds the fetched bytes; `limits.max_rows` clamps the
1596
+ merged relation.
1597
+ - The Reader pin is required, must be `html.web_extract`, and is the SAME settings for every page.
1598
+
1599
+ The relation the transform reads is the reader's columns plus `page_id`, `page_url`,
1600
+ `page_fetched_at`, `page_content_sha256`, `page_revision`, `page_discovered_at` and `page_ordinal`.
1601
+ Those names are reserved: a reader that declares one is a registration refusal. Select them in the
1602
+ transform so every row on the table says which page and which revision produced it.
1603
+
1604
+ **Expect the first run not to finish, and say so.** A run that spends its fetch budget still
1605
+ SUCCEEDS; its coverage block reports `complete: false` and names the budget that ended it. The
1606
+ next refresh continues from the ledger — new pages first, then failures oldest first, then
1607
+ revisits — and every row of a page this run did not fetch survives byte for byte. Report the
1608
+ shortfall as what it is, a backfill in progress, not as a failure and not as a complete corpus.
1609
+
1610
+ A page that disappears from the index deletes nothing. A page answering with different content
1611
+ replaces exactly its own rows, increments `page_revision`, and keeps the previous digest: that is
1612
+ a correction, and it is worth saying on the run record when it happens.
1613
+
1614
+ Before registering it, read the discovery block back the way a run will: the address the first
1615
+ request goes to, whether the pagination parameter is already written into that address, whether
1616
+ the records pointer names an array, and whether `discovery.max_requests` plus
1617
+ `pages.max_fetches_per_run` fits inside `limits.max_requests`. Registration refuses all four, and
1618
+ they are the four that are cheapest to get right before a run spends anybody's rate limit.
1619
+
1620
+ The full contract, including every bound and the coverage block's members, is
1621
+ [Source collections](../../docs/SOURCE-COLLECTIONS.md).
1622
+
1573
1623
  ## Readers
1574
1624
 
1575
1625
  `docs/READERS.md` defines Reader behavior. Certified Readers may be pinned on an exact
@@ -1577,10 +1627,11 @@ What it costs the protocol, and what to do instead:
1577
1627
  exact Reader name and version. Unsupported versions refuse by name. A version change is a recipe
1578
1628
  revision.
1579
1629
 
1580
- **Without a pin a source must answer `text/csv` or `text/plain`, and both are parsed as CSV.**
1581
- Anything else is refused `MEDIA_TYPE` before a row is read. So a publisher that serves only JSON or
1582
- XML needs a pin; it is not unbuildable, and it is not a reason to go looking for a different
1583
- publisher.
1630
+ **Direct CSV supports publisher CSV aliases, including Eurostat SDMX-CSV.**
1631
+ Accepted labels include `text/csv`, `text/plain`, `application/csv`, `application/x-csv`,
1632
+ `text/x-csv`, and `application/vnd.sdmx.data+csv`. For title rows, alternate encodings,
1633
+ headerless files, or padded columns, pin `delimited_text@2.0.0` and configure the layout; see
1634
+ `docs/READERS.md`. A publisher needing another format can use its matching Reader.
1584
1635
 
1585
1636
  **A v4 recipe pins a Reader through `connector.parameters`, under three reserved names.**
1586
1637
  `declared_source` is closed and has no member for a decoder, so the pin rides on the parameter array
@@ -1657,11 +1708,13 @@ decoder. Zero matches and multiple matches both refuse.
1657
1708
  | `spreadsheet.xlsx@1.1.0` | Same; also accepts a response served as `application/octet-stream`. |
1658
1709
  | `delimited_text@1.0.0` | `delimiter` (comma or tab); optional `header: true`; optional `encoding: utf-8`. |
1659
1710
  | `delimited_text@1.1.0` | Same; also accepts a response served as `text/plain` (common for public agency CSV such as IEM). |
1711
+ | `delimited_text@2.0.0` | Explicit delimiter, encoding, quoting, header presence, skip_rows, skip_blank_rows, and indexed columns with output names and optional expected_header; unselected_columns requires empty cells unless explicitly set to allow. |
1660
1712
  | `json.tabular@1.0.0` | `columns` with output names and RFC 6901 pointers; optional `document_format` (`json` or `ndjson`), `records_pointer`, and sequential `expand` pointers. Columns are required unless they state `required: false`. |
1661
1713
  | `json.tabular@1.1.0` | Same; also accepts a response served as `text/plain` (common for public agency JSON and NDJSON). |
1662
1714
  | `xml.tabular@1.0.0` | Absolute record element path, declared namespace prefixes, and relative field selectors ending in `text()` or `@attribute`; fields are required unless `required: false`. |
1663
1715
  | `html.tabular@1.0.0` | Absolute record element path and relative text/attribute field selectors; fields are required unless `required: false`. |
1664
1716
  | `html.web_extract@1.0.0` | `mode: dom` with closed CSS-like record/field selectors, or `mode: json` with an inert JSON script selector and RFC 6901 field pointers. |
1717
+ | `html.web_extract@1.1.0` | Same settings as 1.0.0; extracted text follows DOM order, with one space at block-element boundaries and `<br>` and none between inline runs. |
1665
1718
  | `protobuf.tabular@1.0.0` | Digest-pinned base64 FileDescriptorSet, fully-qualified message type, `single` or `length_delimited` framing, and fields with an explicit repeated `explode` or `refuse` choice. |
1666
1719
  | `parquet.tabular@1.0.0` | Optional `columns` selects a bounded ordered Parquet projection. |
1667
1720
  | `xbrl.facts@1.0.0` | `document_kind` (`xbrl` or constrained XML `ixbrl`) and exact namespace/name fact projection; contexts, units, and metadata remain evidence fields, not joins. |
@@ -3087,6 +3087,10 @@ class _PinnedProxyHTTPSConnection(http.client.HTTPSConnection):
3087
3087
  )
3088
3088
  response = http.client.HTTPResponse(raw_socket)
3089
3089
  response.begin()
3090
+ if response.status == 503:
3091
+ raise AcquisitionSecurityError(
3092
+ "CONNECT_PROXY_BUSY", "gateway capacity is temporarily unavailable"
3093
+ )
3090
3094
  if response.status != 200:
3091
3095
  raise AcquisitionSecurityError(
3092
3096
  "CONNECT_PROXY_STATUS", "gateway refused the pinned tunnel"
@@ -279,6 +279,17 @@ MAX_ANY_REQUEST_BYTES = max((MAX_REQUEST_BYTES, *MAX_REQUEST_BYTES_BY_OPERATION.
279
279
  # ``max_carried_source_bytes`` subtracts it before dividing out the base64 expansion, which is
280
280
  # what keeps a fetch ceiling derived from a request budget from being an over-estimate.
281
281
  MAX_REQUEST_ENVELOPE_BYTES = 4 * 1024
282
+
283
+
284
+ # JSON escapes each admitted header character into at most six bytes. Include
285
+ # the actual sealed configuration as well as bounded header/pointer/control overhead.
286
+ def max_generic_api_page_source_bytes(configuration: Mapping[str, Any]) -> int:
287
+ envelope = len(_ipc_json_bytes(dict(configuration))) + 128 * 1024
288
+ return max(0, (_request_byte_budget("generic_api_page") - envelope) // 4 * 3)
289
+
290
+
291
+ GENERIC_API_PAGE_OUTPUT_BYTES = (MAX_RESPONSE_BYTES - 128 * 1024) // 4 * 3
292
+
282
293
  MAX_WORKER_STDERR_BYTES = 64 * 1024
283
294
  # The most rows a response may state, whether it carries them or only their count. One value for
284
295
  # both directions on purpose: a table too long to hand back is also a table too long to have been
@@ -409,6 +420,11 @@ _ALLOWED_ENVIRONMENT = {
409
420
  "PYTHONDONTWRITEBYTECODE": "1",
410
421
  "PYTHONIOENCODING": "utf-8",
411
422
  "PYTHONNOUSERSITE": "1",
423
+ # Native math libraries otherwise reserve one thread stack per host CPU on
424
+ # import. Arrow's NumPy dependency can then exhaust RLIMIT_AS before a
425
+ # request is read, even though a single-thread import fits the same bound.
426
+ "OPENBLAS_NUM_THREADS": "1",
427
+ "OMP_NUM_THREADS": "1",
412
428
  }
413
429
  _FORBIDDEN_EGRESS_HOSTS = frozenset(
414
430
  {
@@ -1220,31 +1236,83 @@ class CrawlerSandbox:
1220
1236
  narrow the family's own defaults; it can never buy more room than the family allows.
1221
1237
  """
1222
1238
 
1223
- return self._invoke(
1224
- {
1225
- "schema_version": SANDBOX_PROTOCOL_VERSION,
1226
- "request_id": request_id,
1227
- "operation": "decode_and_parse",
1228
- "content_base64": base64.b64encode(content).decode("ascii"),
1229
- "data_format": output_format,
1230
- # The media type and the filename of the parsed artifact are the Reader
1231
- # family's declarations, not the coordinator's choice, so they travel back on
1232
- # the response rather than out on the request.
1233
- "media_type": None,
1234
- "filename": None,
1235
- "parse_limits": _parse_limits_dict(limits),
1236
- "url": None,
1237
- "allowed_hostnames": [],
1238
- "approved_endpoints": [],
1239
- "retrieval_limits": None,
1240
- "network_probe_targets": [],
1241
- "reader_pin": dict(reader_pin),
1242
- "reader_budgets": None if reader_budgets is None else dict(reader_budgets),
1243
- "range_plan": None,
1244
- "cycle_survey": None,
1245
- },
1246
- approved_endpoints=(),
1247
- )
1239
+ request = {
1240
+ "schema_version": SANDBOX_PROTOCOL_VERSION,
1241
+ "request_id": request_id,
1242
+ "operation": "decode_and_parse",
1243
+ "content_base64": None,
1244
+ "data_format": output_format,
1245
+ # The media type and the filename of the parsed artifact are the Reader
1246
+ # family's declarations, not the coordinator's choice, so they travel back on
1247
+ # the response rather than out on the request.
1248
+ "media_type": None,
1249
+ "filename": None,
1250
+ "parse_limits": _parse_limits_dict(limits),
1251
+ "url": None,
1252
+ "allowed_hostnames": [],
1253
+ "approved_endpoints": [],
1254
+ "retrieval_limits": None,
1255
+ "network_probe_targets": [],
1256
+ "reader_pin": dict(reader_pin),
1257
+ "reader_budgets": None if reader_budgets is None else dict(reader_budgets),
1258
+ "range_plan": None,
1259
+ "cycle_survey": None,
1260
+ }
1261
+ # Include optional fields _invoke adds, and base64 padding, before allocating a copy.
1262
+ inline_size = len(_ipc_json_bytes(request)) + 4 * ((len(content) + 2) // 3)
1263
+ if inline_size + MAX_REQUEST_ENVELOPE_BYTES <= _request_byte_budget("decode_and_parse"):
1264
+ request["content_base64"] = base64.b64encode(content).decode("ascii")
1265
+ return self._invoke(request, approved_endpoints=())
1266
+ # Keep bulk source bytes outside the control channel. The child receives one
1267
+ # read-only, unlinked regular file; neither a path nor a writable descriptor.
1268
+ pin = _reader_pin_from_request(dict(reader_pin))
1269
+ family = TOOLBOX.resolve(pin.family_id, pin.family_version)
1270
+ budget = family.default_budgets.narrowed_by(reader_budgets)
1271
+ if len(content) > budget.max_input_bytes:
1272
+ raise AcquisitionSecurityError("READER_BUDGET", "decode input exceeds Reader budget")
1273
+ with self._reader_input_descriptor(content) as descriptor:
1274
+ request["content_base64"] = None
1275
+ request["file_input_descriptor"] = descriptor
1276
+ request["file_output_descriptor"] = None
1277
+ return self._invoke(request, approved_endpoints=(), inherited_fds=(descriptor,))
1278
+
1279
+ @contextlib.contextmanager
1280
+ def _reader_input_descriptor(self, content: bytes) -> Iterator[int]:
1281
+ root_fd = os.open(self._staging_root, os.O_RDONLY | os.O_DIRECTORY | os.O_CLOEXEC)
1282
+ name = "reader-" + secrets.token_hex(16)
1283
+ write_fd = read_fd = -1
1284
+ created = False
1285
+ try:
1286
+ write_fd = os.open(
1287
+ name,
1288
+ os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW | os.O_CLOEXEC,
1289
+ 0o600,
1290
+ dir_fd=root_fd,
1291
+ )
1292
+ created = True
1293
+ view = memoryview(content)
1294
+ while view:
1295
+ count = os.write(write_fd, view)
1296
+ if count <= 0:
1297
+ raise OSError("short Reader input write")
1298
+ view = view[count:]
1299
+ read_fd = os.open(name, os.O_RDONLY | os.O_NOFOLLOW | os.O_CLOEXEC, dir_fd=root_fd)
1300
+ written, opened = os.fstat(write_fd), os.fstat(read_fd)
1301
+ if (written.st_dev, written.st_ino) != (opened.st_dev, opened.st_ino):
1302
+ raise AcquisitionSecurityError("SANDBOX_FILE", "Reader input identity changed")
1303
+ os.unlink(name, dir_fd=root_fd)
1304
+ created = False
1305
+ os.close(write_fd)
1306
+ write_fd = -1
1307
+ yield read_fd
1308
+ finally:
1309
+ if created:
1310
+ with contextlib.suppress(OSError):
1311
+ os.unlink(name, dir_fd=root_fd)
1312
+ for descriptor in (write_fd, read_fd, root_fd):
1313
+ if descriptor >= 0:
1314
+ with contextlib.suppress(OSError):
1315
+ os.close(descriptor)
1248
1316
 
1249
1317
  def retrieve_and_parse(
1250
1318
  self,
@@ -1562,6 +1630,7 @@ class CrawlerSandbox:
1562
1630
  prewarm: bool,
1563
1631
  resource_profile: _WorkerResourceProfile = _ORDINARY_WORKER_RESOURCE_PROFILE,
1564
1632
  descriptor_window_fds: tuple[int, int] | None = None,
1633
+ descriptor_reader_fd: int | None = None,
1565
1634
  ) -> _WorkerLaunch:
1566
1635
  """Build the exact confinement one child is started in.
1567
1636
 
@@ -1578,7 +1647,16 @@ class CrawlerSandbox:
1578
1647
  "mostlyright.data_harness.acquisition.sandbox",
1579
1648
  "--worker",
1580
1649
  ]
1581
- if descriptor_window_fds is not None:
1650
+ if descriptor_reader_fd is not None:
1651
+ command = [
1652
+ self._python,
1653
+ "-I",
1654
+ "-m",
1655
+ "mostlyright.data_harness.acquisition.sandbox",
1656
+ "--descriptor-reader-worker",
1657
+ str(descriptor_reader_fd),
1658
+ ]
1659
+ elif descriptor_window_fds is not None:
1582
1660
  source_fd, output_fd = descriptor_window_fds
1583
1661
  command = [
1584
1662
  self._python,
@@ -1761,17 +1839,32 @@ class CrawlerSandbox:
1761
1839
  and self._stream_timeout_seconds is not None
1762
1840
  else self._timeout_seconds
1763
1841
  )
1842
+ descriptor_reader = (
1843
+ operation == "decode_and_parse"
1844
+ and bool(inherited_fds)
1845
+ and isinstance(request.get("reader_pin"), dict)
1846
+ and request["reader_pin"].get("family_id") == "meteorology.grib"
1847
+ and request["reader_pin"].get("family_version") == "1.0.0"
1848
+ )
1764
1849
  launch = (
1765
1850
  self._worker_launch(
1766
1851
  prewarm=False,
1767
1852
  resource_profile=resource_profile,
1768
- descriptor_window_fds=(
1769
- request["file_input_descriptor"],
1770
- request["file_output_descriptor"],
1771
- ),
1853
+ descriptor_reader_fd=request["file_input_descriptor"],
1854
+ )
1855
+ if descriptor_reader
1856
+ else (
1857
+ self._worker_launch(
1858
+ prewarm=False,
1859
+ resource_profile=resource_profile,
1860
+ descriptor_window_fds=(
1861
+ request["file_input_descriptor"],
1862
+ request["file_output_descriptor"],
1863
+ ),
1864
+ )
1865
+ if operation == "parse_streaming_csv_window"
1866
+ else self._worker_launch(prewarm=False)
1772
1867
  )
1773
- if operation == "parse_streaming_csv_window"
1774
- else self._worker_launch(prewarm=False)
1775
1868
  )
1776
1869
  # A warm child is only ever taken for a confinement identical to the one this
1777
1870
  # invocation would have spawned for itself, and only when no socket is in play. Taking
@@ -1795,9 +1888,11 @@ class CrawlerSandbox:
1795
1888
  "networkless_child": self._child_is_networkless(),
1796
1889
  "inherited_fds": inherited_fds,
1797
1890
  "on_output_progress": on_output_progress,
1798
- "descriptor_window": operation == "parse_streaming_csv_window",
1891
+ # Both closed descriptor entrypoints lock down path opens after trusted
1892
+ # prewarm. Other inherited-Reader lanes retain their Landlock boundary.
1893
+ "descriptor_window": operation == "parse_streaming_csv_window" or descriptor_reader,
1799
1894
  }
1800
- if operation == "parse_streaming_csv_window":
1895
+ if operation == "parse_streaming_csv_window" or descriptor_reader:
1801
1896
  worker_arguments["resource_profile"] = resource_profile
1802
1897
  stdout, stderr, returncode = _run_worker_command(launch.argv(), **worker_arguments)
1803
1898
  else:
@@ -1940,8 +2035,88 @@ def _prime_descriptor_window_csv() -> None:
1940
2035
  raise RuntimeError("trusted CSV window prewarm did not produce its fixed result")
1941
2036
 
1942
2037
 
2038
+ def _prime_descriptor_grib_reader() -> None:
2039
+ """Resolve only bundled, trusted GRIB definitions before path access is denied."""
2040
+ from mostlyright.data_harness.readers.grib_eccodes import MeteorologyGribReader, _eccodes
2041
+
2042
+ module = _eccodes()
2043
+ family = MeteorologyGribReader()
2044
+ for sample in ("regular_ll_sfc_grib1", "regular_ll_sfc_grib2"):
2045
+ handle = module.codes_grib_new_from_samples(sample)
2046
+ try:
2047
+ content = module.codes_get_message(handle)
2048
+ names = (
2049
+ ("edition", "edition"),
2050
+ ("param_id", "paramId"),
2051
+ ("type_of_level", "typeOfLevel"),
2052
+ ("level", "level"),
2053
+ ("data_date", "dataDate"),
2054
+ ("data_time", "dataTime"),
2055
+ ("step_range", "stepRange"),
2056
+ )
2057
+ selector = {name: module.codes_get(handle, key) for name, key in names}
2058
+ selector["step_range"] = str(selector["step_range"])
2059
+ finally:
2060
+ module.codes_release(handle)
2061
+ pin = _reader_pin_from_request(
2062
+ {
2063
+ "family_id": family.family_id,
2064
+ "family_version": family.family_version,
2065
+ "decode_options": {
2066
+ "profile_version": 1,
2067
+ "selector": selector,
2068
+ "points": [{"id": "origin", "latitude": "0", "longitude": "0"}],
2069
+ },
2070
+ }
2071
+ )
2072
+ result = family.decode(content, pin, family.default_budgets)
2073
+ parsed = parse_tabular_bytes(
2074
+ result.content,
2075
+ data_format=result.data_format,
2076
+ media_type=result.media_type,
2077
+ filename=result.filename,
2078
+ limits=ParseLimits(),
2079
+ )
2080
+ if result.row_count != 1 or len(parsed.rows) != 1:
2081
+ raise RuntimeError("trusted GRIB prewarm did not produce its fixed result")
2082
+
2083
+
2084
+ def _validate_descriptor_reader_fd(descriptor: int) -> None:
2085
+ if type(descriptor) is not int or descriptor < 3:
2086
+ raise OSError(errno.EINVAL, "invalid Reader descriptor")
2087
+ info = os.fstat(descriptor)
2088
+ mode = fcntl.fcntl(descriptor, fcntl.F_GETFL) & os.O_ACCMODE
2089
+ if not stat.S_ISREG(info.st_mode) or mode != os.O_RDONLY or info.st_nlink != 0:
2090
+ raise OSError(errno.EINVAL, "Reader descriptor must be private and read-only")
2091
+
2092
+
2093
+ def _validate_descriptor_reader_single_thread() -> None:
2094
+ # prctl installs this filter on the calling thread. A native import that left a
2095
+ # helper thread alive must refuse, rather than leave an unfiltered parser executor.
2096
+ if len(list(Path("/proc/self/task").iterdir())) != 1:
2097
+ raise OSError(errno.EPERM, "Reader prewarm left another thread active")
2098
+
2099
+
2100
+ def _validate_descriptor_reader_request(request: dict[str, Any], descriptor: int) -> None:
2101
+ pin = request.get("reader_pin")
2102
+ if (
2103
+ request.get("operation") != "decode_and_parse"
2104
+ or type(request.get("file_input_descriptor")) is not int
2105
+ or request["file_input_descriptor"] != descriptor
2106
+ or request.get("file_output_descriptor") is not None
2107
+ or request.get("content_base64") is not None
2108
+ or not isinstance(pin, dict)
2109
+ or pin.get("family_id") != "meteorology.grib"
2110
+ or pin.get("family_version") != "1.0.0"
2111
+ ):
2112
+ raise AcquisitionSecurityError("SANDBOX_FIELDS", "request differs from locked Reader lane")
2113
+
2114
+
1943
2115
  def worker_main(
1944
- *, prewarm: bool = False, descriptor_window_fds: tuple[int, int] | None = None
2116
+ *,
2117
+ prewarm: bool = False,
2118
+ descriptor_window_fds: tuple[int, int] | None = None,
2119
+ descriptor_reader_fd: int | None = None,
1945
2120
  ) -> int:
1946
2121
  """Read one bounded request from stdin and emit one canonical response.
1947
2122
 
@@ -1966,12 +2141,14 @@ def worker_main(
1966
2141
  recipe can repair, and the code says so.
1967
2142
  """
1968
2143
 
1969
- if prewarm or descriptor_window_fds is not None:
2144
+ if prewarm or descriptor_window_fds is not None or descriptor_reader_fd is not None:
1970
2145
  # Before the request, never after it: the point of priming is that the import cost is
1971
2146
  # paid by an idle child rather than by a bound one. A failure here is a startup
1972
2147
  # failure and is reported on the same channel every other worker refusal uses.
1973
2148
  try:
1974
- if descriptor_window_fds is None:
2149
+ if descriptor_reader_fd is not None:
2150
+ _prime_descriptor_grib_reader()
2151
+ elif descriptor_window_fds is None:
1975
2152
  prime_parquet_support()
1976
2153
  else:
1977
2154
  _prime_descriptor_window_csv()
@@ -1980,13 +2157,24 @@ def worker_main(
1980
2157
  "SANDBOX_UNEXPECTED",
1981
2158
  f"pre-warm raised {type(exc).__name__}, which no refusal maps",
1982
2159
  )
1983
- if descriptor_window_fds is not None:
2160
+ if descriptor_reader_fd is not None or descriptor_window_fds is not None:
1984
2161
  try:
1985
2162
  # Imports may open shared-object/cache descriptors. They are no longer needed
1986
2163
  # once trusted prewarm finishes, so prove the locked phase retains only the
1987
2164
  # stdio pipes and the two coordinator-selected file capabilities.
1988
- _close_child_descriptors_except({0, 1, 2, *descriptor_window_fds})
1989
- _validate_descriptor_window_fds(*descriptor_window_fds)
2165
+ retained = (
2166
+ (descriptor_reader_fd,)
2167
+ if descriptor_reader_fd is not None
2168
+ else descriptor_window_fds
2169
+ )
2170
+ assert retained is not None
2171
+ _close_child_descriptors_except({0, 1, 2, *retained})
2172
+ if descriptor_reader_fd is not None:
2173
+ _validate_descriptor_reader_single_thread()
2174
+ _validate_descriptor_reader_fd(descriptor_reader_fd)
2175
+ else:
2176
+ assert descriptor_window_fds is not None
2177
+ _validate_descriptor_window_fds(*descriptor_window_fds)
1990
2178
  install_descriptor_window_seccomp()
1991
2179
  except OSError:
1992
2180
  return _worker_error(
@@ -1995,7 +2183,7 @@ def worker_main(
1995
2183
  )
1996
2184
  marker = (
1997
2185
  DESCRIPTOR_WINDOW_LOCKED_MARKER
1998
- if descriptor_window_fds is not None
2186
+ if descriptor_window_fds is not None or descriptor_reader_fd is not None
1999
2187
  else WORKER_READY_MARKER
2000
2188
  )
2001
2189
  sys.stdout.buffer.write(marker)
@@ -2017,6 +2205,8 @@ def worker_main(
2017
2205
  "SANDBOX_IPC_LIMIT",
2018
2206
  "request exceeds the IPC byte budget for its operation",
2019
2207
  )
2208
+ if descriptor_reader_fd is not None:
2209
+ _validate_descriptor_reader_request(request, descriptor_reader_fd)
2020
2210
  response = _execute_worker_request(request)
2021
2211
  encoded = _ipc_json_bytes(response)
2022
2212
  if len(encoded) > MAX_RESPONSE_BYTES:
@@ -2063,7 +2253,11 @@ def _execute_worker_request(request: dict[str, Any]) -> dict[str, Any]:
2063
2253
  request = {**request, "generic_api_page": None}
2064
2254
  if request.get("operation") != "parse_streaming_csv_window" and "window_stream" not in request:
2065
2255
  request = {**request, "window_stream": None}
2066
- if request.get("operation") not in {"parse_evidence_file", "parse_streaming_csv_window"}:
2256
+ if request.get("operation") not in {
2257
+ "parse_evidence_file",
2258
+ "parse_streaming_csv_window",
2259
+ "decode_and_parse",
2260
+ }:
2067
2261
  if (
2068
2262
  request.get("file_input_descriptor") is not None
2069
2263
  or request.get("file_output_descriptor") is not None
@@ -2076,6 +2270,10 @@ def _execute_worker_request(request: dict[str, Any]) -> dict[str, Any]:
2076
2270
  "file_input_descriptor": None,
2077
2271
  "file_output_descriptor": None,
2078
2272
  }
2273
+ if request.get("operation") == "decode_and_parse":
2274
+ request = {"file_input_descriptor": None, "file_output_descriptor": None, **request}
2275
+ if request["file_output_descriptor"] is not None:
2276
+ raise AcquisitionSecurityError("SANDBOX_FIELDS", "decode cannot carry output authority")
2079
2277
  expected = {
2080
2278
  "schema_version",
2081
2279
  "request_id",
@@ -2253,6 +2451,7 @@ def _execute_worker_request(request: dict[str, Any]) -> dict[str, Any]:
2253
2451
  pagination=configuration.pagination,
2254
2452
  limits=configuration.limits,
2255
2453
  records_pointer=page.get("records_pointer"),
2454
+ max_output_bytes=GENERIC_API_PAGE_OUTPUT_BYTES,
2256
2455
  )
2257
2456
  if v3
2258
2457
  else interpret_generic_api_page(
@@ -2260,6 +2459,7 @@ def _execute_worker_request(request: dict[str, Any]) -> dict[str, Any]:
2260
2459
  headers,
2261
2460
  response=configuration.response,
2262
2461
  pagination=configuration.pagination,
2462
+ max_output_bytes=GENERIC_API_PAGE_OUTPUT_BYTES,
2263
2463
  )
2264
2464
  )
2265
2465
  except Exception as error:
@@ -2653,7 +2853,7 @@ def _decode_in_worker(
2653
2853
  "SANDBOX_FIELDS",
2654
2854
  "decode request cannot choose the media type or filename the Reader declares",
2655
2855
  )
2656
- content = _request_content(request)
2856
+ content = _reader_request_content(request)
2657
2857
  return _decode_content_in_worker(
2658
2858
  request,
2659
2859
  base,
@@ -2663,6 +2863,53 @@ def _decode_in_worker(
2663
2863
  )
2664
2864
 
2665
2865
 
2866
+ def _reader_request_content(request: dict[str, Any]) -> bytes:
2867
+ descriptor = request.get("file_input_descriptor")
2868
+ if descriptor is None:
2869
+ return _request_content(request)
2870
+ if request["content_base64"] is not None or type(descriptor) is not int or descriptor < 3:
2871
+ raise AcquisitionSecurityError("SANDBOX_FILE", "invalid Reader input authority")
2872
+ pin = _reader_pin_from_request(request["reader_pin"])
2873
+ family = TOOLBOX.resolve(pin.family_id, pin.family_version)
2874
+ budget = family.default_budgets.narrowed_by(request["reader_budgets"])
2875
+ try:
2876
+ info = os.fstat(descriptor)
2877
+ mode = fcntl.fcntl(descriptor, fcntl.F_GETFL) & os.O_ACCMODE
2878
+ if not stat.S_ISREG(info.st_mode) or mode != os.O_RDONLY or info.st_nlink != 0:
2879
+ raise AcquisitionSecurityError(
2880
+ "SANDBOX_FILE", "Reader input must be private read-only file"
2881
+ )
2882
+ if info.st_size > budget.max_input_bytes:
2883
+ raise AcquisitionSecurityError("READER_BUDGET", "decode input exceeds Reader budget")
2884
+ # CPython duplicates a descriptor with F_DUPFD_CLOEXEC, which the closed
2885
+ # descriptor filter intentionally denies. Read the retained capability directly
2886
+ # using already permitted syscalls, without adding another descriptor or authority.
2887
+ offset = os.lseek(descriptor, 0, os.SEEK_CUR)
2888
+ chunks: list[bytes] = []
2889
+ remaining = info.st_size + 1
2890
+ try:
2891
+ os.lseek(descriptor, 0, os.SEEK_SET)
2892
+ while remaining:
2893
+ chunk = os.read(descriptor, min(remaining, 1024 * 1024))
2894
+ if not chunk:
2895
+ break
2896
+ chunks.append(chunk)
2897
+ remaining -= len(chunk)
2898
+ finally:
2899
+ os.lseek(descriptor, offset, os.SEEK_SET)
2900
+ content = b"".join(chunks)
2901
+ after = os.fstat(descriptor)
2902
+
2903
+ def identity(value: os.stat_result) -> tuple[int, int, int, int, int]:
2904
+ return (value.st_dev, value.st_ino, value.st_size, value.st_mtime_ns, value.st_ctime_ns)
2905
+
2906
+ if len(content) != info.st_size or identity(after) != identity(info):
2907
+ raise AcquisitionSecurityError("SANDBOX_FILE", "Reader input changed during decode")
2908
+ return content
2909
+ except OSError as error:
2910
+ raise AcquisitionSecurityError("SANDBOX_FILE", "Reader input unavailable") from error
2911
+
2912
+
2666
2913
  def _retrieve_decode_in_worker(
2667
2914
  request: dict[str, Any],
2668
2915
  base: dict[str, Any],
@@ -4585,6 +4832,11 @@ def _policy_document(operation: str) -> dict[str, Any]:
4585
4832
  # of that authority, which is the thing an attestation should be bound to.
4586
4833
  if operation in READER_PERFORMING_OPERATIONS:
4587
4834
  policy["reader_contract"] = READER_CONTRACT_VERSION
4835
+ if operation == "decode_and_parse":
4836
+ policy["reader_input"] = "inline-or-private-readonly-unlinked-descriptor-v1"
4837
+ policy["reader_descriptor_boundary"] = {
4838
+ "meteorology.grib@1.0.0": "trusted-prewarm-descriptor-only-seccomp-v1"
4839
+ }
4588
4840
  return policy
4589
4841
 
4590
4842
 
@@ -7156,4 +7408,10 @@ if __name__ == "__main__":
7156
7408
  except ValueError:
7157
7409
  raise SystemExit(2) from None
7158
7410
  raise SystemExit(worker_main(descriptor_window_fds=descriptors))
7411
+ if len(sys.argv) == 3 and sys.argv[1] == "--descriptor-reader-worker":
7412
+ try:
7413
+ descriptor = int(sys.argv[2], 10)
7414
+ except ValueError:
7415
+ raise SystemExit(2) from None
7416
+ raise SystemExit(worker_main(descriptor_reader_fd=descriptor))
7159
7417
  raise SystemExit(2)