mostlyright-data 0.9.7__tar.gz → 0.9.9__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 (326) hide show
  1. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/PKG-INFO +8 -4
  2. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/README.md +7 -3
  3. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/pyproject.toml +5 -3
  4. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/cli.py +31 -9
  5. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/download.py +74 -1
  6. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/propose.py +146 -2
  7. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/router.py +453 -50
  8. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/remediation.py +1 -1
  9. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/.gitignore +0 -0
  10. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/scripts/hatch_build.py +0 -0
  11. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/__init__.py +0 -0
  12. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/acquisition/__init__.py +0 -0
  13. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/acquisition/http.py +0 -0
  14. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/acquisition/parsing.py +0 -0
  15. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/acquisition/ranges.py +0 -0
  16. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/acquisition/result_download.py +0 -0
  17. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/acquisition/retention_admission.py +0 -0
  18. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/acquisition/sandbox.py +0 -0
  19. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/acquisition/url_policy.py +0 -0
  20. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/agent_runtime.py +0 -0
  21. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/assets/logo-ink.svg +0 -0
  22. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/backends/__init__.py +0 -0
  23. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/backends/pandas_backend.py +0 -0
  24. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/backends/polars_backend.py +0 -0
  25. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/backends/protocol.py +0 -0
  26. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/backends/reference.py +0 -0
  27. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/backends/registry.py +0 -0
  28. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/backends/restrictions.py +0 -0
  29. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/canonical.py +0 -0
  30. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/catalog_job.py +0 -0
  31. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/contracts.py +0 -0
  32. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/coordinator.py +0 -0
  33. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/deploy.py +0 -0
  34. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/deploy_target.py +0 -0
  35. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/deployment_evidence.py +0 -0
  36. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/event_presentation.py +0 -0
  37. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/events.py +0 -0
  38. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/fast_delimited.py +0 -0
  39. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/fleet.py +0 -0
  40. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/formats.py +0 -0
  41. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/governors.py +0 -0
  42. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_bootstrap.py +0 -0
  43. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_crawler.py +0 -0
  44. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_crawler_container_smoke.py +0 -0
  45. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_crawler_fetch.py +0 -0
  46. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_crawler_job.py +0 -0
  47. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_crawler_protocol.py +0 -0
  48. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_dataset.py +0 -0
  49. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_deploy.py +0 -0
  50. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_handoff.py +0 -0
  51. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_ingestion_contract.py +0 -0
  52. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_ingestion_job.py +0 -0
  53. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_ingestion_job_smoke.py +0 -0
  54. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_session_container_smoke.py +0 -0
  55. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_session_worker.py +0 -0
  56. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_session_worker_job_smoke.py +0 -0
  57. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/hosted_worker.py +0 -0
  58. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ingestion/__init__.py +0 -0
  59. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ingestion/contracts.py +0 -0
  60. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ingestion/faults.py +0 -0
  61. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ingestion/gcs_store.py +0 -0
  62. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ingestion/spool.py +0 -0
  63. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ingestion/store.py +0 -0
  64. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/key_seam.py +0 -0
  65. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/linux_process_boundary.py +0 -0
  66. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/local_contracts.py +0 -0
  67. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/local_search/__init__.py +0 -0
  68. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/local_search/build_index.py +0 -0
  69. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/local_search/contracts.py +0 -0
  70. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/local_search/query_trace.py +0 -0
  71. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/local_search/retrieval.py +0 -0
  72. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/local_search/sealed.py +0 -0
  73. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/local_search/service.py +0 -0
  74. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/CONTRACT.md +0 -0
  75. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/__init__.py +0 -0
  76. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/chrome.py +0 -0
  77. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/code_body.py +0 -0
  78. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/document.py +0 -0
  79. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/frame.py +0 -0
  80. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/interactive.py +0 -0
  81. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/markdown_body.py +0 -0
  82. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/mr_components.py +0 -0
  83. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/outputs_data.py +0 -0
  84. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/outputs_rich.py +0 -0
  85. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/outputs_source.py +0 -0
  86. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/outputs_stage.py +0 -0
  87. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/outputs_text.py +0 -0
  88. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/parse.py +0 -0
  89. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/status.py +0 -0
  90. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/nbrender/tokens.py +0 -0
  91. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/notebook.py +0 -0
  92. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/offline.py +0 -0
  93. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/operation_registry.py +0 -0
  94. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/operator_setup.py +0 -0
  95. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/pipeline.py +0 -0
  96. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/plan_graph.py +0 -0
  97. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/preparation/__init__.py +0 -0
  98. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/preparation/contracts.py +0 -0
  99. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/preparation/engine.py +0 -0
  100. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/preparation/errors.py +0 -0
  101. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/preparation/gates.py +0 -0
  102. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/preparation/joins.py +0 -0
  103. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/preparation/profile.py +0 -0
  104. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/preparation/table.py +0 -0
  105. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/preparation/transforms.py +0 -0
  106. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/progress_events.py +0 -0
  107. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/__init__.py +0 -0
  108. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/containers.py +0 -0
  109. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/contracts.py +0 -0
  110. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/delimited.py +0 -0
  111. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/grib2/__init__.py +0 -0
  112. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/grib2/admission.py +0 -0
  113. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/grib2/decode.py +0 -0
  114. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/grib2/geometry.py +0 -0
  115. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/grib2/portable_math.py +0 -0
  116. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/json_tabular.py +0 -0
  117. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/parquet_tabular.py +0 -0
  118. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/registry.py +0 -0
  119. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/README.md +0 -0
  120. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.gzip/1.0.0/cities_one_stream/cities.csv.gz +0 -0
  121. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.gzip/1.0.0/cities_one_stream/expected.json +0 -0
  122. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.gzip/1.1.0/cities_one_stream/cities.csv.gz +0 -0
  123. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.gzip/1.1.0/cities_one_stream/expected.json +0 -0
  124. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.tar/1.0.0/cities_beside_a_directory_entry/cities.tar +0 -0
  125. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.tar/1.0.0/cities_beside_a_directory_entry/expected.json +0 -0
  126. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.tar/1.1.0/cities_beside_a_directory_entry/cities.tar +0 -0
  127. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.tar/1.1.0/cities_beside_a_directory_entry/expected.json +0 -0
  128. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.zip/1.0.0/cities_beside_a_second_member/cities.zip +0 -0
  129. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.zip/1.0.0/cities_beside_a_second_member/expected.json +0 -0
  130. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.zip/1.1.0/dwd_semicolon_station_member/dwd-station.zip +0 -0
  131. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.zip/1.1.0/dwd_semicolon_station_member/expected.json +0 -0
  132. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.zip/1.2.0/dwd_semicolon_station_member/dwd-station.zip +0 -0
  133. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/archive.zip/1.2.0/dwd_semicolon_station_member/expected.json +0 -0
  134. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/delimited_text/1.0.0/an_ordinary_comma_separated_table/cities.csv +0 -0
  135. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/delimited_text/1.0.0/an_ordinary_comma_separated_table/expected.json +0 -0
  136. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/delimited_text/1.0.0/quoted_fields_holding_the_delimiter/cities.tsv +0 -0
  137. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/delimited_text/1.0.0/quoted_fields_holding_the_delimiter/expected.json +0 -0
  138. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/delimited_text/1.1.0/an_hourly_observation_table_served_as_plain_text/expected.json +0 -0
  139. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/delimited_text/1.1.0/an_hourly_observation_table_served_as_plain_text/observations.csv +0 -0
  140. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/json.tabular/1.0.0/nested_hourly_observations/expected.json +0 -0
  141. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/json.tabular/1.0.0/nested_hourly_observations/stations.json +0 -0
  142. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/json.tabular/1.1.0/an_observation_stream_served_as_plain_text/expected.json +0 -0
  143. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/json.tabular/1.1.0/an_observation_stream_served_as_plain_text/observations.ndjson +0 -0
  144. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/parquet.tabular/1.0.0/two_columns/expected.json +0 -0
  145. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/parquet.tabular/1.0.0/two_columns/prices.parquet +0 -0
  146. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/an_ordinary_table_beside_a_second_sheet/cities.xlsx +0 -0
  147. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/an_ordinary_table_beside_a_second_sheet/expected.json +0 -0
  148. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/shares_the_workbook_had_already_computed/expected.json +0 -0
  149. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/shares_the_workbook_had_already_computed/shares.xlsx +0 -0
  150. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.1.0/shares_the_workbook_had_already_computed/expected.json +0 -0
  151. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.1.0/shares_the_workbook_had_already_computed/shares.xlsx +0 -0
  152. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/README.md +0 -0
  153. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/gfs_2m_temperature/expected.json +0 -0
  154. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/gfs_2m_temperature/gfs-2m-temperature.grib2 +0 -0
  155. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_2m_temperature/expected.json +0 -0
  156. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_2m_temperature/hrrr-2m-temperature.grib2 +0 -0
  157. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_categorical_rain/expected.json +0 -0
  158. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_categorical_rain/hrrr-categorical-rain.grib2 +0 -0
  159. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/weather.grib2/2.0.0/hrrr_2m_temperature/expected.json +0 -0
  160. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples/weather.grib2/2.0.0/hrrr_2m_temperature/hrrr-2m-temperature.grib2 +0 -0
  161. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/samples.py +0 -0
  162. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/spreadsheet.py +0 -0
  163. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/readers/tabular.py +0 -0
  164. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/recipe.py +0 -0
  165. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/repair/__init__.py +0 -0
  166. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/repair/adapters.py +0 -0
  167. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/repair/contracts.py +0 -0
  168. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/repair/coordinator.py +0 -0
  169. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/repair/errors.py +0 -0
  170. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/review.py +0 -0
  171. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/rowset.py +0 -0
  172. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/serving.py +0 -0
  173. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/serving_edge.py +0 -0
  174. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/serving_http.py +0 -0
  175. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/session_probes.py +0 -0
  176. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/signing.py +0 -0
  177. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/source_discovery.py +0 -0
  178. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/__init__.py +0 -0
  179. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/_adapter_steps.py +0 -0
  180. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/adapters.py +0 -0
  181. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/authenticated_https.py +0 -0
  182. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/authenticated_https_v2.py +0 -0
  183. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/cadence.py +0 -0
  184. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/cadence_emission.py +0 -0
  185. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/cadence_history.py +0 -0
  186. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/__init__.py +0 -0
  187. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/admission.py +0 -0
  188. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/authoring.py +0 -0
  189. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/authoring_policy.py +0 -0
  190. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/authoring_shards.py +0 -0
  191. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/bounded_io.py +0 -0
  192. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/channel.py +0 -0
  193. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/channel_client.py +0 -0
  194. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/contracts.py +0 -0
  195. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/coverage.py +0 -0
  196. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/delta.py +0 -0
  197. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/embedding.py +0 -0
  198. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/entry_v2.py +0 -0
  199. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/fill.py +0 -0
  200. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/fill_partitions.py +0 -0
  201. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/fill_staging.py +0 -0
  202. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/gating.py +0 -0
  203. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/generation_receipt.py +0 -0
  204. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/harvest/__init__.py +0 -0
  205. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/harvest/ckan.py +0 -0
  206. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/harvest/datagov_v4.py +0 -0
  207. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/harvest/protocol.py +0 -0
  208. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/harvest/sdmx.py +0 -0
  209. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/harvest/stac.py +0 -0
  210. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/health.py +0 -0
  211. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/hosted_catalog.py +0 -0
  212. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/identity_history.py +0 -0
  213. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/neural.py +0 -0
  214. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/packed_catalog.py +0 -0
  215. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/packed_retrieval.py +0 -0
  216. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/packed_writer.py +0 -0
  217. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/query_trace.py +0 -0
  218. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/recommend.py +0 -0
  219. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/retrieval.py +0 -0
  220. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/retrieval_manifest.py +0 -0
  221. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/rights_decisions.py +0 -0
  222. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/sealed.py +0 -0
  223. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/search.py +0 -0
  224. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/streaming_delta.py +0 -0
  225. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/catalog/update.py +0 -0
  226. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/collections.py +0 -0
  227. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/contracts.py +0 -0
  228. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/deletion.py +0 -0
  229. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/fitness.py +0 -0
  230. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/governance.py +0 -0
  231. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/hosted.py +0 -0
  232. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/integration.py +0 -0
  233. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/range_reader.py +0 -0
  234. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/registry.py +0 -0
  235. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/rights_rule.py +0 -0
  236. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/source_cadence_vectors.v1.json +0 -0
  237. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/sports.py +0 -0
  238. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/stream.py +0 -0
  239. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/stream_capture_session.py +0 -0
  240. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/stream_connector.py +0 -0
  241. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/stream_connectors/polymarket.clob-market.v1.json +0 -0
  242. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/stream_recorder.py +0 -0
  243. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/stream_registry.py +0 -0
  244. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/stream_rotation.py +0 -0
  245. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/stream_series.py +0 -0
  246. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/sources/stream_transport.py +0 -0
  247. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/studio_boundary.py +0 -0
  248. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/__init__.py +0 -0
  249. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/acquire.py +0 -0
  250. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/acquire_cancel.py +0 -0
  251. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/approvals.py +0 -0
  252. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/commands.py +0 -0
  253. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/narrative.py +0 -0
  254. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/parity.py +0 -0
  255. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/research.py +0 -0
  256. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/runs.py +0 -0
  257. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/session.py +0 -0
  258. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/stream.py +0 -0
  259. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/transport.py +0 -0
  260. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/vocabulary.py +0 -0
  261. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/thin/workers.py +0 -0
  262. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ucum/TABLE-PIN.json +0 -0
  263. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ucum/ucum-subset.v1.json +0 -0
  264. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/unit_flow.py +0 -0
  265. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/units.py +0 -0
  266. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/__init__.py +0 -0
  267. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/approve.py +0 -0
  268. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/author_yaml.py +0 -0
  269. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/cloud_auth.py +0 -0
  270. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/__init__.py +0 -0
  271. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/approve.py +0 -0
  272. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/auth.py +0 -0
  273. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/author.py +0 -0
  274. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/catalog_author.py +0 -0
  275. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/catalog_fill.py +0 -0
  276. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/catalog_harvest.py +0 -0
  277. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/catalog_publish.py +0 -0
  278. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/catalog_search.py +0 -0
  279. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/catalog_update.py +0 -0
  280. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/deploy.py +0 -0
  281. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/deploy_dataset.py +0 -0
  282. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/deploy_plan.py +0 -0
  283. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/deploy_status.py +0 -0
  284. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/diff.py +0 -0
  285. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/index.py +0 -0
  286. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/inventory.py +0 -0
  287. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/list_builds.py +0 -0
  288. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/login.py +0 -0
  289. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/peek.py +0 -0
  290. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/plan_check.py +0 -0
  291. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/preflight.py +0 -0
  292. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/record.py +0 -0
  293. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/review_setup.py +0 -0
  294. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/search.py +0 -0
  295. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/show.py +0 -0
  296. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/commands/whoami.py +0 -0
  297. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/credential_native.py +0 -0
  298. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/credential_store.py +0 -0
  299. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/credentials.py +0 -0
  300. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/diffing.py +0 -0
  301. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/headline.py +0 -0
  302. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/hosted_acquisition.py +0 -0
  303. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/hosted_run_status.py +0 -0
  304. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/inventory.py +0 -0
  305. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/local_review.py +0 -0
  306. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/login.py +0 -0
  307. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/path_kind.py +0 -0
  308. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/peek.py +0 -0
  309. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/plain_file.py +0 -0
  310. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/plan_check.py +0 -0
  311. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/preflight.py +0 -0
  312. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/readers.py +0 -0
  313. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/render.py +0 -0
  314. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/ux/workload.py +0 -0
  315. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/viewer.py +0 -0
  316. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/visual_run/__init__.py +0 -0
  317. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/visual_run/authoring.py +0 -0
  318. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/visual_run/contracts.py +0 -0
  319. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/visual_run/materialize.py +0 -0
  320. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/visual_run/observations.py +0 -0
  321. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/visual_run/query.py +0 -0
  322. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/visual_run/reducer.py +0 -0
  323. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/visual_run/sdk.py +0 -0
  324. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/visual_run/store.py +0 -0
  325. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/visual_run/transport.py +0 -0
  326. {mostlyright_data-0.9.7 → mostlyright_data-0.9.9}/src/mostlyright/data_harness/watch.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mostlyright-data
