topos-node 1.3.2__tar.gz → 1.3.3__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 (597) hide show
  1. {topos_node-1.3.2/topos_node.egg-info → topos_node-1.3.3}/PKG-INFO +1 -1
  2. {topos_node-1.3.2 → topos_node-1.3.3}/pyproject.toml +1 -1
  3. {topos_node-1.3.2 → topos_node-1.3.3}/topos/__version__.py +2 -2
  4. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/signal_features.py +40 -0
  5. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/state.py +34 -2
  6. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/triage/dashboard.py +9 -1
  7. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/triage/intents.py +83 -6
  8. {topos_node-1.3.2 → topos_node-1.3.3}/topos/protocol/handled_message_types.json +2 -0
  9. topos_node-1.3.3/topos/storage/db/migrations/__init__.py +190 -0
  10. topos_node-1.3.3/topos/storage/db/migrations/backup.py +125 -0
  11. topos_node-1.3.3/topos/storage/db/migrations/registry.py +318 -0
  12. topos_node-1.3.3/topos/storage/db/migrations/registry_checksums.json +31 -0
  13. {topos_node-1.3.2 → topos_node-1.3.3}/topos/upgrades/__init__.py +49 -15
  14. {topos_node-1.3.2 → topos_node-1.3.3}/topos/upgrades/manifests.json +40 -10
  15. {topos_node-1.3.2 → topos_node-1.3.3/topos_node.egg-info}/PKG-INFO +1 -1
  16. {topos_node-1.3.2 → topos_node-1.3.3}/topos_node.egg-info/SOURCES.txt +3 -0
  17. topos_node-1.3.2/topos/storage/db/migrations/__init__.py +0 -326
  18. {topos_node-1.3.2 → topos_node-1.3.3}/LICENSE +0 -0
  19. {topos_node-1.3.2 → topos_node-1.3.3}/MANIFEST.in +0 -0
  20. {topos_node-1.3.2 → topos_node-1.3.3}/README.md +0 -0
  21. {topos_node-1.3.2 → topos_node-1.3.3}/setup.cfg +0 -0
  22. {topos_node-1.3.2 → topos_node-1.3.3}/shared/__init__.py +0 -0
  23. {topos_node-1.3.2 → topos_node-1.3.3}/shared/filtering.py +0 -0
  24. {topos_node-1.3.2 → topos_node-1.3.3}/shared/schema_registry.py +0 -0
  25. {topos_node-1.3.2 → topos_node-1.3.3}/tests/test_extensions.py +0 -0
  26. {topos_node-1.3.2 → topos_node-1.3.3}/tests/test_llm_integrations_storage.py +0 -0
  27. {topos_node-1.3.2 → topos_node-1.3.3}/tests/test_protocol_handled_types.py +0 -0
  28. {topos_node-1.3.2 → topos_node-1.3.3}/topos/__init__.py +0 -0
  29. {topos_node-1.3.2 → topos_node-1.3.3}/topos/analytics/__init__.py +0 -0
  30. {topos_node-1.3.2 → topos_node-1.3.3}/topos/analytics/duckdb_adapter.py +0 -0
  31. {topos_node-1.3.2 → topos_node-1.3.3}/topos/analytics/messenger_communities.py +0 -0
  32. {topos_node-1.3.2 → topos_node-1.3.3}/topos/analytics/messenger_graph.py +0 -0
  33. {topos_node-1.3.2 → topos_node-1.3.3}/topos/analytics/messenger_labels.py +0 -0
  34. {topos_node-1.3.2 → topos_node-1.3.3}/topos/analytics/profiles.py +0 -0
  35. {topos_node-1.3.2 → topos_node-1.3.3}/topos/analytics/query_engine.py +0 -0
  36. {topos_node-1.3.2 → topos_node-1.3.3}/topos/analytics/raw_queries.py +0 -0
  37. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/__init__.py +0 -0
  38. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/analytics.py +0 -0
  39. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/app_registry.py +0 -0
  40. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/backup.py +0 -0
  41. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/compute_remote.py +0 -0
  42. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/conversation_context.py +0 -0
  43. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/data_commit.py +0 -0
  44. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/data_explorer_table_prefs.py +0 -0
  45. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/database_explorer.py +0 -0
  46. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/db.py +0 -0
  47. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/device.py +0 -0
  48. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/engine_run.py +0 -0
  49. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/enrichment.py +0 -0
  50. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/enrichment_lab.py +0 -0
  51. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/facts_llm_config.py +0 -0
  52. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/filter_lab.py +0 -0
  53. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/health.py +0 -0
  54. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/home_chat.py +0 -0
  55. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/ingestion_api.py +0 -0
  56. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/ingestion_compat.py +0 -0
  57. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/ingestion_sources.py +0 -0
  58. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/intelligence_lifecycle.py +0 -0
  59. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/llm.py +0 -0
  60. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/local_mcp.py +0 -0
  61. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/messenger_analytics.py +0 -0
  62. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/privacy_disclose.py +0 -0
  63. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/query_api.py +0 -0
  64. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/runtime_bootstrap.py +0 -0
  65. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/sanitization_ollama_config.py +0 -0
  66. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/shell.py +0 -0
  67. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/signal.py +0 -0
  68. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/signal_extraction_config.py +0 -0
  69. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/source_install.py +0 -0
  70. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/source_scrub.py +0 -0
  71. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/sources.py +0 -0
  72. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/sources_overview.py +0 -0
  73. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/sync.py +0 -0
  74. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/tool_index.py +0 -0
  75. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/ui_config.py +0 -0
  76. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/uma_data.py +0 -0
  77. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/upgrades.py +0 -0
  78. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/usage.py +0 -0
  79. {topos_node-1.3.2 → topos_node-1.3.3}/topos/api/user_identity.py +0 -0
  80. {topos_node-1.3.2 → topos_node-1.3.3}/topos/app.py +0 -0
  81. {topos_node-1.3.2 → topos_node-1.3.3}/topos/auth.py +0 -0
  82. {topos_node-1.3.2 → topos_node-1.3.3}/topos/canonicalization/__init__.py +0 -0
  83. {topos_node-1.3.2 → topos_node-1.3.3}/topos/canonicalization/mappers/__init__.py +0 -0
  84. {topos_node-1.3.2 → topos_node-1.3.3}/topos/canonicalization/mappers/base.py +0 -0
  85. {topos_node-1.3.2 → topos_node-1.3.3}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
  86. {topos_node-1.3.2 → topos_node-1.3.3}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
  87. {topos_node-1.3.2 → topos_node-1.3.3}/topos/canonicalization/mappers/demo_mappers.py +0 -0
  88. {topos_node-1.3.2 → topos_node-1.3.3}/topos/canonicalization/mappers/documents_mapper.py +0 -0
  89. {topos_node-1.3.2 → topos_node-1.3.3}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
  90. {topos_node-1.3.2 → topos_node-1.3.3}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
  91. {topos_node-1.3.2 → topos_node-1.3.3}/topos/canonicalization/mappers/grok_mapper.py +0 -0
  92. {topos_node-1.3.2 → topos_node-1.3.3}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
  93. {topos_node-1.3.2 → topos_node-1.3.3}/topos/canonicalization/models.py +0 -0
  94. {topos_node-1.3.2 → topos_node-1.3.3}/topos/canonicalization/resolver.py +0 -0
  95. {topos_node-1.3.2 → topos_node-1.3.3}/topos/cli/__init__.py +0 -0
  96. {topos_node-1.3.2 → topos_node-1.3.3}/topos/cli/__main__.py +0 -0
  97. {topos_node-1.3.2 → topos_node-1.3.3}/topos/cli/assets/topos_blk_rounded.png +0 -0
  98. {topos_node-1.3.2 → topos_node-1.3.3}/topos/cli/assets/topos_white.png +0 -0
  99. {topos_node-1.3.2 → topos_node-1.3.3}/topos/cli/commands.py +0 -0
  100. {topos_node-1.3.2 → topos_node-1.3.3}/topos/cli/tray.py +0 -0
  101. {topos_node-1.3.2 → topos_node-1.3.3}/topos/config/__init__.py +0 -0
  102. {topos_node-1.3.2 → topos_node-1.3.3}/topos/config/conversation_context_llm.py +0 -0
  103. {topos_node-1.3.2 → topos_node-1.3.3}/topos/config/facts_llm.py +0 -0
  104. {topos_node-1.3.2 → topos_node-1.3.3}/topos/config/sanitization_ollama.py +0 -0
  105. {topos_node-1.3.2 → topos_node-1.3.3}/topos/config/settings.py +0 -0
  106. {topos_node-1.3.2 → topos_node-1.3.3}/topos/config/signal_extraction.py +0 -0
  107. {topos_node-1.3.2 → topos_node-1.3.3}/topos/config/uvicorn_logging.json +0 -0
  108. {topos_node-1.3.2 → topos_node-1.3.3}/topos/contacts/__init__.py +0 -0
  109. {topos_node-1.3.2 → topos_node-1.3.3}/topos/contacts/identity.py +0 -0
  110. {topos_node-1.3.2 → topos_node-1.3.3}/topos/control_plane_client.py +0 -0
  111. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/__init__.py +0 -0
  112. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/api_models.py +0 -0
  113. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/connection_resilience.py +0 -0
  114. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/device_helpers.py +0 -0
  115. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/errors.py +0 -0
  116. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/events.py +0 -0
  117. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/__init__.py +0 -0
  118. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/common.py +0 -0
  119. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/complexity.py +0 -0
  120. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/config.py +0 -0
  121. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/contacts_import.py +0 -0
  122. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/database_explorer.py +0 -0
  123. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/device.py +0 -0
  124. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/enrichment.py +0 -0
  125. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/enrichment_lab.py +0 -0
  126. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/filter_lab.py +0 -0
  127. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/home_chat.py +0 -0
  128. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/ingest.py +0 -0
  129. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/messages.py +0 -0
  130. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/messenger_analytics.py +0 -0
  131. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/query.py +0 -0
  132. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/registry.py +0 -0
  133. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/routines.py +0 -0
  134. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/sources.py +0 -0
  135. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/timeline_daily.py +0 -0
  136. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/tool_index.py +0 -0
  137. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/handlers/uma.py +0 -0
  138. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/logging.py +0 -0
  139. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/metrics.py +0 -0
  140. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/routine_access.py +0 -0
  141. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/startup_banner.py +0 -0
  142. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/table_layers.py +0 -0
  143. {topos_node-1.3.2 → topos_node-1.3.3}/topos/core/types.py +0 -0
  144. {topos_node-1.3.2 → topos_node-1.3.3}/topos/data_explorer_row_delete.py +0 -0
  145. {topos_node-1.3.2 → topos_node-1.3.3}/topos/data_explorer_table_prefs.py +0 -0
  146. {topos_node-1.3.2 → topos_node-1.3.3}/topos/data_explorer_tables.py +0 -0
  147. {topos_node-1.3.2 → topos_node-1.3.3}/topos/disclosure/__init__.py +0 -0
  148. {topos_node-1.3.2 → topos_node-1.3.3}/topos/disclosure/canonical_writer.py +0 -0
  149. {topos_node-1.3.2 → topos_node-1.3.3}/topos/disclosure/content_policy.py +0 -0
  150. {topos_node-1.3.2 → topos_node-1.3.3}/topos/disclosure/field_registry.py +0 -0
  151. {topos_node-1.3.2 → topos_node-1.3.3}/topos/disclosure/privacy_layer.py +0 -0
  152. {topos_node-1.3.2 → topos_node-1.3.3}/topos/disclosure/tier.py +0 -0
  153. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/__init__.py +0 -0
  154. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/backends/__init__.py +0 -0
  155. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/backends/base.py +0 -0
  156. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/backends/generative_prompts.py +0 -0
  157. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/backends/generative_response.py +0 -0
  158. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/backends/huggingface.py +0 -0
  159. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/backends/ollama.py +0 -0
  160. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/backends/openai.py +0 -0
  161. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/backends/openai_compatible.py +0 -0
  162. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/backends/redpill.py +0 -0
  163. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/backends/stub.py +0 -0
  164. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/client.py +0 -0
  165. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/engine.py +0 -0
  166. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/intake.py +0 -0
  167. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/memory_utils.py +0 -0
  168. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/model_cache.py +0 -0
  169. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/pipeline_memory.py +0 -0
  170. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/queue_manager.py +0 -0
  171. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/registration.py +0 -0
  172. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/result_formatter.py +0 -0
  173. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/router.py +0 -0
  174. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/scoped_token.py +0 -0
  175. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/tasks.py +0 -0
  176. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/transport.py +0 -0
  177. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/usage_guard.py +0 -0
  178. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/usage_observation.py +0 -0
  179. {topos_node-1.3.2 → topos_node-1.3.3}/topos/engine/validator.py +0 -0
  180. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/__init__.py +0 -0
  181. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/catalog.py +0 -0
  182. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/derived_tables.py +0 -0
  183. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/job_writer.py +0 -0
  184. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/__init__.py +0 -0
  185. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/base.py +0 -0
  186. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/__init__.py +0 -0
  187. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
  188. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
  189. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/attention_triage_job.py +0 -0
  190. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
  191. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
  192. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +0 -0
  193. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/dimension_summary_job.py +0 -0
  194. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
  195. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
  196. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/entities_job.py +0 -0
  197. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
  198. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
  199. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
  200. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
  201. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
  202. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
  203. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
  204. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
  205. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
  206. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/url_classification_core.py +0 -0
  207. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/url_classification_enrichment_job.py +0 -0
  208. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/canonical/url_classification_signal_job.py +0 -0
  209. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/raw/__init__.py +0 -0
  210. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
  211. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/raw/language_job.py +0 -0
  212. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
  213. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
  214. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/model_overrides.py +0 -0
  215. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/models/__init__.py +0 -0
  216. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/models/manager.py +0 -0
  217. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/models/mvp_defaults.py +0 -0
  218. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/models/registry.py +0 -0
  219. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/models/versioning.py +0 -0
  220. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/orchestrator.py +0 -0
  221. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/processor.py +0 -0
  222. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/progress_bar.py +0 -0
  223. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/registry_contract.py +0 -0
  224. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/signal_derivation_config.json +0 -0
  225. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/source_overrides.py +0 -0
  226. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment/website_classifier.py +0 -0
  227. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment_lab/__init__.py +0 -0
  228. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment_lab/bundles.py +0 -0
  229. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment_lab/model_resolve.py +0 -0
  230. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment_lab/schema.py +0 -0
  231. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment_lab/service.py +0 -0
  232. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment_lab/store.py +0 -0
  233. {topos_node-1.3.2 → topos_node-1.3.3}/topos/enrichment_lab/worker.py +0 -0
  234. {topos_node-1.3.2 → topos_node-1.3.3}/topos/evals/__init__.py +0 -0
  235. {topos_node-1.3.2 → topos_node-1.3.3}/topos/evals/enrichment_eval.py +0 -0
  236. {topos_node-1.3.2 → topos_node-1.3.3}/topos/extensions.py +0 -0
  237. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/__init__.py +0 -0
  238. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/canonical.py +0 -0
  239. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/engine.py +0 -0
  240. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/entropy.py +0 -0
  241. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/focus.py +0 -0
  242. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/graph_metrics.py +0 -0
  243. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/influence.py +0 -0
  244. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/projection.py +0 -0
  245. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/snapshots.py +0 -0
  246. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/store.py +0 -0
  247. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/topic_merge.py +0 -0
  248. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/topics.py +0 -0
  249. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/topics_daily.py +0 -0
  250. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/complexity/volatility.py +0 -0
  251. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/entities/__init__.py +0 -0
  252. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/entities/consolidation.py +0 -0
  253. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/entities/declared_mappings.py +0 -0
  254. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/entities/dossier.py +0 -0
  255. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/entities/edges.py +0 -0
  256. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/entities/fact_materializer.py +0 -0
  257. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/entities/graph_enrichers.py +0 -0
  258. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/entities/graph_refresh.py +0 -0
  259. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/entities/graph_search.py +0 -0
  260. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/entities/linking.py +0 -0
  261. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/entities/maintenance.py +0 -0
  262. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/entities/reads.py +0 -0
  263. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/entities/resolver.py +0 -0
  264. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/facts/__init__.py +0 -0
  265. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/facts/extract.py +0 -0
  266. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/facts/llm_extract.py +0 -0
  267. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/facts/reads.py +0 -0
  268. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/facts/store.py +0 -0
  269. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/facts/verdicts.py +0 -0
  270. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/fit/evaluator.py +0 -0
  271. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/fit/opportunity_types.json +0 -0
  272. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/lifecycle/__init__.py +0 -0
  273. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/lifecycle/blackhole.py +0 -0
  274. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/lifecycle/blackhole_guard.py +0 -0
  275. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/lifecycle/blackhole_llm.py +0 -0
  276. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/lifecycle/blackhole_rebuild.py +0 -0
  277. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/lifecycle/derived_scrub.py +0 -0
  278. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/lifecycle/exclusions.py +0 -0
  279. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/lifecycle/gc.py +0 -0
  280. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/provenance/__init__.py +0 -0
  281. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/provenance/posture.py +0 -0
  282. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/provenance/roles.py +0 -0
  283. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/__init__.py +0 -0
  284. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/brief_canonical_loader.py +0 -0
  285. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/brief_ontology.py +0 -0
  286. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/brief_renderer.py +0 -0
  287. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/brief_schemas.py +0 -0
  288. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/chunking.py +0 -0
  289. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/cluster_labels.py +0 -0
  290. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/conversation_context.py +0 -0
  291. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/data_health.py +0 -0
  292. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/definitions/brief_ontologies.json +0 -0
  293. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/definitions/intentions.json +0 -0
  294. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/definitions/profile.json +0 -0
  295. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/definitions/relationships.json +0 -0
  296. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
  297. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/definitions/time.json +0 -0
  298. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/definitions/work.json +0 -0
  299. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/dimension_briefs.py +0 -0
  300. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/dimension_definition_loader.py +0 -0
  301. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/dimension_profiles.py +0 -0
  302. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/dimension_registry.py +0 -0
  303. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/embed_context.py +0 -0
  304. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/extraction/artifact_router.py +0 -0
  305. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/extraction/artifact_store.py +0 -0
  306. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/extraction/rule_extractors.py +0 -0
  307. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/graph_sanitize.py +0 -0
  308. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/hybrid_search.py +0 -0
  309. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/incremental_clustering.py +0 -0
  310. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/model_recommendations.py +0 -0
  311. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/query_embed_cache.py +0 -0
  312. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/schemas.py +0 -0
  313. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/service.py +0 -0
  314. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/signal_object_store.py +0 -0
  315. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/source_hydration.py +0 -0
  316. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/structured_signal.py +0 -0
  317. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/tool_index.py +0 -0
  318. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/topic_clustering.py +0 -0
  319. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/typed_stores/aggregates.py +0 -0
  320. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/typed_stores/commitments.py +0 -0
  321. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/typed_stores/rhythm.py +0 -0
  322. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
  323. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/vector_codec.py +0 -0
  324. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/vector_math.py +0 -0
  325. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/signal/vector_settings.py +0 -0
  326. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/stats/__init__.py +0 -0
  327. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/stats/definitions.py +0 -0
  328. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/stats/engine.py +0 -0
  329. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/stats/fold.py +0 -0
  330. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/stats/insights.py +0 -0
  331. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/timeline_projection.py +0 -0
  332. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/timeline_rollup.py +0 -0
  333. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/triage/__init__.py +0 -0
  334. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/triage/badges.py +0 -0
  335. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/triage/daily.py +0 -0
  336. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/triage/instruments.py +0 -0
  337. {topos_node-1.3.2 → topos_node-1.3.3}/topos/features/triage/readiness.py +0 -0
  338. {topos_node-1.3.2 → topos_node-1.3.3}/topos/filter_lab/__init__.py +0 -0
  339. {topos_node-1.3.2 → topos_node-1.3.3}/topos/filter_lab/bundles.py +0 -0
  340. {topos_node-1.3.2 → topos_node-1.3.3}/topos/filter_lab/schema.py +0 -0
  341. {topos_node-1.3.2 → topos_node-1.3.3}/topos/filter_lab/service.py +0 -0
  342. {topos_node-1.3.2 → topos_node-1.3.3}/topos/filter_lab/store.py +0 -0
  343. {topos_node-1.3.2 → topos_node-1.3.3}/topos/filter_lab/worker.py +0 -0
  344. {topos_node-1.3.2 → topos_node-1.3.3}/topos/home_chat/__init__.py +0 -0
  345. {topos_node-1.3.2 → topos_node-1.3.3}/topos/home_chat/schema.py +0 -0
  346. {topos_node-1.3.2 → topos_node-1.3.3}/topos/home_chat/store.py +0 -0
  347. {topos_node-1.3.2 → topos_node-1.3.3}/topos/hosted_pool_lease.py +0 -0
  348. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/__init__.py +0 -0
  349. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/canonical_pipeline.py +0 -0
  350. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/checkpoints/__init__.py +0 -0
  351. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
  352. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
  353. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/inbox_crypto.py +0 -0
  354. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/inbox_drain.py +0 -0
  355. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/ingest_helpers.py +0 -0
  356. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/jobs.py +0 -0
  357. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/journal_location_fanout.py +0 -0
  358. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/journal_time_log_normalize.py +0 -0
  359. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/local_sync.py +0 -0
  360. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/log_preview.py +0 -0
  361. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/manager.py +0 -0
  362. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parser.py +0 -0
  363. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parsers/__init__.py +0 -0
  364. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parsers/base.py +0 -0
  365. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parsers/browser_parser.py +0 -0
  366. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parsers/calendar_parser.py +0 -0
  367. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
  368. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
  369. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
  370. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parsers/documents_parser.py +0 -0
  371. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parsers/github_activity_parser.py +0 -0
  372. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
  373. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parsers/grok_parser.py +0 -0
  374. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parsers/messenger_parser.py +0 -0
  375. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/parsers/voxterm_parser.py +0 -0
  376. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/progress.py +0 -0
  377. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/reprocess.py +0 -0
  378. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/sources/__init__.py +0 -0
  379. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/sources/base.py +0 -0
  380. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/sources/calendar.py +0 -0
  381. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/sources/chatgpt.py +0 -0
  382. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/sources/contact_importers.py +0 -0
  383. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/sources/grok.py +0 -0
  384. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/sources/imessage_reader.py +0 -0
  385. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/sources/signal_export_parser.py +0 -0
  386. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/sources/signal_reader.py +0 -0
  387. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/state_machine.py +0 -0
  388. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/triggers/__init__.py +0 -0
  389. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/triggers/file_trigger.py +0 -0
  390. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
  391. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/usage_inbox_dedupe.py +0 -0
  392. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/validation/__init__.py +0 -0
  393. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/validation/base.py +0 -0
  394. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/validation/schema_registry.py +0 -0
  395. {topos_node-1.3.2 → topos_node-1.3.3}/topos/ingestion/validation/schema_validator.py +0 -0
  396. {topos_node-1.3.2 → topos_node-1.3.3}/topos/lineage/__init__.py +0 -0
  397. {topos_node-1.3.2 → topos_node-1.3.3}/topos/lineage/provenance.py +0 -0
  398. {topos_node-1.3.2 → topos_node-1.3.3}/topos/lineage/tracker.py +0 -0
  399. {topos_node-1.3.2 → topos_node-1.3.3}/topos/llm_integrations_storage.py +0 -0
  400. {topos_node-1.3.2 → topos_node-1.3.3}/topos/mcp_stdio_proxy.py +0 -0
  401. {topos_node-1.3.2 → topos_node-1.3.3}/topos/observability/__init__.py +0 -0
  402. {topos_node-1.3.2 → topos_node-1.3.3}/topos/observability/alerts.py +0 -0
  403. {topos_node-1.3.2 → topos_node-1.3.3}/topos/observability/metrics.py +0 -0
  404. {topos_node-1.3.2 → topos_node-1.3.3}/topos/observability/tracing.py +0 -0
  405. {topos_node-1.3.2 → topos_node-1.3.3}/topos/openai_client.py +0 -0
  406. {topos_node-1.3.2 → topos_node-1.3.3}/topos/pipeline/__init__.py +0 -0
  407. {topos_node-1.3.2 → topos_node-1.3.3}/topos/pipeline/audit.py +0 -0
  408. {topos_node-1.3.2 → topos_node-1.3.3}/topos/pipeline/envelope.py +0 -0
  409. {topos_node-1.3.2 → topos_node-1.3.3}/topos/pipeline/job_runner.py +0 -0
  410. {topos_node-1.3.2 → topos_node-1.3.3}/topos/pipeline/job_store.py +0 -0
  411. {topos_node-1.3.2 → topos_node-1.3.3}/topos/pipeline/stages.py +0 -0
  412. {topos_node-1.3.2 → topos_node-1.3.3}/topos/pipeline/stub_enqueue.py +0 -0
  413. {topos_node-1.3.2 → topos_node-1.3.3}/topos/projections/__init__.py +0 -0
  414. {topos_node-1.3.2 → topos_node-1.3.3}/topos/projections/vector_index/__init__.py +0 -0
  415. {topos_node-1.3.2 → topos_node-1.3.3}/topos/projections/vector_index/base.py +0 -0
  416. {topos_node-1.3.2 → topos_node-1.3.3}/topos/projections/vector_index/builders.py +0 -0
  417. {topos_node-1.3.2 → topos_node-1.3.3}/topos/projections/vector_index/health_checks.py +0 -0
  418. {topos_node-1.3.2 → topos_node-1.3.3}/topos/protocol/__init__.py +0 -0
  419. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/__init__.py +0 -0
  420. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/audit.py +0 -0
  421. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/ddr.py +0 -0
  422. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/disclosure.py +0 -0
  423. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/fingerprint.py +0 -0
  424. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/game_layer.py +0 -0
  425. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/grant_cache.py +0 -0
  426. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/inference.py +0 -0
  427. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/intent.py +0 -0
  428. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/manifest.py +0 -0
  429. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/manifest_validation.py +0 -0
  430. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/minimizer.py +0 -0
  431. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/negotiation.py +0 -0
  432. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/pipeline.py +0 -0
  433. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/planner.py +0 -0
  434. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/retrieval.py +0 -0
  435. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/runtime.py +0 -0
  436. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/scope_registry.json +0 -0
  437. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/scope_registry_loader.py +0 -0
  438. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/session.py +0 -0
  439. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/session_utils.py +0 -0
  440. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/source_generation.py +0 -0
  441. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/truth_facts.py +0 -0
  442. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/truth_prompts.py +0 -0
  443. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/turn_classifier.py +0 -0
  444. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/types.py +0 -0
  445. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/verify.py +0 -0
  446. {topos_node-1.3.2 → topos_node-1.3.3}/topos/query/verify_modes.py +0 -0
  447. {topos_node-1.3.2 → topos_node-1.3.3}/topos/rate_limit.py +0 -0
  448. {topos_node-1.3.2 → topos_node-1.3.3}/topos/routines/__init__.py +0 -0
  449. {topos_node-1.3.2 → topos_node-1.3.3}/topos/routines/schema.py +0 -0
  450. {topos_node-1.3.2 → topos_node-1.3.3}/topos/routines/store.py +0 -0
  451. {topos_node-1.3.2 → topos_node-1.3.3}/topos/runtime_housekeeping.py +0 -0
  452. {topos_node-1.3.2 → topos_node-1.3.3}/topos/runtime_shutdown.py +0 -0
  453. {topos_node-1.3.2 → topos_node-1.3.3}/topos/runtime_update.py +0 -0
  454. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sanitization/__init__.py +0 -0
  455. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sanitization/nsfw_classifier.py +0 -0
  456. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sanitization/ollama_transforms.py +0 -0
  457. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sanitization/prewarm.py +0 -0
  458. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sanitization/privacy_filter.py +0 -0
  459. {topos_node-1.3.2 → topos_node-1.3.3}/topos/scope_resolution.py +0 -0
  460. {topos_node-1.3.2 → topos_node-1.3.3}/topos/services/__init__.py +0 -0
  461. {topos_node-1.3.2 → topos_node-1.3.3}/topos/services/container.py +0 -0
  462. {topos_node-1.3.2 → topos_node-1.3.3}/topos/services/embeddings/__init__.py +0 -0
  463. {topos_node-1.3.2 → topos_node-1.3.3}/topos/services/embeddings/base.py +0 -0
  464. {topos_node-1.3.2 → topos_node-1.3.3}/topos/services/embeddings/local.py +0 -0
  465. {topos_node-1.3.2 → topos_node-1.3.3}/topos/services/embeddings/remote.py +0 -0
  466. {topos_node-1.3.2 → topos_node-1.3.3}/topos/services/interfaces.py +0 -0
  467. {topos_node-1.3.2 → topos_node-1.3.3}/topos/services/llm/__init__.py +0 -0
  468. {topos_node-1.3.2 → topos_node-1.3.3}/topos/services/llm/base.py +0 -0
  469. {topos_node-1.3.2 → topos_node-1.3.3}/topos/services/llm/openai.py +0 -0
  470. {topos_node-1.3.2 → topos_node-1.3.3}/topos/services/local.py +0 -0
  471. {topos_node-1.3.2 → topos_node-1.3.3}/topos/services/postgres.py +0 -0
  472. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sources/__init__.py +0 -0
  473. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sources/bundled_canonical_triples.py +0 -0
  474. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sources/canonical_signal_defaults.py +0 -0
  475. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sources/definitions.py +0 -0
  476. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sources/install_service.py +0 -0
  477. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sources/registry.py +0 -0
  478. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sources/runtime_install.py +0 -0
  479. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sources/scrub_attribution.py +0 -0
  480. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sources/scrub_service.py +0 -0
  481. {topos_node-1.3.2 → topos_node-1.3.3}/topos/startup_banner.py +0 -0
  482. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/__init__.py +0 -0
  483. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/adapters/__init__.py +0 -0
  484. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/adapters/factory.py +0 -0
  485. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/adapters/fakes.py +0 -0
  486. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/adapters/postgres/stores.py +0 -0
  487. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/adapters/protocols.py +0 -0
  488. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/adapters/sqlite/__init__.py +0 -0
  489. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/adapters/sqlite/stores.py +0 -0
  490. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/adapters/sqlite/vector_search.py +0 -0
  491. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/canonical/__init__.py +0 -0
  492. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/canonical/activity_tables.py +0 -0
  493. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/canonical/ai_chat/__init__.py +0 -0
  494. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
  495. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/canonical/ai_chat/mapper.py +0 -0
  496. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/canonical/ai_chat/model.py +0 -0
  497. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/canonical/ai_chat/tables.py +0 -0
  498. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
  499. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/canonical/canonical_store.py +0 -0
  500. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/canonical/conversations_tables.py +0 -0
  501. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/canonical/mapping_store.py +0 -0
  502. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/canonical/postgres.py +0 -0
  503. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/__init__.py +0 -0
  504. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/client.py +0 -0
  505. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/connection_tuning.py +0 -0
  506. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
  507. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/actor_role_v1.py +0 -0
  508. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
  509. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
  510. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
  511. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
  512. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
  513. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
  514. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/complexity_v1.py +0 -0
  515. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
  516. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
  517. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/documents_v1.py +0 -0
  518. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/entity_blackhole_v1.py +0 -0
  519. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
  520. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/episodes_v1.py +0 -0
  521. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
  522. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
  523. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
  524. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
  525. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
  526. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
  527. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
  528. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/remediation_person_model.py +0 -0
  529. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/scope_source_generation.py +0 -0
  530. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
  531. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
  532. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/signal_objects.py +0 -0
  533. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
  534. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
  535. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
  536. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
  537. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
  538. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
  539. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
  540. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
  541. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
  542. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
  543. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
  544. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
  545. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
  546. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
  547. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
  548. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
  549. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
  550. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
  551. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
  552. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
  553. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
  554. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/paths.py +0 -0
  555. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/postgres.py +0 -0
  556. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/schema.py +0 -0
  557. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/storage_breakdown.py +0 -0
  558. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/db/write_gate.py +0 -0
  559. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/enrichment/__init__.py +0 -0
  560. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
  561. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
  562. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/normalized/__init__.py +0 -0
  563. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/normalized/normalized_store.py +0 -0
  564. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/oplog/__init__.py +0 -0
  565. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/oplog/decision.py +0 -0
  566. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/oplog/oplog_store.py +0 -0
  567. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/oplog/postgres.py +0 -0
  568. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/person/identity_resolver.py +0 -0
  569. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/projections/__init__.py +0 -0
  570. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/projections/index_ops_store.py +0 -0
  571. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/projections/vector_index_store.py +0 -0
  572. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/raw/__init__.py +0 -0
  573. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/raw/browser_flat_tables.py +0 -0
  574. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/raw/file_store.py +0 -0
  575. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/raw/raw_store.py +0 -0
  576. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/raw/raw_tables_manager.py +0 -0
  577. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/raw/sqlite_raw_store.py +0 -0
  578. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/security/encryption.py +0 -0
  579. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/signal_identity.py +0 -0
  580. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/source_settings.py +0 -0
  581. {topos_node-1.3.2 → topos_node-1.3.3}/topos/storage/user_identity.py +0 -0
  582. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sync/__init__.py +0 -0
  583. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sync/client.py +0 -0
  584. {topos_node-1.3.2 → topos_node-1.3.3}/topos/sync_handlers.py +0 -0
  585. {topos_node-1.3.2 → topos_node-1.3.3}/topos/testing/__init__.py +0 -0
  586. {topos_node-1.3.2 → topos_node-1.3.3}/topos/testing/lifespan.py +0 -0
  587. {topos_node-1.3.2 → topos_node-1.3.3}/topos/uma_contact_enrichment.py +0 -0
  588. {topos_node-1.3.2 → topos_node-1.3.3}/topos/uma_filters.py +0 -0
  589. {topos_node-1.3.2 → topos_node-1.3.3}/topos/uma_resource_id.py +0 -0
  590. {topos_node-1.3.2 → topos_node-1.3.3}/topos/uma_rpt.py +0 -0
  591. {topos_node-1.3.2 → topos_node-1.3.3}/topos/upgrades/runner.py +0 -0
  592. {topos_node-1.3.2 → topos_node-1.3.3}/topos/utils/base_object.py +0 -0
  593. {topos_node-1.3.2 → topos_node-1.3.3}/topos/websocket_client.py +0 -0
  594. {topos_node-1.3.2 → topos_node-1.3.3}/topos_node.egg-info/dependency_links.txt +0 -0
  595. {topos_node-1.3.2 → topos_node-1.3.3}/topos_node.egg-info/entry_points.txt +0 -0
  596. {topos_node-1.3.2 → topos_node-1.3.3}/topos_node.egg-info/requires.txt +0 -0
  597. {topos_node-1.3.2 → topos_node-1.3.3}/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.3
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.3"
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.3"
4
+ __version_info__ = (1, 3, 3)
5
5
 
