topos-node 1.3.7__tar.gz → 1.3.8__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 (622) hide show
  1. {topos_node-1.3.7/topos_node.egg-info → topos_node-1.3.8}/PKG-INFO +1 -1
  2. {topos_node-1.3.7 → topos_node-1.3.8}/pyproject.toml +1 -1
  3. {topos_node-1.3.7 → topos_node-1.3.8}/topos/__version__.py +2 -2
  4. {topos_node-1.3.7 → topos_node-1.3.8}/topos/cli/tray.py +6 -0
  5. {topos_node-1.3.7 → topos_node-1.3.8}/topos/control_plane_client.py +20 -3
  6. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/ingest.py +23 -13
  7. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/state.py +22 -1
  8. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/attention_triage_job.py +26 -6
  9. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/dimension_summary_job.py +57 -24
  10. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/entities_job.py +9 -1
  11. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/statistics_job.py +43 -21
  12. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/timeline_job.py +12 -3
  13. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/orchestrator.py +71 -10
  14. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/graph_refresh.py +32 -0
  15. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/canonical_pipeline.py +24 -9
  16. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/ingest_helpers.py +87 -52
  17. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/manager.py +109 -94
  18. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/reprocess.py +32 -25
  19. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/scope_registry.json +12 -4
  20. {topos_node-1.3.7 → topos_node-1.3.8}/topos/runtime_update.py +65 -2
  21. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/__init__.py +88 -1
  22. topos_node-1.3.8/topos/storage/db/write_gate.py +688 -0
  23. topos_node-1.3.8/topos/testing/lifespan.py +69 -0
  24. {topos_node-1.3.7 → topos_node-1.3.8}/topos/upgrades/manifests.json +9 -0
  25. {topos_node-1.3.7 → topos_node-1.3.8}/topos/upgrades/runner.py +10 -3
  26. {topos_node-1.3.7 → topos_node-1.3.8/topos_node.egg-info}/PKG-INFO +1 -1
  27. topos_node-1.3.7/topos/storage/db/write_gate.py +0 -336
  28. topos_node-1.3.7/topos/testing/lifespan.py +0 -22
  29. {topos_node-1.3.7 → topos_node-1.3.8}/LICENSE +0 -0
  30. {topos_node-1.3.7 → topos_node-1.3.8}/MANIFEST.in +0 -0
  31. {topos_node-1.3.7 → topos_node-1.3.8}/README.md +0 -0
  32. {topos_node-1.3.7 → topos_node-1.3.8}/setup.cfg +0 -0
  33. {topos_node-1.3.7 → topos_node-1.3.8}/shared/__init__.py +0 -0
  34. {topos_node-1.3.7 → topos_node-1.3.8}/shared/filtering.py +0 -0
  35. {topos_node-1.3.7 → topos_node-1.3.8}/shared/schema_registry.py +0 -0
  36. {topos_node-1.3.7 → topos_node-1.3.8}/tests/test_extensions.py +0 -0
  37. {topos_node-1.3.7 → topos_node-1.3.8}/tests/test_llm_integrations_storage.py +0 -0
  38. {topos_node-1.3.7 → topos_node-1.3.8}/tests/test_prewarm_first_run.py +0 -0
  39. {topos_node-1.3.7 → topos_node-1.3.8}/tests/test_protocol_handled_types.py +0 -0
  40. {topos_node-1.3.7 → topos_node-1.3.8}/tests/test_system_computer_name.py +0 -0
  41. {topos_node-1.3.7 → topos_node-1.3.8}/topos/__init__.py +0 -0
  42. {topos_node-1.3.7 → topos_node-1.3.8}/topos/analytics/__init__.py +0 -0
  43. {topos_node-1.3.7 → topos_node-1.3.8}/topos/analytics/duckdb_adapter.py +0 -0
  44. {topos_node-1.3.7 → topos_node-1.3.8}/topos/analytics/messenger_communities.py +0 -0
  45. {topos_node-1.3.7 → topos_node-1.3.8}/topos/analytics/messenger_graph.py +0 -0
  46. {topos_node-1.3.7 → topos_node-1.3.8}/topos/analytics/messenger_labels.py +0 -0
  47. {topos_node-1.3.7 → topos_node-1.3.8}/topos/analytics/profiles.py +0 -0
  48. {topos_node-1.3.7 → topos_node-1.3.8}/topos/analytics/query_engine.py +0 -0
  49. {topos_node-1.3.7 → topos_node-1.3.8}/topos/analytics/raw_queries.py +0 -0
  50. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/__init__.py +0 -0
  51. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/analytics.py +0 -0
  52. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/app_registry.py +0 -0
  53. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/backup.py +0 -0
  54. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/compute_remote.py +0 -0
  55. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/conversation_context.py +0 -0
  56. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/data_commit.py +0 -0
  57. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/data_explorer_table_prefs.py +0 -0
  58. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/database_explorer.py +0 -0
  59. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/db.py +0 -0
  60. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/device.py +0 -0
  61. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/engine_run.py +0 -0
  62. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/enrichment.py +0 -0
  63. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/enrichment_lab.py +0 -0
  64. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/facts_llm_config.py +0 -0
  65. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/filter_lab.py +0 -0
  66. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/health.py +0 -0
  67. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/home_chat.py +0 -0
  68. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/ingestion_api.py +0 -0
  69. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/ingestion_compat.py +0 -0
  70. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/ingestion_sources.py +0 -0
  71. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/intelligence_lifecycle.py +0 -0
  72. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/llm.py +0 -0
  73. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/local_mcp.py +0 -0
  74. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/messenger_analytics.py +0 -0
  75. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/privacy_disclose.py +0 -0
  76. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/query_api.py +0 -0
  77. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/runtime_bootstrap.py +0 -0
  78. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/sanitization_ollama_config.py +0 -0
  79. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/shell.py +0 -0
  80. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/signal.py +0 -0
  81. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/signal_extraction_config.py +0 -0
  82. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/source_install.py +0 -0
  83. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/source_scrub.py +0 -0
  84. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/sources.py +0 -0
  85. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/sources_overview.py +0 -0
  86. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/sync.py +0 -0
  87. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/tool_index.py +0 -0
  88. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/ui_config.py +0 -0
  89. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/uma_data.py +0 -0
  90. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/upgrades.py +0 -0
  91. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/usage.py +0 -0
  92. {topos_node-1.3.7 → topos_node-1.3.8}/topos/api/user_identity.py +0 -0
  93. {topos_node-1.3.7 → topos_node-1.3.8}/topos/app.py +0 -0
  94. {topos_node-1.3.7 → topos_node-1.3.8}/topos/auth.py +0 -0
  95. {topos_node-1.3.7 → topos_node-1.3.8}/topos/canonicalization/__init__.py +0 -0
  96. {topos_node-1.3.7 → topos_node-1.3.8}/topos/canonicalization/mappers/__init__.py +0 -0
  97. {topos_node-1.3.7 → topos_node-1.3.8}/topos/canonicalization/mappers/base.py +0 -0
  98. {topos_node-1.3.7 → topos_node-1.3.8}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
  99. {topos_node-1.3.7 → topos_node-1.3.8}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
  100. {topos_node-1.3.7 → topos_node-1.3.8}/topos/canonicalization/mappers/demo_mappers.py +0 -0
  101. {topos_node-1.3.7 → topos_node-1.3.8}/topos/canonicalization/mappers/documents_mapper.py +0 -0
  102. {topos_node-1.3.7 → topos_node-1.3.8}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
  103. {topos_node-1.3.7 → topos_node-1.3.8}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
  104. {topos_node-1.3.7 → topos_node-1.3.8}/topos/canonicalization/mappers/grok_mapper.py +0 -0
  105. {topos_node-1.3.7 → topos_node-1.3.8}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
  106. {topos_node-1.3.7 → topos_node-1.3.8}/topos/canonicalization/models.py +0 -0
  107. {topos_node-1.3.7 → topos_node-1.3.8}/topos/canonicalization/resolver.py +0 -0
  108. {topos_node-1.3.7 → topos_node-1.3.8}/topos/cli/__init__.py +0 -0
  109. {topos_node-1.3.7 → topos_node-1.3.8}/topos/cli/__main__.py +0 -0
  110. {topos_node-1.3.7 → topos_node-1.3.8}/topos/cli/assets/topos_blk_rounded.png +0 -0
  111. {topos_node-1.3.7 → topos_node-1.3.8}/topos/cli/assets/topos_white.png +0 -0
  112. {topos_node-1.3.7 → topos_node-1.3.8}/topos/cli/commands.py +0 -0
  113. {topos_node-1.3.7 → topos_node-1.3.8}/topos/cli/reprocess_cmd.py +0 -0
  114. {topos_node-1.3.7 → topos_node-1.3.8}/topos/config/__init__.py +0 -0
  115. {topos_node-1.3.7 → topos_node-1.3.8}/topos/config/conversation_context_llm.py +0 -0
  116. {topos_node-1.3.7 → topos_node-1.3.8}/topos/config/facts_llm.py +0 -0
  117. {topos_node-1.3.7 → topos_node-1.3.8}/topos/config/model_packs.py +0 -0
  118. {topos_node-1.3.7 → topos_node-1.3.8}/topos/config/sanitization_ollama.py +0 -0
  119. {topos_node-1.3.7 → topos_node-1.3.8}/topos/config/settings.py +0 -0
  120. {topos_node-1.3.7 → topos_node-1.3.8}/topos/config/signal_extraction.py +0 -0
  121. {topos_node-1.3.7 → topos_node-1.3.8}/topos/config/uvicorn_logging.json +0 -0
  122. {topos_node-1.3.7 → topos_node-1.3.8}/topos/contacts/__init__.py +0 -0
  123. {topos_node-1.3.7 → topos_node-1.3.8}/topos/contacts/identity.py +0 -0
  124. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/__init__.py +0 -0
  125. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/api_models.py +0 -0
  126. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/connection_resilience.py +0 -0
  127. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/device_helpers.py +0 -0
  128. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/errors.py +0 -0
  129. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/events.py +0 -0
  130. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/__init__.py +0 -0
  131. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/common.py +0 -0
  132. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/complexity.py +0 -0
  133. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/config.py +0 -0
  134. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/contacts_import.py +0 -0
  135. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/database_explorer.py +0 -0
  136. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/device.py +0 -0
  137. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/enrichment.py +0 -0
  138. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/enrichment_lab.py +0 -0
  139. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/filter_lab.py +0 -0
  140. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/graph_query.py +0 -0
  141. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/home_chat.py +0 -0
  142. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/messages.py +0 -0
  143. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/messenger_analytics.py +0 -0
  144. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/query.py +0 -0
  145. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/registry.py +0 -0
  146. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/routines.py +0 -0
  147. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/signal_features.py +0 -0
  148. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/sources.py +0 -0
  149. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/timeline_daily.py +0 -0
  150. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/tool_index.py +0 -0
  151. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/handlers/uma.py +0 -0
  152. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/logging.py +0 -0
  153. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/metrics.py +0 -0
  154. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/routine_access.py +0 -0
  155. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/startup_banner.py +0 -0
  156. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/table_layers.py +0 -0
  157. {topos_node-1.3.7 → topos_node-1.3.8}/topos/core/types.py +0 -0
  158. {topos_node-1.3.7 → topos_node-1.3.8}/topos/data_explorer_row_delete.py +0 -0
  159. {topos_node-1.3.7 → topos_node-1.3.8}/topos/data_explorer_table_prefs.py +0 -0
  160. {topos_node-1.3.7 → topos_node-1.3.8}/topos/data_explorer_tables.py +0 -0
  161. {topos_node-1.3.7 → topos_node-1.3.8}/topos/disclosure/__init__.py +0 -0
  162. {topos_node-1.3.7 → topos_node-1.3.8}/topos/disclosure/canonical_writer.py +0 -0
  163. {topos_node-1.3.7 → topos_node-1.3.8}/topos/disclosure/content_policy.py +0 -0
  164. {topos_node-1.3.7 → topos_node-1.3.8}/topos/disclosure/field_registry.py +0 -0
  165. {topos_node-1.3.7 → topos_node-1.3.8}/topos/disclosure/privacy_layer.py +0 -0
  166. {topos_node-1.3.7 → topos_node-1.3.8}/topos/disclosure/tier.py +0 -0
  167. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/__init__.py +0 -0
  168. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/backends/__init__.py +0 -0
  169. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/backends/base.py +0 -0
  170. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/backends/generative_prompts.py +0 -0
  171. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/backends/generative_response.py +0 -0
  172. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/backends/huggingface.py +0 -0
  173. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/backends/ollama.py +0 -0
  174. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/backends/openai.py +0 -0
  175. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/backends/openai_compatible.py +0 -0
  176. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/backends/redpill.py +0 -0
  177. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/backends/stub.py +0 -0
  178. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/client.py +0 -0
  179. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/engine.py +0 -0
  180. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/intake.py +0 -0
  181. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/memory_utils.py +0 -0
  182. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/model_cache.py +0 -0
  183. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/pipeline_memory.py +0 -0
  184. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/queue_manager.py +0 -0
  185. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/registration.py +0 -0
  186. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/result_formatter.py +0 -0
  187. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/router.py +0 -0
  188. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/scoped_token.py +0 -0
  189. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/tasks.py +0 -0
  190. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/transport.py +0 -0
  191. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/usage_guard.py +0 -0
  192. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/usage_observation.py +0 -0
  193. {topos_node-1.3.7 → topos_node-1.3.8}/topos/engine/validator.py +0 -0
  194. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/__init__.py +0 -0
  195. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/catalog.py +0 -0
  196. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/derivation_recovery.py +0 -0
  197. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/derived_tables.py +0 -0
  198. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/job_writer.py +0 -0
  199. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/__init__.py +0 -0
  200. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/base.py +0 -0
  201. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/__init__.py +0 -0
  202. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
  203. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
  204. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
  205. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
  206. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +0 -0
  207. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
  208. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
  209. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
  210. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
  211. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
  212. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
  213. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
  214. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
  215. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
  216. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/url_classification_core.py +0 -0
  217. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/url_classification_enrichment_job.py +0 -0
  218. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/canonical/url_classification_signal_job.py +0 -0
  219. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/raw/__init__.py +0 -0
  220. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
  221. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/raw/language_job.py +0 -0
  222. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
  223. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
  224. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/model_overrides.py +0 -0
  225. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/models/__init__.py +0 -0
  226. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/models/manager.py +0 -0
  227. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/models/mvp_defaults.py +0 -0
  228. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/models/registry.py +0 -0
  229. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/models/versioning.py +0 -0
  230. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/pipeline_activity.py +0 -0
  231. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/processor.py +0 -0
  232. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/progress_bar.py +0 -0
  233. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/registry_contract.py +0 -0
  234. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/signal_derivation_config.json +0 -0
  235. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/source_overrides.py +0 -0
  236. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment/website_classifier.py +0 -0
  237. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment_lab/__init__.py +0 -0
  238. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment_lab/bundles.py +0 -0
  239. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment_lab/model_resolve.py +0 -0
  240. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment_lab/schema.py +0 -0
  241. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment_lab/service.py +0 -0
  242. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment_lab/store.py +0 -0
  243. {topos_node-1.3.7 → topos_node-1.3.8}/topos/enrichment_lab/worker.py +0 -0
  244. {topos_node-1.3.7 → topos_node-1.3.8}/topos/evals/__init__.py +0 -0
  245. {topos_node-1.3.7 → topos_node-1.3.8}/topos/evals/enrichment_eval.py +0 -0
  246. {topos_node-1.3.7 → topos_node-1.3.8}/topos/extensions.py +0 -0
  247. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/__init__.py +0 -0
  248. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/canonical.py +0 -0
  249. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/engine.py +0 -0
  250. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/entropy.py +0 -0
  251. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/focus.py +0 -0
  252. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/graph_metrics.py +0 -0
  253. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/influence.py +0 -0
  254. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/projection.py +0 -0
  255. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/snapshots.py +0 -0
  256. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/store.py +0 -0
  257. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/topic_merge.py +0 -0
  258. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/topics.py +0 -0
  259. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/topics_daily.py +0 -0
  260. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/complexity/volatility.py +0 -0
  261. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/__init__.py +0 -0
  262. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/affinity.py +0 -0
  263. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/affinity_owner.py +0 -0
  264. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/affinity_quality.py +0 -0
  265. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/consolidation.py +0 -0
  266. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/context_vectors.py +0 -0
  267. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/cypher.py +0 -0
  268. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/declared_mappings.py +0 -0
  269. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/dossier.py +0 -0
  270. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/edges.py +0 -0
  271. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/fact_materializer.py +0 -0
  272. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/graph_enrichers.py +0 -0
  273. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/graph_search.py +0 -0
  274. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/linking.py +0 -0
  275. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/maintenance.py +0 -0
  276. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/reads.py +0 -0
  277. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/rebuild_subprocess.py +0 -0
  278. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/entities/resolver.py +0 -0
  279. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/facts/__init__.py +0 -0
  280. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/facts/extract.py +0 -0
  281. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/facts/llm_extract.py +0 -0
  282. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/facts/reads.py +0 -0
  283. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/facts/store.py +0 -0
  284. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/facts/verdicts.py +0 -0
  285. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/fit/evaluator.py +0 -0
  286. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/fit/opportunity_types.json +0 -0
  287. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/lifecycle/__init__.py +0 -0
  288. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/lifecycle/blackhole.py +0 -0
  289. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/lifecycle/blackhole_guard.py +0 -0
  290. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/lifecycle/blackhole_llm.py +0 -0
  291. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/lifecycle/blackhole_rebuild.py +0 -0
  292. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/lifecycle/derived_scrub.py +0 -0
  293. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/lifecycle/exclusions.py +0 -0
  294. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/lifecycle/gc.py +0 -0
  295. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/provenance/__init__.py +0 -0
  296. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/provenance/posture.py +0 -0
  297. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/provenance/roles.py +0 -0
  298. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/__init__.py +0 -0
  299. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/brief_canonical_loader.py +0 -0
  300. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/brief_ontology.py +0 -0
  301. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/brief_renderer.py +0 -0
  302. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/brief_schemas.py +0 -0
  303. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/chunking.py +0 -0
  304. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/cluster_labels.py +0 -0
  305. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/conversation_context.py +0 -0
  306. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/data_health.py +0 -0
  307. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/definitions/brief_ontologies.json +0 -0
  308. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/definitions/intentions.json +0 -0
  309. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/definitions/profile.json +0 -0
  310. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/definitions/relationships.json +0 -0
  311. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
  312. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/definitions/time.json +0 -0
  313. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/definitions/work.json +0 -0
  314. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/derived_spec.py +0 -0
  315. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/dimension_briefs.py +0 -0
  316. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/dimension_definition_loader.py +0 -0
  317. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/dimension_profiles.py +0 -0
  318. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/dimension_registry.py +0 -0
  319. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/embed_context.py +0 -0
  320. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/extraction/artifact_router.py +0 -0
  321. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/extraction/artifact_store.py +0 -0
  322. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/extraction/rule_extractors.py +0 -0
  323. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/graph_sanitize.py +0 -0
  324. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/hybrid_search.py +0 -0
  325. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/incremental_clustering.py +0 -0
  326. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/model_recommendations.py +0 -0
  327. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/query_embed_cache.py +0 -0
  328. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/schemas.py +0 -0
  329. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/service.py +0 -0
  330. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/signal_object_store.py +0 -0
  331. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/source_hydration.py +0 -0
  332. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/structured_signal.py +0 -0
  333. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/tool_index.py +0 -0
  334. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/topic_clustering.py +0 -0
  335. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/typed_stores/aggregates.py +0 -0
  336. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/typed_stores/commitments.py +0 -0
  337. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/typed_stores/rhythm.py +0 -0
  338. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
  339. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/vector_codec.py +0 -0
  340. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/vector_math.py +0 -0
  341. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/signal/vector_settings.py +0 -0
  342. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/stats/__init__.py +0 -0
  343. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/stats/definitions.py +0 -0
  344. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/stats/engine.py +0 -0
  345. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/stats/fold.py +0 -0
  346. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/stats/insights.py +0 -0
  347. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/timeline_projection.py +0 -0
  348. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/timeline_rollup.py +0 -0
  349. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/triage/__init__.py +0 -0
  350. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/triage/badges.py +0 -0
  351. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/triage/daily.py +0 -0
  352. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/triage/dashboard.py +0 -0
  353. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/triage/instruments.py +0 -0
  354. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/triage/intents.py +0 -0
  355. {topos_node-1.3.7 → topos_node-1.3.8}/topos/features/triage/readiness.py +0 -0
  356. {topos_node-1.3.7 → topos_node-1.3.8}/topos/filter_lab/__init__.py +0 -0
  357. {topos_node-1.3.7 → topos_node-1.3.8}/topos/filter_lab/bundles.py +0 -0
  358. {topos_node-1.3.7 → topos_node-1.3.8}/topos/filter_lab/schema.py +0 -0
  359. {topos_node-1.3.7 → topos_node-1.3.8}/topos/filter_lab/service.py +0 -0
  360. {topos_node-1.3.7 → topos_node-1.3.8}/topos/filter_lab/store.py +0 -0
  361. {topos_node-1.3.7 → topos_node-1.3.8}/topos/filter_lab/worker.py +0 -0
  362. {topos_node-1.3.7 → topos_node-1.3.8}/topos/home_chat/__init__.py +0 -0
  363. {topos_node-1.3.7 → topos_node-1.3.8}/topos/home_chat/schema.py +0 -0
  364. {topos_node-1.3.7 → topos_node-1.3.8}/topos/home_chat/store.py +0 -0
  365. {topos_node-1.3.7 → topos_node-1.3.8}/topos/hosted_pool_lease.py +0 -0
  366. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/__init__.py +0 -0
  367. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/checkpoints/__init__.py +0 -0
  368. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
  369. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
  370. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/inbox_crypto.py +0 -0
  371. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/inbox_drain.py +0 -0
  372. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/jobs.py +0 -0
  373. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/journal_location_fanout.py +0 -0
  374. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/journal_time_log_normalize.py +0 -0
  375. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/local_sync.py +0 -0
  376. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/log_preview.py +0 -0
  377. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parser.py +0 -0
  378. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parsers/__init__.py +0 -0
  379. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parsers/base.py +0 -0
  380. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parsers/browser_parser.py +0 -0
  381. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parsers/calendar_parser.py +0 -0
  382. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
  383. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
  384. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
  385. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parsers/documents_parser.py +0 -0
  386. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parsers/github_activity_parser.py +0 -0
  387. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
  388. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parsers/grok_parser.py +0 -0
  389. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parsers/messenger_parser.py +0 -0
  390. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/parsers/voxterm_parser.py +0 -0
  391. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/progress.py +0 -0
  392. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/sources/__init__.py +0 -0
  393. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/sources/base.py +0 -0
  394. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/sources/calendar.py +0 -0
  395. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/sources/chatgpt.py +0 -0
  396. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/sources/contact_importers.py +0 -0
  397. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/sources/grok.py +0 -0
  398. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/sources/imessage_reader.py +0 -0
  399. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/sources/signal_export_parser.py +0 -0
  400. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/sources/signal_reader.py +0 -0
  401. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/state_machine.py +0 -0
  402. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/triggers/__init__.py +0 -0
  403. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/triggers/file_trigger.py +0 -0
  404. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
  405. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/usage_inbox_dedupe.py +0 -0
  406. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/validation/__init__.py +0 -0
  407. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/validation/base.py +0 -0
  408. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/validation/schema_registry.py +0 -0
  409. {topos_node-1.3.7 → topos_node-1.3.8}/topos/ingestion/validation/schema_validator.py +0 -0
  410. {topos_node-1.3.7 → topos_node-1.3.8}/topos/lineage/__init__.py +0 -0
  411. {topos_node-1.3.7 → topos_node-1.3.8}/topos/lineage/provenance.py +0 -0
  412. {topos_node-1.3.7 → topos_node-1.3.8}/topos/lineage/tracker.py +0 -0
  413. {topos_node-1.3.7 → topos_node-1.3.8}/topos/llm_integrations_storage.py +0 -0
  414. {topos_node-1.3.7 → topos_node-1.3.8}/topos/mcp_stdio_proxy.py +0 -0
  415. {topos_node-1.3.7 → topos_node-1.3.8}/topos/observability/__init__.py +0 -0
  416. {topos_node-1.3.7 → topos_node-1.3.8}/topos/observability/alerts.py +0 -0
  417. {topos_node-1.3.7 → topos_node-1.3.8}/topos/observability/metrics.py +0 -0
  418. {topos_node-1.3.7 → topos_node-1.3.8}/topos/observability/tracing.py +0 -0
  419. {topos_node-1.3.7 → topos_node-1.3.8}/topos/openai_client.py +0 -0
  420. {topos_node-1.3.7 → topos_node-1.3.8}/topos/pipeline/__init__.py +0 -0
  421. {topos_node-1.3.7 → topos_node-1.3.8}/topos/pipeline/audit.py +0 -0
  422. {topos_node-1.3.7 → topos_node-1.3.8}/topos/pipeline/envelope.py +0 -0
  423. {topos_node-1.3.7 → topos_node-1.3.8}/topos/pipeline/job_runner.py +0 -0
  424. {topos_node-1.3.7 → topos_node-1.3.8}/topos/pipeline/job_store.py +0 -0
  425. {topos_node-1.3.7 → topos_node-1.3.8}/topos/pipeline/stages.py +0 -0
  426. {topos_node-1.3.7 → topos_node-1.3.8}/topos/pipeline/stub_enqueue.py +0 -0
  427. {topos_node-1.3.7 → topos_node-1.3.8}/topos/projections/__init__.py +0 -0
  428. {topos_node-1.3.7 → topos_node-1.3.8}/topos/projections/vector_index/__init__.py +0 -0
  429. {topos_node-1.3.7 → topos_node-1.3.8}/topos/projections/vector_index/base.py +0 -0
  430. {topos_node-1.3.7 → topos_node-1.3.8}/topos/projections/vector_index/builders.py +0 -0
  431. {topos_node-1.3.7 → topos_node-1.3.8}/topos/projections/vector_index/health_checks.py +0 -0
  432. {topos_node-1.3.7 → topos_node-1.3.8}/topos/protocol/__init__.py +0 -0
  433. {topos_node-1.3.7 → topos_node-1.3.8}/topos/protocol/handled_message_types.json +0 -0
  434. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/__init__.py +0 -0
  435. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/audit.py +0 -0
  436. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/cohort_resolvers.py +0 -0
  437. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/ddr.py +0 -0
  438. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/disclosure.py +0 -0
  439. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/fingerprint.py +0 -0
  440. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/game_layer.py +0 -0
  441. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/grant_cache.py +0 -0
  442. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/inference.py +0 -0
  443. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/intent.py +0 -0
  444. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/manifest.py +0 -0
  445. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/manifest_validation.py +0 -0
  446. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/minimizer.py +0 -0
  447. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/negotiation.py +0 -0
  448. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/pipeline.py +0 -0
  449. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/planner.py +0 -0
  450. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/retrieval.py +0 -0
  451. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/runtime.py +0 -0
  452. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/scope_registry_loader.py +0 -0
  453. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/session.py +0 -0
  454. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/session_utils.py +0 -0
  455. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/source_generation.py +0 -0
  456. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/truth_facts.py +0 -0
  457. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/truth_prompts.py +0 -0
  458. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/turn_classifier.py +0 -0
  459. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/types.py +0 -0
  460. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/verify.py +0 -0
  461. {topos_node-1.3.7 → topos_node-1.3.8}/topos/query/verify_modes.py +0 -0
  462. {topos_node-1.3.7 → topos_node-1.3.8}/topos/rate_limit.py +0 -0
  463. {topos_node-1.3.7 → topos_node-1.3.8}/topos/routines/__init__.py +0 -0
  464. {topos_node-1.3.7 → topos_node-1.3.8}/topos/routines/schema.py +0 -0
  465. {topos_node-1.3.7 → topos_node-1.3.8}/topos/routines/store.py +0 -0
  466. {topos_node-1.3.7 → topos_node-1.3.8}/topos/runtime_housekeeping.py +0 -0
  467. {topos_node-1.3.7 → topos_node-1.3.8}/topos/runtime_shutdown.py +0 -0
  468. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sanitization/__init__.py +0 -0
  469. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sanitization/nsfw_classifier.py +0 -0
  470. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sanitization/ollama_transforms.py +0 -0
  471. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sanitization/prewarm.py +0 -0
  472. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sanitization/privacy_filter.py +0 -0
  473. {topos_node-1.3.7 → topos_node-1.3.8}/topos/scope_resolution.py +0 -0
  474. {topos_node-1.3.7 → topos_node-1.3.8}/topos/services/__init__.py +0 -0
  475. {topos_node-1.3.7 → topos_node-1.3.8}/topos/services/container.py +0 -0
  476. {topos_node-1.3.7 → topos_node-1.3.8}/topos/services/embeddings/__init__.py +0 -0
  477. {topos_node-1.3.7 → topos_node-1.3.8}/topos/services/embeddings/base.py +0 -0
  478. {topos_node-1.3.7 → topos_node-1.3.8}/topos/services/embeddings/local.py +0 -0
  479. {topos_node-1.3.7 → topos_node-1.3.8}/topos/services/embeddings/remote.py +0 -0
  480. {topos_node-1.3.7 → topos_node-1.3.8}/topos/services/interfaces.py +0 -0
  481. {topos_node-1.3.7 → topos_node-1.3.8}/topos/services/llm/__init__.py +0 -0
  482. {topos_node-1.3.7 → topos_node-1.3.8}/topos/services/llm/base.py +0 -0
  483. {topos_node-1.3.7 → topos_node-1.3.8}/topos/services/llm/openai.py +0 -0
  484. {topos_node-1.3.7 → topos_node-1.3.8}/topos/services/local.py +0 -0
  485. {topos_node-1.3.7 → topos_node-1.3.8}/topos/services/postgres.py +0 -0
  486. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sources/__init__.py +0 -0
  487. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sources/bundled_canonical_triples.py +0 -0
  488. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sources/canonical_signal_defaults.py +0 -0
  489. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sources/definitions.py +0 -0
  490. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sources/install_service.py +0 -0
  491. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sources/registry.py +0 -0
  492. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sources/runtime_install.py +0 -0
  493. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sources/scrub_attribution.py +0 -0
  494. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sources/scrub_service.py +0 -0
  495. {topos_node-1.3.7 → topos_node-1.3.8}/topos/startup_banner.py +0 -0
  496. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/__init__.py +0 -0
  497. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/adapters/__init__.py +0 -0
  498. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/adapters/factory.py +0 -0
  499. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/adapters/fakes.py +0 -0
  500. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/adapters/postgres/stores.py +0 -0
  501. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/adapters/protocols.py +0 -0
  502. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/adapters/sqlite/__init__.py +0 -0
  503. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/adapters/sqlite/stores.py +0 -0
  504. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/adapters/sqlite/vector_search.py +0 -0
  505. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/canonical/__init__.py +0 -0
  506. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/canonical/activity_tables.py +0 -0
  507. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/canonical/ai_chat/__init__.py +0 -0
  508. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
  509. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/canonical/ai_chat/mapper.py +0 -0
  510. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/canonical/ai_chat/model.py +0 -0
  511. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/canonical/ai_chat/tables.py +0 -0
  512. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
  513. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/canonical/canonical_store.py +0 -0
  514. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/canonical/conversations_tables.py +0 -0
  515. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/canonical/mapping_store.py +0 -0
  516. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/canonical/postgres.py +0 -0
  517. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/__init__.py +0 -0
  518. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/client.py +0 -0
  519. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/connection_tuning.py +0 -0
  520. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
  521. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/actor_role_v1.py +0 -0
  522. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/affinity_pair_labels_v1.py +0 -0
  523. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
  524. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
  525. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/backup.py +0 -0
  526. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
  527. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
  528. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
  529. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
  530. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/complexity_v1.py +0 -0
  531. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
  532. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
  533. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/documents_v1.py +0 -0
  534. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/enrichment_spec_version_v1.py +0 -0
  535. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/entity_affinity_v1.py +0 -0
  536. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/entity_blackhole_v1.py +0 -0
  537. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/entity_context_vectors_v1.py +0 -0
  538. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/entity_context_vectors_v2.py +0 -0
  539. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
  540. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/entity_mentions_authored_v1.py +0 -0
  541. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/episodes_v1.py +0 -0
  542. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
  543. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
  544. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
  545. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
  546. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
  547. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
  548. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/message_emotions_role_backfill_v1.py +0 -0
  549. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/message_emotions_role_v1.py +0 -0
  550. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
  551. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/registry.py +0 -0
  552. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/registry_checksums.json +0 -0
  553. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/remediation_person_model.py +0 -0
  554. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/scope_source_generation.py +0 -0
  555. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
  556. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
  557. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/signal_objects.py +0 -0
  558. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
  559. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
  560. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/signal_summaries_drop_v1.py +0 -0
  561. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
  562. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
  563. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
  564. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
  565. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
  566. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
  567. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
  568. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
  569. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
  570. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
  571. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
  572. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
  573. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
  574. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
  575. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
  576. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
  577. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
  578. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
  579. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
  580. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/paths.py +0 -0
  581. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/postgres.py +0 -0
  582. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/schema.py +0 -0
  583. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/db/storage_breakdown.py +0 -0
  584. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/enrichment/__init__.py +0 -0
  585. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
  586. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
  587. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/normalized/__init__.py +0 -0
  588. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/normalized/normalized_store.py +0 -0
  589. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/oplog/__init__.py +0 -0
  590. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/oplog/decision.py +0 -0
  591. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/oplog/oplog_store.py +0 -0
  592. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/oplog/postgres.py +0 -0
  593. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/person/identity_resolver.py +0 -0
  594. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/projections/__init__.py +0 -0
  595. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/projections/index_ops_store.py +0 -0
  596. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/projections/vector_index_store.py +0 -0
  597. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/raw/__init__.py +0 -0
  598. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/raw/browser_flat_tables.py +0 -0
  599. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/raw/file_store.py +0 -0
  600. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/raw/raw_store.py +0 -0
  601. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/raw/raw_tables_manager.py +0 -0
  602. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/raw/sqlite_raw_store.py +0 -0
  603. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/security/encryption.py +0 -0
  604. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/signal_identity.py +0 -0
  605. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/source_settings.py +0 -0
  606. {topos_node-1.3.7 → topos_node-1.3.8}/topos/storage/user_identity.py +0 -0
  607. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sync/__init__.py +0 -0
  608. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sync/client.py +0 -0
  609. {topos_node-1.3.7 → topos_node-1.3.8}/topos/sync_handlers.py +0 -0
  610. {topos_node-1.3.7 → topos_node-1.3.8}/topos/testing/__init__.py +0 -0
  611. {topos_node-1.3.7 → topos_node-1.3.8}/topos/uma_contact_enrichment.py +0 -0
  612. {topos_node-1.3.7 → topos_node-1.3.8}/topos/uma_filters.py +0 -0
  613. {topos_node-1.3.7 → topos_node-1.3.8}/topos/uma_resource_id.py +0 -0
  614. {topos_node-1.3.7 → topos_node-1.3.8}/topos/uma_rpt.py +0 -0
  615. {topos_node-1.3.7 → topos_node-1.3.8}/topos/upgrades/__init__.py +0 -0
  616. {topos_node-1.3.7 → topos_node-1.3.8}/topos/utils/base_object.py +0 -0
  617. {topos_node-1.3.7 → topos_node-1.3.8}/topos/websocket_client.py +0 -0
  618. {topos_node-1.3.7 → topos_node-1.3.8}/topos_node.egg-info/SOURCES.txt +0 -0
  619. {topos_node-1.3.7 → topos_node-1.3.8}/topos_node.egg-info/dependency_links.txt +0 -0
  620. {topos_node-1.3.7 → topos_node-1.3.8}/topos_node.egg-info/entry_points.txt +0 -0
  621. {topos_node-1.3.7 → topos_node-1.3.8}/topos_node.egg-info/requires.txt +0 -0
  622. {topos_node-1.3.7 → topos_node-1.3.8}/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.7