3
- Version: 0.9.7
3
+ Version: 0.9.9
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/
@@ -126,7 +126,10 @@ The local execution lane runs only on Linux:
126
126
  python -m pip install "mostlyright-data[local]"
127
127
  ```
128
128
 
129
- It builds and checks worker inputs. It is not required for the hosted client.
129
+ It is not required for the hosted client, and it is off by default: `mr-data` sends that work to
130
+ the backend. What still runs on this computer is catalog authoring, the search index, and the
131
+ commands that check a document or a run folder. A command with no backend lane refuses by name and
132
+ says why.
130
133
 
131
134
  ## Documentation
132
135
 
@@ -138,11 +141,12 @@ It builds and checks worker inputs. It is not required for the hosted client.
138
141
  Use `mr-data --help` for the full command list and options. Commands that support
139
142
  `--json` write one JSON object.
140
143
 
141
- For local builds, `--input-root` and `--output` may use relative paths.
144
+ `--input-root` and `--output` may use relative paths.
142
145
 
143
146
  ## Behavior and limits
144
147
 
145
- - `mr-data review --local RUN_DIR` exits 1 when a check fails.
148
+ - `mr-data review RUN_DIR --local` runs the deterministic checks and writes no review decision. It exits 1 when a check fails. Write the flag after the command name; before it, `--local` is the lane selector.
149
+ - `mr-data review RUN_DIR --report REPORT` seals a review decision from signed reviewer reports.
146
150
  - The weather reader accepts one extracted GRIB2 record. It refuses a multi-record GFS or HRRR file.
147
151
  - Hosted credential-free acquisition supports one single-address public HTTPS object. Bounded collections require both local attestations.
148
152
 
@@ -45,7 +45,10 @@ The local execution lane runs only on Linux:
45
45
  python -m pip install "mostlyright-data[local]"
46
46
  ```