6
6
  __all__ = ["__version__", "__version_info__"]
@@ -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
@@ -61,6 +61,8 @@ def attention_dashboard_data(conn: sqlite3.Connection, *, days: int = 14,
61
61
  for v in verdicts:
62
62
  v["title"] = (titles.get(v["record_id"]) or v["table"] or "")[:90]
63
63
 
64
+ from .intents import intent_status
65
+
64
66
  intents = []
65
67
  for row in conn.execute(
66
68
  "SELECT payload_json, valid_from FROM signal_objects WHERE object_type='declared_intent' "
@@ -72,12 +74,18 @@ def attention_dashboard_data(conn: sqlite3.Connection, *, days: int = 14,
72
74
  continue
73
75
  # Pin instant lives on the row — surface it so pin days are plottable.
74
76
  intent.setdefault("pinned_at", row[1])
77
+ intent["status"] = intent_status(intent)
75
78
  intents.append(intent)
79
+ # Faded pins are not live steering, but the app shows what elapsed rather
80
+ # than letting an intent vanish silently.
81
+ faded = sorted((i for i in intents if i["status"] == "faded"),
82
+ key=lambda i: str(i.get("origin_timeframe") or ""), reverse=True)[:5]
76
83
  return {
77
84
  "days": days,
78
85
  "verdicts": verdicts,
79
86
  "summaries": summaries,
80
- "active_intents": [i for i in intents if i.get("status", "active") == "active"],
87
+ "active_intents": [i for i in intents if i["status"] == "active"],
88
+ "faded_intents": faded,
81
89
  "badges": earned_badges(conn),
82
90
  "current_badge": current_badge(conn),
83
91
  "rank": rank(conn),
@@ -14,10 +14,17 @@ from __future__ import annotations
14
14
  import json
15
15
  import re
16
16
  import sqlite3
17
+ from datetime import date, timedelta
17
18
  from typing import Any, Dict, List, Optional, Tuple
18
19
 
19
20
  from ..signal.signal_object_store import SignalObjectStore
20
21
 
22
+ # A pin is a bet with a shelf life. The horizon is coarse on purpose — owners
23
+ # think in "weeks / months / this quarter", not in target dates — and it is the
24
+ # only thing that decides when the pin stops steering.
25
+ HORIZON_DAYS = {"weeks": 21, "months": 60, "quarter": 90}
26
+ DEFAULT_HORIZON = "quarter"
27
+
21
28
  _STOP = {"the", "a", "an", "and", "or", "of", "to", "in", "for", "on", "with",
22
29
  "my", "our", "their", "this", "that", "is", "are", "be", "see",
23
30
  "more", "new", "build", "collect", "evidence", "people", "things"}
@@ -28,15 +35,46 @@ def _keywords(text: str) -> List[str]:
28
35
  return [w for w in words if w not in _STOP]
29
36
 
30
37
 
38
+ def _parse_day(value: Any) -> Optional[date]:
39
+ try:
40
+ return date.fromisoformat(str(value)[:10])
41
+ except (TypeError, ValueError):
42
+ return None
43
+
44
+
45
+ def intent_faded(intent: Dict[str, Any], *, today: Optional[date] = None) -> bool:
46
+ """Has this pin's horizon elapsed since it was declared?
47
+
48
+ Read-time only — nothing is ever rewritten. An intent with no parseable
49
+ origin never fades (we cannot date it, so we keep steering by it).
50
+ """
51
+ origin = _parse_day(intent.get("origin_timeframe"))
52
+ if origin is None:
53
+ return False
54
+ days = HORIZON_DAYS.get(str(intent.get("horizon") or DEFAULT_HORIZON),
55
+ HORIZON_DAYS[DEFAULT_HORIZON])
56
+ return origin + timedelta(days=days) < (today or date.today())
57
+
58
+
59
+ def intent_status(intent: Dict[str, Any], *, today: Optional[date] = None) -> str:
60
+ """Reported status: an explicit retire wins, otherwise the horizon decides."""
61
+ stored = str(intent.get("status") or "active")
62
+ if stored != "active":
63
+ return stored
64
+ return "faded" if intent_faded(intent, today=today) else "active"
65
+
66
+
31
67
  def pin_intent(conn: sqlite3.Connection, intent_text: str, *,
32
- horizon: str = "quarter", links: Optional[List[str]] = None,
68
+ horizon: str = DEFAULT_HORIZON, links: Optional[List[str]] = None,
33
69
  origin_timeframe: Optional[str] = None) -> Dict[str, Any]:
34
70
  """F1: create (or refresh) a declared_intent signal object."""
35
71
  key = "intent:" + re.sub(r"[^a-z0-9]+", "-", intent_text.lower())[:60].strip("-")
36
72
  payload = {
37
73
  "intent_text": intent_text,
38
74
  "horizon": horizon,
39
- "origin_timeframe": origin_timeframe,
75
+ # The fade clock starts the moment the pin is made unless the owner
76
+ # backdates it — an undated pin would otherwise steer forever.
77
+ "origin_timeframe": origin_timeframe or date.today().isoformat(),
40
78
  "status": "active",
41
79
  "links": links or [],
42
80
  "keywords": _keywords(intent_text),
@@ -49,7 +87,7 @@ def pin_intent(conn: sqlite3.Connection, intent_text: str, *,
49
87
  confidence=1.0, extractor_version="owner_declared", created_by="owner")
50
88
 
51
89
 
52
- def active_intents(conn: sqlite3.Connection) -> List[Dict[str, Any]]:
90
+ def _all_intents(conn: sqlite3.Connection) -> List[Dict[str, Any]]:
53
91
  try:
54
92
  rows = conn.execute(
55
93
  "SELECT object_key, payload_json FROM signal_objects "
@@ -62,12 +100,51 @@ def active_intents(conn: sqlite3.Connection) -> List[Dict[str, Any]]:
62
100
  p = json.loads(pj)
63
101
  except (TypeError, ValueError):
64
102
  continue
65
- if p.get("status", "active") == "active":
66
- p["_key"] = key
67
- out.append(p)
103
+ p["_key"] = key
104
+ out.append(p)
68
105
  return out
69
106
 
70
107
 
108
+ def active_intents(conn: sqlite3.Connection,
109
+ *, today: Optional[date] = None) -> List[Dict[str, Any]]:
110
+ """The live pins: neither retired by hand nor faded by their horizon."""
111
+ return [p for p in _all_intents(conn) if intent_status(p, today=today) == "active"]
112
+
113
+
114
+ def faded_intents(conn: sqlite3.Connection, *, limit: int = 5,
115
+ today: Optional[date] = None) -> List[Dict[str, Any]]:
116
+ """Pins whose horizon has elapsed, most recently declared first."""
117
+ out = []
118
+ for p in _all_intents(conn):
119
+ if intent_status(p, today=today) != "faded":
120
+ continue
121
+ p["status"] = "faded"
122
+ out.append(p)
123
+ out.sort(key=lambda p: str(p.get("origin_timeframe") or ""), reverse=True)
124
+ return out[:limit]
125
+
126
+
127
+ def retire_intent(conn: sqlite3.Connection, object_key: str) -> Optional[Dict[str, Any]]:
128
+ """Manual retire — the owner calling it before the horizon does."""
129
+ key = str(object_key or "").strip()
130
+ row = conn.execute(
131
+ "SELECT payload_json FROM signal_objects WHERE object_type='declared_intent' "
132
+ "AND object_key=? AND valid_to IS NULL", (key,)).fetchone()
133
+ if not row:
134
+ return None
135
+ try:
136
+ payload = json.loads(row[0])
137
+ except (TypeError, ValueError):
138
+ return None
139
+ payload["status"] = "retired"
140
+ payload.pop("_key", None)
141
+ store = SignalObjectStore(conn)
142
+ return store.upsert_object(
143
+ "intentions", "declared_intent", key, payload,
144
+ source_refs=[{"declared_by": "owner"}],
145
+ confidence=1.0, extractor_version="owner_declared", created_by="owner")
146
+
147
+
71
148
  def intent_match(text: str, intents: List[Dict[str, Any]],
72
149
  item_vec=None, intent_vecs=None) -> Tuple[float, Optional[str]]:
73
150
  """F2 semantic term: max proximity of an item to any active intent.
@@ -172,7 +172,9 @@
172
172
  "signal_list_topic_clusters",
173
173
  "signal_list_vectors",
174
174
  "signal_owner_override_object",
175
+ "signal_pin_intent",
175
176
  "signal_refresh_brief",
177
+ "signal_retire_intent",
176
178
  "signal_search_vectors",
177
179
  "signal_set_worn_badge",
178
180
  "signal_timeline_daily",
@@ -0,0 +1,190 @@
1
+ """Wiki MVP storage migration runner — single registry (PLAN §4a)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import sqlite3
7
+ from typing import List, Optional
8
+
9
+ from .backup import (
10
+ InsufficientDiskForBackup,
11
+ backup_database_before_migrations,
12
+ connection_db_path,
13
+ )
14
+ # Re-export migration IDs + registry used by tests/tools.
15
+ from .registry import * # noqa: F403
16
+ from .registry import MIGRATIONS, MigrationSpec, max_migration_order # noqa: F401
17
+ from .canonical_disclosure_v1 import apply_canonical_disclosure_v1_up # noqa: F401
18
+ from .canonical_nsfw_v1 import apply_canonical_nsfw_v1_up # noqa: F401
19
+ from .complexity_v1 import apply_complexity_v1_up # noqa: F401
20
+ from .activity_events_content_v1 import apply_activity_events_content_v1_up # noqa: F401
21
+ from .actor_role_v1 import apply_actor_role_v1_up # noqa: F401
22
+ from .entity_blackhole_v1 import apply_entity_blackhole_v1_up # noqa: F401
23
+ from .attention_triage_v1 import apply_attention_triage_v1_up # noqa: F401
24
+ from .attention_triage_v2 import apply_attention_triage_v2_up # noqa: F401
25
+ from .documents_v1 import apply_documents_v1_up # noqa: F401
26
+ from .canonical_address_book_v1 import apply_canonical_address_book_v1_up # noqa: F401
27
+
28
+ logger = logging.getLogger("topos.storage.db.migrations")
29
+
30
+ __all__ = [
31
+ "MigrationError",
32
+ "DowngradeGuardError",
33
+ "MigrationSpec",
34
+ "MIGRATIONS",
35
+ "apply_all_migrations",
36
+ "ensure_migrations_applied",
37
+ "pending_ledger_migrations",
38
+ "read_user_version",
39
+ "max_migration_order",
40
+ ]
41
+
42
+
43
+ class MigrationError(RuntimeError):
44
+ """Schema migration failed; the database must not be served half-migrated."""
45
+
46
+
47
+ class DowngradeGuardError(MigrationError):
48
+ """Database ``user_version`` is newer than this build knows how to open."""
49
+
50
+
51
+ def _migration_applied(conn: sqlite3.Connection, migration_id: str) -> bool:
52
+ try:
53
+ row = conn.execute(
54
+ "SELECT 1 FROM wiki_schema_migrations WHERE migration_id=?",
55
+ (migration_id,),
56
+ ).fetchone()
57
+ return row is not None
58
+ except sqlite3.OperationalError:
59
+ return False
60
+
61
+
62
+ def _table_exists(conn: sqlite3.Connection, table: str) -> bool:
63
+ try:
64
+ row = conn.execute(
65
+ "SELECT name FROM sqlite_master WHERE type='table' AND name=?",
66
+ (table,),
67
+ ).fetchone()
68
+ return row is not None
69
+ except sqlite3.OperationalError:
70
+ return False
71
+
72
+
73
+ def read_user_version(conn: sqlite3.Connection) -> int:
74
+ row = conn.execute("PRAGMA user_version").fetchone()
75
+ if row is None:
76
+ return 0
77
+ return int(row[0])
78
+
79
+
80
+ def _stamp_user_version(conn: sqlite3.Connection, order: int) -> None:
81
+ conn.execute(f"PRAGMA user_version = {int(order)}")
82
+
83
+
84
+ def _shipped_version() -> str:
85
+ try:
86
+ from ....__version__ import __version__
87
+
88
+ return str(__version__)
89
+ except Exception: # noqa: BLE001
90
+ return "unknown"
91
+
92
+
93
+ def _needs_apply(conn: sqlite3.Connection, spec: MigrationSpec) -> bool:
94
+ if spec.always_run:
95
+ return True
96
+ if not _migration_applied(conn, spec.id):
97
+ return True
98
+ if spec.also_if_missing_table and not _table_exists(conn, spec.also_if_missing_table):
99
+ return True
100
+ return False
101
+
102
+
103
+ def pending_ledger_migrations(conn: sqlite3.Connection) -> List[MigrationSpec]:
104
+ """Ledger-guarded migrations that have not yet been recorded as applied.
105
+
106
+ Used to decide whether a pre-migration backup is required. ``always_run``
107
+ steps alone do not trigger a backup.
108
+ """
109
+ pending: List[MigrationSpec] = []
110
+ for spec in MIGRATIONS:
111
+ if spec.always_run:
112
+ continue
113
+ if not _migration_applied(conn, spec.id):
114
+ pending.append(spec)
115
+ continue
116
+ if spec.also_if_missing_table and not _table_exists(
117
+ conn, spec.also_if_missing_table
118
+ ):
119
+ pending.append(spec)
120
+ return pending
121
+
122
+
123
+ def apply_all_migrations(conn: sqlite3.Connection) -> None:
124
+ """Apply every migration unconditionally (tests / offline tools)."""
125
+ for spec in MIGRATIONS:
126
+ spec.fn(conn)
127
+ _stamp_user_version(conn, max_migration_order())
128
+
129
+
130
+ def ensure_migrations_applied(
131
+ conn: sqlite3.Connection,
132
+ *,
133
+ skip_backup: bool = False,
134
+ ) -> Optional[str]:
135
+ """Apply pending schema migrations; fail loud on error.
136
+
137
+ Returns the backup path string when a pre-migration backup was written,
138
+ otherwise None. Raises ``DowngradeGuardError`` / ``MigrationError`` on
139
+ failure — callers must not serve a half-migrated database.
140
+ """
141
+ max_order = max_migration_order()
142
+ current = read_user_version(conn)
143
+ if current > max_order:
144
+ raise DowngradeGuardError(
145
+ f"database was upgraded by a newer topos-node "
146
+ f"(PRAGMA user_version={current} > {max_order} known to this build); "
147
+ f"upgrade the package or restore the pre-upgrade backup under "
148
+ f"~/.topos/backups/"
149
+ )
150
+
151
+ pending = pending_ledger_migrations(conn)
152
+ backup_path: Optional[str] = None
153
+
154
+ # Fast path: fully stamped DB with nothing pending — only always_run steps.
155
+ if current >= max_order and not pending:
156
+ for spec in MIGRATIONS:
157
+ if not spec.always_run:
158
+ continue
159
+ try:
160
+ spec.fn(conn)
161
+ except Exception as exc: # noqa: BLE001
162
+ raise MigrationError(
163
+ f"always-run migration {spec.id!r} failed: {exc}"
164
+ ) from exc
165
+ return None
166
+
167
+ if pending and not skip_backup and connection_db_path(conn) is not None:
168
+ try:
169
+ path = backup_database_before_migrations(
170
+ conn, shipped_version=_shipped_version()
171
+ )
172
+ if path is not None:
173
+ backup_path = str(path)
174
+ except InsufficientDiskForBackup as exc:
175
+ logger.error("%s", exc)
176
+ raise MigrationError(str(exc)) from exc
177
+
178
+ for spec in MIGRATIONS:
179
+ if not _needs_apply(conn, spec):
180
+ continue
181
+ try:
182
+ spec.fn(conn)
183
+ except Exception as exc: # noqa: BLE001
184
+ hint = f" Restore from {backup_path}." if backup_path else ""
185
+ raise MigrationError(
186
+ f"schema migration {spec.id!r} (order={spec.order}) failed: {exc}.{hint}"
187
+ ) from exc
188
+
189
+ _stamp_user_version(conn, max_order)
190
+ return backup_path
@@ -0,0 +1,125 @@
1
+ """Pre-migration SQLite backup (PLAN_NODE_RELEASE_MIGRATIONS §4a.5)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import os
7
+ import shutil
8
+ import sqlite3
9
+ from datetime import datetime, timezone
10
+ from pathlib import Path
11
+ from typing import List, Optional
12
+
13
+ logger = logging.getLogger("topos.storage.db.migrations.backup")
14
+
15
+ BACKUP_RETENTION = 2
16
+ _BACKUP_DIR_ENV = "TOPOS_BACKUP_DIR"
17
+
18
+
19
+ class InsufficientDiskForBackup(RuntimeError):
20
+ """Raised when free disk is below 2× DB size and backup cannot proceed safely."""
21
+
22
+
23
+ def backup_dir_for(db_path: Path) -> Path:
24
+ override = os.environ.get(_BACKUP_DIR_ENV)
25
+ if override:
26
+ return Path(override)
27
+ return db_path.expanduser().resolve().parent / "backups"
28
+
29
+
30
+ def connection_db_path(conn: sqlite3.Connection) -> Optional[Path]:
31
+ """Return the on-disk path for the main DB, or None for :memory:/temp."""
32
+ try:
33
+ rows = conn.execute("PRAGMA database_list").fetchall()
34
+ except sqlite3.Error:
35
+ return None
36
+ for row in rows:
37
+ # row: (seq, name, file)
38
+ name = row[1] if not hasattr(row, "keys") else row["name"]
39
+ file_path = row[2] if not hasattr(row, "keys") else row["file"]
40
+ if str(name) != "main":
41
+ continue
42
+ if not file_path:
43
+ return None
44
+ path = Path(str(file_path))
45
+ if not path.is_file():
46
+ return None
47
+ return path
48
+ return None
49
+
50
+
51
+ def _free_bytes(path: Path) -> Optional[int]:
52
+ try:
53
+ usage = shutil.disk_usage(path if path.is_dir() else path.parent)
54
+ return int(usage.free)
55
+ except OSError:
56
+ return None
57
+
58
+
59
+ def prune_old_backups(directory: Path, *, keep: int = BACKUP_RETENTION) -> List[Path]:
60
+ """Keep the newest ``keep`` ``database-pre-v*.db`` files; delete older ones."""
61
+ if not directory.is_dir():
62
+ return []
63
+ candidates = sorted(
64
+ directory.glob("database-pre-v*.db"),
65
+ key=lambda p: p.stat().st_mtime,
66
+ reverse=True,
67
+ )
68
+ removed: List[Path] = []
69
+ for stale in candidates[keep:]:
70
+ try:
71
+ stale.unlink()
72
+ removed.append(stale)
73
+ except OSError as exc:
74
+ logger.warning("Failed to prune backup %s: %s", stale, exc)
75
+ return removed
76
+
77
+
78
+ def backup_database_before_migrations(
79
+ conn: sqlite3.Connection,
80
+ *,
81
+ shipped_version: str,
82
+ keep: int = BACKUP_RETENTION,
83
+ ) -> Optional[Path]:
84
+ """Copy the live DB to ``~/.topos/backups/database-pre-v{ver}-{ts}.db``.
85
+
86
+ Returns the backup path, or None when there is no on-disk DB (in-memory /
87
+ test fixtures). Raises ``InsufficientDiskForBackup`` when free space is
88
+ below 2× the DB size (skip-with-loud-warning is the caller's choice — we
89
+ raise so boot can decide fail-loud vs warn).
90
+ """
91
+ db_path = connection_db_path(conn)
92
+ if db_path is None:
93
+ return None
94
+
95
+ dest_dir = backup_dir_for(db_path)
96
+ dest_dir.mkdir(parents=True, exist_ok=True)
97
+
98
+ size = db_path.stat().st_size
99
+ free = _free_bytes(dest_dir)
100
+ if free is not None and size > 0 and free < 2 * size:
101
+ raise InsufficientDiskForBackup(
102
+ f"free disk {free} bytes < 2× database size {size} bytes; "
103
+ f"refusing to migrate without a pre-upgrade backup under {dest_dir}"
104
+ )
105
+
106
+ stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
107
+ safe_ver = "".join(ch if ch.isalnum() or ch in "._-" else "_" for ch in shipped_version)
108
+ dest = dest_dir / f"database-pre-v{safe_ver}-{stamp}.db"
109
+ if dest.exists():
110
+ dest.unlink()
111
+
112
+ src = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True)
113
+ try:
114
+ dst = sqlite3.connect(str(dest))
115
+ try:
116
+ with dst:
117
+ src.backup(dst)
118
+ finally:
119
+ dst.close()
120
+ finally:
121
+ src.close()
122
+
123
+ prune_old_backups(dest_dir, keep=keep)
124
+ logger.info("Pre-migration backup written to %s (%.1f MB)", dest, dest.stat().st_size / 1e6)
125
+ return dest