topos-node 1.3.3__tar.gz → 1.3.4__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 (599) hide show
  1. {topos_node-1.3.3/topos_node.egg-info → topos_node-1.3.4}/PKG-INFO +1 -1
  2. {topos_node-1.3.3 → topos_node-1.3.4}/pyproject.toml +1 -1
  3. {topos_node-1.3.3 → topos_node-1.3.4}/topos/__version__.py +2 -2
  4. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/enrichment.py +72 -14
  5. topos_node-1.3.4/topos/api/upgrades.py +55 -0
  6. {topos_node-1.3.3 → topos_node-1.3.4}/topos/cli/commands.py +22 -0
  7. {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/settings.py +6 -0
  8. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/api_models.py +5 -0
  9. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/config.py +31 -0
  10. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/catalog.py +13 -1
  11. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/derived_tables.py +123 -84
  12. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/job_writer.py +36 -0
  13. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/models/mvp_defaults.py +27 -0
  14. topos_node-1.3.4/topos/protocol/handled_message_types.json +208 -0
  15. {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/llm/openai.py +49 -3
  16. {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/local.py +44 -1
  17. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/sqlite/stores.py +100 -43
  18. topos_node-1.3.4/topos/storage/db/migrations/enrichment_spec_version_v1.py +50 -0
  19. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/registry.py +6 -0
  20. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/registry_checksums.json +1 -0
  21. {topos_node-1.3.3 → topos_node-1.3.4}/topos/upgrades/__init__.py +6 -0
  22. {topos_node-1.3.3 → topos_node-1.3.4}/topos/upgrades/manifests.json +19 -0
  23. {topos_node-1.3.3 → topos_node-1.3.4}/topos/upgrades/runner.py +183 -7
  24. {topos_node-1.3.3 → topos_node-1.3.4/topos_node.egg-info}/PKG-INFO +1 -1
  25. {topos_node-1.3.3 → topos_node-1.3.4}/topos_node.egg-info/SOURCES.txt +1 -0
  26. topos_node-1.3.3/topos/api/upgrades.py +0 -30
  27. topos_node-1.3.3/topos/protocol/handled_message_types.json +0 -207
  28. {topos_node-1.3.3 → topos_node-1.3.4}/LICENSE +0 -0
  29. {topos_node-1.3.3 → topos_node-1.3.4}/MANIFEST.in +0 -0
  30. {topos_node-1.3.3 → topos_node-1.3.4}/README.md +0 -0
  31. {topos_node-1.3.3 → topos_node-1.3.4}/setup.cfg +0 -0
  32. {topos_node-1.3.3 → topos_node-1.3.4}/shared/__init__.py +0 -0
  33. {topos_node-1.3.3 → topos_node-1.3.4}/shared/filtering.py +0 -0
  34. {topos_node-1.3.3 → topos_node-1.3.4}/shared/schema_registry.py +0 -0
  35. {topos_node-1.3.3 → topos_node-1.3.4}/tests/test_extensions.py +0 -0
  36. {topos_node-1.3.3 → topos_node-1.3.4}/tests/test_llm_integrations_storage.py +0 -0
  37. {topos_node-1.3.3 → topos_node-1.3.4}/tests/test_protocol_handled_types.py +0 -0
  38. {topos_node-1.3.3 → topos_node-1.3.4}/topos/__init__.py +0 -0
  39. {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/__init__.py +0 -0
  40. {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/duckdb_adapter.py +0 -0
  41. {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/messenger_communities.py +0 -0
  42. {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/messenger_graph.py +0 -0
  43. {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/messenger_labels.py +0 -0
  44. {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/profiles.py +0 -0
  45. {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/query_engine.py +0 -0
  46. {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/raw_queries.py +0 -0
  47. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/__init__.py +0 -0
  48. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/analytics.py +0 -0
  49. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/app_registry.py +0 -0
  50. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/backup.py +0 -0
  51. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/compute_remote.py +0 -0
  52. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/conversation_context.py +0 -0
  53. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/data_commit.py +0 -0
  54. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/data_explorer_table_prefs.py +0 -0
  55. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/database_explorer.py +0 -0
  56. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/db.py +0 -0
  57. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/device.py +0 -0
  58. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/engine_run.py +0 -0
  59. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/enrichment_lab.py +0 -0
  60. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/facts_llm_config.py +0 -0
  61. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/filter_lab.py +0 -0
  62. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/health.py +0 -0
  63. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/home_chat.py +0 -0
  64. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/ingestion_api.py +0 -0
  65. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/ingestion_compat.py +0 -0
  66. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/ingestion_sources.py +0 -0
  67. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/intelligence_lifecycle.py +0 -0
  68. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/llm.py +0 -0
  69. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/local_mcp.py +0 -0
  70. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/messenger_analytics.py +0 -0
  71. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/privacy_disclose.py +0 -0
  72. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/query_api.py +0 -0
  73. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/runtime_bootstrap.py +0 -0
  74. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/sanitization_ollama_config.py +0 -0
  75. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/shell.py +0 -0
  76. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/signal.py +0 -0
  77. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/signal_extraction_config.py +0 -0
  78. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/source_install.py +0 -0
  79. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/source_scrub.py +0 -0
  80. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/sources.py +0 -0
  81. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/sources_overview.py +0 -0
  82. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/sync.py +0 -0
  83. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/tool_index.py +0 -0
  84. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/ui_config.py +0 -0
  85. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/uma_data.py +0 -0
  86. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/usage.py +0 -0
  87. {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/user_identity.py +0 -0
  88. {topos_node-1.3.3 → topos_node-1.3.4}/topos/app.py +0 -0
  89. {topos_node-1.3.3 → topos_node-1.3.4}/topos/auth.py +0 -0
  90. {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/__init__.py +0 -0
  91. {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/__init__.py +0 -0
  92. {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/base.py +0 -0
  93. {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
  94. {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
  95. {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/demo_mappers.py +0 -0
  96. {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/documents_mapper.py +0 -0
  97. {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
  98. {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
  99. {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/grok_mapper.py +0 -0
  100. {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
  101. {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/models.py +0 -0
  102. {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/resolver.py +0 -0
  103. {topos_node-1.3.3 → topos_node-1.3.4}/topos/cli/__init__.py +0 -0
  104. {topos_node-1.3.3 → topos_node-1.3.4}/topos/cli/__main__.py +0 -0
  105. {topos_node-1.3.3 → topos_node-1.3.4}/topos/cli/assets/topos_blk_rounded.png +0 -0
  106. {topos_node-1.3.3 → topos_node-1.3.4}/topos/cli/assets/topos_white.png +0 -0
  107. {topos_node-1.3.3 → topos_node-1.3.4}/topos/cli/tray.py +0 -0
  108. {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/__init__.py +0 -0
  109. {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/conversation_context_llm.py +0 -0
  110. {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/facts_llm.py +0 -0
  111. {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/sanitization_ollama.py +0 -0
  112. {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/signal_extraction.py +0 -0
  113. {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/uvicorn_logging.json +0 -0
  114. {topos_node-1.3.3 → topos_node-1.3.4}/topos/contacts/__init__.py +0 -0
  115. {topos_node-1.3.3 → topos_node-1.3.4}/topos/contacts/identity.py +0 -0
  116. {topos_node-1.3.3 → topos_node-1.3.4}/topos/control_plane_client.py +0 -0
  117. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/__init__.py +0 -0
  118. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/connection_resilience.py +0 -0
  119. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/device_helpers.py +0 -0
  120. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/errors.py +0 -0
  121. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/events.py +0 -0
  122. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/__init__.py +0 -0
  123. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/common.py +0 -0
  124. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/complexity.py +0 -0
  125. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/contacts_import.py +0 -0
  126. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/database_explorer.py +0 -0
  127. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/device.py +0 -0
  128. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/enrichment.py +0 -0
  129. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/enrichment_lab.py +0 -0
  130. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/filter_lab.py +0 -0
  131. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/home_chat.py +0 -0
  132. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/ingest.py +0 -0
  133. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/messages.py +0 -0
  134. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/messenger_analytics.py +0 -0
  135. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/query.py +0 -0
  136. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/registry.py +0 -0
  137. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/routines.py +0 -0
  138. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/signal_features.py +0 -0
  139. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/sources.py +0 -0
  140. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/timeline_daily.py +0 -0
  141. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/tool_index.py +0 -0
  142. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/uma.py +0 -0
  143. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/logging.py +0 -0
  144. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/metrics.py +0 -0
  145. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/routine_access.py +0 -0
  146. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/startup_banner.py +0 -0
  147. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/state.py +0 -0
  148. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/table_layers.py +0 -0
  149. {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/types.py +0 -0
  150. {topos_node-1.3.3 → topos_node-1.3.4}/topos/data_explorer_row_delete.py +0 -0
  151. {topos_node-1.3.3 → topos_node-1.3.4}/topos/data_explorer_table_prefs.py +0 -0
  152. {topos_node-1.3.3 → topos_node-1.3.4}/topos/data_explorer_tables.py +0 -0
  153. {topos_node-1.3.3 → topos_node-1.3.4}/topos/disclosure/__init__.py +0 -0
  154. {topos_node-1.3.3 → topos_node-1.3.4}/topos/disclosure/canonical_writer.py +0 -0
  155. {topos_node-1.3.3 → topos_node-1.3.4}/topos/disclosure/content_policy.py +0 -0
  156. {topos_node-1.3.3 → topos_node-1.3.4}/topos/disclosure/field_registry.py +0 -0
  157. {topos_node-1.3.3 → topos_node-1.3.4}/topos/disclosure/privacy_layer.py +0 -0
  158. {topos_node-1.3.3 → topos_node-1.3.4}/topos/disclosure/tier.py +0 -0
  159. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/__init__.py +0 -0
  160. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/__init__.py +0 -0
  161. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/base.py +0 -0
  162. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/generative_prompts.py +0 -0
  163. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/generative_response.py +0 -0
  164. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/huggingface.py +0 -0
  165. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/ollama.py +0 -0
  166. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/openai.py +0 -0
  167. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/openai_compatible.py +0 -0
  168. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/redpill.py +0 -0
  169. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/stub.py +0 -0
  170. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/client.py +0 -0
  171. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/engine.py +0 -0
  172. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/intake.py +0 -0
  173. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/memory_utils.py +0 -0
  174. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/model_cache.py +0 -0
  175. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/pipeline_memory.py +0 -0
  176. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/queue_manager.py +0 -0
  177. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/registration.py +0 -0
  178. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/result_formatter.py +0 -0
  179. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/router.py +0 -0
  180. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/scoped_token.py +0 -0
  181. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/tasks.py +0 -0
  182. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/transport.py +0 -0
  183. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/usage_guard.py +0 -0
  184. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/usage_observation.py +0 -0
  185. {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/validator.py +0 -0
  186. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/__init__.py +0 -0
  187. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/__init__.py +0 -0
  188. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/base.py +0 -0
  189. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/__init__.py +0 -0
  190. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
  191. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
  192. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/attention_triage_job.py +0 -0
  193. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
  194. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
  195. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +0 -0
  196. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/dimension_summary_job.py +0 -0
  197. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
  198. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
  199. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/entities_job.py +0 -0
  200. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
  201. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
  202. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
  203. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
  204. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
  205. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
  206. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
  207. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
  208. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
  209. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/url_classification_core.py +0 -0
  210. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/url_classification_enrichment_job.py +0 -0
  211. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/url_classification_signal_job.py +0 -0
  212. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/raw/__init__.py +0 -0
  213. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
  214. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/raw/language_job.py +0 -0
  215. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
  216. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
  217. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/model_overrides.py +0 -0
  218. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/models/__init__.py +0 -0
  219. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/models/manager.py +0 -0
  220. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/models/registry.py +0 -0
  221. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/models/versioning.py +0 -0
  222. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/orchestrator.py +0 -0
  223. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/processor.py +0 -0
  224. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/progress_bar.py +0 -0
  225. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/registry_contract.py +0 -0
  226. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/signal_derivation_config.json +0 -0
  227. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/source_overrides.py +0 -0
  228. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/website_classifier.py +0 -0
  229. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/__init__.py +0 -0
  230. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/bundles.py +0 -0
  231. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/model_resolve.py +0 -0
  232. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/schema.py +0 -0
  233. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/service.py +0 -0
  234. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/store.py +0 -0
  235. {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/worker.py +0 -0
  236. {topos_node-1.3.3 → topos_node-1.3.4}/topos/evals/__init__.py +0 -0
  237. {topos_node-1.3.3 → topos_node-1.3.4}/topos/evals/enrichment_eval.py +0 -0
  238. {topos_node-1.3.3 → topos_node-1.3.4}/topos/extensions.py +0 -0
  239. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/__init__.py +0 -0
  240. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/canonical.py +0 -0
  241. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/engine.py +0 -0
  242. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/entropy.py +0 -0
  243. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/focus.py +0 -0
  244. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/graph_metrics.py +0 -0
  245. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/influence.py +0 -0
  246. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/projection.py +0 -0
  247. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/snapshots.py +0 -0
  248. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/store.py +0 -0
  249. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/topic_merge.py +0 -0
  250. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/topics.py +0 -0
  251. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/topics_daily.py +0 -0
  252. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/volatility.py +0 -0
  253. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/__init__.py +0 -0
  254. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/consolidation.py +0 -0
  255. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/declared_mappings.py +0 -0
  256. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/dossier.py +0 -0
  257. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/edges.py +0 -0
  258. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/fact_materializer.py +0 -0
  259. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/graph_enrichers.py +0 -0
  260. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/graph_refresh.py +0 -0
  261. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/graph_search.py +0 -0
  262. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/linking.py +0 -0
  263. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/maintenance.py +0 -0
  264. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/reads.py +0 -0
  265. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/resolver.py +0 -0
  266. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/facts/__init__.py +0 -0
  267. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/facts/extract.py +0 -0
  268. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/facts/llm_extract.py +0 -0
  269. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/facts/reads.py +0 -0
  270. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/facts/store.py +0 -0
  271. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/facts/verdicts.py +0 -0
  272. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/fit/evaluator.py +0 -0
  273. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/fit/opportunity_types.json +0 -0
  274. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/__init__.py +0 -0
  275. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/blackhole.py +0 -0
  276. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/blackhole_guard.py +0 -0
  277. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/blackhole_llm.py +0 -0
  278. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/blackhole_rebuild.py +0 -0
  279. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/derived_scrub.py +0 -0
  280. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/exclusions.py +0 -0
  281. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/gc.py +0 -0
  282. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/provenance/__init__.py +0 -0
  283. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/provenance/posture.py +0 -0
  284. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/provenance/roles.py +0 -0
  285. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/__init__.py +0 -0
  286. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/brief_canonical_loader.py +0 -0
  287. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/brief_ontology.py +0 -0
  288. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/brief_renderer.py +0 -0
  289. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/brief_schemas.py +0 -0
  290. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/chunking.py +0 -0
  291. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/cluster_labels.py +0 -0
  292. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/conversation_context.py +0 -0
  293. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/data_health.py +0 -0
  294. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/brief_ontologies.json +0 -0
  295. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/intentions.json +0 -0
  296. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/profile.json +0 -0
  297. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/relationships.json +0 -0
  298. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
  299. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/time.json +0 -0
  300. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/work.json +0 -0
  301. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/dimension_briefs.py +0 -0
  302. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/dimension_definition_loader.py +0 -0
  303. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/dimension_profiles.py +0 -0
  304. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/dimension_registry.py +0 -0
  305. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/embed_context.py +0 -0
  306. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/extraction/artifact_router.py +0 -0
  307. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/extraction/artifact_store.py +0 -0
  308. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/extraction/rule_extractors.py +0 -0
  309. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/graph_sanitize.py +0 -0
  310. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/hybrid_search.py +0 -0
  311. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/incremental_clustering.py +0 -0
  312. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/model_recommendations.py +0 -0
  313. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/query_embed_cache.py +0 -0
  314. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/schemas.py +0 -0
  315. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/service.py +0 -0
  316. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/signal_object_store.py +0 -0
  317. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/source_hydration.py +0 -0
  318. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/structured_signal.py +0 -0
  319. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/tool_index.py +0 -0
  320. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/topic_clustering.py +0 -0
  321. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/typed_stores/aggregates.py +0 -0
  322. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/typed_stores/commitments.py +0 -0
  323. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/typed_stores/rhythm.py +0 -0
  324. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
  325. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/vector_codec.py +0 -0
  326. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/vector_math.py +0 -0
  327. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/vector_settings.py +0 -0
  328. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/stats/__init__.py +0 -0
  329. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/stats/definitions.py +0 -0
  330. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/stats/engine.py +0 -0
  331. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/stats/fold.py +0 -0
  332. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/stats/insights.py +0 -0
  333. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/timeline_projection.py +0 -0
  334. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/timeline_rollup.py +0 -0
  335. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/__init__.py +0 -0
  336. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/badges.py +0 -0
  337. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/daily.py +0 -0
  338. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/dashboard.py +0 -0
  339. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/instruments.py +0 -0
  340. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/intents.py +0 -0
  341. {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/readiness.py +0 -0
  342. {topos_node-1.3.3 → topos_node-1.3.4}/topos/filter_lab/__init__.py +0 -0
  343. {topos_node-1.3.3 → topos_node-1.3.4}/topos/filter_lab/bundles.py +0 -0
  344. {topos_node-1.3.3 → topos_node-1.3.4}/topos/filter_lab/schema.py +0 -0
  345. {topos_node-1.3.3 → topos_node-1.3.4}/topos/filter_lab/service.py +0 -0
  346. {topos_node-1.3.3 → topos_node-1.3.4}/topos/filter_lab/store.py +0 -0
  347. {topos_node-1.3.3 → topos_node-1.3.4}/topos/filter_lab/worker.py +0 -0
  348. {topos_node-1.3.3 → topos_node-1.3.4}/topos/home_chat/__init__.py +0 -0
  349. {topos_node-1.3.3 → topos_node-1.3.4}/topos/home_chat/schema.py +0 -0
  350. {topos_node-1.3.3 → topos_node-1.3.4}/topos/home_chat/store.py +0 -0
  351. {topos_node-1.3.3 → topos_node-1.3.4}/topos/hosted_pool_lease.py +0 -0
  352. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/__init__.py +0 -0
  353. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/canonical_pipeline.py +0 -0
  354. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/checkpoints/__init__.py +0 -0
  355. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
  356. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
  357. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/inbox_crypto.py +0 -0
  358. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/inbox_drain.py +0 -0
  359. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/ingest_helpers.py +0 -0
  360. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/jobs.py +0 -0
  361. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/journal_location_fanout.py +0 -0
  362. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/journal_time_log_normalize.py +0 -0
  363. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/local_sync.py +0 -0
  364. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/log_preview.py +0 -0
  365. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/manager.py +0 -0
  366. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parser.py +0 -0
  367. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/__init__.py +0 -0
  368. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/base.py +0 -0
  369. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/browser_parser.py +0 -0
  370. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/calendar_parser.py +0 -0
  371. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
  372. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
  373. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
  374. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/documents_parser.py +0 -0
  375. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/github_activity_parser.py +0 -0
  376. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
  377. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/grok_parser.py +0 -0
  378. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/messenger_parser.py +0 -0
  379. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/voxterm_parser.py +0 -0
  380. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/progress.py +0 -0
  381. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/reprocess.py +0 -0
  382. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/__init__.py +0 -0
  383. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/base.py +0 -0
  384. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/calendar.py +0 -0
  385. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/chatgpt.py +0 -0
  386. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/contact_importers.py +0 -0
  387. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/grok.py +0 -0
  388. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/imessage_reader.py +0 -0
  389. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/signal_export_parser.py +0 -0
  390. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/signal_reader.py +0 -0
  391. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/state_machine.py +0 -0
  392. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/triggers/__init__.py +0 -0
  393. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/triggers/file_trigger.py +0 -0
  394. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
  395. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/usage_inbox_dedupe.py +0 -0
  396. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/validation/__init__.py +0 -0
  397. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/validation/base.py +0 -0
  398. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/validation/schema_registry.py +0 -0
  399. {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/validation/schema_validator.py +0 -0
  400. {topos_node-1.3.3 → topos_node-1.3.4}/topos/lineage/__init__.py +0 -0
  401. {topos_node-1.3.3 → topos_node-1.3.4}/topos/lineage/provenance.py +0 -0
  402. {topos_node-1.3.3 → topos_node-1.3.4}/topos/lineage/tracker.py +0 -0
  403. {topos_node-1.3.3 → topos_node-1.3.4}/topos/llm_integrations_storage.py +0 -0
  404. {topos_node-1.3.3 → topos_node-1.3.4}/topos/mcp_stdio_proxy.py +0 -0
  405. {topos_node-1.3.3 → topos_node-1.3.4}/topos/observability/__init__.py +0 -0
  406. {topos_node-1.3.3 → topos_node-1.3.4}/topos/observability/alerts.py +0 -0
  407. {topos_node-1.3.3 → topos_node-1.3.4}/topos/observability/metrics.py +0 -0
  408. {topos_node-1.3.3 → topos_node-1.3.4}/topos/observability/tracing.py +0 -0
  409. {topos_node-1.3.3 → topos_node-1.3.4}/topos/openai_client.py +0 -0
  410. {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/__init__.py +0 -0
  411. {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/audit.py +0 -0
  412. {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/envelope.py +0 -0
  413. {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/job_runner.py +0 -0
  414. {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/job_store.py +0 -0
  415. {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/stages.py +0 -0
  416. {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/stub_enqueue.py +0 -0
  417. {topos_node-1.3.3 → topos_node-1.3.4}/topos/projections/__init__.py +0 -0
  418. {topos_node-1.3.3 → topos_node-1.3.4}/topos/projections/vector_index/__init__.py +0 -0
  419. {topos_node-1.3.3 → topos_node-1.3.4}/topos/projections/vector_index/base.py +0 -0
  420. {topos_node-1.3.3 → topos_node-1.3.4}/topos/projections/vector_index/builders.py +0 -0
  421. {topos_node-1.3.3 → topos_node-1.3.4}/topos/projections/vector_index/health_checks.py +0 -0
  422. {topos_node-1.3.3 → topos_node-1.3.4}/topos/protocol/__init__.py +0 -0
  423. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/__init__.py +0 -0
  424. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/audit.py +0 -0
  425. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/ddr.py +0 -0
  426. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/disclosure.py +0 -0
  427. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/fingerprint.py +0 -0
  428. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/game_layer.py +0 -0
  429. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/grant_cache.py +0 -0
  430. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/inference.py +0 -0
  431. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/intent.py +0 -0
  432. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/manifest.py +0 -0
  433. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/manifest_validation.py +0 -0
  434. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/minimizer.py +0 -0
  435. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/negotiation.py +0 -0
  436. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/pipeline.py +0 -0
  437. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/planner.py +0 -0
  438. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/retrieval.py +0 -0
  439. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/runtime.py +0 -0
  440. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/scope_registry.json +0 -0
  441. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/scope_registry_loader.py +0 -0
  442. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/session.py +0 -0
  443. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/session_utils.py +0 -0
  444. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/source_generation.py +0 -0
  445. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/truth_facts.py +0 -0
  446. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/truth_prompts.py +0 -0
  447. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/turn_classifier.py +0 -0
  448. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/types.py +0 -0
  449. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/verify.py +0 -0
  450. {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/verify_modes.py +0 -0
  451. {topos_node-1.3.3 → topos_node-1.3.4}/topos/rate_limit.py +0 -0
  452. {topos_node-1.3.3 → topos_node-1.3.4}/topos/routines/__init__.py +0 -0
  453. {topos_node-1.3.3 → topos_node-1.3.4}/topos/routines/schema.py +0 -0
  454. {topos_node-1.3.3 → topos_node-1.3.4}/topos/routines/store.py +0 -0
  455. {topos_node-1.3.3 → topos_node-1.3.4}/topos/runtime_housekeeping.py +0 -0
  456. {topos_node-1.3.3 → topos_node-1.3.4}/topos/runtime_shutdown.py +0 -0
  457. {topos_node-1.3.3 → topos_node-1.3.4}/topos/runtime_update.py +0 -0
  458. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sanitization/__init__.py +0 -0
  459. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sanitization/nsfw_classifier.py +0 -0
  460. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sanitization/ollama_transforms.py +0 -0
  461. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sanitization/prewarm.py +0 -0
  462. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sanitization/privacy_filter.py +0 -0
  463. {topos_node-1.3.3 → topos_node-1.3.4}/topos/scope_resolution.py +0 -0
  464. {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/__init__.py +0 -0
  465. {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/container.py +0 -0
  466. {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/embeddings/__init__.py +0 -0
  467. {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/embeddings/base.py +0 -0
  468. {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/embeddings/local.py +0 -0
  469. {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/embeddings/remote.py +0 -0
  470. {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/interfaces.py +0 -0
  471. {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/llm/__init__.py +0 -0
  472. {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/llm/base.py +0 -0
  473. {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/postgres.py +0 -0
  474. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/__init__.py +0 -0
  475. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/bundled_canonical_triples.py +0 -0
  476. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/canonical_signal_defaults.py +0 -0
  477. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/definitions.py +0 -0
  478. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/install_service.py +0 -0
  479. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/registry.py +0 -0
  480. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/runtime_install.py +0 -0
  481. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/scrub_attribution.py +0 -0
  482. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/scrub_service.py +0 -0
  483. {topos_node-1.3.3 → topos_node-1.3.4}/topos/startup_banner.py +0 -0
  484. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/__init__.py +0 -0
  485. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/__init__.py +0 -0
  486. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/factory.py +0 -0
  487. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/fakes.py +0 -0
  488. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/postgres/stores.py +0 -0
  489. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/protocols.py +0 -0
  490. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/sqlite/__init__.py +0 -0
  491. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/sqlite/vector_search.py +0 -0
  492. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/__init__.py +0 -0
  493. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/activity_tables.py +0 -0
  494. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/__init__.py +0 -0
  495. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
  496. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/mapper.py +0 -0
  497. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/model.py +0 -0
  498. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/tables.py +0 -0
  499. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
  500. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/canonical_store.py +0 -0
  501. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/conversations_tables.py +0 -0
  502. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/mapping_store.py +0 -0
  503. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/postgres.py +0 -0
  504. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/__init__.py +0 -0
  505. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/client.py +0 -0
  506. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/connection_tuning.py +0 -0
  507. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/__init__.py +0 -0
  508. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
  509. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/actor_role_v1.py +0 -0
  510. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
  511. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
  512. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/backup.py +0 -0
  513. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
  514. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
  515. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
  516. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
  517. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/complexity_v1.py +0 -0
  518. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
  519. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
  520. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/documents_v1.py +0 -0
  521. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/entity_blackhole_v1.py +0 -0
  522. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
  523. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/episodes_v1.py +0 -0
  524. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
  525. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
  526. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
  527. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
  528. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
  529. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
  530. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
  531. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/remediation_person_model.py +0 -0
  532. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/scope_source_generation.py +0 -0
  533. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
  534. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
  535. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/signal_objects.py +0 -0
  536. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
  537. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
  538. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
  539. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
  540. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
  541. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
  542. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
  543. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
  544. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
  545. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
  546. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
  547. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
  548. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
  549. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
  550. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
  551. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
  552. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
  553. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
  554. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
  555. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
  556. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
  557. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/paths.py +0 -0
  558. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/postgres.py +0 -0
  559. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/schema.py +0 -0
  560. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/storage_breakdown.py +0 -0
  561. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/write_gate.py +0 -0
  562. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/enrichment/__init__.py +0 -0
  563. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
  564. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
  565. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/normalized/__init__.py +0 -0
  566. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/normalized/normalized_store.py +0 -0
  567. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/oplog/__init__.py +0 -0
  568. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/oplog/decision.py +0 -0
  569. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/oplog/oplog_store.py +0 -0
  570. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/oplog/postgres.py +0 -0
  571. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/person/identity_resolver.py +0 -0
  572. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/projections/__init__.py +0 -0
  573. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/projections/index_ops_store.py +0 -0
  574. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/projections/vector_index_store.py +0 -0
  575. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/raw/__init__.py +0 -0
  576. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/raw/browser_flat_tables.py +0 -0
  577. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/raw/file_store.py +0 -0
  578. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/raw/raw_store.py +0 -0
  579. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/raw/raw_tables_manager.py +0 -0
  580. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/raw/sqlite_raw_store.py +0 -0
  581. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/security/encryption.py +0 -0
  582. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/signal_identity.py +0 -0
  583. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/source_settings.py +0 -0
  584. {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/user_identity.py +0 -0
  585. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sync/__init__.py +0 -0
  586. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sync/client.py +0 -0
  587. {topos_node-1.3.3 → topos_node-1.3.4}/topos/sync_handlers.py +0 -0
  588. {topos_node-1.3.3 → topos_node-1.3.4}/topos/testing/__init__.py +0 -0
  589. {topos_node-1.3.3 → topos_node-1.3.4}/topos/testing/lifespan.py +0 -0
  590. {topos_node-1.3.3 → topos_node-1.3.4}/topos/uma_contact_enrichment.py +0 -0
  591. {topos_node-1.3.3 → topos_node-1.3.4}/topos/uma_filters.py +0 -0
  592. {topos_node-1.3.3 → topos_node-1.3.4}/topos/uma_resource_id.py +0 -0
  593. {topos_node-1.3.3 → topos_node-1.3.4}/topos/uma_rpt.py +0 -0
  594. {topos_node-1.3.3 → topos_node-1.3.4}/topos/utils/base_object.py +0 -0
  595. {topos_node-1.3.3 → topos_node-1.3.4}/topos/websocket_client.py +0 -0
  596. {topos_node-1.3.3 → topos_node-1.3.4}/topos_node.egg-info/dependency_links.txt +0 -0
  597. {topos_node-1.3.3 → topos_node-1.3.4}/topos_node.egg-info/entry_points.txt +0 -0
  598. {topos_node-1.3.3 → topos_node-1.3.4}/topos_node.egg-info/requires.txt +0 -0
  599. {topos_node-1.3.3 → topos_node-1.3.4}/topos_node.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: topos-node
3
- Version: 1.3.3
3
+ Version: 1.3.4
4
4
  Summary: Topos personal AI engine (FastAPI): local data, sync, control plane WebSocket client
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Homepage, https://topos.dialogues.ai
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "topos-node"
7
- version = "1.3.3"
7
+ version = "1.3.4"
8
8
  description = "Topos personal AI engine (FastAPI): local data, sync, control plane WebSocket client"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -1,6 +1,6 @@
1
1
  """Topos Control Plane Version Information."""
2
2
 
3
- __version__ = "1.3.3"
4
- __version_info__ = (1, 3, 3)
3
+ __version__ = "1.3.4"
4
+ __version_info__ = (1, 3, 4)
5
5
 
6
6
  __all__ = ["__version__", "__version_info__"]
@@ -572,19 +572,33 @@ async def _generic_backfill_core(
572
572
  "errors": [],
573
573
  }
574
574
  else:
575
+ from ..enrichment.catalog import catalog_spec_version
576
+
575
577
  coverage_table = coverage_table_for_job(job_name)
576
578
  if coverage_table and _table_exists(db_conn, coverage_table):
577
579
  cols = _table_columns(db_conn, coverage_table)
578
580
  id_col = "message_id" if "message_id" in cols else "record_id"
579
581
  if "source_id" in cols and id_col in cols:
580
- done = {
581
- str(row[0])
582
- for row in db_conn.execute(
583
- f"SELECT DISTINCT {id_col} FROM {coverage_table} WHERE source_id=?",
584
- (source_id,),
585
- ).fetchall()
586
- if row[0]
587
- }
582
+ min_spec = catalog_spec_version(job_name)
583
+ if "spec_version" in cols:
584
+ done = {
585
+ str(row[0])
586
+ for row in db_conn.execute(
587
+ f"SELECT DISTINCT {id_col} FROM {coverage_table} "
588
+ f"WHERE source_id=? AND COALESCE(spec_version, 0) >= ?",
589
+ (source_id, min_spec),
590
+ ).fetchall()
591
+ if row[0]
592
+ }
593
+ else:
594
+ done = {
595
+ str(row[0])
596
+ for row in db_conn.execute(
597
+ f"SELECT DISTINCT {id_col} FROM {coverage_table} WHERE source_id=?",
598
+ (source_id,),
599
+ ).fetchall()
600
+ if row[0]
601
+ }
588
602
  records = [r for r in records if _record_identifier(r) not in done]
589
603
 
590
604
  if isinstance(limit, int) and limit > 0:
@@ -650,13 +664,45 @@ async def _generic_backfill_core(
650
664
  }
651
665
 
652
666
 
653
- def _get_enriched_message_ids(table_name: str, conn) -> set[str]:
654
- """Get set of message_ids that have enrichment records in the given table."""
667
+ def _get_enriched_message_ids(
668
+ table_name: str,
669
+ conn,
670
+ *,
671
+ min_spec_version: Optional[int] = None,
672
+ ) -> set[str]:
673
+ """Ids that already satisfy coverage for ``table_name``.
674
+
675
+ When ``min_spec_version`` is set and the table has ``spec_version``, only
676
+ rows with ``COALESCE(spec_version, 0) >= min_spec_version`` count as done
677
+ (PLAN M3 stale predicate). Otherwise presence-only.
678
+ """
655
679
  if not conn:
656
680
  return set()
657
681
  try:
658
- cursor = conn.execute(f"SELECT DISTINCT message_id FROM {table_name}")
659
- return {row[0] for row in cursor.fetchall()}
682
+ cols = _table_columns(conn, table_name)
683
+ if not cols:
684
+ return set()
685
+ if "message_id" in cols and "record_id" in cols:
686
+ id_expr = "COALESCE(message_id, record_id)"
687
+ elif "message_id" in cols:
688
+ id_expr = "message_id"
689
+ elif "record_id" in cols:
690
+ id_expr = "record_id"
691
+ else:
692
+ return set()
693
+ if (
694
+ min_spec_version is not None
695
+ and "spec_version" in cols
696
+ and isinstance(min_spec_version, int)
697
+ ):
698
+ cursor = conn.execute(
699
+ f"SELECT DISTINCT {id_expr} FROM {table_name} "
700
+ f"WHERE COALESCE(spec_version, 0) >= ?",
701
+ (int(min_spec_version),),
702
+ )
703
+ else:
704
+ cursor = conn.execute(f"SELECT DISTINCT {id_expr} FROM {table_name}")
705
+ return {str(row[0]) for row in cursor.fetchall() if row[0]}
660
706
  except Exception as e:
661
707
  logger.warning("Failed to query enriched message IDs from %s: %s", table_name, e)
662
708
  return set()
@@ -758,12 +804,18 @@ async def _find_unprocessed_messages(
758
804
  db_conn, source_def, dataset_id=dataset_id
759
805
  )
760
806
  if generic_messages:
807
+ from ..enrichment.catalog import catalog_spec_version
808
+
761
809
  enriched: Optional[set[str]] = None
762
810
  job_table_map = {job.get_job_name(): job.get_derived_table() for job in CANONICAL_JOBS}
763
811
  for job_name in jobs_to_check:
764
812
  table_name = job_table_map.get(job_name)
765
813
  if table_name:
766
- job_ids = _get_enriched_message_ids(table_name, db_conn)
814
+ job_ids = _get_enriched_message_ids(
815
+ table_name,
816
+ db_conn,
817
+ min_spec_version=catalog_spec_version(job_name),
818
+ )
767
819
  enriched = job_ids if enriched is None else (enriched & job_ids)
768
820
  else:
769
821
  logger.warning("Unknown enrichment job: %s (skipping check)", job_name)
@@ -947,6 +999,8 @@ async def _find_unprocessed_messages(
947
999
  # row for it (intersection). The previous union behavior skipped messages
948
1000
  # that had been enriched by any single job, leaving partial enrichment
949
1001
  # permanently un-backfillable.
1002
+ from ..enrichment.catalog import catalog_spec_version
1003
+
950
1004
  enriched_ids: Optional[set[str]] = None
951
1005
  # Create a mapping from job name to table name using the job registry
952
1006
  job_to_table = {job.get_job_name(): job.get_derived_table() for job in CANONICAL_JOBS}
@@ -954,7 +1008,11 @@ async def _find_unprocessed_messages(
954
1008
  for job_name in jobs_to_check:
955
1009
  table_name = job_to_table.get(job_name)
956
1010
  if table_name:
957
- job_ids = _get_enriched_message_ids(table_name, db_conn)
1011
+ job_ids = _get_enriched_message_ids(
1012
+ table_name,
1013
+ db_conn,
1014
+ min_spec_version=catalog_spec_version(job_name),
1015
+ )
958
1016
  enriched_ids = job_ids if enriched_ids is None else (enriched_ids & job_ids)
959
1017
  else:
960
1018
  logger.warning("Unknown enrichment job: %s (skipping check)", job_name)
@@ -0,0 +1,55 @@
1
+ """Upgrade status + consent surface for schema/derived migration steps.
2
+
3
+ The UI shows "Upgrading your intelligence…" while auto steps run, and prompts
4
+ for ``pending_consent`` slow-lane steps (PLAN_NODE_RELEASE_MIGRATIONS M3).
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Any, Dict, Optional
10
+
11
+ from fastapi import APIRouter, Depends, HTTPException
12
+ from pydantic import BaseModel, Field
13
+
14
+ from ..auth import require_api_key
15
+
16
+ router = APIRouter()
17
+
18
+
19
+ def _status_payload() -> Dict[str, Any]:
20
+ from ..core.state import get_db_connection
21
+ from ..features.entities.graph_refresh import status as refresh_status
22
+ from ..upgrades.runner import runner_status
23
+
24
+ conn = get_db_connection()
25
+ upgrade = runner_status(conn) if conn is not None else {"enabled": False, "error": "no database"}
26
+ return {"upgrade": upgrade, "graph_refresh": refresh_status()}
27
+
28
+
29
+ @router.get("/v1/upgrade/status", dependencies=[Depends(require_api_key)])
30
+ async def get_upgrade_status() -> Dict[str, Any]:
31
+ return _status_payload()
32
+
33
+
34
+ class UpgradeConsentBody(BaseModel):
35
+ step_id: str = Field(..., min_length=1)
36
+ # Optional: run the step immediately after consent (default true).
37
+ run_now: bool = True
38
+
39
+
40
+ @router.post("/v1/upgrade/consent", dependencies=[Depends(require_api_key)])
41
+ async def post_upgrade_consent(body: UpgradeConsentBody) -> Dict[str, Any]:
42
+ from ..core.state import get_db_connection
43
+ from ..upgrades.runner import consent_upgrade_step, run_pending_upgrades
44
+
45
+ conn = get_db_connection()
46
+ if conn is None:
47
+ raise HTTPException(status_code=503, detail="database unavailable")
48
+ try:
49
+ result = consent_upgrade_step(conn, body.step_id.strip())
50
+ except ValueError as exc:
51
+ raise HTTPException(status_code=404, detail=str(exc)) from exc
52
+ run_result: Optional[Dict[str, Any]] = None
53
+ if body.run_now:
54
+ run_result = run_pending_upgrades(conn)
55
+ return {"status": "ok", "consent": result, "run": run_result, **_status_payload()}
@@ -307,6 +307,28 @@ def main(db_path, topos_key, set_topos_key, discover, port, host, skip_update_ch
307
307
  start_background_housekeeping()
308
308
 
309
309
  _emit_startup_banner(host=host, port=port)
310
+ try:
311
+ from topos.core.state import get_db_connection
312
+ from topos.upgrades.runner import runner_status
313
+
314
+ _conn = get_db_connection()
315
+ if _conn is not None:
316
+ _pending = (runner_status(_conn).get("pending_consent_steps") or [])
317
+ if _pending:
318
+ click.echo("")
319
+ click.echo("Upgrade steps waiting for your consent:")
320
+ for step in _pending:
321
+ click.echo(
322
+ f" • {step.get('id')}: {step.get('title') or step.get('why') or ''}"
323
+ f" (cost={step.get('cost') or 'slow'})"
324
+ )
325
+ click.echo(
326
+ "Approve with: POST /v1/upgrade/consent {\"step_id\": \"...\"} "
327
+ "or the Engine settings banner."
328
+ )
329
+ click.echo("")
330
+ except Exception:
331
+ pass
310
332
 
311
333
  from topos.cli import tray as tray_module
312
334
 
@@ -140,6 +140,12 @@ class Settings(BaseSettings):
140
140
  sanitization_ollama_host: Optional[str] = Field(None, env="SANITIZATION_OLLAMA_HOST")
141
141
  sanitization_ollama_default_model: str = Field("llama3.2", env="SANITIZATION_OLLAMA_DEFAULT_MODEL")
142
142
  sanitization_ollama_timeout_sec: float = Field(120.0, env="SANITIZATION_OLLAMA_TIMEOUT_SEC")
143
+ # llm_generation / routine hops — must cover local thinking models. Do NOT
144
+ # reuse sanitization_ollama_timeout_sec (120s): that cuts digest synthesis
145
+ # mid-flight and surfaces as "Ollama unreachable".
146
+ engine_ollama_generate_timeout_sec: float = Field(
147
+ 300.0, env="ENGINE_OLLAMA_GENERATE_TIMEOUT_SEC"
148
+ )
143
149
  ollama_list_timeout_sec: float = Field(10.0, env="OLLAMA_LIST_TIMEOUT_SEC")
144
150
  sanitization_ollama_auto_pull: bool = Field(True, env="SANITIZATION_OLLAMA_AUTO_PULL")
145
151
  sanitization_ollama_max_input_chars: int = Field(8000, env="SANITIZATION_OLLAMA_MAX_INPUT_CHARS")
@@ -108,6 +108,11 @@ class DeviceInfoResponse(BaseModel):
108
108
  oplog_bytes_since_last_sync: Optional[int] = None
109
109
  database_size_bytes: Optional[int] = None
110
110
  storage_breakdown: Optional[Dict[str, Any]] = None
111
+ # Upgrade runner summary (PLAN_NODE_RELEASE_MIGRATIONS M5). Optional for
112
+ # older clients / hosted paths without a SQLite upgrade ledger.
113
+ upgrade_baseline: Optional[str] = None
114
+ pending_upgrade_steps: Optional[List[str]] = None
115
+ pending_consent_steps: Optional[List[Any]] = None
111
116
 
112
117
 
113
118
  class DeviceNameRequest(BaseModel):
@@ -467,6 +467,37 @@ async def handle_get_upgrade_status(message):
467
467
  return {"id": req_id, "status": "error", "error": str(exc)}
468
468
 
469
469
 
470
+ @handles("consent_upgrade_step")
471
+ async def handle_consent_upgrade_step(message):
472
+ """Approve a pending_consent upgrade step (PLAN M3)."""
473
+ req_id = message.get("id")
474
+ if not req_id:
475
+ return None
476
+ payload = message.get("payload") or {}
477
+ step_id = str(payload.get("step_id") or "").strip()
478
+ if not step_id:
479
+ return {"id": req_id, "status": "error", "error": "step_id required"}
480
+ run_now = bool(payload.get("run_now", True))
481
+ try:
482
+ from ...core.state import get_db_connection
483
+ from ...upgrades.runner import consent_upgrade_step, run_pending_upgrades
484
+
485
+ conn = get_db_connection()
486
+ if conn is None:
487
+ return {"id": req_id, "status": "error", "error": "database unavailable"}
488
+ result = consent_upgrade_step(conn, step_id)
489
+ run_result = run_pending_upgrades(conn) if run_now else None
490
+ return {
491
+ "id": req_id,
492
+ "status": "ok",
493
+ "payload": {"consent": result, "run": run_result},
494
+ }
495
+ except ValueError as exc:
496
+ return {"id": req_id, "status": "error", "error": str(exc)}
497
+ except Exception as exc: # noqa: BLE001
498
+ return {"id": req_id, "status": "error", "error": str(exc)}
499
+
500
+
470
501
  @handles("get_exposure_profile_config")
471
502
  async def handle_get_exposure_profile_config(message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
472
503
  req_id = message.get("id")
@@ -15,7 +15,7 @@ from dataclasses import dataclass, field
15
15
  from typing import Any, Dict, List, Optional, Tuple
16
16
 
17
17
  from .jobs import CANONICAL_JOBS, RAW_JOBS, SIGNAL_JOB_REGISTRY
18
- from .models.mvp_defaults import MVP_JOB_SPECS
18
+ from .models.mvp_defaults import MVP_JOB_SPECS, job_spec_version
19
19
 
20
20
  LANE_RAW = "raw"
21
21
  LANE_CANONICAL = "canonical"
@@ -48,6 +48,8 @@ class EnrichmentCatalogEntry:
48
48
  # Raw-lane stubs that currently produce no output.
49
49
  stub: bool = False
50
50
  value_props: Tuple[str, ...] = field(default_factory=tuple)
51
+ # Output-contract version; bump when prior coverage rows are stale (M3).
52
+ spec_version: int = 1
51
53
 
52
54
  def to_dict(self) -> Dict[str, Any]:
53
55
  return {
@@ -66,6 +68,7 @@ class EnrichmentCatalogEntry:
66
68
  "baseline": self.baseline,
67
69
  "stub": self.stub,
68
70
  "value_props": list(self.value_props),
71
+ "spec_version": int(self.spec_version),
69
72
  }
70
73
 
71
74
 
@@ -334,10 +337,19 @@ def _build_catalog() -> Dict[str, EnrichmentCatalogEntry]:
334
337
  baseline=job_id in baseline,
335
338
  stub=is_stub,
336
339
  value_props=tuple(meta.get("value_props") or ()),
340
+ spec_version=job_spec_version(job_id),
337
341
  )
338
342
  return entries
339
343
 
340
344
 
345
+ def catalog_spec_version(job_id: str) -> int:
346
+ """Return the catalog ``spec_version`` for ``job_id`` (default 1)."""
347
+ entry = get_catalog_entry(job_id)
348
+ if entry is not None:
349
+ return int(entry.spec_version)
350
+ return job_spec_version(job_id)
351
+
352
+
341
353
  _CATALOG: Optional[Dict[str, EnrichmentCatalogEntry]] = None
342
354
 
343
355
 
@@ -38,6 +38,18 @@ def _insert_matching_columns(
38
38
  )
39
39
 
40
40
 
41
+ def _record_spec_version(record: Dict[str, Any], job_id: str = "") -> int:
42
+ raw = record.get("spec_version")
43
+ if raw is not None:
44
+ try:
45
+ return int(raw)
46
+ except (TypeError, ValueError):
47
+ pass
48
+ from .models.mvp_defaults import job_spec_version
49
+
50
+ return job_spec_version(job_id or str(record.get("job_id") or ""))
51
+
52
+
41
53
  class DerivedTablesManager(BaseObject):
42
54
  """Manages derived tables for enrichment data."""
43
55
 
@@ -210,26 +222,18 @@ class DerivedTablesManager(BaseObject):
210
222
  if isinstance(all_emotions_val, list)
211
223
  else (all_emotions_val if isinstance(all_emotions_val, str) else "[]")
212
224
  )
213
- values.append(
214
- (
215
- record.get("message_id"),
216
- record.get("source_id"),
217
- record.get("emotion_label"),
218
- record.get("confidence"),
219
- record.get("model_name") or record.get("model"),
220
- all_emotions_str,
221
- extracted_at,
222
- )
223
- )
224
- self.conn.executemany(
225
- """
226
- INSERT OR REPLACE INTO message_emotions (
227
- message_id, source_id, emotion_label, confidence,
228
- model_name, all_emotions_json, created_at
229
- ) VALUES (?, ?, ?, ?, ?, ?, ?)
230
- """,
231
- values,
232
- )
225
+ row = {
226
+ "message_id": record.get("message_id"),
227
+ "source_id": record.get("source_id"),
228
+ "emotion_label": record.get("emotion_label"),
229
+ "confidence": record.get("confidence"),
230
+ "model_name": record.get("model_name") or record.get("model"),
231
+ "all_emotions_json": all_emotions_str,
232
+ "created_at": extracted_at,
233
+ "spec_version": _record_spec_version(record, "emo_27"),
234
+ }
235
+ _insert_matching_columns(self.conn, "message_emotions", cols, row)
236
+ values.append(1)
233
237
  elif use_wiki:
234
238
  import json
235
239
  import uuid
@@ -238,21 +242,17 @@ class DerivedTablesManager(BaseObject):
238
242
  message_id = record.get("message_id") or record.get("record_id")
239
243
  emotion_id = str(record.get("emotion_id") or uuid.uuid4())
240
244
  payload = json.dumps({**record, "message_id": message_id})
241
- self.conn.execute(
242
- """
243
- INSERT OR REPLACE INTO message_emotions (
244
- emotion_id, record_id, source_id, model, provider, payload_json
245
- ) VALUES (?, ?, ?, ?, ?, ?)
246
- """,
247
- (
248
- emotion_id,
249
- message_id,
250
- record.get("source_id"),
251
- record.get("model_name") or record.get("model"),
252
- record.get("provider"),
253
- payload,
254
- ),
255
- )
245
+ row = {
246
+ "emotion_id": emotion_id,
247
+ "record_id": message_id,
248
+ "source_id": record.get("source_id"),
249
+ "model": record.get("model_name") or record.get("model"),
250
+ "provider": record.get("provider"),
251
+ "payload_json": payload,
252
+ "spec_version": _record_spec_version(record, "emo_27"),
253
+ }
254
+ _insert_matching_columns(self.conn, "message_emotions", cols, row)
255
+ values = [1] # noqa: F841 — keep written accounting below
256
256
  else:
257
257
  logger.warning("%s: message_emotions schema not recognized", self)
258
258
  return 0
@@ -292,21 +292,20 @@ class DerivedTablesManager(BaseObject):
292
292
  entity_id = str(record.get("entity_id") or uuid.uuid4())
293
293
  payload = json.dumps({**record, "record_id": record_id, "entity_id": entity_id})
294
294
  if "payload_json" in cols:
295
- self.conn.execute(
296
- """
297
- INSERT OR REPLACE INTO message_entities (
298
- entity_id, record_id, source_id, entity_text, model, provider, payload_json
299
- ) VALUES (?, ?, ?, ?, ?, ?, ?)
300
- """,
301
- (
302
- entity_id,
303
- record_id,
304
- record.get("source_id"),
305
- entity_text,
306
- record.get("model"),
307
- record.get("provider"),
308
- payload,
309
- ),
295
+ _insert_matching_columns(
296
+ self.conn,
297
+ "message_entities",
298
+ cols,
299
+ {
300
+ "entity_id": entity_id,
301
+ "record_id": record_id,
302
+ "source_id": record.get("source_id"),
303
+ "entity_text": entity_text,
304
+ "model": record.get("model"),
305
+ "provider": record.get("provider"),
306
+ "payload_json": payload,
307
+ "spec_version": _record_spec_version(record, "entities"),
308
+ },
310
309
  )
311
310
  if "message_id" in cols:
312
311
  try:
@@ -341,21 +340,20 @@ class DerivedTablesManager(BaseObject):
341
340
  if not goal_text:
342
341
  continue
343
342
  goal_id = str(record.get("goal_id") or uuid.uuid4())
344
- self.conn.execute(
345
- """
346
- INSERT OR REPLACE INTO user_goals (
347
- goal_id, record_id, source_id, goal_text, model, provider, payload_json
348
- ) VALUES (?, ?, ?, ?, ?, ?, ?)
349
- """,
350
- (
351
- goal_id,
352
- record_id,
353
- record.get("source_id"),
354
- goal_text,
355
- record.get("model"),
356
- record.get("provider"),
357
- json.dumps({**record, "goal_id": goal_id}),
358
- ),
343
+ _insert_matching_columns(
344
+ self.conn,
345
+ "user_goals",
346
+ cols,
347
+ {
348
+ "goal_id": goal_id,
349
+ "record_id": record_id,
350
+ "source_id": record.get("source_id"),
351
+ "goal_text": goal_text,
352
+ "model": record.get("model"),
353
+ "provider": record.get("provider"),
354
+ "payload_json": json.dumps({**record, "goal_id": goal_id}),
355
+ "spec_version": _record_spec_version(record, "goal_extraction"),
356
+ },
359
357
  )
360
358
  written += 1
361
359
  commit_connection(self.conn)
@@ -406,6 +404,7 @@ class DerivedTablesManager(BaseObject):
406
404
  "model": record.get("model"),
407
405
  "provider": record.get("provider"),
408
406
  "payload_json": json.dumps({**record, "topic_id": topic_id}),
407
+ "spec_version": _record_spec_version(record, "topics"),
409
408
  }
410
409
  if "message_id" in cols:
411
410
  values["message_id"] = record.get("message_id") or record_id
@@ -435,6 +434,7 @@ class DerivedTablesManager(BaseObject):
435
434
  "model": record.get("model"),
436
435
  "provider": record.get("provider"),
437
436
  "payload_json": json.dumps({**record, "sentiment_id": sentiment_id}),
437
+ "spec_version": _record_spec_version(record, "sentiment"),
438
438
  }
439
439
  if "message_id" in cols:
440
440
  values["message_id"] = record.get("message_id") or record_id
@@ -464,6 +464,7 @@ class DerivedTablesManager(BaseObject):
464
464
  "dims": record.get("dims") or (len(vector) if isinstance(vector, list) else None),
465
465
  "vector_json": json.dumps(vector) if vector is not None else None,
466
466
  "payload_json": json.dumps({**record, "embedding_id": embedding_id}),
467
+ "spec_version": _record_spec_version(record, "embeddings"),
467
468
  }
468
469
  if "message_id" in cols:
469
470
  values["message_id"] = record.get("message_id") or record_id
@@ -487,32 +488,70 @@ class DerivedTablesManager(BaseObject):
487
488
  for i in range(0, len(records), batch_size):
488
489
  batch = records[i : i + batch_size]
489
490
  values = []
491
+ cols = _table_columns(self.conn, "browser_url_classification")
490
492
  for record in batch:
491
493
  record_id = record.get("record_id") or record.get("event_id")
492
494
  if not record_id:
493
495
  continue
494
- values.append(
495
- (
496
- record.get("enriched_from_table") or "activity_events",
497
- record_id,
498
- record.get("dataset_id"),
499
- record.get("url"),
500
- record.get("title"),
501
- record.get("url_category") or record.get("category"),
502
- record.get("url_confidence") if record.get("url_confidence") is not None else record.get("confidence"),
503
- record.get("model_name") or record.get("model"),
496
+ row = {
497
+ "enriched_from_table": record.get("enriched_from_table") or "activity_events",
498
+ "record_id": record_id,
499
+ "dataset_id": record.get("dataset_id"),
500
+ "url": record.get("url"),
501
+ "title": record.get("title"),
502
+ "url_category": record.get("url_category") or record.get("category"),
503
+ "url_confidence": (
504
+ record.get("url_confidence")
505
+ if record.get("url_confidence") is not None
506
+ else record.get("confidence")
507
+ ),
508
+ "model_name": record.get("model_name") or record.get("model"),
509
+ "updated_at": "datetime('now')",
510
+ "spec_version": _record_spec_version(record, "url_classification"),
511
+ }
512
+ # updated_at uses SQL datetime — keep prior executemany path for that col
513
+ if "spec_version" in cols:
514
+ self.conn.execute(
515
+ """
516
+ INSERT OR REPLACE INTO browser_url_classification
517
+ (enriched_from_table, record_id, dataset_id, url, title,
518
+ url_category, url_confidence, model_name, updated_at, spec_version)
519
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'), ?)
520
+ """,
521
+ (
522
+ row["enriched_from_table"],
523
+ row["record_id"],
524
+ row["dataset_id"],
525
+ row["url"],
526
+ row["title"],
527
+ row["url_category"],
528
+ row["url_confidence"],
529
+ row["model_name"],
530
+ row["spec_version"],
531
+ ),
504
532
  )
505
- )
533
+ else:
534
+ self.conn.execute(
535
+ """
536
+ INSERT OR REPLACE INTO browser_url_classification
537
+ (enriched_from_table, record_id, dataset_id, url, title,
538
+ url_category, url_confidence, model_name, updated_at)
539
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
540
+ """,
541
+ (
542
+ row["enriched_from_table"],
543
+ row["record_id"],
544
+ row["dataset_id"],
545
+ row["url"],
546
+ row["title"],
547
+ row["url_category"],
548
+ row["url_confidence"],
549
+ row["model_name"],
550
+ ),
551
+ )
552
+ values.append(1)
506
553
  if not values:
507
554
  continue
508
- self.conn.executemany(
509
- """
510
- INSERT OR REPLACE INTO browser_url_classification
511
- (enriched_from_table, record_id, dataset_id, url, title, url_category, url_confidence, model_name, updated_at)
512
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
513
- """,
514
- values,
515
- )
516
555
  commit_connection(self.conn)
517
556
  written += len(values)
518
557
  except Exception as exc: