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,532 @@
1
+ """Pluggable embedding backends, and the local integer encoder the catalog ships with.
2
+
3
+ Similarity finds candidates. Facts decide. Nothing in this module ever gates anything, and the
4
+ gating path never imports it.
5
+
6
+ Three properties are load-bearing.
7
+
8
+ **A backend is a seam, not a dependency.** ``EmbeddingBackend`` is a protocol and
9
+ ``BackendRegistry`` is an allowlist in the same shape as the coordinator's adapter allowlist, so a
10
+ better encoder can be dropped in later. The default one, ``LexicalHashingBackend``, is pure
11
+ standard library: no network, no weights, no filesystem, no process spawn. A backend that cannot
12
+ say that about itself registers with ``query_safe=False`` and a catalog sealed by it refuses to
13
+ load at query time. ``DEFAULT_BACKENDS`` -- the allowlist the query-time load path falls back to --
14
+ is sealed at construction, so that fallback cannot be widened at run time by an importer; a
15
+ different inventory is a registry you build and pass, visibly, at the call site.
16
+
17
+ **No IEEE-754 arithmetic anywhere.** Every step from text to vector is integer: sha256 bucketing,
18
+ an integer signed accumulator, ``math.isqrt`` for the norm, and integer round-half-away-from-zero
19
+ for the scaling. That is not fastidiousness. A vector that differs in its last bit between arm64
20
+ and x86_64 would make retrieval host-dependent, and the digest authority refuses non-integer JSON
21
+ numbers outright, so a real number could never be sealed even if one were computed. A test reads
22
+ this module's own syntax tree and fails if a division, a square root, or the name of the
23
+ real-number type appears in it.
24
+
25
+ **One bounded seam carries provider-scale encoding.** ``encode_many`` is the only entry point a
26
+ provider-scale publisher may use, and it is a bounded loop over the same scalar ``encode`` rather
27
+ than a second encoder: at most 1000 items and 8 MiB of aggregate UTF-8 per invocation, one exact
28
+ vector per input in input order, all-or-nothing, and a counter record the seam mints from work it
29
+ measured itself. Nothing about it is faster than the scalar path, which is the honest position --
30
+ no native batch was measured on either declared runtime tuple, so none is offered and none is
31
+ claimed to be equivalent.
32
+ """
33
+
34
+ from __future__ import annotations
35
+
36
+ import hashlib
37
+ import math
38
+ import re
39
+ from dataclasses import dataclass
40
+ from typing import Any, Protocol
41
+
42
+ from mostlyright.data_harness.sources.catalog.contracts import QUANTIZATIONS
43
+ from mostlyright.data_harness.sources.contracts import SourceContractError
44
+
45
+ DIMENSIONS = 256
46
+ SCALE = 10_000
47
+ MAX_ENCODE_CHARS = 100_000
48
+ MIN_SUBTOKEN_SOURCE = 5
49
+ SUBTOKEN_LENGTH = 4
50
+
51
+ # The bounds on one outer `encode_many` call. Both are hard: a publisher that has more work than
52
+ # this issues more invocations, each one separately bounded and separately metered.
53
+ MAX_BATCH_ITEMS = 1_000
54
+ MAX_BATCH_UTF8_BYTES = 8 * 1024 * 1024
55
+
56
+ #: The only encoding-adapter mode that exists. It is a fixed property of this seam rather than a
57
+ #: caller-selectable option: every backend behind `encode_many` runs the same bounded scalar loop.
58
+ BOUNDED_SCALAR_ADAPTER = "bounded_scalar_adapter"
59
+
60
+ _TOKEN = re.compile(r"[a-z0-9]+")
61
+ _IDENTIFIER = re.compile(r"^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$")
62
+ _SEMVER = re.compile(r"^[1-9][0-9]*\.[0-9]+\.[0-9]+$")
63
+
64
+
65
+ def _identifier(value: Any, path: str) -> str:
66
+ if not isinstance(value, str) or not _IDENTIFIER.fullmatch(value):
67
+ raise SourceContractError(
68
+ "IDENTIFIER",
69
+ path,
70
+ "must be a lowercase dotted/dashed/underscored identifier",
71
+ )
72
+ return value
73
+
74
+
75
+ def _semver(value: Any, path: str) -> str:
76
+ if not isinstance(value, str) or not _SEMVER.fullmatch(value):
77
+ raise SourceContractError("SEMVER", path, "must be a positive-major semantic version")
78
+ return value
79
+
80
+
81
+ @dataclass(frozen=True)
82
+ class BackendDescriptor:
83
+ """The immutable identity of one embedding backend.
84
+
85
+ ``query_safe`` is the query-time trust boundary. It is true only for a backend that is *pure*:
86
+ it opens no socket, reads no file, loads no weights, spawns no process, and calls no paid API.
87
+ A remote or weight-loading backend must register with ``query_safe=False``; a catalog sealed
88
+ by such a backend is then refused by the query-time load path rather than quietly pulling a
89
+ model onto the runtime path.
90
+ """
91
+
92
+ backend_id: str
93
+ backend_version: str
94
+ dimensions: int
95
+ quantization: str
96
+ query_safe: bool
97
+
98
+ def __post_init__(self) -> None:
99
+ _identifier(self.backend_id, "backend.backend_id")
100
+ _semver(self.backend_version, "backend.backend_version")
101
+ if type(self.dimensions) is not int or not 1 <= self.dimensions <= 4_096:
102
+ raise SourceContractError(
103
+ "INTEGER",
104
+ "backend.dimensions",
105
+ "must be an integer in [1, 4096]",
106
+ )
107
+ if self.quantization not in QUANTIZATIONS:
108
+ raise SourceContractError(
109
+ "ENUM",
110
+ "backend.quantization",
111
+ f"must be one of {sorted(QUANTIZATIONS)}",
112
+ )
113
+ if type(self.query_safe) is not bool:
114
+ raise SourceContractError("BOOLEAN", "backend.query_safe", "must be a boolean")
115
+
116
+ @property
117
+ def coordinate(self) -> str:
118
+ return f"{self.backend_id}@{self.backend_version}"
119
+
120
+
121
+ @dataclass(frozen=True)
122
+ class PinnedLocalBackendDescriptor(BackendDescriptor):
123
+ """Explicit v2 identity for a verified local-model sidecar.
124
+
125
+ This is deliberately not a reinterpretation of ``query_safe``. A local model reads governed
126
+ sidecar bytes and loads an optional runtime, so it remains false and cannot enter a v1 sealed
127
+ index. The v2 caller must select the resolver explicitly and receives the root, PIN, artifact,
128
+ and supported runtime-tuple coordinate it selected.
129
+ """
130
+
131
+ model_root: str
132
+ pin_sha256: str
133
+ coordinate_sha256: str
134
+ runtime_tuple: str
135
+ runtime_closure_sha256: str
136
+ artifact_sha256s: tuple[tuple[str, str], ...]
137
+
138
+ def __post_init__(self) -> None:
139
+ super().__post_init__()
140
+ if self.query_safe:
141
+ raise SourceContractError(
142
+ "NEURAL_QUERY_SAFE",
143
+ "backend.query_safe",
144
+ "a sidecar-loading backend cannot claim the v1 query-safe capability",
145
+ )
146
+ if not isinstance(self.model_root, str) or not self.model_root.startswith("/"):
147
+ raise SourceContractError(
148
+ "NEURAL_MODEL_ROOT_ABSOLUTE",
149
+ "backend.model_root",
150
+ "must be an absolute caller-supplied path",
151
+ )
152
+ for value, path in (
153
+ (self.pin_sha256, "backend.pin_sha256"),
154
+ (self.coordinate_sha256, "backend.coordinate_sha256"),
155
+ (self.runtime_closure_sha256, "backend.runtime_closure_sha256"),
156
+ ):
157
+ if not isinstance(value, str) or re.fullmatch(r"[0-9a-f]{64}", value) is None:
158
+ raise SourceContractError("SHA256", path, "must be a lowercase SHA-256 digest")
159
+ _identifier(self.runtime_tuple, "backend.runtime_tuple")
160
+ if (
161
+ not self.artifact_sha256s
162
+ or tuple(sorted(self.artifact_sha256s)) != self.artifact_sha256s
163
+ ):
164
+ raise SourceContractError(
165
+ "NEURAL_ARTIFACT_COORDINATE",
166
+ "backend.artifact_sha256s",
167
+ "must be a non-empty path-sorted artifact coordinate",
168
+ )
169
+ for path, digest in self.artifact_sha256s:
170
+ if not isinstance(path, str) or not path or "/" in path or "\\" in path:
171
+ raise SourceContractError(
172
+ "NEURAL_ARTIFACT_COORDINATE",
173
+ "backend.artifact_sha256s",
174
+ "artifact paths must be single safe names",
175
+ )
176
+ if not isinstance(digest, str) or re.fullmatch(r"[0-9a-f]{64}", digest) is None:
177
+ raise SourceContractError(
178
+ "NEURAL_ARTIFACT_COORDINATE",
179
+ "backend.artifact_sha256s",
180
+ "artifact digests must be lowercase SHA-256 values",
181
+ )
182
+
183
+ @property
184
+ def coordinate(self) -> str:
185
+ return (
186
+ f"{self.backend_id}@{self.backend_version}"
187
+ f"#{self.runtime_tuple}:{self.coordinate_sha256}:{self.runtime_closure_sha256}"
188
+ )
189
+
190
+
191
+ @dataclass(frozen=True)
192
+ class BatchEncodeResult:
193
+ """One outer bounded encoding invocation: its vectors, and the work it metered doing them.
194
+
195
+ The counters are the point. A provider-scale publisher has to state how much encoding a
196
+ generation cost, and a total it computes from its own intentions proves nothing -- it would
197
+ reconcile with itself whether or not the encoder ran. So this record is minted by
198
+ ``encode_many`` from work it observed: ``batch_invocations`` is always exactly one because this
199
+ record *is* one invocation, ``scalar_invocations`` is the number of times the underlying scalar
200
+ ``encode`` was actually called, and ``encoded_utf8_bytes`` is the aggregate the seam measured
201
+ before it encoded anything. A publisher spanning several invocations sums ordered records; it
202
+ never authors one.
203
+
204
+ ``adapter_mode`` is fixed. It exists so the publication evidence says out loud which
205
+ implementation produced the vectors, and there is exactly one: the bounded scalar adapter. No
206
+ native batching was measured on either declared runtime tuple, so no other mode may be recorded
207
+ here, and a record claiming one is refused rather than believed.
208
+ """
209
+
210
+ adapter_mode: str
211
+ backend_coordinate: str
212
+ vectors: tuple[tuple[int, ...], ...]
213
+ batch_invocations: int
214
+ scalar_invocations: int
215
+ encoded_utf8_bytes: int
216
+
217
+ def __post_init__(self) -> None:
218
+ if self.adapter_mode != BOUNDED_SCALAR_ADAPTER:
219
+ raise SourceContractError(
220
+ "EMBEDDING_BATCH_ADAPTER",
221
+ "embedding.batch.adapter_mode",
222
+ f"the only encoding adapter is {BOUNDED_SCALAR_ADAPTER!r}",
223
+ )
224
+ if not isinstance(self.backend_coordinate, str) or not self.backend_coordinate:
225
+ raise SourceContractError(
226
+ "EMBEDDING_BATCH_COUNTER",
227
+ "embedding.batch.backend_coordinate",
228
+ "the invocation must name the exact backend coordinate that produced it",
229
+ )
230
+ if type(self.vectors) is not tuple or not 1 <= len(self.vectors) <= MAX_BATCH_ITEMS:
231
+ raise SourceContractError(
232
+ "EMBEDDING_BATCH_COUNTER",
233
+ "embedding.batch.vectors",
234
+ f"one invocation carries 1 to {MAX_BATCH_ITEMS} vectors",
235
+ )
236
+ if type(self.batch_invocations) is not int or self.batch_invocations != 1:
237
+ raise SourceContractError(
238
+ "EMBEDDING_BATCH_COUNTER",
239
+ "embedding.batch.batch_invocations",
240
+ "one counter record accounts for exactly one outer batch invocation",
241
+ )
242
+ if type(self.scalar_invocations) is not int or self.scalar_invocations != len(self.vectors):
243
+ raise SourceContractError(
244
+ "EMBEDDING_BATCH_COUNTER",
245
+ "embedding.batch.scalar_invocations",
246
+ "the bounded scalar adapter invokes scalar encode exactly once per item",
247
+ )
248
+ if (
249
+ type(self.encoded_utf8_bytes) is not int
250
+ or not 0 <= self.encoded_utf8_bytes <= MAX_BATCH_UTF8_BYTES
251
+ ):
252
+ raise SourceContractError(
253
+ "EMBEDDING_BATCH_COUNTER",
254
+ "embedding.batch.encoded_utf8_bytes",
255
+ f"metered input bytes must be in [0, {MAX_BATCH_UTF8_BYTES}]",
256
+ )
257
+
258
+
259
+ class EmbeddingBackend(Protocol):
260
+ """One way of turning text into a sealed integer vector."""
261
+
262
+ @property
263
+ def descriptor(self) -> BackendDescriptor:
264
+ """Return the immutable backend identity."""
265
+
266
+ def encode(self, text: str) -> tuple[int, ...]:
267
+ """Return this text's quantized vector, of exactly ``descriptor.dimensions`` integers."""
268
+
269
+ def encode_many(self, texts: tuple[str, ...] | list[str]) -> BatchEncodeResult:
270
+ """Return one exact vector per input, in order, with this invocation's own counters."""
271
+
272
+
273
+ def encode_many_bounded(
274
+ backend: EmbeddingBackend, texts: tuple[str, ...] | list[str]
275
+ ) -> BatchEncodeResult:
276
+ """The one bounded provider-scale seam: a scalar loop, in order, with metered work.
277
+
278
+ Every backend's ``encode_many`` is this function. That is deliberate. A per-backend batch
279
+ implementation is where a batch stops being equal to its scalar equivalent -- padding to the
280
+ longest member of a batch, a different reduction order, a runtime kernel selected by shape --
281
+ and no cross-platform receipt proves that any of those still produce the sealed bytes.
282
+ A loop needs no such receipt: the vectors are the scalar vectors, because they *are* the scalar
283
+ vectors.
284
+
285
+ Two things are metered separately and neither is inferred from the other. Aggregate UTF-8 bytes
286
+ are counted first, over the whole input, before a single item is encoded, so an oversized batch
287
+ costs nothing to refuse. Underlying scalar invocations are then counted as they happen, so the
288
+ reported count is an observation rather than ``len(texts)`` restated.
289
+
290
+ The seam is all-or-nothing. A typed refusal from the scalar encoder -- a deadline, a lost
291
+ worker, an over-long item -- propagates unchanged and no partial batch is returned, because a
292
+ publisher that received nine of ten vectors would have no honest way to say so.
293
+ """
294
+
295
+ if type(texts) is not tuple and type(texts) is not list:
296
+ raise SourceContractError(
297
+ "EMBEDDING_BATCH_SEQUENCE",
298
+ "embedding.texts",
299
+ "must be a materialized tuple or list of texts, not a string, mapping, or iterator",
300
+ )
301
+ items = tuple(texts)
302
+ if not items:
303
+ raise SourceContractError(
304
+ "EMBEDDING_BATCH_EMPTY",
305
+ "embedding.texts",
306
+ "one invocation encodes at least one text",
307
+ )
308
+ if len(items) > MAX_BATCH_ITEMS:
309
+ raise SourceContractError(
310
+ "EMBEDDING_BATCH_ITEM_LIMIT",
311
+ "embedding.texts",
312
+ f"one invocation encodes at most {MAX_BATCH_ITEMS} texts",
313
+ )
314
+
315
+ encoded_utf8_bytes = 0
316
+ for position, text in enumerate(items):
317
+ if type(text) is not str:
318
+ raise SourceContractError(
319
+ "EMBEDDING_BATCH_ITEM_TYPE",
320
+ f"embedding.texts[{position}]",
321
+ "every item must be a string",
322
+ )
323
+ encoded_utf8_bytes += len(text.encode("utf-8"))
324
+ if encoded_utf8_bytes > MAX_BATCH_UTF8_BYTES:
325
+ raise SourceContractError(
326
+ "EMBEDDING_BATCH_BYTE_LIMIT",
327
+ "embedding.texts",
328
+ f"one invocation encodes at most {MAX_BATCH_UTF8_BYTES} aggregate UTF-8 bytes",
329
+ )
330
+
331
+ dimensions = backend.descriptor.dimensions
332
+ vectors: list[tuple[int, ...]] = []
333
+ first_seen: dict[str, tuple[int, ...]] = {}
334
+ scalar_invocations = 0
335
+ for position, text in enumerate(items):
336
+ vector = backend.encode(text)
337
+ scalar_invocations += 1
338
+ if (
339
+ type(vector) is not tuple
340
+ or len(vector) != dimensions
341
+ or any(type(value) is not int for value in vector)
342
+ ):
343
+ raise SourceContractError(
344
+ "EMBEDDING_BATCH_RESULT",
345
+ f"embedding.vectors[{position}]",
346
+ f"each scalar result must be exactly {dimensions} integers",
347
+ )
348
+ # A repeated text must receive its own identical vector. The encoder is deterministic, so
349
+ # a disagreement here is a result arriving against the wrong request -- a reordered or
350
+ # stale response -- which is the one mis-binding a serial loop cannot otherwise see.
351
+ if first_seen.setdefault(text, vector) != vector:
352
+ raise SourceContractError(
353
+ "EMBEDDING_BATCH_ORDER",
354
+ f"embedding.vectors[{position}]",
355
+ "a repeated text received a different vector, so results are not in input order",
356
+ )
357
+ vectors.append(vector)
358
+
359
+ if len(vectors) != len(items) or scalar_invocations != len(items):
360
+ raise SourceContractError(
361
+ "EMBEDDING_BATCH_RESULT",
362
+ "embedding.vectors",
363
+ "the invocation produced a partial result set",
364
+ )
365
+ return BatchEncodeResult(
366
+ adapter_mode=BOUNDED_SCALAR_ADAPTER,
367
+ backend_coordinate=backend.descriptor.coordinate,
368
+ vectors=tuple(vectors),
369
+ batch_invocations=1,
370
+ scalar_invocations=scalar_invocations,
371
+ encoded_utf8_bytes=encoded_utf8_bytes,
372
+ )
373
+
374
+
375
+ def resolve_local_neural_backend(
376
+ model_root: Any,
377
+ ) -> EmbeddingBackend:
378
+ """Resolve the governed v2 neural backend from one explicit sidecar root.
379
+
380
+ The exact module name is the allowlisted boundary. A built-in dynamic import keeps this module
381
+ and all lexical/query imports free of the optional runtime. Resolution prepares the
382
+ authenticated private worker before returning, so each later ``encode`` call covers inference
383
+ only.
384
+ """
385
+
386
+ module = __import__(
387
+ "mostlyright.data_harness.sources.catalog.neural",
388
+ fromlist=("resolve_local_neural_backend",),
389
+ )
390
+ return module.resolve_local_neural_backend(model_root)
391
+
392
+
393
+ class BackendRegistry:
394
+ """Allowlist of embedding backends, in the shape of the coordinator's adapter allowlist.
395
+
396
+ ``sealed`` closes the allowlist to further registration. It exists for one instance --
397
+ ``DEFAULT_BACKENDS``, the registry ``SealedEmbeddingIndex.load`` resolves against when a caller
398
+ names none. A process-global whose membership any
399
+ importer can widen at run time is not a control: widening it with a ``query_safe=True``
400
+ descriptor is all it would take to make ``load`` accept a catalog sealed by a backend that
401
+ opens a socket. A caller that genuinely wants a different inventory builds its own registry and
402
+ passes it, which is a visible act at the call site rather than an invisible one at import time.
403
+
404
+ Sealing is one-way and set at construction. There is no unseal.
405
+ """
406
+
407
+ def __init__(
408
+ self,
409
+ backends: tuple[EmbeddingBackend, ...] = (),
410
+ *,
411
+ sealed: bool = False,
412
+ ) -> None:
413
+ self._backends: dict[tuple[str, str], EmbeddingBackend] = {}
414
+ self._sealed = False
415
+ for backend in backends:
416
+ self.register(backend)
417
+ if type(sealed) is not bool:
418
+ raise SourceContractError("BOOLEAN", "registry.sealed", "must be a boolean")
419
+ self._sealed = sealed
420
+
421
+ @property
422
+ def sealed(self) -> bool:
423
+ """Whether this allowlist is closed to further registration."""
424
+
425
+ return self._sealed
426
+
427
+ def register(self, backend: EmbeddingBackend) -> None:
428
+ if self._sealed:
429
+ raise SourceContractError(
430
+ "EMBEDDING_BACKEND_REGISTRY_SEALED",
431
+ "registry",
432
+ "this backend allowlist is sealed and cannot be widened; build your own registry "
433
+ "and pass it explicitly instead",
434
+ )
435
+ descriptor = backend.descriptor
436
+ if not isinstance(descriptor, BackendDescriptor):
437
+ raise SourceContractError(
438
+ "EMBEDDING_BACKEND_DESCRIPTOR",
439
+ "backend.descriptor",
440
+ "backend descriptor must use the strict contract",
441
+ )
442
+ key = (descriptor.backend_id, descriptor.backend_version)
443
+ if key in self._backends:
444
+ raise SourceContractError(
445
+ "EMBEDDING_BACKEND_DUPLICATE",
446
+ "registry",
447
+ f"backend {descriptor.coordinate} is already registered",
448
+ )
449
+ self._backends[key] = backend
450
+
451
+ def resolve(self, backend_id: str, backend_version: str) -> EmbeddingBackend:
452
+ try:
453
+ return self._backends[(backend_id, backend_version)]
454
+ except KeyError:
455
+ raise SourceContractError(
456
+ "EMBEDDING_BACKEND_UNAVAILABLE",
457
+ "vector.backend_id",
458
+ f"backend {backend_id}@{backend_version} is not allowlisted",
459
+ ) from None
460
+
461
+ def inventory(self) -> tuple[BackendDescriptor, ...]:
462
+ return tuple(self._backends[key].descriptor for key in sorted(self._backends))
463
+
464
+
465
+ class LexicalHashingBackend:
466
+ """The default local encoder: hashed unigrams plus character 4-grams, integer-quantized.
467
+
468
+ The 4-grams are a cheap stemming surrogate. They are what lets a query phrased as "produce"
469
+ reach a description that says "production" without a stemmer, a stopword list, or a model.
470
+ """
471
+
472
+ _DESCRIPTOR = BackendDescriptor(
473
+ backend_id="lexical_hashing",
474
+ backend_version="1.0.0",
475
+ dimensions=DIMENSIONS,
476
+ quantization="int32_fixed_point_10000",
477
+ query_safe=True,
478
+ )
479
+
480
+ @property
481
+ def descriptor(self) -> BackendDescriptor:
482
+ return self._DESCRIPTOR
483
+
484
+ def encode(self, text: str) -> tuple[int, ...]:
485
+ if not isinstance(text, str):
486
+ raise SourceContractError("TYPE", "embedding.text", "must be a string")
487
+ if len(text) > MAX_ENCODE_CHARS:
488
+ raise SourceContractError(
489
+ "EMBEDDING_INPUT_LIMIT",
490
+ "embedding.text",
491
+ f"encode input exceeds {MAX_ENCODE_CHARS} characters",
492
+ )
493
+ accumulator = [0] * DIMENSIONS
494
+ for token in _tokens(text):
495
+ digest = hashlib.sha256(token.encode("utf-8")).digest()
496
+ bucket = int.from_bytes(digest[:4], "big") % DIMENSIONS
497
+ accumulator[bucket] += 1 if digest[4] & 1 else -1
498
+ square_sum = sum(value * value for value in accumulator)
499
+ if square_sum == 0:
500
+ return (0,) * DIMENSIONS
501
+ # Exact integer square root. No IEEE-754 operation is involved anywhere on this path, so
502
+ # the vector is bit-identical on every host.
503
+ norm = math.isqrt(square_sum)
504
+ if norm == 0:
505
+ return (0,) * DIMENSIONS
506
+ scaled: list[int] = []
507
+ for value in accumulator:
508
+ sign = -1 if value < 0 else 1
509
+ # Integer round-half-away-from-zero of |value| * SCALE / norm.
510
+ scaled.append(sign * ((abs(value) * SCALE * 2 + norm) // (norm * 2)))
511
+ return tuple(scaled)
512
+
513
+ def encode_many(self, texts: tuple[str, ...] | list[str]) -> BatchEncodeResult:
514
+ return encode_many_bounded(self, texts)
515
+
516
+
517
+ def _tokens(text: str) -> list[str]:
518
+ """Lowercased unigrams, plus character 4-grams of every unigram longer than five."""
519
+
520
+ tokens: list[str] = []
521
+ for match in _TOKEN.finditer(text.lower()):
522
+ token = match.group()
523
+ tokens.append(token)
524
+ if len(token) > MIN_SUBTOKEN_SOURCE:
525
+ for start in range(len(token) - SUBTOKEN_LENGTH + 1):
526
+ tokens.append(token[start : start + SUBTOKEN_LENGTH])
527
+ return tokens
528
+
529
+
530
+ # Sealed. This is the allowlist `SealedEmbeddingIndex.load` uses when a caller names none.
531
+ # See `BackendRegistry` for why it may not be widened in place.
532
+ DEFAULT_BACKENDS = BackendRegistry((LexicalHashingBackend(),), sealed=True)