3
+ Version: 1.3.8
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.7"
7
+ version = "1.3.8"
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.7"
4
- __version_info__ = (1, 3, 7)
3
+ __version__ = "1.3.8"
4
+ __version_info__ = (1, 3, 8)
5
5
 
6
6
  __all__ = ["__version__", "__version_info__"]
@@ -329,6 +329,8 @@ class ToposTray:
329
329
  items.append("Show Logs")
330
330
  if self.update.get("applying"):
331
331
  items.append("Installing update…")
332
+ elif self.update.get("last_result") == "failed":
333
+ items.append("Update failed — click to retry")
332
334
  elif self.update.get("last_result") == "success":
333
335
  items.append("Update installed — restart to finish")
334
336
  elif self.update.get("available"):
@@ -368,6 +370,10 @@ class ToposTray:
368
370
  items.append(pystray.MenuItem("Show Logs", self._show_logs))
369
371
  if self.update.get("applying"):
370
372
  items.append(pystray.MenuItem("Installing update…", None, enabled=False))
373
+ elif self.update.get("last_result") == "failed":
374
+ # Clickable: a failed update that renders nothing is
375
+ # indistinguishable from a click that never registered.
376
+ items.append(pystray.MenuItem("Update failed — click to retry", self._apply_update))
371
377
  elif self.update.get("last_result") == "success":