47
47
 
48
- It builds and checks worker inputs. It is not required for the hosted client.
48
+ It is not required for the hosted client, and it is off by default: `mr-data` sends that work to
49
+ the backend. What still runs on this computer is catalog authoring, the search index, and the
50
+ commands that check a document or a run folder. A command with no backend lane refuses by name and
51
+ says why.
49
52
 
50
53
  ## Documentation
51
54
 
@@ -57,11 +60,12 @@ It builds and checks worker inputs. It is not required for the hosted client.
57
60
  Use `mr-data --help` for the full command list and options. Commands that support
58
61
  `--json` write one JSON object.
59
62
 
60
- For local builds, `--input-root` and `--output` may use relative paths.
63
+ `--input-root` and `--output` may use relative paths.
61
64
 
62
65
  ## Behavior and limits
63
66
 
64
- - `mr-data review --local RUN_DIR` exits 1 when a check fails.
67
+ - `mr-data review RUN_DIR --local` runs the deterministic checks and writes no review decision. It exits 1 when a check fails. Write the flag after the command name; before it, `--local` is the lane selector.
68
+ - `mr-data review RUN_DIR --report REPORT` seals a review decision from signed reviewer reports.
65
69
  - The weather reader accepts one extracted GRIB2 record. It refuses a multi-record GFS or HRRR file.
