topos-node 1.3.2__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 (600) hide show
  1. {topos_node-1.3.2/topos_node.egg-info → topos_node-1.3.4}/PKG-INFO +1 -1
  2. {topos_node-1.3.2 → topos_node-1.3.4}/pyproject.toml +1 -1
  3. {topos_node-1.3.2 → topos_node-1.3.4}/topos/__version__.py +2 -2
  4. {topos_node-1.3.2 → 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.2 → topos_node-1.3.4}/topos/cli/commands.py +22 -0
  7. {topos_node-1.3.2 → topos_node-1.3.4}/topos/config/settings.py +6 -0
  8. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/api_models.py +5 -0
  9. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/config.py +31 -0
  10. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/signal_features.py +40 -0
  11. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/state.py +34 -2
  12. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/catalog.py +13 -1
  13. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/derived_tables.py +123 -84
  14. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/job_writer.py +36 -0
  15. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/models/mvp_defaults.py +27 -0
  16. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/triage/dashboard.py +9 -1
  17. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/triage/intents.py +83 -6
  18. topos_node-1.3.4/topos/protocol/handled_message_types.json +208 -0
  19. {topos_node-1.3.2 → topos_node-1.3.4}/topos/services/llm/openai.py +49 -3
  20. {topos_node-1.3.2 → topos_node-1.3.4}/topos/services/local.py +44 -1
  21. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/adapters/sqlite/stores.py +100 -43
  22. topos_node-1.3.4/topos/storage/db/migrations/__init__.py +190 -0
  23. topos_node-1.3.4/topos/storage/db/migrations/backup.py +125 -0
  24. topos_node-1.3.4/topos/storage/db/migrations/enrichment_spec_version_v1.py +50 -0
  25. topos_node-1.3.4/topos/storage/db/migrations/registry.py +324 -0
  26. topos_node-1.3.4/topos/storage/db/migrations/registry_checksums.json +32 -0
  27. {topos_node-1.3.2 → topos_node-1.3.4}/topos/upgrades/__init__.py +55 -15
  28. {topos_node-1.3.2 → topos_node-1.3.4}/topos/upgrades/manifests.json +59 -10
  29. {topos_node-1.3.2 → topos_node-1.3.4}/topos/upgrades/runner.py +183 -7
  30. {topos_node-1.3.2 → topos_node-1.3.4/topos_node.egg-info}/PKG-INFO +1 -1
  31. {topos_node-1.3.2 → topos_node-1.3.4}/topos_node.egg-info/SOURCES.txt +4 -0
  32. topos_node-1.3.2/topos/api/upgrades.py +0 -30
  33. topos_node-1.3.2/topos/protocol/handled_message_types.json +0 -205
  34. topos_node-1.3.2/topos/storage/db/migrations/__init__.py +0 -326
  35. {topos_node-1.3.2 → topos_node-1.3.4}/LICENSE +0 -0
  36. {topos_node-1.3.2 → topos_node-1.3.4}/MANIFEST.in +0 -0
  37. {topos_node-1.3.2 → topos_node-1.3.4}/README.md +0 -0
  38. {topos_node-1.3.2 → topos_node-1.3.4}/setup.cfg +0 -0
  39. {topos_node-1.3.2 → topos_node-1.3.4}/shared/__init__.py +0 -0
  40. {topos_node-1.3.2 → topos_node-1.3.4}/shared/filtering.py +0 -0
  41. {topos_node-1.3.2 → topos_node-1.3.4}/shared/schema_registry.py +0 -0
  42. {topos_node-1.3.2 → topos_node-1.3.4}/tests/test_extensions.py +0 -0
  43. {topos_node-1.3.2 → topos_node-1.3.4}/tests/test_llm_integrations_storage.py +0 -0
  44. {topos_node-1.3.2 → topos_node-1.3.4}/tests/test_protocol_handled_types.py +0 -0
  45. {topos_node-1.3.2 → topos_node-1.3.4}/topos/__init__.py +0 -0
  46. {topos_node-1.3.2 → topos_node-1.3.4}/topos/analytics/__init__.py +0 -0
  47. {topos_node-1.3.2 → topos_node-1.3.4}/topos/analytics/duckdb_adapter.py +0 -0
  48. {topos_node-1.3.2 → topos_node-1.3.4}/topos/analytics/messenger_communities.py +0 -0
  49. {topos_node-1.3.2 → topos_node-1.3.4}/topos/analytics/messenger_graph.py +0 -0
  50. {topos_node-1.3.2 → topos_node-1.3.4}/topos/analytics/messenger_labels.py +0 -0
  51. {topos_node-1.3.2 → topos_node-1.3.4}/topos/analytics/profiles.py +0 -0
  52. {topos_node-1.3.2 → topos_node-1.3.4}/topos/analytics/query_engine.py +0 -0
  53. {topos_node-1.3.2 → topos_node-1.3.4}/topos/analytics/raw_queries.py +0 -0
  54. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/__init__.py +0 -0
  55. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/analytics.py +0 -0
  56. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/app_registry.py +0 -0
  57. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/backup.py +0 -0
  58. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/compute_remote.py +0 -0
  59. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/conversation_context.py +0 -0
  60. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/data_commit.py +0 -0
  61. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/data_explorer_table_prefs.py +0 -0
  62. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/database_explorer.py +0 -0
  63. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/db.py +0 -0
  64. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/device.py +0 -0
  65. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/engine_run.py +0 -0
  66. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/enrichment_lab.py +0 -0
  67. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/facts_llm_config.py +0 -0
  68. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/filter_lab.py +0 -0
  69. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/health.py +0 -0
  70. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/home_chat.py +0 -0
  71. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/ingestion_api.py +0 -0
  72. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/ingestion_compat.py +0 -0
  73. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/ingestion_sources.py +0 -0
  74. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/intelligence_lifecycle.py +0 -0
  75. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/llm.py +0 -0
  76. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/local_mcp.py +0 -0
  77. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/messenger_analytics.py +0 -0
  78. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/privacy_disclose.py +0 -0
  79. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/query_api.py +0 -0
  80. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/runtime_bootstrap.py +0 -0
  81. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/sanitization_ollama_config.py +0 -0
  82. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/shell.py +0 -0
  83. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/signal.py +0 -0
  84. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/signal_extraction_config.py +0 -0
  85. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/source_install.py +0 -0
  86. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/source_scrub.py +0 -0
  87. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/sources.py +0 -0
  88. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/sources_overview.py +0 -0
  89. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/sync.py +0 -0
  90. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/tool_index.py +0 -0
  91. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/ui_config.py +0 -0
  92. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/uma_data.py +0 -0
  93. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/usage.py +0 -0
  94. {topos_node-1.3.2 → topos_node-1.3.4}/topos/api/user_identity.py +0 -0
  95. {topos_node-1.3.2 → topos_node-1.3.4}/topos/app.py +0 -0
  96. {topos_node-1.3.2 → topos_node-1.3.4}/topos/auth.py +0 -0
  97. {topos_node-1.3.2 → topos_node-1.3.4}/topos/canonicalization/__init__.py +0 -0
  98. {topos_node-1.3.2 → topos_node-1.3.4}/topos/canonicalization/mappers/__init__.py +0 -0
  99. {topos_node-1.3.2 → topos_node-1.3.4}/topos/canonicalization/mappers/base.py +0 -0
  100. {topos_node-1.3.2 → topos_node-1.3.4}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
  101. {topos_node-1.3.2 → topos_node-1.3.4}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
  102. {topos_node-1.3.2 → topos_node-1.3.4}/topos/canonicalization/mappers/demo_mappers.py +0 -0
  103. {topos_node-1.3.2 → topos_node-1.3.4}/topos/canonicalization/mappers/documents_mapper.py +0 -0
  104. {topos_node-1.3.2 → topos_node-1.3.4}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
  105. {topos_node-1.3.2 → topos_node-1.3.4}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
  106. {topos_node-1.3.2 → topos_node-1.3.4}/topos/canonicalization/mappers/grok_mapper.py +0 -0
  107. {topos_node-1.3.2 → topos_node-1.3.4}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
  108. {topos_node-1.3.2 → topos_node-1.3.4}/topos/canonicalization/models.py +0 -0
  109. {topos_node-1.3.2 → topos_node-1.3.4}/topos/canonicalization/resolver.py +0 -0
  110. {topos_node-1.3.2 → topos_node-1.3.4}/topos/cli/__init__.py +0 -0
  111. {topos_node-1.3.2 → topos_node-1.3.4}/topos/cli/__main__.py +0 -0
  112. {topos_node-1.3.2 → topos_node-1.3.4}/topos/cli/assets/topos_blk_rounded.png +0 -0
  113. {topos_node-1.3.2 → topos_node-1.3.4}/topos/cli/assets/topos_white.png +0 -0
  114. {topos_node-1.3.2 → topos_node-1.3.4}/topos/cli/tray.py +0 -0
  115. {topos_node-1.3.2 → topos_node-1.3.4}/topos/config/__init__.py +0 -0
  116. {topos_node-1.3.2 → topos_node-1.3.4}/topos/config/conversation_context_llm.py +0 -0
  117. {topos_node-1.3.2 → topos_node-1.3.4}/topos/config/facts_llm.py +0 -0
  118. {topos_node-1.3.2 → topos_node-1.3.4}/topos/config/sanitization_ollama.py +0 -0
  119. {topos_node-1.3.2 → topos_node-1.3.4}/topos/config/signal_extraction.py +0 -0
  120. {topos_node-1.3.2 → topos_node-1.3.4}/topos/config/uvicorn_logging.json +0 -0
  121. {topos_node-1.3.2 → topos_node-1.3.4}/topos/contacts/__init__.py +0 -0
  122. {topos_node-1.3.2 → topos_node-1.3.4}/topos/contacts/identity.py +0 -0
  123. {topos_node-1.3.2 → topos_node-1.3.4}/topos/control_plane_client.py +0 -0
  124. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/__init__.py +0 -0
  125. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/connection_resilience.py +0 -0
  126. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/device_helpers.py +0 -0
  127. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/errors.py +0 -0
  128. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/events.py +0 -0
  129. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/__init__.py +0 -0
  130. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/common.py +0 -0
  131. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/complexity.py +0 -0
  132. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/contacts_import.py +0 -0
  133. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/database_explorer.py +0 -0
  134. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/device.py +0 -0
  135. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/enrichment.py +0 -0
  136. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/enrichment_lab.py +0 -0
  137. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/filter_lab.py +0 -0
  138. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/home_chat.py +0 -0
  139. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/ingest.py +0 -0
  140. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/messages.py +0 -0
  141. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/messenger_analytics.py +0 -0
  142. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/query.py +0 -0
  143. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/registry.py +0 -0
  144. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/routines.py +0 -0
  145. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/sources.py +0 -0
  146. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/timeline_daily.py +0 -0
  147. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/tool_index.py +0 -0
  148. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/handlers/uma.py +0 -0
  149. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/logging.py +0 -0
  150. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/metrics.py +0 -0
  151. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/routine_access.py +0 -0
  152. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/startup_banner.py +0 -0
  153. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/table_layers.py +0 -0
  154. {topos_node-1.3.2 → topos_node-1.3.4}/topos/core/types.py +0 -0
  155. {topos_node-1.3.2 → topos_node-1.3.4}/topos/data_explorer_row_delete.py +0 -0
  156. {topos_node-1.3.2 → topos_node-1.3.4}/topos/data_explorer_table_prefs.py +0 -0
  157. {topos_node-1.3.2 → topos_node-1.3.4}/topos/data_explorer_tables.py +0 -0
  158. {topos_node-1.3.2 → topos_node-1.3.4}/topos/disclosure/__init__.py +0 -0
  159. {topos_node-1.3.2 → topos_node-1.3.4}/topos/disclosure/canonical_writer.py +0 -0
  160. {topos_node-1.3.2 → topos_node-1.3.4}/topos/disclosure/content_policy.py +0 -0
  161. {topos_node-1.3.2 → topos_node-1.3.4}/topos/disclosure/field_registry.py +0 -0
  162. {topos_node-1.3.2 → topos_node-1.3.4}/topos/disclosure/privacy_layer.py +0 -0
  163. {topos_node-1.3.2 → topos_node-1.3.4}/topos/disclosure/tier.py +0 -0
  164. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/__init__.py +0 -0
  165. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/backends/__init__.py +0 -0
  166. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/backends/base.py +0 -0
  167. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/backends/generative_prompts.py +0 -0
  168. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/backends/generative_response.py +0 -0
  169. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/backends/huggingface.py +0 -0
  170. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/backends/ollama.py +0 -0
  171. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/backends/openai.py +0 -0
  172. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/backends/openai_compatible.py +0 -0
  173. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/backends/redpill.py +0 -0
  174. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/backends/stub.py +0 -0
  175. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/client.py +0 -0
  176. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/engine.py +0 -0
  177. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/intake.py +0 -0
  178. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/memory_utils.py +0 -0
  179. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/model_cache.py +0 -0
  180. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/pipeline_memory.py +0 -0
  181. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/queue_manager.py +0 -0
  182. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/registration.py +0 -0
  183. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/result_formatter.py +0 -0
  184. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/router.py +0 -0
  185. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/scoped_token.py +0 -0
  186. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/tasks.py +0 -0
  187. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/transport.py +0 -0
  188. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/usage_guard.py +0 -0
  189. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/usage_observation.py +0 -0
  190. {topos_node-1.3.2 → topos_node-1.3.4}/topos/engine/validator.py +0 -0
  191. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/__init__.py +0 -0
  192. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/__init__.py +0 -0
  193. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/base.py +0 -0
  194. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/__init__.py +0 -0
  195. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
  196. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
  197. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/attention_triage_job.py +0 -0
  198. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
  199. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
  200. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +0 -0
  201. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/dimension_summary_job.py +0 -0
  202. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
  203. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
  204. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/entities_job.py +0 -0
  205. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
  206. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
  207. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
  208. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
  209. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
  210. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
  211. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
  212. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
  213. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
  214. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/url_classification_core.py +0 -0
  215. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/url_classification_enrichment_job.py +0 -0
  216. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/url_classification_signal_job.py +0 -0
  217. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/raw/__init__.py +0 -0
  218. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
  219. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/raw/language_job.py +0 -0
  220. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
  221. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
  222. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/model_overrides.py +0 -0
  223. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/models/__init__.py +0 -0
  224. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/models/manager.py +0 -0
  225. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/models/registry.py +0 -0
  226. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/models/versioning.py +0 -0
  227. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/orchestrator.py +0 -0
  228. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/processor.py +0 -0
  229. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/progress_bar.py +0 -0
  230. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/registry_contract.py +0 -0
  231. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/signal_derivation_config.json +0 -0
  232. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/source_overrides.py +0 -0
  233. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment/website_classifier.py +0 -0
  234. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment_lab/__init__.py +0 -0
  235. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment_lab/bundles.py +0 -0
  236. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment_lab/model_resolve.py +0 -0
  237. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment_lab/schema.py +0 -0
  238. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment_lab/service.py +0 -0
  239. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment_lab/store.py +0 -0
  240. {topos_node-1.3.2 → topos_node-1.3.4}/topos/enrichment_lab/worker.py +0 -0
  241. {topos_node-1.3.2 → topos_node-1.3.4}/topos/evals/__init__.py +0 -0
  242. {topos_node-1.3.2 → topos_node-1.3.4}/topos/evals/enrichment_eval.py +0 -0
  243. {topos_node-1.3.2 → topos_node-1.3.4}/topos/extensions.py +0 -0
  244. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/__init__.py +0 -0
  245. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/canonical.py +0 -0
  246. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/engine.py +0 -0
  247. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/entropy.py +0 -0
  248. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/focus.py +0 -0
  249. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/graph_metrics.py +0 -0
  250. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/influence.py +0 -0
  251. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/projection.py +0 -0
  252. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/snapshots.py +0 -0
  253. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/store.py +0 -0
  254. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/topic_merge.py +0 -0
  255. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/topics.py +0 -0
  256. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/topics_daily.py +0 -0
  257. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/complexity/volatility.py +0 -0
  258. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/entities/__init__.py +0 -0
  259. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/entities/consolidation.py +0 -0
  260. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/entities/declared_mappings.py +0 -0
  261. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/entities/dossier.py +0 -0
  262. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/entities/edges.py +0 -0
  263. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/entities/fact_materializer.py +0 -0
  264. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/entities/graph_enrichers.py +0 -0
  265. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/entities/graph_refresh.py +0 -0
  266. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/entities/graph_search.py +0 -0
  267. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/entities/linking.py +0 -0
  268. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/entities/maintenance.py +0 -0
  269. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/entities/reads.py +0 -0
  270. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/entities/resolver.py +0 -0
  271. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/facts/__init__.py +0 -0
  272. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/facts/extract.py +0 -0
  273. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/facts/llm_extract.py +0 -0
  274. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/facts/reads.py +0 -0
  275. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/facts/store.py +0 -0
  276. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/facts/verdicts.py +0 -0
  277. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/fit/evaluator.py +0 -0
  278. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/fit/opportunity_types.json +0 -0
  279. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/lifecycle/__init__.py +0 -0
  280. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/lifecycle/blackhole.py +0 -0
  281. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/lifecycle/blackhole_guard.py +0 -0
  282. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/lifecycle/blackhole_llm.py +0 -0
  283. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/lifecycle/blackhole_rebuild.py +0 -0
  284. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/lifecycle/derived_scrub.py +0 -0
  285. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/lifecycle/exclusions.py +0 -0
  286. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/lifecycle/gc.py +0 -0
  287. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/provenance/__init__.py +0 -0
  288. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/provenance/posture.py +0 -0
  289. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/provenance/roles.py +0 -0
  290. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/__init__.py +0 -0
  291. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/brief_canonical_loader.py +0 -0
  292. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/brief_ontology.py +0 -0
  293. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/brief_renderer.py +0 -0
  294. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/brief_schemas.py +0 -0
  295. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/chunking.py +0 -0
  296. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/cluster_labels.py +0 -0
  297. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/conversation_context.py +0 -0
  298. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/data_health.py +0 -0
  299. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/definitions/brief_ontologies.json +0 -0
  300. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/definitions/intentions.json +0 -0
  301. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/definitions/profile.json +0 -0
  302. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/definitions/relationships.json +0 -0
  303. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
  304. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/definitions/time.json +0 -0
  305. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/definitions/work.json +0 -0
  306. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/dimension_briefs.py +0 -0
  307. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/dimension_definition_loader.py +0 -0
  308. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/dimension_profiles.py +0 -0
  309. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/dimension_registry.py +0 -0
  310. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/embed_context.py +0 -0
  311. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/extraction/artifact_router.py +0 -0
  312. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/extraction/artifact_store.py +0 -0
  313. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/extraction/rule_extractors.py +0 -0
  314. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/graph_sanitize.py +0 -0
  315. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/hybrid_search.py +0 -0
  316. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/incremental_clustering.py +0 -0
  317. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/model_recommendations.py +0 -0
  318. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/query_embed_cache.py +0 -0
  319. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/schemas.py +0 -0
  320. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/service.py +0 -0
  321. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/signal_object_store.py +0 -0
  322. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/source_hydration.py +0 -0
  323. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/structured_signal.py +0 -0
  324. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/tool_index.py +0 -0
  325. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/topic_clustering.py +0 -0
  326. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/typed_stores/aggregates.py +0 -0
  327. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/typed_stores/commitments.py +0 -0
  328. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/typed_stores/rhythm.py +0 -0
  329. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
  330. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/vector_codec.py +0 -0
  331. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/vector_math.py +0 -0
  332. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/signal/vector_settings.py +0 -0
  333. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/stats/__init__.py +0 -0
  334. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/stats/definitions.py +0 -0
  335. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/stats/engine.py +0 -0
  336. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/stats/fold.py +0 -0
  337. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/stats/insights.py +0 -0
  338. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/timeline_projection.py +0 -0
  339. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/timeline_rollup.py +0 -0
  340. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/triage/__init__.py +0 -0
  341. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/triage/badges.py +0 -0
  342. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/triage/daily.py +0 -0
  343. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/triage/instruments.py +0 -0
  344. {topos_node-1.3.2 → topos_node-1.3.4}/topos/features/triage/readiness.py +0 -0
  345. {topos_node-1.3.2 → topos_node-1.3.4}/topos/filter_lab/__init__.py +0 -0
  346. {topos_node-1.3.2 → topos_node-1.3.4}/topos/filter_lab/bundles.py +0 -0
  347. {topos_node-1.3.2 → topos_node-1.3.4}/topos/filter_lab/schema.py +0 -0
  348. {topos_node-1.3.2 → topos_node-1.3.4}/topos/filter_lab/service.py +0 -0
  349. {topos_node-1.3.2 → topos_node-1.3.4}/topos/filter_lab/store.py +0 -0
  350. {topos_node-1.3.2 → topos_node-1.3.4}/topos/filter_lab/worker.py +0 -0
  351. {topos_node-1.3.2 → topos_node-1.3.4}/topos/home_chat/__init__.py +0 -0
  352. {topos_node-1.3.2 → topos_node-1.3.4}/topos/home_chat/schema.py +0 -0
  353. {topos_node-1.3.2 → topos_node-1.3.4}/topos/home_chat/store.py +0 -0
  354. {topos_node-1.3.2 → topos_node-1.3.4}/topos/hosted_pool_lease.py +0 -0
  355. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/__init__.py +0 -0
  356. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/canonical_pipeline.py +0 -0
  357. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/checkpoints/__init__.py +0 -0
  358. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
  359. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
  360. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/inbox_crypto.py +0 -0
  361. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/inbox_drain.py +0 -0
  362. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/ingest_helpers.py +0 -0
  363. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/jobs.py +0 -0
  364. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/journal_location_fanout.py +0 -0
  365. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/journal_time_log_normalize.py +0 -0
  366. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/local_sync.py +0 -0
  367. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/log_preview.py +0 -0
  368. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/manager.py +0 -0
  369. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parser.py +0 -0
  370. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parsers/__init__.py +0 -0
  371. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parsers/base.py +0 -0
  372. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parsers/browser_parser.py +0 -0
  373. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parsers/calendar_parser.py +0 -0
  374. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
  375. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
  376. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
  377. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parsers/documents_parser.py +0 -0
  378. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parsers/github_activity_parser.py +0 -0
  379. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
  380. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parsers/grok_parser.py +0 -0
  381. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parsers/messenger_parser.py +0 -0
  382. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/parsers/voxterm_parser.py +0 -0
  383. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/progress.py +0 -0
  384. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/reprocess.py +0 -0
  385. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/sources/__init__.py +0 -0
  386. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/sources/base.py +0 -0
  387. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/sources/calendar.py +0 -0
  388. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/sources/chatgpt.py +0 -0
  389. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/sources/contact_importers.py +0 -0
  390. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/sources/grok.py +0 -0
  391. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/sources/imessage_reader.py +0 -0
  392. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/sources/signal_export_parser.py +0 -0
  393. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/sources/signal_reader.py +0 -0
  394. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/state_machine.py +0 -0
  395. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/triggers/__init__.py +0 -0
  396. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/triggers/file_trigger.py +0 -0
  397. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
  398. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/usage_inbox_dedupe.py +0 -0
  399. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/validation/__init__.py +0 -0
  400. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/validation/base.py +0 -0
  401. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/validation/schema_registry.py +0 -0
  402. {topos_node-1.3.2 → topos_node-1.3.4}/topos/ingestion/validation/schema_validator.py +0 -0
  403. {topos_node-1.3.2 → topos_node-1.3.4}/topos/lineage/__init__.py +0 -0
  404. {topos_node-1.3.2 → topos_node-1.3.4}/topos/lineage/provenance.py +0 -0
  405. {topos_node-1.3.2 → topos_node-1.3.4}/topos/lineage/tracker.py +0 -0
  406. {topos_node-1.3.2 → topos_node-1.3.4}/topos/llm_integrations_storage.py +0 -0
  407. {topos_node-1.3.2 → topos_node-1.3.4}/topos/mcp_stdio_proxy.py +0 -0
  408. {topos_node-1.3.2 → topos_node-1.3.4}/topos/observability/__init__.py +0 -0
  409. {topos_node-1.3.2 → topos_node-1.3.4}/topos/observability/alerts.py +0 -0
  410. {topos_node-1.3.2 → topos_node-1.3.4}/topos/observability/metrics.py +0 -0
  411. {topos_node-1.3.2 → topos_node-1.3.4}/topos/observability/tracing.py +0 -0
  412. {topos_node-1.3.2 → topos_node-1.3.4}/topos/openai_client.py +0 -0
  413. {topos_node-1.3.2 → topos_node-1.3.4}/topos/pipeline/__init__.py +0 -0
  414. {topos_node-1.3.2 → topos_node-1.3.4}/topos/pipeline/audit.py +0 -0
  415. {topos_node-1.3.2 → topos_node-1.3.4}/topos/pipeline/envelope.py +0 -0
  416. {topos_node-1.3.2 → topos_node-1.3.4}/topos/pipeline/job_runner.py +0 -0
  417. {topos_node-1.3.2 → topos_node-1.3.4}/topos/pipeline/job_store.py +0 -0
  418. {topos_node-1.3.2 → topos_node-1.3.4}/topos/pipeline/stages.py +0 -0
  419. {topos_node-1.3.2 → topos_node-1.3.4}/topos/pipeline/stub_enqueue.py +0 -0
  420. {topos_node-1.3.2 → topos_node-1.3.4}/topos/projections/__init__.py +0 -0
  421. {topos_node-1.3.2 → topos_node-1.3.4}/topos/projections/vector_index/__init__.py +0 -0
  422. {topos_node-1.3.2 → topos_node-1.3.4}/topos/projections/vector_index/base.py +0 -0
  423. {topos_node-1.3.2 → topos_node-1.3.4}/topos/projections/vector_index/builders.py +0 -0
  424. {topos_node-1.3.2 → topos_node-1.3.4}/topos/projections/vector_index/health_checks.py +0 -0
  425. {topos_node-1.3.2 → topos_node-1.3.4}/topos/protocol/__init__.py +0 -0
  426. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/__init__.py +0 -0
  427. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/audit.py +0 -0
  428. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/ddr.py +0 -0
  429. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/disclosure.py +0 -0
  430. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/fingerprint.py +0 -0
  431. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/game_layer.py +0 -0
  432. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/grant_cache.py +0 -0
  433. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/inference.py +0 -0
  434. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/intent.py +0 -0
  435. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/manifest.py +0 -0
  436. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/manifest_validation.py +0 -0
  437. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/minimizer.py +0 -0
  438. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/negotiation.py +0 -0
  439. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/pipeline.py +0 -0
  440. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/planner.py +0 -0
  441. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/retrieval.py +0 -0
  442. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/runtime.py +0 -0
  443. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/scope_registry.json +0 -0
  444. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/scope_registry_loader.py +0 -0
  445. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/session.py +0 -0
  446. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/session_utils.py +0 -0
  447. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/source_generation.py +0 -0
  448. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/truth_facts.py +0 -0
  449. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/truth_prompts.py +0 -0
  450. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/turn_classifier.py +0 -0
  451. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/types.py +0 -0
  452. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/verify.py +0 -0
  453. {topos_node-1.3.2 → topos_node-1.3.4}/topos/query/verify_modes.py +0 -0
  454. {topos_node-1.3.2 → topos_node-1.3.4}/topos/rate_limit.py +0 -0
  455. {topos_node-1.3.2 → topos_node-1.3.4}/topos/routines/__init__.py +0 -0
  456. {topos_node-1.3.2 → topos_node-1.3.4}/topos/routines/schema.py +0 -0
  457. {topos_node-1.3.2 → topos_node-1.3.4}/topos/routines/store.py +0 -0
  458. {topos_node-1.3.2 → topos_node-1.3.4}/topos/runtime_housekeeping.py +0 -0
  459. {topos_node-1.3.2 → topos_node-1.3.4}/topos/runtime_shutdown.py +0 -0
  460. {topos_node-1.3.2 → topos_node-1.3.4}/topos/runtime_update.py +0 -0
  461. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sanitization/__init__.py +0 -0
  462. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sanitization/nsfw_classifier.py +0 -0
  463. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sanitization/ollama_transforms.py +0 -0
  464. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sanitization/prewarm.py +0 -0
  465. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sanitization/privacy_filter.py +0 -0
  466. {topos_node-1.3.2 → topos_node-1.3.4}/topos/scope_resolution.py +0 -0
  467. {topos_node-1.3.2 → topos_node-1.3.4}/topos/services/__init__.py +0 -0
  468. {topos_node-1.3.2 → topos_node-1.3.4}/topos/services/container.py +0 -0
  469. {topos_node-1.3.2 → topos_node-1.3.4}/topos/services/embeddings/__init__.py +0 -0
  470. {topos_node-1.3.2 → topos_node-1.3.4}/topos/services/embeddings/base.py +0 -0
  471. {topos_node-1.3.2 → topos_node-1.3.4}/topos/services/embeddings/local.py +0 -0
  472. {topos_node-1.3.2 → topos_node-1.3.4}/topos/services/embeddings/remote.py +0 -0
  473. {topos_node-1.3.2 → topos_node-1.3.4}/topos/services/interfaces.py +0 -0
  474. {topos_node-1.3.2 → topos_node-1.3.4}/topos/services/llm/__init__.py +0 -0
  475. {topos_node-1.3.2 → topos_node-1.3.4}/topos/services/llm/base.py +0 -0
  476. {topos_node-1.3.2 → topos_node-1.3.4}/topos/services/postgres.py +0 -0
  477. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sources/__init__.py +0 -0
  478. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sources/bundled_canonical_triples.py +0 -0
  479. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sources/canonical_signal_defaults.py +0 -0
  480. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sources/definitions.py +0 -0
  481. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sources/install_service.py +0 -0
  482. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sources/registry.py +0 -0
  483. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sources/runtime_install.py +0 -0
  484. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sources/scrub_attribution.py +0 -0
  485. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sources/scrub_service.py +0 -0
  486. {topos_node-1.3.2 → topos_node-1.3.4}/topos/startup_banner.py +0 -0
  487. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/__init__.py +0 -0
  488. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/adapters/__init__.py +0 -0
  489. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/adapters/factory.py +0 -0
  490. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/adapters/fakes.py +0 -0
  491. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/adapters/postgres/stores.py +0 -0
  492. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/adapters/protocols.py +0 -0
  493. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/adapters/sqlite/__init__.py +0 -0
  494. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/adapters/sqlite/vector_search.py +0 -0
  495. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/canonical/__init__.py +0 -0
  496. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/canonical/activity_tables.py +0 -0
  497. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/__init__.py +0 -0
  498. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
  499. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/mapper.py +0 -0
  500. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/model.py +0 -0
  501. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/tables.py +0 -0
  502. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
  503. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/canonical/canonical_store.py +0 -0
  504. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/canonical/conversations_tables.py +0 -0
  505. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/canonical/mapping_store.py +0 -0
  506. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/canonical/postgres.py +0 -0
  507. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/__init__.py +0 -0
  508. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/client.py +0 -0
  509. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/connection_tuning.py +0 -0
  510. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
  511. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/actor_role_v1.py +0 -0
  512. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
  513. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
  514. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
  515. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
  516. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
  517. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
  518. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/complexity_v1.py +0 -0
  519. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
  520. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
  521. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/documents_v1.py +0 -0
  522. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/entity_blackhole_v1.py +0 -0
  523. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
  524. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/episodes_v1.py +0 -0
  525. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
  526. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
  527. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
  528. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
  529. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
  530. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
  531. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
  532. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/remediation_person_model.py +0 -0
  533. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/scope_source_generation.py +0 -0
  534. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
  535. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
  536. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/signal_objects.py +0 -0
  537. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
  538. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
  539. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
  540. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
  541. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
  542. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
  543. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
  544. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
  545. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
  546. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
  547. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
  548. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
  549. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
  550. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
  551. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
  552. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
  553. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
  554. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
  555. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
  556. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
  557. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
  558. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/paths.py +0 -0
  559. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/postgres.py +0 -0
  560. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/schema.py +0 -0
  561. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/storage_breakdown.py +0 -0
  562. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/db/write_gate.py +0 -0
  563. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/enrichment/__init__.py +0 -0
  564. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
  565. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
  566. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/normalized/__init__.py +0 -0
  567. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/normalized/normalized_store.py +0 -0
  568. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/oplog/__init__.py +0 -0
  569. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/oplog/decision.py +0 -0
  570. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/oplog/oplog_store.py +0 -0
  571. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/oplog/postgres.py +0 -0
  572. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/person/identity_resolver.py +0 -0
  573. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/projections/__init__.py +0 -0
  574. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/projections/index_ops_store.py +0 -0
  575. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/projections/vector_index_store.py +0 -0
  576. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/raw/__init__.py +0 -0
  577. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/raw/browser_flat_tables.py +0 -0
  578. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/raw/file_store.py +0 -0
  579. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/raw/raw_store.py +0 -0
  580. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/raw/raw_tables_manager.py +0 -0
  581. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/raw/sqlite_raw_store.py +0 -0
  582. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/security/encryption.py +0 -0
  583. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/signal_identity.py +0 -0
  584. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/source_settings.py +0 -0
  585. {topos_node-1.3.2 → topos_node-1.3.4}/topos/storage/user_identity.py +0 -0
  586. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sync/__init__.py +0 -0
  587. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sync/client.py +0 -0
  588. {topos_node-1.3.2 → topos_node-1.3.4}/topos/sync_handlers.py +0 -0
  589. {topos_node-1.3.2 → topos_node-1.3.4}/topos/testing/__init__.py +0 -0
  590. {topos_node-1.3.2 → topos_node-1.3.4}/topos/testing/lifespan.py +0 -0
  591. {topos_node-1.3.2 → topos_node-1.3.4}/topos/uma_contact_enrichment.py +0 -0
  592. {topos_node-1.3.2 → topos_node-1.3.4}/topos/uma_filters.py +0 -0
  593. {topos_node-1.3.2 → topos_node-1.3.4}/topos/uma_resource_id.py +0 -0
  594. {topos_node-1.3.2 → topos_node-1.3.4}/topos/uma_rpt.py +0 -0
  595. {topos_node-1.3.2 → topos_node-1.3.4}/topos/utils/base_object.py +0 -0
  596. {topos_node-1.3.2 → topos_node-1.3.4}/topos/websocket_client.py +0 -0
  597. {topos_node-1.3.2 → topos_node-1.3.4}/topos_node.egg-info/dependency_links.txt +0 -0
  598. {topos_node-1.3.2 → topos_node-1.3.4}/topos_node.egg-info/entry_points.txt +0 -0
  599. {topos_node-1.3.2 → topos_node-1.3.4}/topos_node.egg-info/requires.txt +0 -0
  600. {topos_node-1.3.2 → 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.2
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.2"
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.2"
4
- __version_info__ = (1, 3, 2)
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")
@@ -993,3 +993,43 @@ async def handle_signal_set_worn_badge(message: Dict[str, Any]) -> Optional[Dict
993
993
  return {"id": req_id, "status": "ok", "payload": {"worn": worn_badge(conn)}}
994
994
  except Exception as exc: # noqa: BLE001
995
995
  return {"id": req_id, "status": "error", "error": str(exc)}
996
+
997
+
998
+ @handles("signal_pin_intent")
999
+ async def handle_signal_pin_intent(message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
1000
+ req_id = message.get("id")
1001
+ if not req_id:
1002
+ return None
1003
+ payload = message.get("payload") or {}
1004
+ try:
1005
+ from ...features.triage.intents import active_intents, pin_intent
1006
+
1007
+ intent_text = str(payload.get("intent_text") or "").strip()
1008
+ if not intent_text:
1009
+ raise ValueError("intent_text is required")
1010
+ conn = hub.get_db_connection()
1011
+ pin_intent(
1012
+ conn,
1013
+ intent_text,
1014
+ horizon=payload.get("horizon") or "quarter",
1015
+ links=payload.get("links") or [],
1016
+ )
1017
+ return {"id": req_id, "status": "ok", "payload": {"intents": active_intents(conn)}}
1018
+ except Exception as exc: # noqa: BLE001
1019
+ return {"id": req_id, "status": "error", "error": str(exc)}
1020
+
1021
+
1022
+ @handles("signal_retire_intent")
1023
+ async def handle_signal_retire_intent(message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
1024
+ req_id = message.get("id")
1025
+ if not req_id:
1026
+ return None
1027
+ payload = message.get("payload") or {}
1028
+ try:
1029
+ from ...features.triage.intents import active_intents, retire_intent
1030
+
1031
+ conn = hub.get_db_connection()
1032
+ retire_intent(conn, payload.get("object_key") or "")
1033
+ return {"id": req_id, "status": "ok", "payload": {"intents": active_intents(conn)}}
1034
+ except Exception as exc: # noqa: BLE001
1035
+ return {"id": req_id, "status": "error", "error": str(exc)}
@@ -293,11 +293,37 @@ def get_db_connection() -> Optional[sqlite3.Connection]:
293
293
  except Exception as tuning_exc: # noqa: BLE001
294
294
  logger.warning("Connection tuning skipped: %s", tuning_exc)
295
295
  try:
296
- from ..storage.db.migrations import ensure_migrations_applied
296
+ from ..storage.db.migrations import (
297
+ DowngradeGuardError,
298
+ MigrationError,
299
+ ensure_migrations_applied,
300
+ )
297
301
 
298
302
  ensure_migrations_applied(db_conn)
303
+ except (MigrationError, DowngradeGuardError) as migration_exc:
304
+ # Shape migrations must fail loud — serving a half-migrated DB corrupts data.
305
+ logger.error("Schema migration failed; refusing to open database: %s", migration_exc)
306
+ try:
307
+ db_conn.close()
308
+ except Exception: # noqa: BLE001
309
+ pass
310
+ db_conn = None
311
+ _db_conn_path = None
312
+ raise
299
313
  except Exception as migration_exc: # noqa: BLE001
300
- logger.warning("Wiki MVP migrations skipped on startup: %s", migration_exc)
314
+ from ..storage.db.migrations import MigrationError as _MigrationError
315
+
316
+ logger.error(
317
+ "Unexpected schema migration failure; refusing to open database: %s",
318
+ migration_exc,
319
+ )
320
+ try:
321
+ db_conn.close()
322
+ except Exception: # noqa: BLE001
323
+ pass
324
+ db_conn = None
325
+ _db_conn_path = None
326
+ raise _MigrationError(str(migration_exc)) from migration_exc
301
327
  try:
302
328
  from ..storage.raw.browser_flat_tables import backfill_browser_visits_from_raw_retention
303
329
 
@@ -306,6 +332,12 @@ def get_db_connection() -> Optional[sqlite3.Connection]:
306
332
  logger.debug("browser_visits raw→flat backfill skipped: %s", backfill_exc)
307
333
  return db_conn
308
334
  except Exception as e:
335
+ # Shape-migration failures must propagate (fail loud). Only soft-fail
336
+ # unrelated connection errors so callers can treat conn=None as "no DB".
337
+ from ..storage.db.migrations import DowngradeGuardError, MigrationError
338
+
339
+ if isinstance(e, (MigrationError, DowngradeGuardError)):
340
+ raise
309
341
  logger.warning("Failed to create database connection: %s", e)
310
342
  db_conn = None
311
343
  _db_conn_path = None
@@ -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