372
378
  items.append(pystray.MenuItem("Update installed — restart to finish", None, enabled=False))
373
379
  elif self.update.get("available"):
@@ -29,6 +29,12 @@ logger = logging.getLogger("topos.control_plane_client")
29
29
 
30
30
  # Lightweight CP RPCs that must stay responsive while ingest/enrichment runs.
31
31
  # UI-critical reads and scheduler ops only — no ingest/enrichment writes.
32
+ #: Keepalive. The control plane's own uvicorn pings at 30s with a 120s
33
+ #: deadline; the node pings faster so IT notices a dead link first and
34
+ #: reconnects, rather than waiting to be evicted.
35
+ PING_INTERVAL_SECONDS = 20.0
36
+ PING_TIMEOUT_SECONDS = 20.0
37
+
32
38
  _FAST_INBOUND_MESSAGE_TYPES = frozenset(
33
39
  {
34
40
  "healthcheck",
@@ -297,9 +303,20 @@ class ControlPlaneClient:
297
303
  self.control_plane_url,
298
304
  additional_headers=headers,
299
305
  ssl=ssl_context,
300
- # Transform-heavy requests can block the event loop in the handler path long enough
301
- # to miss pong deadlines; disable pong timeout-driven disconnects.
302
- ping_timeout=None,
306
+ # A real pong deadline, restored once the client got its own
307
+ # thread and loop. It was disabled because handlers ran here
308
+ # and could block long enough to miss pongs — that reason is
309
+ # gone: handlers now marshal to the app loop, so this loop is
310
+ # always free to answer and to notice silence.
311
+ #
312
+ # Disabling it turned every silent connection death into a
313
+ # permanent wedge: `async for raw in ws` blocked forever, no
314
+ # exception fired, no reconnect was scheduled, and the node
315
+ # reported "connected" while the control plane had no socket
316
+ # at all. Observed live 2026-08-08 — 25 minutes wedged, with
317
+ # the web app correctly showing the Topos offline.
318
+ ping_interval=PING_INTERVAL_SECONDS,
319
+ ping_timeout=PING_TIMEOUT_SECONDS,
303
320
  ) as ws:
304
321
  self._ws = ws
305
322
  self._set_state("connected")
@@ -215,20 +215,30 @@ async def handle_app_ingest(message: Dict[str, Any]) -> Optional[Dict[str, Any]]
215
215
  len(errors),
216
216
  errors[0].get("error"),
217
217
  )
