mostlyright-data 0.9.0__py3-none-any.whl

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 (314) hide show
  1. mostlyright/data_harness/__init__.py +158 -0
  2. mostlyright/data_harness/acquisition/__init__.py +55 -0
  3. mostlyright/data_harness/acquisition/http.py +2773 -0
  4. mostlyright/data_harness/acquisition/parsing.py +809 -0
  5. mostlyright/data_harness/acquisition/ranges.py +495 -0
  6. mostlyright/data_harness/acquisition/result_download.py +360 -0
  7. mostlyright/data_harness/acquisition/retention_admission.py +248 -0
  8. mostlyright/data_harness/acquisition/sandbox.py +4888 -0
  9. mostlyright/data_harness/acquisition/url_policy.py +530 -0
  10. mostlyright/data_harness/agent_runtime.py +2743 -0
  11. mostlyright/data_harness/assets/logo-ink.svg +31 -0
  12. mostlyright/data_harness/backends/__init__.py +28 -0
  13. mostlyright/data_harness/backends/pandas_backend.py +350 -0
  14. mostlyright/data_harness/backends/polars_backend.py +366 -0
  15. mostlyright/data_harness/backends/protocol.py +124 -0
  16. mostlyright/data_harness/backends/reference.py +83 -0
  17. mostlyright/data_harness/backends/registry.py +55 -0
  18. mostlyright/data_harness/backends/restrictions.py +126 -0
  19. mostlyright/data_harness/canonical.py +333 -0
  20. mostlyright/data_harness/catalog_job.py +625 -0
  21. mostlyright/data_harness/cli.py +5398 -0
  22. mostlyright/data_harness/contracts.py +53 -0
  23. mostlyright/data_harness/coordinator.py +1307 -0
  24. mostlyright/data_harness/deploy.py +924 -0
  25. mostlyright/data_harness/deploy_target.py +312 -0
  26. mostlyright/data_harness/deployment_evidence.py +1067 -0
  27. mostlyright/data_harness/event_presentation.py +576 -0
  28. mostlyright/data_harness/events.py +2152 -0
  29. mostlyright/data_harness/fast_delimited.py +239 -0
  30. mostlyright/data_harness/fleet.py +237 -0
  31. mostlyright/data_harness/formats.py +236 -0
  32. mostlyright/data_harness/governors.py +1163 -0
  33. mostlyright/data_harness/hosted_bootstrap.py +972 -0
  34. mostlyright/data_harness/hosted_crawler.py +1115 -0
  35. mostlyright/data_harness/hosted_crawler_container_smoke.py +351 -0
  36. mostlyright/data_harness/hosted_crawler_fetch.py +423 -0
  37. mostlyright/data_harness/hosted_crawler_job.py +1277 -0
  38. mostlyright/data_harness/hosted_crawler_protocol.py +676 -0
  39. mostlyright/data_harness/hosted_dataset.py +1500 -0
  40. mostlyright/data_harness/hosted_deploy.py +3037 -0
  41. mostlyright/data_harness/hosted_handoff.py +62 -0
  42. mostlyright/data_harness/hosted_ingestion_contract.py +504 -0
  43. mostlyright/data_harness/hosted_ingestion_job.py +356 -0
  44. mostlyright/data_harness/hosted_ingestion_job_smoke.py +40 -0
  45. mostlyright/data_harness/hosted_session_container_smoke.py +194 -0
  46. mostlyright/data_harness/hosted_session_worker.py +3554 -0
  47. mostlyright/data_harness/hosted_session_worker_job_smoke.py +46 -0
  48. mostlyright/data_harness/hosted_worker.py +6784 -0
  49. mostlyright/data_harness/ingestion/__init__.py +56 -0
  50. mostlyright/data_harness/ingestion/contracts.py +461 -0
  51. mostlyright/data_harness/ingestion/faults.py +42 -0
  52. mostlyright/data_harness/ingestion/gcs_store.py +1162 -0
  53. mostlyright/data_harness/ingestion/spool.py +130 -0
  54. mostlyright/data_harness/ingestion/store.py +885 -0
  55. mostlyright/data_harness/key_seam.py +434 -0
  56. mostlyright/data_harness/linux_process_boundary.py +262 -0
  57. mostlyright/data_harness/local_contracts.py +2880 -0
  58. mostlyright/data_harness/local_search/__init__.py +5 -0
  59. mostlyright/data_harness/local_search/build_index.py +1087 -0
  60. mostlyright/data_harness/local_search/contracts.py +920 -0
  61. mostlyright/data_harness/local_search/query_trace.py +266 -0
  62. mostlyright/data_harness/local_search/retrieval.py +700 -0
  63. mostlyright/data_harness/local_search/sealed.py +474 -0
  64. mostlyright/data_harness/local_search/service.py +784 -0
  65. mostlyright/data_harness/nbrender/CONTRACT.md +212 -0
  66. mostlyright/data_harness/nbrender/__init__.py +12 -0
  67. mostlyright/data_harness/nbrender/chrome.py +359 -0
  68. mostlyright/data_harness/nbrender/code_body.py +266 -0
  69. mostlyright/data_harness/nbrender/document.py +407 -0
  70. mostlyright/data_harness/nbrender/frame.py +275 -0
  71. mostlyright/data_harness/nbrender/interactive.py +337 -0
  72. mostlyright/data_harness/nbrender/markdown_body.py +477 -0
  73. mostlyright/data_harness/nbrender/mr_components.py +134 -0
  74. mostlyright/data_harness/nbrender/outputs_data.py +595 -0
  75. mostlyright/data_harness/nbrender/outputs_rich.py +906 -0
  76. mostlyright/data_harness/nbrender/outputs_source.py +260 -0
  77. mostlyright/data_harness/nbrender/outputs_stage.py +176 -0
  78. mostlyright/data_harness/nbrender/outputs_text.py +400 -0
  79. mostlyright/data_harness/nbrender/parse.py +394 -0
  80. mostlyright/data_harness/nbrender/status.py +40 -0
  81. mostlyright/data_harness/nbrender/tokens.py +1295 -0
  82. mostlyright/data_harness/notebook.py +1710 -0
  83. mostlyright/data_harness/offline.py +2049 -0
  84. mostlyright/data_harness/operation_registry.py +1007 -0
  85. mostlyright/data_harness/operator_setup.py +239 -0
  86. mostlyright/data_harness/pipeline.py +6428 -0
  87. mostlyright/data_harness/plan_graph.py +2026 -0
  88. mostlyright/data_harness/preparation/__init__.py +104 -0
  89. mostlyright/data_harness/preparation/contracts.py +1017 -0
  90. mostlyright/data_harness/preparation/engine.py +221 -0
  91. mostlyright/data_harness/preparation/errors.py +14 -0
  92. mostlyright/data_harness/preparation/gates.py +751 -0
  93. mostlyright/data_harness/preparation/joins.py +574 -0
  94. mostlyright/data_harness/preparation/profile.py +384 -0
  95. mostlyright/data_harness/preparation/table.py +217 -0
  96. mostlyright/data_harness/preparation/transforms.py +568 -0
  97. mostlyright/data_harness/progress_events.py +534 -0
  98. mostlyright/data_harness/readers/__init__.py +46 -0
  99. mostlyright/data_harness/readers/containers.py +963 -0
  100. mostlyright/data_harness/readers/contracts.py +542 -0
  101. mostlyright/data_harness/readers/delimited.py +257 -0
  102. mostlyright/data_harness/readers/grib2/__init__.py +33 -0
  103. mostlyright/data_harness/readers/grib2/admission.py +722 -0
  104. mostlyright/data_harness/readers/grib2/decode.py +1009 -0
  105. mostlyright/data_harness/readers/grib2/geometry.py +1133 -0
  106. mostlyright/data_harness/readers/grib2/portable_math.py +501 -0
  107. mostlyright/data_harness/readers/json_tabular.py +485 -0
  108. mostlyright/data_harness/readers/registry.py +514 -0
  109. mostlyright/data_harness/readers/samples/README.md +110 -0
  110. mostlyright/data_harness/readers/samples/archive.gzip/1.0.0/cities_one_stream/cities.csv.gz +0 -0
  111. mostlyright/data_harness/readers/samples/archive.gzip/1.0.0/cities_one_stream/expected.json +24 -0
  112. mostlyright/data_harness/readers/samples/archive.gzip/1.1.0/cities_one_stream/cities.csv.gz +0 -0
  113. mostlyright/data_harness/readers/samples/archive.gzip/1.1.0/cities_one_stream/expected.json +24 -0
  114. mostlyright/data_harness/readers/samples/archive.tar/1.0.0/cities_beside_a_directory_entry/cities.tar +0 -0
  115. mostlyright/data_harness/readers/samples/archive.tar/1.0.0/cities_beside_a_directory_entry/expected.json +24 -0
  116. mostlyright/data_harness/readers/samples/archive.tar/1.1.0/cities_beside_a_directory_entry/cities.tar +0 -0
  117. mostlyright/data_harness/readers/samples/archive.tar/1.1.0/cities_beside_a_directory_entry/expected.json +24 -0
  118. mostlyright/data_harness/readers/samples/archive.zip/1.0.0/cities_beside_a_second_member/cities.zip +0 -0
  119. mostlyright/data_harness/readers/samples/archive.zip/1.0.0/cities_beside_a_second_member/expected.json +25 -0
  120. mostlyright/data_harness/readers/samples/archive.zip/1.1.0/dwd_semicolon_station_member/dwd-station.zip +0 -0
  121. mostlyright/data_harness/readers/samples/archive.zip/1.1.0/dwd_semicolon_station_member/expected.json +25 -0
  122. mostlyright/data_harness/readers/samples/archive.zip/1.2.0/dwd_semicolon_station_member/dwd-station.zip +0 -0
  123. mostlyright/data_harness/readers/samples/archive.zip/1.2.0/dwd_semicolon_station_member/expected.json +25 -0
  124. mostlyright/data_harness/readers/samples/delimited_text/1.0.0/an_ordinary_comma_separated_table/cities.csv +3 -0
  125. mostlyright/data_harness/readers/samples/delimited_text/1.0.0/an_ordinary_comma_separated_table/expected.json +23 -0
  126. mostlyright/data_harness/readers/samples/delimited_text/1.0.0/quoted_fields_holding_the_delimiter/cities.tsv +5 -0
  127. mostlyright/data_harness/readers/samples/delimited_text/1.0.0/quoted_fields_holding_the_delimiter/expected.json +25 -0
  128. mostlyright/data_harness/readers/samples/delimited_text/1.1.0/an_hourly_observation_table_served_as_plain_text/expected.json +30 -0
  129. mostlyright/data_harness/readers/samples/delimited_text/1.1.0/an_hourly_observation_table_served_as_plain_text/observations.csv +5 -0
  130. mostlyright/data_harness/readers/samples/json.tabular/1.0.0/nested_hourly_observations/expected.json +44 -0
  131. mostlyright/data_harness/readers/samples/json.tabular/1.0.0/nested_hourly_observations/stations.json +1 -0
  132. mostlyright/data_harness/readers/samples/json.tabular/1.1.0/an_observation_stream_served_as_plain_text/expected.json +48 -0
  133. mostlyright/data_harness/readers/samples/json.tabular/1.1.0/an_observation_stream_served_as_plain_text/observations.ndjson +4 -0
  134. mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/an_ordinary_table_beside_a_second_sheet/cities.xlsx +0 -0
  135. mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/an_ordinary_table_beside_a_second_sheet/expected.json +24 -0
  136. mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/shares_the_workbook_had_already_computed/expected.json +27 -0
  137. mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/shares_the_workbook_had_already_computed/shares.xlsx +0 -0
  138. mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.1.0/shares_the_workbook_had_already_computed/expected.json +27 -0
  139. mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.1.0/shares_the_workbook_had_already_computed/shares.xlsx +0 -0
  140. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/README.md +20 -0
  141. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/gfs_2m_temperature/expected.json +55 -0
  142. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/gfs_2m_temperature/gfs-2m-temperature.grib2 +0 -0
  143. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_2m_temperature/expected.json +54 -0
  144. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_2m_temperature/hrrr-2m-temperature.grib2 +0 -0
  145. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_categorical_rain/expected.json +54 -0
  146. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_categorical_rain/hrrr-categorical-rain.grib2 +0 -0
  147. mostlyright/data_harness/readers/samples/weather.grib2/2.0.0/hrrr_2m_temperature/expected.json +54 -0
  148. mostlyright/data_harness/readers/samples/weather.grib2/2.0.0/hrrr_2m_temperature/hrrr-2m-temperature.grib2 +0 -0
  149. mostlyright/data_harness/readers/samples.py +582 -0
  150. mostlyright/data_harness/readers/spreadsheet.py +803 -0
  151. mostlyright/data_harness/readers/tabular.py +510 -0
  152. mostlyright/data_harness/recipe.py +5321 -0
  153. mostlyright/data_harness/repair/__init__.py +78 -0
  154. mostlyright/data_harness/repair/adapters.py +274 -0
  155. mostlyright/data_harness/repair/contracts.py +872 -0
  156. mostlyright/data_harness/repair/coordinator.py +1099 -0
  157. mostlyright/data_harness/repair/errors.py +16 -0
  158. mostlyright/data_harness/review.py +2533 -0
  159. mostlyright/data_harness/rowset.py +283 -0
  160. mostlyright/data_harness/serving.py +1975 -0
  161. mostlyright/data_harness/serving_edge.py +590 -0
  162. mostlyright/data_harness/serving_http.py +1031 -0
  163. mostlyright/data_harness/session_probes.py +759 -0
  164. mostlyright/data_harness/signing.py +101 -0
  165. mostlyright/data_harness/source_discovery.py +898 -0
  166. mostlyright/data_harness/sources/__init__.py +209 -0
  167. mostlyright/data_harness/sources/_adapter_steps.py +213 -0
  168. mostlyright/data_harness/sources/adapters.py +1214 -0
  169. mostlyright/data_harness/sources/cadence.py +1428 -0
  170. mostlyright/data_harness/sources/cadence_emission.py +453 -0
  171. mostlyright/data_harness/sources/cadence_history.py +546 -0
  172. mostlyright/data_harness/sources/catalog/__init__.py +17 -0
  173. mostlyright/data_harness/sources/catalog/admission.py +477 -0
  174. mostlyright/data_harness/sources/catalog/authoring.py +1701 -0
  175. mostlyright/data_harness/sources/catalog/authoring_policy.py +701 -0
  176. mostlyright/data_harness/sources/catalog/authoring_shards.py +1217 -0
  177. mostlyright/data_harness/sources/catalog/bounded_io.py +231 -0
  178. mostlyright/data_harness/sources/catalog/channel.py +523 -0
  179. mostlyright/data_harness/sources/catalog/channel_client.py +296 -0
  180. mostlyright/data_harness/sources/catalog/contracts.py +825 -0
  181. mostlyright/data_harness/sources/catalog/coverage.py +137 -0
  182. mostlyright/data_harness/sources/catalog/delta.py +1340 -0
  183. mostlyright/data_harness/sources/catalog/embedding.py +532 -0
  184. mostlyright/data_harness/sources/catalog/entry_v2.py +1182 -0
  185. mostlyright/data_harness/sources/catalog/fill.py +3889 -0
  186. mostlyright/data_harness/sources/catalog/fill_partitions.py +459 -0
  187. mostlyright/data_harness/sources/catalog/fill_staging.py +1105 -0
  188. mostlyright/data_harness/sources/catalog/gating.py +374 -0
  189. mostlyright/data_harness/sources/catalog/generation_receipt.py +1607 -0
  190. mostlyright/data_harness/sources/catalog/harvest/__init__.py +7 -0
  191. mostlyright/data_harness/sources/catalog/harvest/ckan.py +384 -0
  192. mostlyright/data_harness/sources/catalog/harvest/datagov_v4.py +798 -0
  193. mostlyright/data_harness/sources/catalog/harvest/protocol.py +964 -0
  194. mostlyright/data_harness/sources/catalog/harvest/sdmx.py +445 -0
  195. mostlyright/data_harness/sources/catalog/harvest/stac.py +384 -0
  196. mostlyright/data_harness/sources/catalog/health.py +447 -0
  197. mostlyright/data_harness/sources/catalog/hosted_catalog.py +105 -0
  198. mostlyright/data_harness/sources/catalog/identity_history.py +1549 -0
  199. mostlyright/data_harness/sources/catalog/neural.py +1618 -0
  200. mostlyright/data_harness/sources/catalog/packed_catalog.py +2345 -0
  201. mostlyright/data_harness/sources/catalog/packed_retrieval.py +1517 -0
  202. mostlyright/data_harness/sources/catalog/packed_writer.py +2802 -0
  203. mostlyright/data_harness/sources/catalog/query_trace.py +1037 -0
  204. mostlyright/data_harness/sources/catalog/recommend.py +171 -0
  205. mostlyright/data_harness/sources/catalog/retrieval.py +230 -0
  206. mostlyright/data_harness/sources/catalog/retrieval_manifest.py +995 -0
  207. mostlyright/data_harness/sources/catalog/rights_decisions.py +254 -0
  208. mostlyright/data_harness/sources/catalog/sealed.py +560 -0
  209. mostlyright/data_harness/sources/catalog/search.py +230 -0
  210. mostlyright/data_harness/sources/catalog/streaming_delta.py +1097 -0
  211. mostlyright/data_harness/sources/catalog/update.py +891 -0
  212. mostlyright/data_harness/sources/collections.py +815 -0
  213. mostlyright/data_harness/sources/contracts.py +2223 -0
  214. mostlyright/data_harness/sources/deletion.py +761 -0
  215. mostlyright/data_harness/sources/fitness.py +162 -0
  216. mostlyright/data_harness/sources/governance.py +163 -0
  217. mostlyright/data_harness/sources/hosted.py +173 -0
  218. mostlyright/data_harness/sources/integration.py +218 -0
  219. mostlyright/data_harness/sources/range_reader.py +418 -0
  220. mostlyright/data_harness/sources/registry.py +514 -0
  221. mostlyright/data_harness/sources/rights_rule.py +59 -0
  222. mostlyright/data_harness/sources/source_cadence_vectors.v1.json +1 -0
  223. mostlyright/data_harness/sources/sports.py +521 -0
  224. mostlyright/data_harness/sources/stream.py +524 -0
  225. mostlyright/data_harness/sources/stream_connector.py +418 -0
  226. mostlyright/data_harness/sources/stream_recorder.py +1404 -0
  227. mostlyright/data_harness/studio_boundary.py +2019 -0
  228. mostlyright/data_harness/thin/__init__.py +37 -0
  229. mostlyright/data_harness/thin/acquire.py +1137 -0
  230. mostlyright/data_harness/thin/acquire_cancel.py +579 -0
  231. mostlyright/data_harness/thin/approvals.py +617 -0
  232. mostlyright/data_harness/thin/commands.py +406 -0
  233. mostlyright/data_harness/thin/download.py +194 -0
  234. mostlyright/data_harness/thin/narrative.py +589 -0
  235. mostlyright/data_harness/thin/parity.py +1070 -0
  236. mostlyright/data_harness/thin/propose.py +2759 -0
  237. mostlyright/data_harness/thin/research.py +1663 -0
  238. mostlyright/data_harness/thin/router.py +924 -0
  239. mostlyright/data_harness/thin/runs.py +519 -0
  240. mostlyright/data_harness/thin/session.py +281 -0
  241. mostlyright/data_harness/thin/stream.py +501 -0
  242. mostlyright/data_harness/thin/transport.py +187 -0
  243. mostlyright/data_harness/thin/vocabulary.py +368 -0
  244. mostlyright/data_harness/thin/workers.py +164 -0
  245. mostlyright/data_harness/ucum/TABLE-PIN.json +40 -0
  246. mostlyright/data_harness/ucum/ucum-subset.v1.json +632 -0
  247. mostlyright/data_harness/unit_flow.py +927 -0
  248. mostlyright/data_harness/units.py +572 -0
  249. mostlyright/data_harness/ux/__init__.py +9 -0
  250. mostlyright/data_harness/ux/approve.py +485 -0
  251. mostlyright/data_harness/ux/author_yaml.py +597 -0
  252. mostlyright/data_harness/ux/cloud_auth.py +447 -0
  253. mostlyright/data_harness/ux/commands/__init__.py +260 -0
  254. mostlyright/data_harness/ux/commands/approve.py +136 -0
  255. mostlyright/data_harness/ux/commands/auth.py +744 -0
  256. mostlyright/data_harness/ux/commands/author.py +79 -0
  257. mostlyright/data_harness/ux/commands/catalog_author.py +403 -0
  258. mostlyright/data_harness/ux/commands/catalog_fill.py +523 -0
  259. mostlyright/data_harness/ux/commands/catalog_harvest.py +545 -0
  260. mostlyright/data_harness/ux/commands/catalog_publish.py +1838 -0
  261. mostlyright/data_harness/ux/commands/catalog_search.py +71 -0
  262. mostlyright/data_harness/ux/commands/catalog_update.py +437 -0
  263. mostlyright/data_harness/ux/commands/deploy.py +134 -0
  264. mostlyright/data_harness/ux/commands/deploy_dataset.py +98 -0
  265. mostlyright/data_harness/ux/commands/deploy_plan.py +105 -0
  266. mostlyright/data_harness/ux/commands/deploy_status.py +104 -0
  267. mostlyright/data_harness/ux/commands/diff.py +74 -0
  268. mostlyright/data_harness/ux/commands/index.py +84 -0
  269. mostlyright/data_harness/ux/commands/inventory.py +47 -0
  270. mostlyright/data_harness/ux/commands/list_builds.py +143 -0
  271. mostlyright/data_harness/ux/commands/login.py +63 -0
  272. mostlyright/data_harness/ux/commands/peek.py +236 -0
  273. mostlyright/data_harness/ux/commands/plan_check.py +90 -0
  274. mostlyright/data_harness/ux/commands/preflight.py +97 -0
  275. mostlyright/data_harness/ux/commands/record.py +107 -0
  276. mostlyright/data_harness/ux/commands/review_setup.py +47 -0
  277. mostlyright/data_harness/ux/commands/search.py +440 -0
  278. mostlyright/data_harness/ux/commands/show.py +61 -0
  279. mostlyright/data_harness/ux/commands/whoami.py +37 -0
  280. mostlyright/data_harness/ux/credential_native.py +551 -0
  281. mostlyright/data_harness/ux/credential_store.py +1055 -0
  282. mostlyright/data_harness/ux/credentials.py +631 -0
  283. mostlyright/data_harness/ux/diffing.py +444 -0
  284. mostlyright/data_harness/ux/headline.py +671 -0
  285. mostlyright/data_harness/ux/hosted_acquisition.py +974 -0
  286. mostlyright/data_harness/ux/hosted_run_status.py +619 -0
  287. mostlyright/data_harness/ux/inventory.py +427 -0
  288. mostlyright/data_harness/ux/local_review.py +375 -0
  289. mostlyright/data_harness/ux/login.py +691 -0
  290. mostlyright/data_harness/ux/path_kind.py +147 -0
  291. mostlyright/data_harness/ux/peek.py +1000 -0
  292. mostlyright/data_harness/ux/plain_file.py +178 -0
  293. mostlyright/data_harness/ux/plan_check.py +311 -0
  294. mostlyright/data_harness/ux/preflight.py +918 -0
  295. mostlyright/data_harness/ux/readers.py +1124 -0
  296. mostlyright/data_harness/ux/remediation.py +2195 -0
  297. mostlyright/data_harness/ux/render.py +657 -0
  298. mostlyright/data_harness/ux/workload.py +1077 -0
  299. mostlyright/data_harness/viewer.py +3713 -0
  300. mostlyright/data_harness/visual_run/__init__.py +83 -0
  301. mostlyright/data_harness/visual_run/authoring.py +235 -0
  302. mostlyright/data_harness/visual_run/contracts.py +673 -0
  303. mostlyright/data_harness/visual_run/materialize.py +486 -0
  304. mostlyright/data_harness/visual_run/observations.py +874 -0
  305. mostlyright/data_harness/visual_run/query.py +259 -0
  306. mostlyright/data_harness/visual_run/reducer.py +280 -0
  307. mostlyright/data_harness/visual_run/sdk.py +892 -0
  308. mostlyright/data_harness/visual_run/store.py +584 -0
  309. mostlyright/data_harness/visual_run/transport.py +239 -0
  310. mostlyright/data_harness/watch.py +2999 -0
  311. mostlyright_data-0.9.0.dist-info/METADATA +607 -0
  312. mostlyright_data-0.9.0.dist-info/RECORD +314 -0
  313. mostlyright_data-0.9.0.dist-info/WHEEL +4 -0
  314. mostlyright_data-0.9.0.dist-info/entry_points.txt +12 -0
@@ -0,0 +1,546 @@
1
+ """The local append-only empirical observation history one operator retains for one source.
2
+
3
+ Hosted probes append to a chain Studio authenticates and persists. A local probe has no Studio,
4
+ so this module is the local coordinator's equivalent: one folder per source epoch, one immutable
5
+ canonical record per probe, and the same digest chain the contract validates.
6
+
7
+ Three properties are the point, and each is enforced rather than described. The history is
8
+ append-only, because a probe record is created with ``O_EXCL`` and a sequence that already exists
9
+ is a refusal rather than an overwrite. It is canonical, because every record is the exact
10
+ canonical JSON bytes of its document and is re-parsed through the contract on the way back in.
11
+ It is digest-bound, because each record carries the observation, the observation's digest, and
12
+ the probe receipt whose digest that observation names -- so a record that was edited no longer
13
+ verifies against itself, and a record moved between histories no longer verifies against its
14
+ predecessor.
15
+
16
+ The stored authority is what fixes the epoch. The contract requires a new inference epoch when
17
+ the connector configuration, locator, program, source authority, Reader, Reader options, frontier
18
+ derivation, time interpretation, or algorithm changes, so a history whose authority no longer
19
+ matches the one this probe was given is refused whole rather than continued. Two epochs never
20
+ enter one inference.
21
+
22
+ This module reads no clock and no network. It grants nothing: a local history is evidence an
23
+ operator retained, not a release, an approval, or a schedule.
24
+ """
25
+
26
+ from __future__ import annotations
27
+
28
+ import os
29
+ import stat
30
+ from dataclasses import dataclass
31
+ from pathlib import Path
32
+ from typing import Any
33
+
34
+ from mostlyright.data_harness.canonical import (
35
+ CanonicalJSONError,
36
+ canonical_json_bytes,
37
+ canonical_sha256,
38
+ parse_canonical_json,
39
+ )
40
+ from mostlyright.data_harness.sources.cadence import (
41
+ CadenceContractError,
42
+ EmpiricalSourceObservation,
43
+ parse_empirical_source_observation,
44
+ validate_observation_history,
45
+ )
46
+ from mostlyright.data_harness.sources.cadence_emission import (
47
+ SOURCE_CADENCE_AUTHORITY_FIELDS,
48
+ SourceCadenceAuthority,
49
+ SourceCadenceEmissionError,
50
+ )
51
+ from mostlyright.data_harness.sources.contracts import (
52
+ AcquisitionRequest,
53
+ decode_options_digest,
54
+ )
55
+ from mostlyright.data_harness.ux.plain_file import (
56
+ MISSING,
57
+ PlainFileRefusal,
58
+ read_plain_file,
59
+ )
60
+
61
+ LOCAL_CADENCE_AUTHORITY_SCHEMA = "harness-local-source-cadence-authority.v1"
62
+ LOCAL_CADENCE_RECORD_SCHEMA = "harness-local-source-cadence-record.v1"
63
+ LOCAL_CADENCE_PROBE_REFUSAL_SCHEMA = "harness-local-source-probe-refusal.v1"
64
+
65
+ #: The contract's own ceiling on one inference history. Refusing at the same number keeps a
66
+ #: folder that can still be read by ``infer_source_cadence`` from being written past the point
67
+ #: where it cannot.
68
+ MAX_LOCAL_OBSERVATIONS = 4_096
69
+ _AUTHORITY_NAME = "authority.json"
70
+ _OBSERVATIONS_NAME = "observations"
71
+ _RECORD_KEYS = frozenset({"schema_version", "observation", "observation_digest", "probe_receipt"})
72
+ # A record is small: one observation, one receipt. The ceiling is a bound on what this reads
73
+ # from a folder another local user may also write to, not a size anything here aims for.
74
+ _MAX_RECORD_BYTES = 1 << 20
75
+
76
+
77
+ class LocalCadenceHistoryError(ValueError):
78
+ """Typed refusal raised by the local observation history."""
79
+
80
+ def __init__(self, code: str, detail: str) -> None:
81
+ self.code = code
82
+ self.detail = detail
83
+ super().__init__(f"{detail} [{code}]")
84
+
85
+
86
+ @dataclass(frozen=True)
87
+ class LocalObservationHistory:
88
+ """One epoch's stored authority and its complete validated observation chain."""
89
+
90
+ directory: Path
91
+ authority: SourceCadenceAuthority
92
+ observations: tuple[EmpiricalSourceObservation, ...]
93
+
94
+ @property
95
+ def next_sequence(self) -> int:
96
+ return len(self.observations)
97
+
98
+ @property
99
+ def previous_observation_digest(self) -> str | None:
100
+ return self.observations[-1].digest if self.observations else None
101
+
102
+ @property
103
+ def latest_acquired(self) -> EmpiricalSourceObservation | None:
104
+ """Return the newest observation that acquired bytes, which is the change baseline.
105
+
106
+ A probe that acquired nothing proves nothing about the content, so it can neither be a
107
+ baseline nor erase one. Reading backwards for the newest acquired fact is what lets a
108
+ failed probe sit between two acquisitions without turning the next one into a change.
109
+ """
110
+
111
+ for observation in reversed(self.observations):
112
+ if observation.content_digest is not None:
113
+ return observation
114
+ return None
115
+
116
+
117
+ def parse_local_cadence_authority(value: Any) -> SourceCadenceAuthority:
118
+ """Parse one operator-stated local cadence authority document."""
119
+
120
+ try:
121
+ return SourceCadenceAuthority.from_mapping(
122
+ value,
123
+ schema_version=LOCAL_CADENCE_AUTHORITY_SCHEMA,
124
+ )
125
+ except SourceCadenceEmissionError as error:
126
+ raise LocalCadenceHistoryError("CADENCE_AUTHORITY_INVALID", error.detail) from error
127
+
128
+
129
+ def require_authority_binds_request(
130
+ authority: SourceCadenceAuthority,
131
+ request: AcquisitionRequest,
132
+ ) -> None:
133
+ """Refuse an authority that does not describe the acquisition it is recording.
134
+
135
+ A local coordinator states the epoch identity, exactly as Studio states it hosted. Two of
136
+ its eleven fields are not statements at all locally, because this side holds the acquisition
137
+ document and can check them. The locator is the canonical query digest: an authority whose
138
+ locator names another address would splice two sources into one history, and the inference
139
+ would read a cadence neither publisher has. The Reader coordinate is the pinned decoder:
140
+ an authority naming a Reader the request did not entitle would attribute this epoch's parse
141
+ to code that never ran.
142
+
143
+ The remaining fields stay statements this side takes as given, the way the hosted producer
144
+ takes Studio's. Recording that difference is the point of checking the two that can be
145
+ checked rather than none.
146
+ """
147
+
148
+ if authority.locator_digest != request.query_digest:
149
+ raise LocalCadenceHistoryError(
150
+ "CADENCE_AUTHORITY_LOCATOR",
151
+ "the cadence authority names a locator other than this request's exact query",
152
+ )
153
+ pin = request.reader_pin
154
+ if pin is None:
155
+ return
156
+ if (
157
+ authority.reader_family_id != pin["family_id"]
158
+ or authority.reader_family_version != pin["family_version"]
159
+ or authority.reader_options_digest != decode_options_digest(pin["decode_options"])
160
+ ):
161
+ raise LocalCadenceHistoryError(
162
+ "CADENCE_AUTHORITY_READER",
163
+ "the cadence authority names a Reader coordinate this request did not entitle",
164
+ )
165
+
166
+
167
+ def probe_refusal_document(
168
+ *,
169
+ source_id: str,
170
+ request_digest: str,
171
+ query_digest: str,
172
+ acquisition_environment: str,
173
+ clean_room_attestation_digest: str,
174
+ external_network_policy_attestation: str,
175
+ refusal_code: str,
176
+ probed_at: str,
177
+ ) -> dict[str, Any]:
178
+ """Seal what a refused probe proves, so its observation has a receipt to bind.
179
+
180
+ Every observation names a probe receipt, because evidence that a probe happened is what
181
+ separates a recorded absence from an assumption. A refused probe acquired nothing, so there
182
+ is no acquisition receipt to name and this document is the receipt: the exact request, the
183
+ confinement it ran in, and the typed code the source interaction returned. It holds no
184
+ response body, no header text, and no acquired fact, because the probe obtained none.
185
+ """
186
+
187
+ return {
188
+ "schema_version": LOCAL_CADENCE_PROBE_REFUSAL_SCHEMA,
189
+ "source_id": source_id,
190
+ "request_digest": request_digest,
191
+ "query_digest": query_digest,
192
+ "acquisition_environment": acquisition_environment,
193
+ "clean_room_attestation_digest": clean_room_attestation_digest,
194
+ "external_network_policy_attestation": external_network_policy_attestation,
195
+ "refusal_code": refusal_code,
196
+ "probed_at": probed_at,
197
+ }
198
+
199
+
200
+ def open_local_history(
201
+ directory: Path,
202
+ *,
203
+ authority: SourceCadenceAuthority | None,
204
+ ) -> LocalObservationHistory:
205
+ """Open or start one local history and return its complete validated chain.
206
+
207
+ ``authority`` is the authority this probe was given. A history that already holds one keeps
208
+ it: the stored bytes decide, and a supplied authority that differs is refused rather than
209
+ merged, because a differing authority is a different epoch and the contract never combines
210
+ two epochs into one inference.
211
+ """
212
+
213
+ root = _require_history_directory(directory)
214
+ stored = _read_authority(root)
215
+ if stored is None:
216
+ if authority is None:
217
+ raise LocalCadenceHistoryError(
218
+ "CADENCE_AUTHORITY_REQUIRED",
219
+ "this history holds no authority yet, so the first probe has to state one",
220
+ )
221
+ try:
222
+ _write_exclusive(root / _AUTHORITY_NAME, canonical_json_bytes(authority.to_dict()))
223
+ except FileExistsError as error:
224
+ raise LocalCadenceHistoryError(
225
+ "CADENCE_AUTHORITY_EXISTS",
226
+ "another probe stated this history's epoch identity first",
227
+ ) from error
228
+ stored = authority
229
+ elif authority is not None and authority.to_dict() != stored.to_dict():
230
+ raise LocalCadenceHistoryError(
231
+ "CADENCE_AUTHORITY_CHANGED",
232
+ "this history was recorded under a different epoch identity",
233
+ )
234
+ observations = _read_observations(root, stored)
235
+ return LocalObservationHistory(directory=root, authority=stored, observations=observations)
236
+
237
+
238
+ def append_local_observation(
239
+ history: LocalObservationHistory,
240
+ observation: EmpiricalSourceObservation,
241
+ probe_receipt: dict[str, Any],
242
+ ) -> LocalObservationHistory:
243
+ """Append one probe record and return the extended, revalidated history."""
244
+
245
+ if observation.sequence != history.next_sequence:
246
+ raise LocalCadenceHistoryError(
247
+ "CADENCE_HISTORY_SEQUENCE",
248
+ "the observation does not continue this history",
249
+ )
250
+ if len(history.observations) >= MAX_LOCAL_OBSERVATIONS:
251
+ raise LocalCadenceHistoryError(
252
+ "CADENCE_HISTORY_FULL",
253
+ "this history already holds every observation one inference may read",
254
+ )
255
+ _require_no_record_beyond(history)
256
+ receipt_digest = canonical_sha256(probe_receipt)
257
+ if receipt_digest != observation.probe_receipt_digest:
258
+ raise LocalCadenceHistoryError(
259
+ "CADENCE_RECEIPT_BINDING",
260
+ "the observation does not name the probe receipt recorded beside it",
261
+ )
262
+ extended = (*history.observations, observation)
263
+ try:
264
+ validate_observation_history(extended)
265
+ except CadenceContractError as error:
266
+ raise LocalCadenceHistoryError("CADENCE_HISTORY_INVALID", error.detail) from error
267
+ record = {
268
+ "schema_version": LOCAL_CADENCE_RECORD_SCHEMA,
269
+ "observation": observation.to_dict(),
270
+ "observation_digest": observation.digest,
271
+ "probe_receipt": dict(probe_receipt),
272
+ }
273
+ observations_root = history.directory / _OBSERVATIONS_NAME
274
+ _make_directory(observations_root)
275
+ try:
276
+ _write_exclusive(
277
+ observations_root / _record_name(observation.sequence),
278
+ canonical_json_bytes(record),
279
+ )
280
+ except FileExistsError as error:
281
+ raise LocalCadenceHistoryError(
282
+ "CADENCE_RECORD_EXISTS",
283
+ "another probe was recorded into this history while this one ran",
284
+ ) from error
285
+ return LocalObservationHistory(
286
+ directory=history.directory,
287
+ authority=history.authority,
288
+ observations=extended,
289
+ )
290
+
291
+
292
+ def _require_no_record_beyond(history: LocalObservationHistory) -> None:
293
+ """Refuse to append when the folder holds a record this history did not read.
294
+
295
+ A read stops at the first missing sequence, which leaves two ways the folder can hold more
296
+ than the history does, and both are refusals.
297
+
298
+ A record at exactly the next coordinate appeared after this history was read, which is a
299
+ second probe of the same source running at the same time. A record *past* it means the read
300
+ stopped at a gap -- an entry removed or never written -- while later entries are still on
301
+ disk. Appending into that gap would write a new sequence the survivors no longer bind, and
302
+ every read afterwards would refuse the chain permanently, because the predecessor they name
303
+ would never exist again.
304
+
305
+ The folder is read once rather than one coordinate probed, because the gap case is exactly
306
+ the one a single probe of the next name cannot see.
307
+ """
308
+
309
+ observations_root = history.directory / _OBSERVATIONS_NAME
310
+ try:
311
+ names = {item.name for item in observations_root.iterdir()}
312
+ except FileNotFoundError:
313
+ return
314
+ except OSError as error:
315
+ raise LocalCadenceHistoryError(
316
+ "CADENCE_HISTORY_UNREADABLE",
317
+ f"the cadence history folder could not be read: {error.strerror or error}",
318
+ ) from error
319
+ beyond = [
320
+ sequence
321
+ for sequence in range(history.next_sequence, MAX_LOCAL_OBSERVATIONS + 1)
322
+ if _record_name(sequence) in names
323
+ ]
324
+ if not beyond:
325
+ return
326
+ if beyond == [history.next_sequence]:
327
+ raise LocalCadenceHistoryError(
328
+ "CADENCE_RECORD_EXISTS",
329
+ "another probe was recorded into this history while this one ran",
330
+ )
331
+ raise LocalCadenceHistoryError(
332
+ "CADENCE_HISTORY_INCOMPLETE",
333
+ "this history holds records past the point it can be read from",
334
+ )
335
+
336
+
337
+ def _record_name(sequence: int) -> str:
338
+ return f"{sequence:010d}.json"
339
+
340
+
341
+ def _require_history_directory(directory: Path) -> Path:
342
+ root = directory.absolute()
343
+ _make_directory(root)
344
+ return root
345
+
346
+
347
+ def _make_directory(path: Path) -> None:
348
+ try:
349
+ path.mkdir(mode=0o700, parents=True, exist_ok=True)
350
+ except OSError as error:
351
+ raise LocalCadenceHistoryError(
352
+ "CADENCE_HISTORY_UNWRITABLE",
353
+ f"the cadence history folder could not be created: {error.strerror or error}",
354
+ ) from error
355
+ # ``lstat`` rather than ``stat``: a link that points at a folder reports a folder through
356
+ # the link, and this has to be a folder this command created or already owns. One test is
357
+ # enough -- a mode is a link or a folder and never both -- so a second ``S_ISLNK`` clause
358
+ # here would be a guard that can never fire.
359
+ if not stat.S_ISDIR(path.lstat().st_mode):
360
+ raise LocalCadenceHistoryError(
361
+ "CADENCE_HISTORY_UNWRITABLE",
362
+ "the cadence history path is not a folder this command can own",
363
+ )
364
+
365
+
366
+ def _write_exclusive(path: Path, payload: bytes) -> None:
367
+ """Create one file, or let the collision reach the caller that can name it.
368
+
369
+ ``O_EXCL`` is the append-only rule. A name that already exists was written by somebody --
370
+ a second probe racing this one, or a second first probe of the same history -- and both are
371
+ refusals rather than overwrites, because what is already there is somebody's evidence.
372
+
373
+ ``FileExistsError`` is deliberately not turned into a typed refusal here. An authority
374
+ written twice and a record written twice are different events with different repairs, so
375
+ each caller raises its own code, written as a literal at its own raise. A code passed in as
376
+ an argument would be a code the repository's typed-code completeness gates cannot see, and
377
+ this repository has been caught by that shape twice already.
378
+ """
379
+
380
+ try:
381
+ descriptor = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
382
+ except OSError as error:
383
+ raise LocalCadenceHistoryError(
384
+ "CADENCE_HISTORY_UNWRITABLE",
385
+ f"the cadence record could not be created: {error.strerror or error}",
386
+ ) from error
387
+ try:
388
+ with os.fdopen(descriptor, "wb") as handle:
389
+ handle.write(payload)
390
+ handle.flush()
391
+ os.fsync(handle.fileno())
392
+ except OSError as error:
393
+ raise LocalCadenceHistoryError(
394
+ "CADENCE_HISTORY_UNWRITABLE",
395
+ f"the cadence record could not be written: {error.strerror or error}",
396
+ ) from error
397
+
398
+
399
+ def _read_document(path: Path) -> Any:
400
+ """Read one stored record, under the open-then-fstat rule every named file is read by.
401
+
402
+ A history folder is an ordinary folder another local user may also write to, so a record is
403
+ read as a bounded plain file rather than by size-then-read, and the bytes have to be the exact
404
+ canonical encoding of what they decode to. A record that is not is not evidence: canonical
405
+ bytes are what its digests were taken over.
406
+ """
407
+
408
+ try:
409
+ raw = read_plain_file(path, max_bytes=_MAX_RECORD_BYTES)
410
+ except PlainFileRefusal as refusal:
411
+ if refusal.reason == MISSING:
412
+ return None
413
+ raise LocalCadenceHistoryError(
414
+ "CADENCE_HISTORY_UNREADABLE",
415
+ f"a cadence history entry is {refusal.reason} and cannot be read as a record",
416
+ ) from None
417
+ except OSError as error:
418
+ raise LocalCadenceHistoryError(
419
+ "CADENCE_HISTORY_UNREADABLE",
420
+ f"a cadence history file could not be read: {error.strerror or error}",
421
+ ) from error
422
+ try:
423
+ value = parse_canonical_json(raw)
424
+ except CanonicalJSONError as error:
425
+ raise LocalCadenceHistoryError(
426
+ "CADENCE_HISTORY_UNREADABLE",
427
+ "a cadence history file is not the exact canonical bytes it was written as",
428
+ ) from error
429
+ if not isinstance(value, dict):
430
+ raise LocalCadenceHistoryError(
431
+ "CADENCE_HISTORY_UNREADABLE",
432
+ "a cadence history file does not hold a document",
433
+ )
434
+ return value
435
+
436
+
437
+ def _read_authority(root: Path) -> SourceCadenceAuthority | None:
438
+ value = _read_document(root / _AUTHORITY_NAME)
439
+ if value is None:
440
+ return None
441
+ if set(value) != SOURCE_CADENCE_AUTHORITY_FIELDS:
442
+ raise LocalCadenceHistoryError(
443
+ "CADENCE_AUTHORITY_INVALID",
444
+ "the stored cadence authority does not have the exact versioned key set",
445
+ )
446
+ return parse_local_cadence_authority(value)
447
+
448
+
449
+ def _read_observations(
450
+ root: Path,
451
+ authority: SourceCadenceAuthority,
452
+ ) -> tuple[EmpiricalSourceObservation, ...]:
453
+ """Re-admit every stored record in sequence and validate the chain it forms.
454
+
455
+ Names are derived rather than listed: a record is read at the coordinate it must occupy, so
456
+ a file dropped into the folder under some other name is not evidence and a gap ends the
457
+ history rather than being skipped over.
458
+ """
459
+
460
+ observations_root = root / _OBSERVATIONS_NAME
461
+ if not observations_root.exists():
462
+ return ()
463
+ observations: list[EmpiricalSourceObservation] = []
464
+ while len(observations) < MAX_LOCAL_OBSERVATIONS:
465
+ value = _read_document(observations_root / _record_name(len(observations)))
466
+ if value is None:
467
+ break
468
+ observations.append(_parse_record(value, sequence=len(observations), authority=authority))
469
+ if (observations_root / _record_name(len(observations))).exists():
470
+ raise LocalCadenceHistoryError(
471
+ "CADENCE_HISTORY_FULL",
472
+ "this history holds more observations than one inference may read",
473
+ )
474
+ try:
475
+ return validate_observation_history(tuple(observations))
476
+ except CadenceContractError as error:
477
+ raise LocalCadenceHistoryError("CADENCE_HISTORY_INVALID", error.detail) from error
478
+
479
+
480
+ def _parse_record(
481
+ value: dict[str, Any],
482
+ *,
483
+ sequence: int,
484
+ authority: SourceCadenceAuthority,
485
+ ) -> EmpiricalSourceObservation:
486
+ if set(value) != _RECORD_KEYS or value["schema_version"] != LOCAL_CADENCE_RECORD_SCHEMA:
487
+ raise LocalCadenceHistoryError(
488
+ "CADENCE_RECORD_INVALID",
489
+ "a cadence record does not have the exact versioned key set",
490
+ )
491
+ receipt = value["probe_receipt"]
492
+ if not isinstance(receipt, dict):
493
+ raise LocalCadenceHistoryError(
494
+ "CADENCE_RECORD_INVALID",
495
+ "a cadence record carries no probe receipt",
496
+ )
497
+ try:
498
+ observation = parse_empirical_source_observation(value["observation"])
499
+ except (CadenceContractError, TypeError, ValueError) as error:
500
+ raise LocalCadenceHistoryError(
501
+ "CADENCE_RECORD_INVALID",
502
+ "a cadence record does not hold an exact observation",
503
+ ) from error
504
+ if observation.digest != value["observation_digest"] or observation.sequence != sequence:
505
+ raise LocalCadenceHistoryError(
506
+ "CADENCE_RECORD_INVALID",
507
+ "a cadence record does not bind the observation stored in it",
508
+ )
509
+ if canonical_sha256(receipt) != observation.probe_receipt_digest:
510
+ raise LocalCadenceHistoryError(
511
+ "CADENCE_RECEIPT_BINDING",
512
+ "a cadence record does not name the probe receipt stored beside it",
513
+ )
514
+ if (
515
+ observation.inference_epoch != authority.inference_epoch
516
+ or observation.connector_configuration_digest != authority.connector_configuration_digest
517
+ or observation.locator_digest != authority.locator_digest
518
+ or observation.recipe_digest != authority.recipe_digest
519
+ or observation.source_authority_digest != authority.source_authority_digest
520
+ or observation.reader_family_id != authority.reader_family_id
521
+ or observation.reader_family_version != authority.reader_family_version
522
+ or observation.reader_options_digest != authority.reader_options_digest
523
+ or observation.frontier_policy_digest != authority.frontier_policy_digest
524
+ or observation.time_interpretation_digest != authority.time_interpretation_digest
525
+ or observation.inference_algorithm_digest != authority.inference_algorithm_digest
526
+ ):
527
+ raise LocalCadenceHistoryError(
528
+ "CADENCE_RECORD_INVALID",
529
+ "a cadence record was recorded under a different epoch identity",
530
+ )
531
+ return observation
532
+
533
+
534
+ __all__ = [
535
+ "LOCAL_CADENCE_AUTHORITY_SCHEMA",
536
+ "LOCAL_CADENCE_PROBE_REFUSAL_SCHEMA",
537
+ "LOCAL_CADENCE_RECORD_SCHEMA",
538
+ "MAX_LOCAL_OBSERVATIONS",
539
+ "LocalCadenceHistoryError",
540
+ "LocalObservationHistory",
541
+ "append_local_observation",
542
+ "open_local_history",
543
+ "parse_local_cadence_authority",
544
+ "probe_refusal_document",
545
+ "require_authority_binds_request",
546
+ ]
@@ -0,0 +1,17 @@
1
+ """Source-catalog subpackage: versioned facts about public sources.
2
+
3
+ This package intentionally carries **no re-exports**. Consumers import the concrete module they
4
+ need (``...sources.catalog.contracts``, and later ``retrieval`` and ``gating``). Two reasons:
5
+
6
+ 1. Retrieval and gating must never share a namespace. Similarity *finds* candidates; structured
7
+ facts *gate* decisions. If both were re-exported here, a gating caller would sit one attribute
8
+ access away from a similarity score, and the separation would become a convention rather than
9
+ a module boundary.
10
+ 2. A package ``__init__`` that names every module is a single contended file. Keeping it empty of
11
+ imports lets the catalog modules land independently.
12
+
13
+ Everything in this package describes **public** sources only. No module here may carry a dataset,
14
+ a recipe, a Reader, or anything learned from a tenant's private source.
15
+ """
16
+
17
+ from __future__ import annotations