66
70
  - Hosted credential-free acquisition supports one single-address public HTTPS object. Bounded collections require both local attestations.
67
71
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mostlyright-data"
3
- version = "0.9.7"
3
+ version = "0.9.9"
4
4
  description = "Mostly Right CLI for reproducible, reviewed Parquet datasets"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13,<3.14"
@@ -54,8 +54,10 @@ mostlyright-studio-client-v3 = { path = "vendor/wheels/mostlyright_studio_client
54
54
  [project.scripts]
55
55
  # ⚠ NOT `cli:main`. `cli` imports `hosted_worker`, which imports pyarrow and cryptography at module
56
56
  # scope, so `cli` cannot even be IMPORTED on a thin install. The router is the one module that can
57
- # run on a bare interpreter and decide which lane this invocation belongs to; with the `local`
58
- # extra present it hands every ordinary invocation straight to `cli.main` unchanged.
57
+ # run on a bare interpreter and decide which lane this invocation belongs to. The local product
58
+ # lanes are off by default, so with the `local` extra present it hands the names that still run on
59
+ # this computer to `cli.main` unchanged, and every other name is answered by the hosted lane or
60
+ # told, by name, that this computer no longer runs it.
59
61
  mr-data = "mostlyright.data_harness.thin.router:main"
60
62
  # ⚠ AND NOT THE MODULES THEMSELVES, for the same reason. Each of these seven is defined in a
61
63
  # module that imports pyarrow or cryptography at module scope -- or, for the catalogue job, reaches
@@ -2260,7 +2260,29 @@ def _require_verify_url(value: str) -> str:
2260
2260
 
2261
2261
 
2262
2262
  def _agent_workflow_surface() -> dict[str, Any]:
2263
- """Return the versioned discovery surface for external data agents."""
2263
+ """Return the versioned discovery surface for external data agents.
2264
+
2265
+ ``implementation_status`` says where a stage runs, and the three values partition the stages
2266
+ rather than describing them: exactly one is true of any stage, and which one is decided by the
2267
+ surface beside it rather than by how the stage feels.
2268
+
2269
+ * ``available`` -- every command the surface names runs from this command line, with no
2270
+ backend: the kept lane-``local`` names and the portable ones.
2271
+ * ``hosted_only`` -- the surface names only hosted-lane commands. The stage still happens, and
2272
+ the named commands are how it is asked for and reported on; what is not true of it is that
2273
+ this computer performs it. A hosted-lane command is not a skipped stage.
2274
+ * ``backend_internal`` -- a backend operator step: it has a name, and nobody runs it from here.
2275
+
2276
+ ⚠ THE STATUS IS THE PROMISE, SO IT IS NOT DECORATION. An agent chooses its route from this
2277
+ payload, and a stage that says ``available`` about a command which exits 2 sends the agent to
2278
+ a refusal it will read as a defect and retry. The word has to be the answer the command would
2279
+ actually give.
2280
+
2281
+ ⚠ AND A SURFACE NAMED TWICE IS CLASSIFIED ONCE. ``view`` appears under two stages; both say
2282
+ ``hosted_only``, because the same command cannot run here in one row and on the backend in the
2283
+ next. ``tests/test_agent_workflow_cli.py`` derives both halves of the partition from the live
2284
+ lane table, so a command that changes lane fails there rather than drifting.
2285
+ """
2264
2286
 
2265
2287
  return {
2266
2288
  "schema_version": "mr-data-agent-workflow.v4",
@@ -2269,9 +2291,9 @@ def _agent_workflow_surface() -> dict[str, Any]:
2269
2291
  "stages": [
2270
2292
  {
2271
2293
  "stage": "viewer_observability",
2272
- "implementation_status": "available",
2294
+ "implementation_status": "hosted_only",
2273
2295
  "judgment_owner": "external_agent",
2274
- "deterministic_surface": "mr-data view",
2296
+ "deterministic_surface": "mr-data watch/view",
2275
2297
  },
2276
2298
  {
2277
2299
  "stage": "question_and_requirements",
@@ -2299,15 +2321,15 @@ def _agent_workflow_surface() -> dict[str, Any]:
2299
2321
  },
2300
2322
  {
2301
2323
  "stage": "recipe_approval",
2302
- "implementation_status": "available",
2324
+ "implementation_status": "hosted_only",
2303
2325
  "judgment_owner": "human",
2304
2326
  "deterministic_surface": "mr-data recipe-approve",
2305
2327
  },
2306
2328
  {
2307
2329
  "stage": "acquire_clean_join_validate_package",
2308
- "implementation_status": "available",
2330
+ "implementation_status": "hosted_only",
2309
2331
  "judgment_owner": "deterministic_worker",
2310
- "deterministic_surface": "mr-data recipe-run/recipe-verify",
2332
+ "deterministic_surface": "mr-data run/status",
2311
2333
  },
2312
2334
  {
2313
2335
  "stage": "independent_review",
@@ -2317,19 +2339,19 @@ def _agent_workflow_surface() -> dict[str, Any]:
2317
2339
  },
2318
2340
  {
2319
2341
  "stage": "independent_verification",
2320
- "implementation_status": "available",
2342
+ "implementation_status": "hosted_only",
2321
2343
  "judgment_owner": "deterministic_verifier",
2322
2344
  "deterministic_surface": "mr-data verify/status/inspect",
2323
2345
  },
2324
2346
  {
2325
2347
  "stage": "handoff",
2326
- "implementation_status": "available",
2348
+ "implementation_status": "hosted_only",
2327
2349
  "judgment_owner": "external_agent",
2328
2350
  "deterministic_surface": "mr-data notebook/view",
2329
2351
  },
2330
2352
  {
2331
2353
  "stage": "hosted_export",
2332
- "implementation_status": "available",
2354
+ "implementation_status": "backend_internal",
2333
2355
  "judgment_owner": "external_agent",
2334
2356
  "deterministic_surface": "mr-data export-hosted-candidate",
2335
2357
  },
@@ -70,6 +70,11 @@ class DownloadedArtifact:
70
70
  media_type: str
71
71
  size_bytes: int
72
72
  content_digest: str
73
+ #: False when the bytes were already on disk, carried the digest the signed session declared,
74
+ #: and were adopted rather than fetched again. Reported so that "it was already here" can
75
+ #: never be read as "it was fetched and checked just now" -- the same reason ``verify`` prints
76
+ #: ``checked_by`` and ``acquire`` prints ``reader_binding``.
77
+ transferred: bool = True
73
78
 
74
79
  def to_receipt(self) -> dict[str, Any]:
75
80
  return {
@@ -78,6 +83,7 @@ class DownloadedArtifact:
78
83
  "media_type": self.media_type,
79
84
  "size_bytes": self.size_bytes,
80
85
  "content_digest": self.content_digest,
86
+ "transferred": self.transferred,
81
87
  }
82
88
 
83
89
 
@@ -103,6 +109,48 @@ def _required_headers(session: Mapping[str, Any]) -> dict[str, str]:
103
109
  return headers
104
110
 
105
111
 
112
+ def _adopted(
113
+ destination: Path,
114
+ *,
115
+ expected_digest: Any,
116
+ expected_preimage: ExpectedPreimage | None,
117
+ ) -> tuple[bool, str, int]:
118
+ """Whether the file already on disk IS this artifact, by the digest the session declared.
119
+
120
+ ⚠ A DIGEST SKIP, NOT AN OVERWRITE. `deploy-dataset` fetches one artifact per kind in a loop,
121
+ and every one was created ``O_EXCL``, so a transfer interrupted after the first of two left a
122
+ folder holding one complete, verified artifact and no way to finish the job except a fresh
123
+ folder that re-downloaded the first as well. On a released dataset of several gigabytes the
124
+ cost of a dropped connection was paid twice (#438).
125
+
126
+ The skip is decided by the SAME fact the download would be verified against, so adopting
127
+ cannot be weaker than fetching: the bytes on disk must hash to the digest the signed session
128
+ declares, in whichever of the two authorities this download uses. Anything present that does
129
+ not match stays ``THIN_DESTINATION_EXISTS``: that file is not this artifact, and replacing it
130
+ silently is exactly what that refusal exists to prevent.
131
+ """
132
+
133
+ size = destination.stat().st_size
134
+ if size > MAX_ARTIFACT_BYTES:
135
+ return False, "", size
136
+ raw = bytearray()
137
+ observed = hashlib.sha256()
138
+ with destination.open("rb") as handle:
139
+ while chunk := handle.read(DOWNLOAD_CHUNK_BYTES):
140
+ observed.update(chunk)
141
+ if expected_preimage is not None:
142
+ raw.extend(chunk)
143
+ digest = observed.hexdigest()
144
+ if expected_preimage is None:
145
+ return f"sha256:{digest}" == expected_digest, f"sha256:{digest}", size
146
+ # The bundle seals its own preimage, so the authority is the excised hash, not the raw one.
147
+ body = bytes(raw)
148
+ if body.count(expected_preimage.excised_field) != 1:
149
+ return False, "", size
150
+ preimage = hashlib.sha256(body.replace(expected_preimage.excised_field, b"", 1)).hexdigest()
151
+ return preimage == expected_preimage.digest, f"sha256:{digest}", size
152
+
153
+
106
154
  def download_signed_artifact(
107
155
  session: Mapping[str, Any],
108
156
  destination: Path,
@@ -153,6 +201,30 @@ def download_signed_artifact(
153
201
 
154
202
  selected = transport or UrlLibTransport()
155
203
  destination.parent.mkdir(parents=True, exist_ok=True)
204
+ # ⚠ A SYMLINK IS NEVER ADOPTED. The write path opens with ``O_NOFOLLOW`` precisely so a
205
+ # symlinked destination is refused rather than followed, and adopting through one would walk
206
+ # around that. Only a regular file in the place the artifact belongs can stand in for it; a
207
+ # symlink falls through to the open below and is refused there, as before.
208
+ #
209
+ # The remaining race is benign: a file swapped between this check and the read would have to
210
+ # hash to the sealed digest to be adopted, and a file that does is the artifact.
211
+ if destination.is_file() and not destination.is_symlink():
212
+ matched, observed_digest, size = _adopted(
213
+ destination, expected_digest=expected_digest, expected_preimage=expected_preimage
214
+ )
215
+ if matched:
216
+ media_type = session.get("media_type")
217
+ artifact_id = session.get("artifact_id")
218
+ return DownloadedArtifact(
219
+ path=destination,
220
+ artifact_id=artifact_id if isinstance(artifact_id, str) else "",
221
+ media_type=(
222
+ media_type if isinstance(media_type, str) else "application/octet-stream"
223
+ ),
224
+ size_bytes=size,
225
+ content_digest=(expected_digest if expected_preimage is None else observed_digest),
226
+ transferred=False,
227
+ )
156
228
  flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
157
229
  if hasattr(os, "O_NOFOLLOW"):
158
230
  flags |= os.O_NOFOLLOW
@@ -165,7 +237,8 @@ def download_signed_artifact(
165
237
  except FileExistsError as error:
166
238
  raise ThinLaneError(
167
239
  "THIN_DESTINATION_EXISTS",
168
- f"{destination} already exists; a hosted download never overwrites a local file",
240
+ f"{destination} already exists and does not carry this artifact's sealed digest, so "
241
+ "it is a different file; a hosted download never overwrites a local file",
169
242
  ) from error
170
243
 
171
244
  try:
@@ -2099,6 +2099,7 @@ def propose(
2099
2099
  recipe = bundle.recipe
2100
2100
  assert recipe is not None
2101
2101
  _check_recipe_sources(recipe, source_ids=source_ids, configurations=configurations)
2102
+ _check_recipe_query_templates(recipe, configurations=configurations)
2102
2103
  research_run_id: str | None = None
2103
2104
  if research_session_id is not None:
2104
2105
  record = _lookup_session(
@@ -2359,6 +2360,149 @@ def _refuse_a_registered_source_the_bundle_no_longer_names(
2359
2360
  )
2360
2361
 
2361
2362
 
2363
+ #: The Reader families a thin install can canonicalize in process. The other five certified
2364
+ #: coordinates -- ``spreadsheet.xlsx`` (two), ``parquet.tabular``, ``weather.grib2`` (two) --
2365
+ #: import openpyxl, pyarrow or mostlyright-grib at module scope, which the thin profile does not
2366
+ #: install. ``propose`` therefore refuses such a pin by name rather than sealing one it cannot
2367
+ #: check; see :func:`_admitted_reader_pin`.
2368
+ _READER_CANONICALIZATION_UNAVAILABLE = (
2369
+ "this Reader family needs a native wheel the hosted profile does not install, so propose "
2370
+ "cannot admit its options here; author the Recipe from an install that has it "
2371
+ '(pip install "mostlyright-data[local]") so the sealed pin is the admitted one'
2372
+ )
2373
+
2374
+
2375
+ def _admitted_reader_pin(pin: Any, *, name: str, path: str) -> Any:
2376
+ """One Reader pin in the form the CRAWLER will recompute, or a refusal naming why not.
2377
+
2378
+ ⚠ WHY AUTHORING HAS TO DO THIS. A pin is digested, and the digest is over the ADMITTED options
2379
+ -- ``family.validate_options`` with every family-defaulted key filled in. An author who writes
2380
+ ``{"delimiter": ","}`` and omits ``encoding``, ``header``, ``expand`` or ``required`` seals a
2381
+ document that digests differently from the one the crawler will reconstruct, and every crawl
2382
+ then fails ``reader_identity`` with nothing naming the cause. That is what killed r13 and r14
2383
+ (#411). Every gate accepted those Recipes -- propose, Studio admission, approval -- and only
2384
+ the crawl refused, unnamed.
2385
+
2386
+ The principle the issue states is the one applied here: an agent authors against ``propose``,
2387
+ so anything Studio or the crawler will refuse at run time must be refused HERE, by name,
2388
+ before a person is asked to approve it.
2389
+
2390
+ ⚠ THE THIN PROFILE CAN DO THIS FOR MOST FAMILIES, AND SAYS SO WHEN IT CANNOT. Importing
2391
+ ``readers.registry`` is stdlib-only, and the registry loads a family lazily, so the ten
2392
+ delimited/JSON/archive coordinates -- ``delimited_text`` among them, which is the family the
2393
+ failing Recipes used -- canonicalize on a bare interpreter. The five that need a native wheel
2394
+ are refused rather than passed through unchecked.
2395
+ """
2396
+
2397
+ if pin is None:
2398
+ return None
2399
+ if not isinstance(pin, dict):
2400
+ raise _invalid(name, path, "must be null or a Reader pin object")
2401
+ _keys(pin, name, path, ("family_id", "family_version", "decode_options"))
2402
+ family_id = pin["family_id"]
2403
+ family_version = pin["family_version"]
2404
+ options = pin["decode_options"]
2405
+ if not isinstance(family_id, str) or not isinstance(family_version, str):
2406
+ raise _invalid(name, path, "family_id and family_version must be strings")
2407
+ if not isinstance(options, dict):
2408
+ raise _invalid(name, f"{path}.decode_options", "must be an object")
2409
+
2410
+ # Imported here rather than at module scope: `propose` is reached on a bare interpreter, and
2411
+ # the registry is only needed when a Recipe actually pins a Reader.
2412
+ from mostlyright.data_harness.readers.registry import TOOLBOX
2413
+
2414
+ try:
2415
+ family = TOOLBOX.resolve(family_id, family_version)
2416
+ except ImportError as error: # the family's native wheel is absent on this install
2417
+ raise ProposeError(
2418
+ "THIN_PROPOSE_READER_PIN",
2419
+ f"{name} {path} pins {family_id}@{family_version}: "
2420
+ f"{_READER_CANONICALIZATION_UNAVAILABLE} ({error})",
2421
+ ) from error
2422
+ except Exception as error: # unknown family, unknown version, or a dependency refusal
2423
+ raise ProposeError(
2424
+ "THIN_PROPOSE_READER_PIN",
2425
+ f"{name} {path} pins {family_id}@{family_version}, which is not a certified Reader "
2426
+ f"coordinate this Harness can admit: {error}",
2427
+ ) from error
2428
+ try:
2429
+ admitted = dict(family.validate_options(options))
2430
+ except Exception as error:
2431
+ raise ProposeError(
2432
+ "THIN_PROPOSE_READER_PIN",
2433
+ f"{name} {path} pins Reader options {family_id}@{family_version} refuses: {error}",
2434
+ ) from error
2435
+ return {
2436
+ "family_id": family_id,
2437
+ "family_version": family_version,
2438
+ "decode_options": admitted,
2439
+ }
2440
+
2441
+
2442
+ def _reader_pin_of(query: Any) -> Any:
2443
+ return query.get("reader_pin") if isinstance(query, dict) else None
2444
+
2445
+
2446
+ def _check_recipe_query_templates(
2447
+ recipe: Mapping[str, Any],
2448
+ *,
2449
+ configurations: Mapping[str, Mapping[str, Any]],
2450
+ ) -> None:
2451
+ """Every recipe query is the query its registered connector holds, in the admitted form.
2452
+
2453
+ ⚠ TWO REFUSALS, BECAUSE THEY ARE TWO MISTAKES. Studio binds ``query_template`` byte-for-byte
2454
+ to the registered connector configuration, so a Recipe whose query has drifted from its source
2455
+ is refused at run time with nothing naming the field. And a raw (non-admitted) Reader pin
2456
+ digests differently from the one the crawler rebuilds, failing ``reader_identity`` on every
2457
+ crawl. Both were accepted by every authoring gate before this (#411); both are named here,
2458
+ with the exact value to write.
2459
+
2460
+ Sources whose adapter carries no connector query -- ``user.file`` snapshots -- are skipped:
2461
+ there is nothing registered to compare against.
2462
+ """
2463
+
2464
+ for source in recipe["sources"]:
2465
+ source_id = source["source_id"]
2466
+ template = source.get("query_template")
2467
+ registered = configurations.get(source_id, {}).get("query")
2468
+ if template is None or registered is None:
2469
+ continue
2470
+ if not isinstance(template, dict):
2471
+ raise _invalid("recipe.json", f"sources[{source_id}].query_template", "must be object")
2472
+
2473
+ admitted_pin = _admitted_reader_pin(
2474
+ _reader_pin_of(template),
2475
+ name="recipe.json",
2476
+ path=f"sources[{source_id}].query_template.reader_pin",
2477
+ )
2478
+ if admitted_pin != _reader_pin_of(template):
2479
+ raise ProposeError(
2480
+ "THIN_PROPOSE_READER_PIN",
2481
+ f"recipe.json source {source_id} pins Reader options that are not the admitted "
2482
+ "form, so its sealed digest is not the one every crawl will recompute and "
2483
+ "reader_identity would fail on each run; write the pin exactly as: "
2484
+ f"{json.dumps(admitted_pin, sort_keys=True)}",
2485
+ )
2486
+
2487
+ differing = sorted(
2488
+ key
2489
+ for key in set(template) | set(registered)
2490
+ if canonical_json_bytes(template.get(key)) != canonical_json_bytes(registered.get(key))
2491
+ )
2492
+ if differing:
2493
+ detail = "; ".join(
2494
+ f"{key}: recipe.json has {json.dumps(template.get(key), sort_keys=True)}, "
2495
+ f"the registered connector has {json.dumps(registered.get(key), sort_keys=True)}"
2496
+ for key in differing
2497
+ )
2498
+ raise ProposeError(
2499
+ "THIN_PROPOSE_SOURCE_QUERY",
2500
+ f"recipe.json source {source_id} carries a query its registered connector "
2501
+ f"configuration does not hold, and Studio binds the two byte-for-byte, so this "
2502
+ f"Recipe would be refused when it ran -- {detail}",
2503
+ )
2504
+
2505
+
2362
2506
  def _check_recipe_sources(
2363
2507
  recipe: Mapping[str, Any],
2364
2508
  *,
@@ -2560,8 +2704,8 @@ def _proposal_receipt(
2560
2704
  and ``mr-data build --hosted`` queues one; it is approved and the confirmation STARTED the
2561
2705
  Build in the same act -- Studio #124 -- and the run is named here because ``mr-data build``
2562
2706
  would refuse it rather than replay it; or it was declined (exit 2). Both commands carry
2563
- ``--hosted``, because on a full install the bare names are the local lane's. Nothing here
2564
- decides anything.
2707
+ ``--hosted`` because it names the lane explicitly and remains valid: the bare names reach the
2708
+ backend on every install. Nothing here decides anything.
2565
2709
  """
2566
2710
 
2567
2711
  payload = _common(client, journal, stage=stage)