218
- db_conn = hub.get_db_connection()
219
- if db_conn and user_id:
218
+ if user_id:
220
219
  resource_id = (payload.get("resource_id") or "").strip() or f"dataset:{user_id}:{dataset_id or 'default'}"
221
- hub.record_uma_request(
222
- db_conn,
223
- owner_user_id=user_id,
224
- resource_id=resource_id,
225
- request_type="write",
226
- endpoint="app_ingest",
227
- requesting_user_id=(payload.get("requesting_user_id") or None),
228
- app_id=payload.get("app_id"),
229
- requesting_user_email=(payload.get("requesting_user_email") or "").strip() or None,
230
- access_channel=(payload.get("access_channel") or "internal").strip() or "internal",
231
- )
220
+
221
+ def _record_app_ingest_uma() -> None:
222
+ # record_uma_request takes the write gate (and on first use runs
223
+ # the uma_access_requests ensure/migrate DDL) — keep it off the
224
+ # event-loop thread. Own connection: get_db_connection is
225
+ # thread-local.
226
+ own = hub.get_db_connection()
227
+ if own is None:
228
+ return
229
+ hub.record_uma_request(
230
+ own,
231
+ owner_user_id=user_id,
232
+ resource_id=resource_id,
233
+ request_type="write",
234
+ endpoint="app_ingest",
235
+ requesting_user_id=(payload.get("requesting_user_id") or None),
236
+ app_id=payload.get("app_id"),
237
+ requesting_user_email=(payload.get("requesting_user_email") or "").strip() or None,
238
+ access_channel=(payload.get("access_channel") or "internal").strip() or "internal",
239
+ )
240
+
241
+ await asyncio.to_thread(_record_app_ingest_uma)
232
242
  response_payload = {
233
243
  "records_processed": processed,
234
244
  "records_total": records_total,
@@ -183,7 +183,9 @@ from ..storage.db.write_gate import ( # noqa: E402
183
183
  batched_writes,
184
184
  commit_connection,
185
185
  db_write_lock,
186
+ register_connection,
186
187
  sqlite_retry_busy,
188
+ unregister_connection,
187
189
  with_db_write,
188
190
  )
189
191
 
@@ -285,6 +287,7 @@ def _get_thread_db_connection(resolved_path: str) -> Optional[sqlite3.Connection
285
287
  _ensure_row_factory(cached)
286
288
  return cached
287
289
  except (sqlite3.ProgrammingError, sqlite3.OperationalError):
290
+ unregister_connection(cached)
288
291
  try:
289
292
  cached.close()
290
293
  except Exception: # noqa: BLE001
@@ -293,6 +296,7 @@ def _get_thread_db_connection(resolved_path: str) -> Optional[sqlite3.Connection
293
296
  _thread_state.path = None
294
297
  elif cached is not None:
295
298
  # Path changed under us (tests re-point DATABASE_PATH).
299
+ unregister_connection(cached)
296
300
  try:
297
301
  cached.close()
298
302
  except Exception: # noqa: BLE001
@@ -314,6 +318,7 @@ def _get_thread_db_connection(resolved_path: str) -> Optional[sqlite3.Connection
314
318
  except Exception as exc: # noqa: BLE001 — tuning is an optimization, not a gate
315
319
  logger.debug("Per-thread connection tuning skipped: %s", exc)
316
320
 
321
+ register_connection(conn)
317
322
  _thread_state.conn = conn
318
323
  _thread_state.path = resolved_path
319
324
  logger.debug(
@@ -329,6 +334,7 @@ def close_thread_db_connection() -> None:
329
334
  conn = getattr(_thread_state, "conn", None)
330
335
  if conn is None:
331
336
  return
337
+ unregister_connection(conn)
332
338
  try:
333
339
  conn.close()
334
340
  except Exception: # noqa: BLE001
@@ -371,6 +377,7 @@ def _get_owner_db_connection() -> Optional[sqlite3.Connection]:
371
377
  try:
372
378
  db_conn.execute("SELECT 1")
373
379
  except (sqlite3.ProgrammingError, sqlite3.OperationalError):
380
+ unregister_connection(db_conn)
374
381
  db_conn = None
375
382
  _db_conn_path = None
376
383
  else:
@@ -398,7 +405,10 @@ def _get_owner_db_connection() -> Optional[sqlite3.Connection]:
398
405
  # it across queries) — closing under them is the use-after-close
399
406
  # that SIGBUSed on 2026-08-08. Dropping the reference lets the last
400
407
  # user finish; the handle closes (rolling back any open
401
- # transaction) when its refcount reaches zero.
408
+ # transaction) when its refcount reaches zero. The watchdog is told
409
+ # here for the same reason it holds no strong reference: it must
410
+ # not be what keeps this handle (or its stale record) around.
411
+ unregister_connection(db_conn)
402
412
  db_conn = None
403
413
  _db_conn_path = None
404
414
 
@@ -410,6 +420,7 @@ def _get_owner_db_connection() -> Optional[sqlite3.Connection]:
410
420
  db_conn.row_factory = sqlite3.Row
411
421
  return db_conn
412
422
  except (sqlite3.ProgrammingError, sqlite3.OperationalError):
423
+ unregister_connection(db_conn)
413
424
  db_conn = None
414
425
  _db_conn_path = None
415
426
 
@@ -425,11 +436,13 @@ def _get_owner_db_connection() -> Optional[sqlite3.Connection]:
425
436
  try:
426
437
  db_conn.execute("SELECT 1")
427
438
  except Exception:
439
+ unregister_connection(db_conn)
428
440
  try:
429
441
  db_conn.close()
430
442
  except Exception: # noqa: BLE001
431
443
  pass
432
444
  else:
445
+ unregister_connection(new_conn)
433
446
  try:
434
447
  new_conn.close()
435
448
  except Exception: # noqa: BLE001
@@ -467,6 +480,11 @@ def _open_owner_db_connection(db_path: Path) -> Optional[sqlite3.Connection]:
467
480
  )
468
481
  except Exception as tuning_exc: # noqa: BLE001
469
482
  logger.warning("Connection tuning skipped: %s", tuning_exc)
483
+ # Registered before migrations run, not after: a migration that returns
484
+ # without committing wedges every writer behind it exactly like any
485
+ # other ungated write, and startup is when the database is least
486
+ # observable.
487
+ register_connection(conn)
470
488
  try:
471
489
  from ..storage.db.migrations import (
472
490
  DowngradeGuardError,
@@ -478,6 +496,7 @@ def _open_owner_db_connection(db_path: Path) -> Optional[sqlite3.Connection]:
478
496
  except (MigrationError, DowngradeGuardError) as migration_exc:
479
497
  # Shape migrations must fail loud — serving a half-migrated DB corrupts data.
480
498
  logger.error("Schema migration failed; refusing to open database: %s", migration_exc)
499
+ unregister_connection(conn)
481
500
  try:
482
501
  conn.close()
483
502
  except Exception: # noqa: BLE001
@@ -490,6 +509,7 @@ def _open_owner_db_connection(db_path: Path) -> Optional[sqlite3.Connection]:
490
509
  "Unexpected schema migration failure; refusing to open database: %s",
491
510
  migration_exc,
492
511
  )
512
+ unregister_connection(conn)
493
513
  try:
494
514
  conn.close()
495
515
  except Exception: # noqa: BLE001
@@ -511,6 +531,7 @@ def _open_owner_db_connection(db_path: Path) -> Optional[sqlite3.Connection]:
511
531
  raise
512
532
  logger.warning("Failed to create database connection: %s", e)
513
533
  if conn is not None:
534
+ unregister_connection(conn)
514
535
  try:
515
536
  conn.close()
516
537
  except Exception: # noqa: BLE001
@@ -7,6 +7,7 @@ unchanged, so re-running a day is safe and cheap.
7
7
 
8
8
  from __future__ import annotations
9
9
 
10
+ import asyncio
10
11
  import logging
11
12
  from typing import Any, Callable, Dict, List, Optional
12
13
 
@@ -34,8 +35,7 @@ class AttentionTriageJob(BaseEnrichmentJob):
34
35
  canonical_messages: List[Dict[str, Any]],
35
36
  progress_callback: Optional[Callable[[int, int], None]] = None,
36
37
  ) -> List[Dict[str, Any]]:
37
- conn = get_db_connection()
38
- if conn is None:
38
+ if get_db_connection() is None:
39
39
  return [{"_deferred": True, "error": "database_unavailable"}]
40
40
  days = set()
41
41
  for row in canonical_messages:
@@ -46,17 +46,37 @@ class AttentionTriageJob(BaseEnrichmentJob):
46
46
  break
47
47
  done = 0
48
48
  for day_iso in sorted(days):
49
+ # A day's re-triage holds the write gate — a blocking OS lock — for
50
+ # its verdict upserts and signal objects. Held on the event loop it
51
+ # stalls every coroutine, including the control-plane keepalive, so
52
+ # each day runs on a worker thread against that thread's own
53
+ # connection. One day per hop also keeps progress incremental.
54
+ def _triage(_day: str = day_iso) -> Optional[Dict[str, Any]]:
55
+ conn = get_db_connection()
56
+ if conn is None:
57
+ return None
58
+ return run_daily_triage(conn, _day)
59
+
49
60
  try:
50
- summary = run_daily_triage(conn, day_iso)
51
- logger.info("attention_triage %s: %s", day_iso, summary.get("quadrants"))
61
+ summary = await asyncio.to_thread(_triage)
62
+ if summary is not None:
63
+ logger.info("attention_triage %s: %s", day_iso, summary.get("quadrants"))
52
64
  except Exception: # one bad day must not sink the batch
53
65
  logger.exception("attention_triage failed for %s", day_iso)
54
66
  done += 1
55
67
  if progress_callback:
56
68
  progress_callback(done, len(days))
57
- try:
69
+
70
+ def _award() -> Optional[List[Any]]:
71
+ conn = get_db_connection()
72
+ if conn is None:
73
+ return None
58
74
  from ....features.triage.badges import award_badges
59
- fresh = award_badges(conn)
75
+
76
+ return award_badges(conn)
77
+
78
+ try:
79
+ fresh = await asyncio.to_thread(_award)
60
80
  if fresh:
61
81
  logger.info("badges awarded: %s", fresh)
62
82
  except Exception:
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import asyncio
3
4
  import logging
4
5
  from typing import Any, Callable, Dict, List, Optional
5
6
 
@@ -120,26 +121,37 @@ class DimensionSummaryJob(BaseEnrichmentJob):
120
121
 
121
122
  structured_result: Dict[str, Any] = {}
122
123
  if structured_signal_enabled():
123
- structured_result = enrich_structured_batch(
124
- prepared,
125
- source_id=str(source_id or "") or None,
126
- only_dimension=only_dimension,
127
- )
128
- # Piggyback (badge-pass pattern): auto-tag new conversations as
129
- # work/personal with the configured local model. Best-effort;
130
- # owner-set tags are never touched.
131
- try:
132
- from ....features.signal.conversation_context import (
133
- classify_untagged_conversations,
134
- )
135
124
 
136
- structured_result["conversation_context"] = (
137
- classify_untagged_conversations(conn)
125
+ def _structured() -> Dict[str, Any]:
126
+ # Artifact routing, the gate aggregates and the scope
127
+ # materializer each take the write gate — a blocking OS lock
128
+ # that on the event loop stalls every coroutine, including the
129
+ # control-plane keepalive. enrich_structured_batch resolves its
130
+ # own connection, so on a worker thread it binds that thread's.
131
+ out = enrich_structured_batch(
132
+ prepared,
133
+ source_id=str(source_id or "") or None,
134
+ only_dimension=only_dimension,
138
135
  )
139
- except Exception as exc: # noqa: BLE001 — never blocks enrichment
140
- logger.debug("conversation-context pass failed: %s", exc)
136
+ # Piggyback (badge-pass pattern): auto-tag new conversations as
137
+ # work/personal with the configured local model. Best-effort;
138
+ # owner-set tags are never touched.
139
+ try:
140
+ from ....features.signal.conversation_context import (
141
+ classify_untagged_conversations,
142
+ )
143
+
144
+ worker_conn = get_db_connection()
145
+ if worker_conn is not None:
146
+ out["conversation_context"] = classify_untagged_conversations(
147
+ worker_conn
148
+ )
149
+ except Exception as exc: # noqa: BLE001 — never blocks enrichment
150
+ logger.debug("conversation-context pass failed: %s", exc)
151
+ return out
152
+
153
+ structured_result = await asyncio.to_thread(_structured)
141
154
 
142
- store = DimensionBriefStore(conn)
143
155
  updated_dims: List[str] = []
144
156
 
145
157
  for idx, dimension in enumerate(dimensions):
@@ -199,13 +211,34 @@ class DimensionSummaryJob(BaseEnrichmentJob):
199
211
  continue
200
212
  if not any(str(v or "").strip() for v in section_updates.values()):
201
213
  continue
202
- store.merge_system_update(
203
- dimension,
204
- section_updates,
205
- source_id=source_id,
206
- model=result.output.get("model") if result.status == "completed" and result.output else None,
207
- provider=provider,
208
- )
214
+
215
+ def _merge(
216
+ _dimension: str = dimension,
217
+ _updates: Dict[str, Optional[str]] = section_updates,
218
+ _model: Optional[str] = (
219
+ result.output.get("model")
220
+ if result.status == "completed" and result.output
221
+ else None
222
+ ),
223
+ _provider: str = provider,
224
+ ) -> None:
225
+ # merge_system_update ensures the brief head and appends a
226
+ # revision, both under the write gate — a blocking OS lock that
227
+ # on the event loop stalls every coroutine, including the
228
+ # control-plane keepalive. The store binds whichever connection
229
+ # it is built with, so build it on the worker thread.
230
+ worker_conn = get_db_connection()
231
+ if worker_conn is None:
232
+ return
233
+ DimensionBriefStore(worker_conn).merge_system_update(
234
+ _dimension,
235
+ _updates,
236
+ source_id=source_id,
237
+ model=_model,
238
+ provider=_provider,
239
+ )
240
+
241
+ await asyncio.to_thread(_merge)
209
242
  updated_dims.append(dimension)
210
243
  if progress_callback:
211
244
  progress_callback(idx + 1, len(dimensions))
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import asyncio
3
4
  import logging
4
5
  import os
5
6
  from typing import Any, Callable, Dict, List, Optional
@@ -169,7 +170,14 @@ class EntitiesJob(BaseEnrichmentJob):
169
170
 
170
171
  if entity_spine_enabled() and results:
171
172
  try:
172
- self._resolve_into_spine(results, canonical_messages)
173
+ # Spine resolution upserts entities, mentions, edges and
174
+ # dossiers under the write gate — a blocking OS lock that on
175
+ # the event loop stalls every coroutine, including the
176
+ # control-plane keepalive. It resolves its own connection, so
177
+ # on a worker thread it binds that thread's handle.
178
+ await asyncio.to_thread(
179
+ self._resolve_into_spine, results, canonical_messages
180
+ )
173
181
  except Exception as exc:
174
182
  logger.warning("entity spine resolution failed: %s", exc)
175
183
 
@@ -10,6 +10,7 @@ Gated by TOPOS_STATS (default on).
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ import asyncio
13
14
  import logging
14
15
  import os
15
16
  from typing import Any, Callable, Dict, List, Optional
@@ -44,24 +45,37 @@ class StatisticsJob(BaseEnrichmentJob):
44
45
  canonical_messages: List[Dict[str, Any]],
45
46
  progress_callback: Optional[Callable[[int, int], None]] = None,
46
47
  ) -> List[Dict[str, Any]]:
47
- conn = get_db_connection()
48
- if conn is None:
48
+ def _fold_and_promote() -> Optional[Dict[str, Any]]:
49
+ # Every step here takes the write gate — a blocking OS lock:
50
+ # StatsEngine's constructor seeds stat definitions, fold_batch
51
+ # holds it for the batch, and promotion runs migrations through
52
+ # AdapterFactory. On the event loop that stalls every coroutine,
53
+ # including the control-plane keepalive, so the whole stretch runs
54
+ # on a worker thread against that thread's own connection.
55
+ conn = get_db_connection()
56
+ if conn is None:
57
+ return None
58
+
59
+ from ....features.stats.engine import StatsEngine
60
+
61
+ engine = StatsEngine(conn)
62
+ folded = dict(engine.fold_batch(canonical_messages))
63
+ folded["promoted"] = 0
64
+ if self._should_promote(conn, folded["rows_folded"]):
65
+ try:
66
+ from ....storage.adapters.factory import AdapterFactory
67
+
68
+ bundle = AdapterFactory.create("local_database", conn=conn)
69
+ folded["promoted"] = engine.promote_insights(bundle)
70
+ self._record_promotion(conn)
71
+ except Exception as exc:
72
+ logger.warning("stat insight promotion failed: %s", exc)
73
+ return folded
74
+
75
+ result = await asyncio.to_thread(_fold_and_promote)
76
+ if result is None:
49
77
  return [{"_deferred": True, "error": "database_unavailable"}]
50
-
51
- from ....features.stats.engine import StatsEngine
52
-
53
- engine = StatsEngine(conn)
54
- result = engine.fold_batch(canonical_messages)
55
- promoted = 0
56
- if self._should_promote(conn, result["rows_folded"]):
57
- try:
58
- from ....storage.adapters.factory import AdapterFactory
59
-
60
- bundle = AdapterFactory.create("local_database", conn=conn)
61
- promoted = engine.promote_insights(bundle)
62
- self._record_promotion(conn)
63
- except Exception as exc:
64
- logger.warning("stat insight promotion failed: %s", exc)
78
+ promoted = result["promoted"]
65
79
 
66
80
  if progress_callback:
67
81
  progress_callback(len(canonical_messages), len(canonical_messages))
@@ -90,10 +104,18 @@ class StatisticsJob(BaseEnrichmentJob):
90
104
  except (json.JSONDecodeError, TypeError, ValueError):
91
105
  pending = 0
92
106
  pending += rows_folded
93
- conn.execute(
94
- "UPDATE stat_state SET state_json=? WHERE stat_id=? AND group_key='' AND bucket_date=''",
95
- (json.dumps({"pending": pending}), _META_STAT_ID),
96
- )
107
+ # Gated AND committed. Ungated this counter update was still a write: it
108
+ # took SQLite's write lock at execute time on the event loop's
109
+ # connection and, with no commit anywhere after it, held that lock for
110
+ # the rest of the pipeline. Every other thread's first write then waited
111
+ # out the full 30s busy_timeout and failed "database is locked" — which
112
+ # is how this job lost its own fold on repeat ingests.
113
+ with with_db_write():
114
+ conn.execute(
115
+ "UPDATE stat_state SET state_json=? WHERE stat_id=? AND group_key='' AND bucket_date=''",
116
+ (json.dumps({"pending": pending}), _META_STAT_ID),
117
+ )
118
+ commit_connection(conn)
97
119
  if pending >= _PROMOTE_EVERY_ROWS:
98
120
  return True
99
121
  stale = conn.execute(
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import asyncio
5
6
  import logging
6
7
  from typing import Any, Callable, Dict, List, Optional
7
8
 
@@ -27,10 +28,18 @@ class TimelineJob(BaseEnrichmentJob):
27
28
  canonical_messages: List[Dict[str, Any]],
28
29
  progress_callback: Optional[Callable[[int, int], None]] = None,
29
30
  ) -> List[Dict[str, Any]]:
30
- conn = get_db_connection()
31
- if conn is None:
31
+ def _project():
32
+ # project_timeline_rows holds the write gate for the whole batch —
33
+ # a blocking OS lock — so it runs on a worker thread with that
34
+ # thread's own connection, never on the event loop.
35
+ conn = get_db_connection()
36
+ if conn is None:
37
+ return None
38
+ return project_timeline_rows(conn, canonical_messages)
39
+
40
+ result = await asyncio.to_thread(_project)
41
+ if result is None:
32
42
  return [{"_deferred": True, "error": "database_unavailable"}]
33
- result = project_timeline_rows(conn, canonical_messages)
34
43
  if progress_callback:
35
44
  progress_callback(len(canonical_messages), len(canonical_messages))
36
45
  logger.debug(