topos-node 1.3.4__tar.gz → 1.3.5__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 (620) hide show
  1. {topos_node-1.3.4/topos_node.egg-info → topos_node-1.3.5}/PKG-INFO +13 -3
  2. {topos_node-1.3.4 → topos_node-1.3.5}/README.md +8 -0
  3. {topos_node-1.3.4 → topos_node-1.3.5}/pyproject.toml +10 -3
  4. topos_node-1.3.5/tests/test_protocol_handled_types.py +293 -0
  5. {topos_node-1.3.4 → topos_node-1.3.5}/topos/__version__.py +2 -2
  6. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/enrichment.py +2 -2
  7. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/ingestion_api.py +14 -0
  8. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/signal.py +126 -1
  9. {topos_node-1.3.4 → topos_node-1.3.5}/topos/cli/commands.py +27 -3
  10. topos_node-1.3.5/topos/cli/reprocess_cmd.py +91 -0
  11. {topos_node-1.3.4 → topos_node-1.3.5}/topos/cli/tray.py +45 -6
  12. {topos_node-1.3.4 → topos_node-1.3.5}/topos/config/conversation_context_llm.py +62 -5
  13. {topos_node-1.3.4 → topos_node-1.3.5}/topos/config/facts_llm.py +39 -4
  14. topos_node-1.3.5/topos/config/model_packs.py +474 -0
  15. {topos_node-1.3.4 → topos_node-1.3.5}/topos/config/sanitization_ollama.py +37 -1
  16. {topos_node-1.3.4 → topos_node-1.3.5}/topos/config/signal_extraction.py +51 -0
  17. {topos_node-1.3.4 → topos_node-1.3.5}/topos/control_plane_client.py +3 -0
  18. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/api_models.py +9 -0
  19. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/__init__.py +2 -1
  20. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/database_explorer.py +3 -3
  21. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/device.py +19 -0
  22. topos_node-1.3.5/topos/core/handlers/graph_query.py +67 -0
  23. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/ingest.py +4 -0
  24. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/messages.py +4 -0
  25. topos_node-1.3.5/topos/core/handlers/registry.py +43 -0
  26. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/signal_features.py +117 -0
  27. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/uma.py +4 -0
  28. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/logging.py +4 -1
  29. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/state.py +115 -4
  30. {topos_node-1.3.4 → topos_node-1.3.5}/topos/data_explorer_row_delete.py +1 -2
  31. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/backends/generative_prompts.py +17 -7
  32. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/backends/ollama.py +12 -2
  33. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/engine.py +11 -0
  34. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/tasks.py +7 -0
  35. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/usage_observation.py +24 -0
  36. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/catalog.py +2 -1
  37. topos_node-1.3.5/topos/enrichment/derivation_recovery.py +378 -0
  38. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/derived_tables.py +64 -23
  39. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/job_writer.py +0 -1
  40. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/_engine_runner.py +21 -1
  41. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/dimension_summary_job.py +4 -0
  42. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/entities_job.py +29 -15
  43. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/topic_clusters_job.py +55 -0
  44. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/orchestrator.py +73 -7
  45. topos_node-1.3.5/topos/enrichment/pipeline_activity.py +51 -0
  46. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/projection.py +85 -3
  47. topos_node-1.3.5/topos/features/entities/affinity.py +487 -0
  48. topos_node-1.3.5/topos/features/entities/affinity_owner.py +401 -0
  49. topos_node-1.3.5/topos/features/entities/affinity_quality.py +592 -0
  50. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/entities/consolidation.py +93 -41
  51. topos_node-1.3.5/topos/features/entities/context_vectors.py +316 -0
  52. topos_node-1.3.5/topos/features/entities/cypher.py +314 -0
  53. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/entities/dossier.py +109 -19
  54. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/entities/edges.py +21 -3
  55. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/entities/graph_refresh.py +32 -7
  56. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/entities/linking.py +43 -8
  57. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/entities/maintenance.py +286 -39
  58. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/entities/reads.py +38 -11
  59. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/entities/resolver.py +82 -21
  60. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/facts/llm_extract.py +52 -21
  61. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/lifecycle/blackhole_rebuild.py +31 -1
  62. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/lifecycle/derived_scrub.py +136 -21
  63. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/lifecycle/exclusions.py +9 -0
  64. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/lifecycle/gc.py +8 -3
  65. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/conversation_context.py +18 -3
  66. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/data_health.py +1 -1
  67. topos_node-1.3.5/topos/features/signal/derived_spec.py +115 -0
  68. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/topic_clustering.py +43 -0
  69. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/stats/insights.py +40 -5
  70. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/reprocess.py +204 -37
  71. {topos_node-1.3.4 → topos_node-1.3.5}/topos/pipeline/job_runner.py +67 -2
  72. {topos_node-1.3.4 → topos_node-1.3.5}/topos/protocol/handled_message_types.json +12 -0
  73. topos_node-1.3.5/topos/query/cohort_resolvers.py +294 -0
  74. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/manifest.py +16 -5
  75. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/manifest_validation.py +91 -0
  76. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/pipeline.py +148 -24
  77. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/planner.py +10 -0
  78. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/retrieval.py +419 -34
  79. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/scope_registry.json +14 -7
  80. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/types.py +4 -0
  81. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sanitization/ollama_transforms.py +23 -1
  82. {topos_node-1.3.4 → topos_node-1.3.5}/topos/services/llm/openai.py +13 -6
  83. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sources/registry.py +16 -7
  84. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sources/scrub_attribution.py +8 -6
  85. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/adapters/fakes.py +9 -0
  86. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/adapters/protocols.py +1 -0
  87. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/adapters/sqlite/stores.py +33 -19
  88. topos_node-1.3.5/topos/storage/db/migrations/affinity_pair_labels_v1.py +58 -0
  89. topos_node-1.3.5/topos/storage/db/migrations/entity_affinity_v1.py +62 -0
  90. topos_node-1.3.5/topos/storage/db/migrations/entity_context_vectors_v1.py +56 -0
  91. topos_node-1.3.5/topos/storage/db/migrations/entity_context_vectors_v2.py +55 -0
  92. topos_node-1.3.5/topos/storage/db/migrations/entity_mentions_authored_v1.py +229 -0
  93. topos_node-1.3.5/topos/storage/db/migrations/message_emotions_role_backfill_v1.py +153 -0
  94. topos_node-1.3.5/topos/storage/db/migrations/message_emotions_role_v1.py +39 -0
  95. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/registry.py +48 -0
  96. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/registry_checksums.json +6 -0
  97. topos_node-1.3.5/topos/storage/db/migrations/signal_summaries_drop_v1.py +30 -0
  98. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/storage_breakdown.py +0 -1
  99. topos_node-1.3.5/topos/storage/db/write_gate.py +203 -0
  100. {topos_node-1.3.4 → topos_node-1.3.5}/topos/upgrades/manifests.json +9 -0
  101. {topos_node-1.3.4 → topos_node-1.3.5/topos_node.egg-info}/PKG-INFO +13 -3
  102. {topos_node-1.3.4 → topos_node-1.3.5}/topos_node.egg-info/SOURCES.txt +20 -0
  103. {topos_node-1.3.4 → topos_node-1.3.5}/topos_node.egg-info/requires.txt +4 -2
  104. topos_node-1.3.4/tests/test_protocol_handled_types.py +0 -70
  105. topos_node-1.3.4/topos/core/handlers/registry.py +0 -21
  106. topos_node-1.3.4/topos/storage/db/write_gate.py +0 -110
  107. {topos_node-1.3.4 → topos_node-1.3.5}/LICENSE +0 -0
  108. {topos_node-1.3.4 → topos_node-1.3.5}/MANIFEST.in +0 -0
  109. {topos_node-1.3.4 → topos_node-1.3.5}/setup.cfg +0 -0
  110. {topos_node-1.3.4 → topos_node-1.3.5}/shared/__init__.py +0 -0
  111. {topos_node-1.3.4 → topos_node-1.3.5}/shared/filtering.py +0 -0
  112. {topos_node-1.3.4 → topos_node-1.3.5}/shared/schema_registry.py +0 -0
  113. {topos_node-1.3.4 → topos_node-1.3.5}/tests/test_extensions.py +0 -0
  114. {topos_node-1.3.4 → topos_node-1.3.5}/tests/test_llm_integrations_storage.py +0 -0
  115. {topos_node-1.3.4 → topos_node-1.3.5}/topos/__init__.py +0 -0
  116. {topos_node-1.3.4 → topos_node-1.3.5}/topos/analytics/__init__.py +0 -0
  117. {topos_node-1.3.4 → topos_node-1.3.5}/topos/analytics/duckdb_adapter.py +0 -0
  118. {topos_node-1.3.4 → topos_node-1.3.5}/topos/analytics/messenger_communities.py +0 -0
  119. {topos_node-1.3.4 → topos_node-1.3.5}/topos/analytics/messenger_graph.py +0 -0
  120. {topos_node-1.3.4 → topos_node-1.3.5}/topos/analytics/messenger_labels.py +0 -0
  121. {topos_node-1.3.4 → topos_node-1.3.5}/topos/analytics/profiles.py +0 -0
  122. {topos_node-1.3.4 → topos_node-1.3.5}/topos/analytics/query_engine.py +0 -0
  123. {topos_node-1.3.4 → topos_node-1.3.5}/topos/analytics/raw_queries.py +0 -0
  124. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/__init__.py +0 -0
  125. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/analytics.py +0 -0
  126. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/app_registry.py +0 -0
  127. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/backup.py +0 -0
  128. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/compute_remote.py +0 -0
  129. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/conversation_context.py +0 -0
  130. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/data_commit.py +0 -0
  131. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/data_explorer_table_prefs.py +0 -0
  132. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/database_explorer.py +0 -0
  133. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/db.py +0 -0
  134. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/device.py +0 -0
  135. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/engine_run.py +0 -0
  136. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/enrichment_lab.py +0 -0
  137. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/facts_llm_config.py +0 -0
  138. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/filter_lab.py +0 -0
  139. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/health.py +0 -0
  140. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/home_chat.py +0 -0
  141. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/ingestion_compat.py +0 -0
  142. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/ingestion_sources.py +0 -0
  143. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/intelligence_lifecycle.py +0 -0
  144. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/llm.py +0 -0
  145. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/local_mcp.py +0 -0
  146. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/messenger_analytics.py +0 -0
  147. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/privacy_disclose.py +0 -0
  148. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/query_api.py +0 -0
  149. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/runtime_bootstrap.py +0 -0
  150. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/sanitization_ollama_config.py +0 -0
  151. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/shell.py +0 -0
  152. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/signal_extraction_config.py +0 -0
  153. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/source_install.py +0 -0
  154. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/source_scrub.py +0 -0
  155. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/sources.py +0 -0
  156. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/sources_overview.py +0 -0
  157. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/sync.py +0 -0
  158. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/tool_index.py +0 -0
  159. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/ui_config.py +0 -0
  160. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/uma_data.py +0 -0
  161. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/upgrades.py +0 -0
  162. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/usage.py +0 -0
  163. {topos_node-1.3.4 → topos_node-1.3.5}/topos/api/user_identity.py +0 -0
  164. {topos_node-1.3.4 → topos_node-1.3.5}/topos/app.py +0 -0
  165. {topos_node-1.3.4 → topos_node-1.3.5}/topos/auth.py +0 -0
  166. {topos_node-1.3.4 → topos_node-1.3.5}/topos/canonicalization/__init__.py +0 -0
  167. {topos_node-1.3.4 → topos_node-1.3.5}/topos/canonicalization/mappers/__init__.py +0 -0
  168. {topos_node-1.3.4 → topos_node-1.3.5}/topos/canonicalization/mappers/base.py +0 -0
  169. {topos_node-1.3.4 → topos_node-1.3.5}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
  170. {topos_node-1.3.4 → topos_node-1.3.5}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
  171. {topos_node-1.3.4 → topos_node-1.3.5}/topos/canonicalization/mappers/demo_mappers.py +0 -0
  172. {topos_node-1.3.4 → topos_node-1.3.5}/topos/canonicalization/mappers/documents_mapper.py +0 -0
  173. {topos_node-1.3.4 → topos_node-1.3.5}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
  174. {topos_node-1.3.4 → topos_node-1.3.5}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
  175. {topos_node-1.3.4 → topos_node-1.3.5}/topos/canonicalization/mappers/grok_mapper.py +0 -0
  176. {topos_node-1.3.4 → topos_node-1.3.5}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
  177. {topos_node-1.3.4 → topos_node-1.3.5}/topos/canonicalization/models.py +0 -0
  178. {topos_node-1.3.4 → topos_node-1.3.5}/topos/canonicalization/resolver.py +0 -0
  179. {topos_node-1.3.4 → topos_node-1.3.5}/topos/cli/__init__.py +0 -0
  180. {topos_node-1.3.4 → topos_node-1.3.5}/topos/cli/__main__.py +0 -0
  181. {topos_node-1.3.4 → topos_node-1.3.5}/topos/cli/assets/topos_blk_rounded.png +0 -0
  182. {topos_node-1.3.4 → topos_node-1.3.5}/topos/cli/assets/topos_white.png +0 -0
  183. {topos_node-1.3.4 → topos_node-1.3.5}/topos/config/__init__.py +0 -0
  184. {topos_node-1.3.4 → topos_node-1.3.5}/topos/config/settings.py +0 -0
  185. {topos_node-1.3.4 → topos_node-1.3.5}/topos/config/uvicorn_logging.json +0 -0
  186. {topos_node-1.3.4 → topos_node-1.3.5}/topos/contacts/__init__.py +0 -0
  187. {topos_node-1.3.4 → topos_node-1.3.5}/topos/contacts/identity.py +0 -0
  188. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/__init__.py +0 -0
  189. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/connection_resilience.py +0 -0
  190. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/device_helpers.py +0 -0
  191. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/errors.py +0 -0
  192. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/events.py +0 -0
  193. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/common.py +0 -0
  194. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/complexity.py +0 -0
  195. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/config.py +0 -0
  196. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/contacts_import.py +0 -0
  197. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/enrichment.py +0 -0
  198. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/enrichment_lab.py +0 -0
  199. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/filter_lab.py +0 -0
  200. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/home_chat.py +0 -0
  201. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/messenger_analytics.py +0 -0
  202. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/query.py +0 -0
  203. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/routines.py +0 -0
  204. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/sources.py +0 -0
  205. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/timeline_daily.py +0 -0
  206. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/handlers/tool_index.py +0 -0
  207. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/metrics.py +0 -0
  208. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/routine_access.py +0 -0
  209. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/startup_banner.py +0 -0
  210. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/table_layers.py +0 -0
  211. {topos_node-1.3.4 → topos_node-1.3.5}/topos/core/types.py +0 -0
  212. {topos_node-1.3.4 → topos_node-1.3.5}/topos/data_explorer_table_prefs.py +0 -0
  213. {topos_node-1.3.4 → topos_node-1.3.5}/topos/data_explorer_tables.py +0 -0
  214. {topos_node-1.3.4 → topos_node-1.3.5}/topos/disclosure/__init__.py +0 -0
  215. {topos_node-1.3.4 → topos_node-1.3.5}/topos/disclosure/canonical_writer.py +0 -0
  216. {topos_node-1.3.4 → topos_node-1.3.5}/topos/disclosure/content_policy.py +0 -0
  217. {topos_node-1.3.4 → topos_node-1.3.5}/topos/disclosure/field_registry.py +0 -0
  218. {topos_node-1.3.4 → topos_node-1.3.5}/topos/disclosure/privacy_layer.py +0 -0
  219. {topos_node-1.3.4 → topos_node-1.3.5}/topos/disclosure/tier.py +0 -0
  220. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/__init__.py +0 -0
  221. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/backends/__init__.py +0 -0
  222. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/backends/base.py +0 -0
  223. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/backends/generative_response.py +0 -0
  224. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/backends/huggingface.py +0 -0
  225. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/backends/openai.py +0 -0
  226. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/backends/openai_compatible.py +0 -0
  227. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/backends/redpill.py +0 -0
  228. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/backends/stub.py +0 -0
  229. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/client.py +0 -0
  230. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/intake.py +0 -0
  231. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/memory_utils.py +0 -0
  232. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/model_cache.py +0 -0
  233. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/pipeline_memory.py +0 -0
  234. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/queue_manager.py +0 -0
  235. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/registration.py +0 -0
  236. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/result_formatter.py +0 -0
  237. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/router.py +0 -0
  238. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/scoped_token.py +0 -0
  239. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/transport.py +0 -0
  240. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/usage_guard.py +0 -0
  241. {topos_node-1.3.4 → topos_node-1.3.5}/topos/engine/validator.py +0 -0
  242. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/__init__.py +0 -0
  243. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/__init__.py +0 -0
  244. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/base.py +0 -0
  245. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/__init__.py +0 -0
  246. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
  247. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/attention_triage_job.py +0 -0
  248. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
  249. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
  250. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +0 -0
  251. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
  252. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
  253. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
  254. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
  255. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
  256. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
  257. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
  258. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
  259. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
  260. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
  261. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/url_classification_core.py +0 -0
  262. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/url_classification_enrichment_job.py +0 -0
  263. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/canonical/url_classification_signal_job.py +0 -0
  264. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/raw/__init__.py +0 -0
  265. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
  266. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/raw/language_job.py +0 -0
  267. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
  268. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
  269. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/model_overrides.py +0 -0
  270. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/models/__init__.py +0 -0
  271. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/models/manager.py +0 -0
  272. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/models/mvp_defaults.py +0 -0
  273. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/models/registry.py +0 -0
  274. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/models/versioning.py +0 -0
  275. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/processor.py +0 -0
  276. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/progress_bar.py +0 -0
  277. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/registry_contract.py +0 -0
  278. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/signal_derivation_config.json +0 -0
  279. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/source_overrides.py +0 -0
  280. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment/website_classifier.py +0 -0
  281. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment_lab/__init__.py +0 -0
  282. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment_lab/bundles.py +0 -0
  283. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment_lab/model_resolve.py +0 -0
  284. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment_lab/schema.py +0 -0
  285. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment_lab/service.py +0 -0
  286. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment_lab/store.py +0 -0
  287. {topos_node-1.3.4 → topos_node-1.3.5}/topos/enrichment_lab/worker.py +0 -0
  288. {topos_node-1.3.4 → topos_node-1.3.5}/topos/evals/__init__.py +0 -0
  289. {topos_node-1.3.4 → topos_node-1.3.5}/topos/evals/enrichment_eval.py +0 -0
  290. {topos_node-1.3.4 → topos_node-1.3.5}/topos/extensions.py +0 -0
  291. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/__init__.py +0 -0
  292. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/canonical.py +0 -0
  293. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/engine.py +0 -0
  294. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/entropy.py +0 -0
  295. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/focus.py +0 -0
  296. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/graph_metrics.py +0 -0
  297. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/influence.py +0 -0
  298. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/snapshots.py +0 -0
  299. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/store.py +0 -0
  300. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/topic_merge.py +0 -0
  301. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/topics.py +0 -0
  302. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/topics_daily.py +0 -0
  303. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/complexity/volatility.py +0 -0
  304. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/entities/__init__.py +0 -0
  305. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/entities/declared_mappings.py +0 -0
  306. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/entities/fact_materializer.py +0 -0
  307. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/entities/graph_enrichers.py +0 -0
  308. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/entities/graph_search.py +0 -0
  309. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/facts/__init__.py +0 -0
  310. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/facts/extract.py +0 -0
  311. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/facts/reads.py +0 -0
  312. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/facts/store.py +0 -0
  313. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/facts/verdicts.py +0 -0
  314. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/fit/evaluator.py +0 -0
  315. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/fit/opportunity_types.json +0 -0
  316. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/lifecycle/__init__.py +0 -0
  317. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/lifecycle/blackhole.py +0 -0
  318. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/lifecycle/blackhole_guard.py +0 -0
  319. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/lifecycle/blackhole_llm.py +0 -0
  320. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/provenance/__init__.py +0 -0
  321. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/provenance/posture.py +0 -0
  322. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/provenance/roles.py +0 -0
  323. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/__init__.py +0 -0
  324. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/brief_canonical_loader.py +0 -0
  325. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/brief_ontology.py +0 -0
  326. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/brief_renderer.py +0 -0
  327. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/brief_schemas.py +0 -0
  328. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/chunking.py +0 -0
  329. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/cluster_labels.py +0 -0
  330. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/definitions/brief_ontologies.json +0 -0
  331. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/definitions/intentions.json +0 -0
  332. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/definitions/profile.json +0 -0
  333. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/definitions/relationships.json +0 -0
  334. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
  335. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/definitions/time.json +0 -0
  336. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/definitions/work.json +0 -0
  337. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/dimension_briefs.py +0 -0
  338. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/dimension_definition_loader.py +0 -0
  339. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/dimension_profiles.py +0 -0
  340. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/dimension_registry.py +0 -0
  341. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/embed_context.py +0 -0
  342. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/extraction/artifact_router.py +0 -0
  343. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/extraction/artifact_store.py +0 -0
  344. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/extraction/rule_extractors.py +0 -0
  345. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/graph_sanitize.py +0 -0
  346. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/hybrid_search.py +0 -0
  347. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/incremental_clustering.py +0 -0
  348. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/model_recommendations.py +0 -0
  349. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/query_embed_cache.py +0 -0
  350. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/schemas.py +0 -0
  351. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/service.py +0 -0
  352. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/signal_object_store.py +0 -0
  353. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/source_hydration.py +0 -0
  354. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/structured_signal.py +0 -0
  355. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/tool_index.py +0 -0
  356. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/typed_stores/aggregates.py +0 -0
  357. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/typed_stores/commitments.py +0 -0
  358. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/typed_stores/rhythm.py +0 -0
  359. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
  360. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/vector_codec.py +0 -0
  361. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/vector_math.py +0 -0
  362. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/signal/vector_settings.py +0 -0
  363. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/stats/__init__.py +0 -0
  364. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/stats/definitions.py +0 -0
  365. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/stats/engine.py +0 -0
  366. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/stats/fold.py +0 -0
  367. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/timeline_projection.py +0 -0
  368. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/timeline_rollup.py +0 -0
  369. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/triage/__init__.py +0 -0
  370. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/triage/badges.py +0 -0
  371. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/triage/daily.py +0 -0
  372. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/triage/dashboard.py +0 -0
  373. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/triage/instruments.py +0 -0
  374. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/triage/intents.py +0 -0
  375. {topos_node-1.3.4 → topos_node-1.3.5}/topos/features/triage/readiness.py +0 -0
  376. {topos_node-1.3.4 → topos_node-1.3.5}/topos/filter_lab/__init__.py +0 -0
  377. {topos_node-1.3.4 → topos_node-1.3.5}/topos/filter_lab/bundles.py +0 -0
  378. {topos_node-1.3.4 → topos_node-1.3.5}/topos/filter_lab/schema.py +0 -0
  379. {topos_node-1.3.4 → topos_node-1.3.5}/topos/filter_lab/service.py +0 -0
  380. {topos_node-1.3.4 → topos_node-1.3.5}/topos/filter_lab/store.py +0 -0
  381. {topos_node-1.3.4 → topos_node-1.3.5}/topos/filter_lab/worker.py +0 -0
  382. {topos_node-1.3.4 → topos_node-1.3.5}/topos/home_chat/__init__.py +0 -0
  383. {topos_node-1.3.4 → topos_node-1.3.5}/topos/home_chat/schema.py +0 -0
  384. {topos_node-1.3.4 → topos_node-1.3.5}/topos/home_chat/store.py +0 -0
  385. {topos_node-1.3.4 → topos_node-1.3.5}/topos/hosted_pool_lease.py +0 -0
  386. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/__init__.py +0 -0
  387. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/canonical_pipeline.py +0 -0
  388. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/checkpoints/__init__.py +0 -0
  389. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
  390. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
  391. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/inbox_crypto.py +0 -0
  392. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/inbox_drain.py +0 -0
  393. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/ingest_helpers.py +0 -0
  394. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/jobs.py +0 -0
  395. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/journal_location_fanout.py +0 -0
  396. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/journal_time_log_normalize.py +0 -0
  397. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/local_sync.py +0 -0
  398. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/log_preview.py +0 -0
  399. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/manager.py +0 -0
  400. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parser.py +0 -0
  401. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parsers/__init__.py +0 -0
  402. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parsers/base.py +0 -0
  403. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parsers/browser_parser.py +0 -0
  404. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parsers/calendar_parser.py +0 -0
  405. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
  406. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
  407. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
  408. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parsers/documents_parser.py +0 -0
  409. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parsers/github_activity_parser.py +0 -0
  410. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
  411. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parsers/grok_parser.py +0 -0
  412. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parsers/messenger_parser.py +0 -0
  413. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/parsers/voxterm_parser.py +0 -0
  414. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/progress.py +0 -0
  415. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/sources/__init__.py +0 -0
  416. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/sources/base.py +0 -0
  417. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/sources/calendar.py +0 -0
  418. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/sources/chatgpt.py +0 -0
  419. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/sources/contact_importers.py +0 -0
  420. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/sources/grok.py +0 -0
  421. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/sources/imessage_reader.py +0 -0
  422. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/sources/signal_export_parser.py +0 -0
  423. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/sources/signal_reader.py +0 -0
  424. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/state_machine.py +0 -0
  425. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/triggers/__init__.py +0 -0
  426. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/triggers/file_trigger.py +0 -0
  427. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
  428. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/usage_inbox_dedupe.py +0 -0
  429. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/validation/__init__.py +0 -0
  430. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/validation/base.py +0 -0
  431. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/validation/schema_registry.py +0 -0
  432. {topos_node-1.3.4 → topos_node-1.3.5}/topos/ingestion/validation/schema_validator.py +0 -0
  433. {topos_node-1.3.4 → topos_node-1.3.5}/topos/lineage/__init__.py +0 -0
  434. {topos_node-1.3.4 → topos_node-1.3.5}/topos/lineage/provenance.py +0 -0
  435. {topos_node-1.3.4 → topos_node-1.3.5}/topos/lineage/tracker.py +0 -0
  436. {topos_node-1.3.4 → topos_node-1.3.5}/topos/llm_integrations_storage.py +0 -0
  437. {topos_node-1.3.4 → topos_node-1.3.5}/topos/mcp_stdio_proxy.py +0 -0
  438. {topos_node-1.3.4 → topos_node-1.3.5}/topos/observability/__init__.py +0 -0
  439. {topos_node-1.3.4 → topos_node-1.3.5}/topos/observability/alerts.py +0 -0
  440. {topos_node-1.3.4 → topos_node-1.3.5}/topos/observability/metrics.py +0 -0
  441. {topos_node-1.3.4 → topos_node-1.3.5}/topos/observability/tracing.py +0 -0
  442. {topos_node-1.3.4 → topos_node-1.3.5}/topos/openai_client.py +0 -0
  443. {topos_node-1.3.4 → topos_node-1.3.5}/topos/pipeline/__init__.py +0 -0
  444. {topos_node-1.3.4 → topos_node-1.3.5}/topos/pipeline/audit.py +0 -0
  445. {topos_node-1.3.4 → topos_node-1.3.5}/topos/pipeline/envelope.py +0 -0
  446. {topos_node-1.3.4 → topos_node-1.3.5}/topos/pipeline/job_store.py +0 -0
  447. {topos_node-1.3.4 → topos_node-1.3.5}/topos/pipeline/stages.py +0 -0
  448. {topos_node-1.3.4 → topos_node-1.3.5}/topos/pipeline/stub_enqueue.py +0 -0
  449. {topos_node-1.3.4 → topos_node-1.3.5}/topos/projections/__init__.py +0 -0
  450. {topos_node-1.3.4 → topos_node-1.3.5}/topos/projections/vector_index/__init__.py +0 -0
  451. {topos_node-1.3.4 → topos_node-1.3.5}/topos/projections/vector_index/base.py +0 -0
  452. {topos_node-1.3.4 → topos_node-1.3.5}/topos/projections/vector_index/builders.py +0 -0
  453. {topos_node-1.3.4 → topos_node-1.3.5}/topos/projections/vector_index/health_checks.py +0 -0
  454. {topos_node-1.3.4 → topos_node-1.3.5}/topos/protocol/__init__.py +0 -0
  455. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/__init__.py +0 -0
  456. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/audit.py +0 -0
  457. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/ddr.py +0 -0
  458. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/disclosure.py +0 -0
  459. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/fingerprint.py +0 -0
  460. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/game_layer.py +0 -0
  461. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/grant_cache.py +0 -0
  462. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/inference.py +0 -0
  463. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/intent.py +0 -0
  464. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/minimizer.py +0 -0
  465. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/negotiation.py +0 -0
  466. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/runtime.py +0 -0
  467. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/scope_registry_loader.py +0 -0
  468. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/session.py +0 -0
  469. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/session_utils.py +0 -0
  470. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/source_generation.py +0 -0
  471. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/truth_facts.py +0 -0
  472. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/truth_prompts.py +0 -0
  473. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/turn_classifier.py +0 -0
  474. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/verify.py +0 -0
  475. {topos_node-1.3.4 → topos_node-1.3.5}/topos/query/verify_modes.py +0 -0
  476. {topos_node-1.3.4 → topos_node-1.3.5}/topos/rate_limit.py +0 -0
  477. {topos_node-1.3.4 → topos_node-1.3.5}/topos/routines/__init__.py +0 -0
  478. {topos_node-1.3.4 → topos_node-1.3.5}/topos/routines/schema.py +0 -0
  479. {topos_node-1.3.4 → topos_node-1.3.5}/topos/routines/store.py +0 -0
  480. {topos_node-1.3.4 → topos_node-1.3.5}/topos/runtime_housekeeping.py +0 -0
  481. {topos_node-1.3.4 → topos_node-1.3.5}/topos/runtime_shutdown.py +0 -0
  482. {topos_node-1.3.4 → topos_node-1.3.5}/topos/runtime_update.py +0 -0
  483. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sanitization/__init__.py +0 -0
  484. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sanitization/nsfw_classifier.py +0 -0
  485. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sanitization/prewarm.py +0 -0
  486. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sanitization/privacy_filter.py +0 -0
  487. {topos_node-1.3.4 → topos_node-1.3.5}/topos/scope_resolution.py +0 -0
  488. {topos_node-1.3.4 → topos_node-1.3.5}/topos/services/__init__.py +0 -0
  489. {topos_node-1.3.4 → topos_node-1.3.5}/topos/services/container.py +0 -0
  490. {topos_node-1.3.4 → topos_node-1.3.5}/topos/services/embeddings/__init__.py +0 -0
  491. {topos_node-1.3.4 → topos_node-1.3.5}/topos/services/embeddings/base.py +0 -0
  492. {topos_node-1.3.4 → topos_node-1.3.5}/topos/services/embeddings/local.py +0 -0
  493. {topos_node-1.3.4 → topos_node-1.3.5}/topos/services/embeddings/remote.py +0 -0
  494. {topos_node-1.3.4 → topos_node-1.3.5}/topos/services/interfaces.py +0 -0
  495. {topos_node-1.3.4 → topos_node-1.3.5}/topos/services/llm/__init__.py +0 -0
  496. {topos_node-1.3.4 → topos_node-1.3.5}/topos/services/llm/base.py +0 -0
  497. {topos_node-1.3.4 → topos_node-1.3.5}/topos/services/local.py +0 -0
  498. {topos_node-1.3.4 → topos_node-1.3.5}/topos/services/postgres.py +0 -0
  499. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sources/__init__.py +0 -0
  500. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sources/bundled_canonical_triples.py +0 -0
  501. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sources/canonical_signal_defaults.py +0 -0
  502. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sources/definitions.py +0 -0
  503. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sources/install_service.py +0 -0
  504. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sources/runtime_install.py +0 -0
  505. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sources/scrub_service.py +0 -0
  506. {topos_node-1.3.4 → topos_node-1.3.5}/topos/startup_banner.py +0 -0
  507. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/__init__.py +0 -0
  508. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/adapters/__init__.py +0 -0
  509. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/adapters/factory.py +0 -0
  510. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/adapters/postgres/stores.py +0 -0
  511. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/adapters/sqlite/__init__.py +0 -0
  512. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/adapters/sqlite/vector_search.py +0 -0
  513. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/canonical/__init__.py +0 -0
  514. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/canonical/activity_tables.py +0 -0
  515. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/canonical/ai_chat/__init__.py +0 -0
  516. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
  517. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/canonical/ai_chat/mapper.py +0 -0
  518. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/canonical/ai_chat/model.py +0 -0
  519. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/canonical/ai_chat/tables.py +0 -0
  520. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
  521. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/canonical/canonical_store.py +0 -0
  522. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/canonical/conversations_tables.py +0 -0
  523. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/canonical/mapping_store.py +0 -0
  524. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/canonical/postgres.py +0 -0
  525. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/__init__.py +0 -0
  526. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/client.py +0 -0
  527. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/connection_tuning.py +0 -0
  528. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/__init__.py +0 -0
  529. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
  530. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/actor_role_v1.py +0 -0
  531. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
  532. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
  533. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/backup.py +0 -0
  534. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
  535. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
  536. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
  537. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
  538. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/complexity_v1.py +0 -0
  539. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
  540. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
  541. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/documents_v1.py +0 -0
  542. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/enrichment_spec_version_v1.py +0 -0
  543. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/entity_blackhole_v1.py +0 -0
  544. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
  545. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/episodes_v1.py +0 -0
  546. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
  547. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
  548. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
  549. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
  550. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
  551. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
  552. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
  553. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/remediation_person_model.py +0 -0
  554. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/scope_source_generation.py +0 -0
  555. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
  556. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
  557. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/signal_objects.py +0 -0
  558. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
  559. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
  560. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
  561. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
  562. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
  563. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
  564. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
  565. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
  566. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
  567. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
  568. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
  569. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
  570. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
  571. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
  572. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
  573. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
  574. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
  575. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
  576. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
  577. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
  578. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
  579. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/paths.py +0 -0
  580. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/postgres.py +0 -0
  581. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/db/schema.py +0 -0
  582. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/enrichment/__init__.py +0 -0
  583. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
  584. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
  585. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/normalized/__init__.py +0 -0
  586. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/normalized/normalized_store.py +0 -0
  587. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/oplog/__init__.py +0 -0
  588. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/oplog/decision.py +0 -0
  589. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/oplog/oplog_store.py +0 -0
  590. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/oplog/postgres.py +0 -0
  591. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/person/identity_resolver.py +0 -0
  592. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/projections/__init__.py +0 -0
  593. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/projections/index_ops_store.py +0 -0
  594. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/projections/vector_index_store.py +0 -0
  595. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/raw/__init__.py +0 -0
  596. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/raw/browser_flat_tables.py +0 -0
  597. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/raw/file_store.py +0 -0
  598. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/raw/raw_store.py +0 -0
  599. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/raw/raw_tables_manager.py +0 -0
  600. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/raw/sqlite_raw_store.py +0 -0
  601. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/security/encryption.py +0 -0
  602. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/signal_identity.py +0 -0
  603. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/source_settings.py +0 -0
  604. {topos_node-1.3.4 → topos_node-1.3.5}/topos/storage/user_identity.py +0 -0
  605. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sync/__init__.py +0 -0
  606. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sync/client.py +0 -0
  607. {topos_node-1.3.4 → topos_node-1.3.5}/topos/sync_handlers.py +0 -0
  608. {topos_node-1.3.4 → topos_node-1.3.5}/topos/testing/__init__.py +0 -0
  609. {topos_node-1.3.4 → topos_node-1.3.5}/topos/testing/lifespan.py +0 -0
  610. {topos_node-1.3.4 → topos_node-1.3.5}/topos/uma_contact_enrichment.py +0 -0
  611. {topos_node-1.3.4 → topos_node-1.3.5}/topos/uma_filters.py +0 -0
  612. {topos_node-1.3.4 → topos_node-1.3.5}/topos/uma_resource_id.py +0 -0
  613. {topos_node-1.3.4 → topos_node-1.3.5}/topos/uma_rpt.py +0 -0
  614. {topos_node-1.3.4 → topos_node-1.3.5}/topos/upgrades/__init__.py +0 -0
  615. {topos_node-1.3.4 → topos_node-1.3.5}/topos/upgrades/runner.py +0 -0
  616. {topos_node-1.3.4 → topos_node-1.3.5}/topos/utils/base_object.py +0 -0
  617. {topos_node-1.3.4 → topos_node-1.3.5}/topos/websocket_client.py +0 -0
  618. {topos_node-1.3.4 → topos_node-1.3.5}/topos_node.egg-info/dependency_links.txt +0 -0
  619. {topos_node-1.3.4 → topos_node-1.3.5}/topos_node.egg-info/entry_points.txt +0 -0
  620. {topos_node-1.3.4 → topos_node-1.3.5}/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.4
3
+ Version: 1.3.5
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
@@ -25,7 +25,7 @@ Requires-Dist: google-cloud-run~=0.16.0
25
25
  Requires-Dist: asgi-lifespan~=2.1.0
26
26
  Requires-Dist: psycopg[binary]~=3.3.3
27
27
  Requires-Dist: duckdb~=1.5.2
28
- Requires-Dist: torch<3,>=2.8.0
28
+ Requires-Dist: torch<2.13,>=2.8.0
29
29
  Requires-Dist: transformers~=5.10.2
30
30
  Requires-Dist: huggingface-hub~=1.18.0
31
31
  Requires-Dist: tqdm~=4.67.3
@@ -33,6 +33,7 @@ Requires-Dist: hf-xet~=1.5.1
33
33
  Requires-Dist: sentence-transformers~=5.6.0
34
34
  Requires-Dist: networkx<3.7,>=3.2.1
35
35
  Requires-Dist: python-louvain<0.17,>=0.16
36
+ Requires-Dist: grand-cypher<0.13,>=0.12
36
37
  Requires-Dist: numpy<3,>=1.26
37
38
  Requires-Dist: scipy<2,>=1.11
38
39
  Requires-Dist: scikit-learn<2,>=1.4
@@ -43,7 +44,7 @@ Provides-Extra: database
43
44
  Requires-Dist: psycopg[binary]~=3.3.3; extra == "database"
44
45
  Provides-Extra: engine
45
46
  Requires-Dist: duckdb~=1.5.2; extra == "engine"
46
- Requires-Dist: torch<3,>=2.8.0; extra == "engine"
47
+ Requires-Dist: torch<2.13,>=2.8.0; extra == "engine"
47
48
  Requires-Dist: transformers~=5.10.2; extra == "engine"
48
49
  Requires-Dist: huggingface-hub~=1.18.0; extra == "engine"
49
50
  Requires-Dist: tqdm~=4.67.3; extra == "engine"
@@ -51,6 +52,7 @@ Requires-Dist: hf-xet~=1.5.1; extra == "engine"
51
52
  Requires-Dist: sentence-transformers~=5.6.0; extra == "engine"
52
53
  Requires-Dist: networkx<3.7,>=3.2.1; extra == "engine"
53
54
  Requires-Dist: python-louvain<0.17,>=0.16; extra == "engine"
55
+ Requires-Dist: grand-cypher<0.13,>=0.12; extra == "engine"
54
56
  Requires-Dist: numpy<3,>=1.26; extra == "engine"
55
57
  Requires-Dist: scipy<2,>=1.11; extra == "engine"
56
58
  Requires-Dist: scikit-learn<2,>=1.4; extra == "engine"
@@ -126,6 +128,14 @@ Topos Engine uses both local and model-hub paths so users can choose flexibility
126
128
 
127
129
  The `shared/` package in this repo is part of the node runtime contract. It contains common schema and filtering definitions used by both API and engine paths.
128
130
 
131
+ ### Architecture notes (where truth lives)
132
+
133
+ This README is orientation, not the architecture ledger. Prefer:
134
+
135
+ - **As-built / why:** sibling `topos-research-wiki` → `20_ARCHITECTURE/` (`As_Built_Node`, firewall, query, MCP, graph, …)
136
+ - **As-is invariants / checks:** sibling `topos-ops-wiki` → `25_SYSTEMS/` (`SYS-node`, `SYS-cognitive-firewall`, …)
137
+ - **Target design:** `topos-data-wiki` (`status: target`) — do not implement from it without checking as-built
138
+
129
139
  ## Quick Start
130
140
 
131
141
  ### 1) Install
@@ -61,6 +61,14 @@ Topos Engine uses both local and model-hub paths so users can choose flexibility
61
61
 
62
62
  The `shared/` package in this repo is part of the node runtime contract. It contains common schema and filtering definitions used by both API and engine paths.
63
63
 
64
+ ### Architecture notes (where truth lives)
65
+
66
+ This README is orientation, not the architecture ledger. Prefer:
67
+
68
+ - **As-built / why:** sibling `topos-research-wiki` → `20_ARCHITECTURE/` (`As_Built_Node`, firewall, query, MCP, graph, …)
69
+ - **As-is invariants / checks:** sibling `topos-ops-wiki` → `25_SYSTEMS/` (`SYS-node`, `SYS-cognitive-firewall`, …)
70
+ - **Target design:** `topos-data-wiki` (`status: target`) — do not implement from it without checking as-built
71
+
64
72
  ## Quick Start
65
73
 
66
74
  ### 1) Install
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "topos-node"
7
- version = "1.3.4"
7
+ version = "1.3.5"
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"
@@ -27,7 +27,7 @@ dependencies = [
27
27
  "asgi-lifespan~=2.1.0",
28
28
  "psycopg[binary]~=3.3.3",
29
29
  "duckdb~=1.5.2",
30
- "torch>=2.8.0,<3",
30
+ "torch>=2.8.0,<2.13",
31
31
  "transformers~=5.10.2",
32
32
  "huggingface-hub~=1.18.0",
33
33
  "tqdm~=4.67.3",
@@ -35,6 +35,10 @@ dependencies = [
35
35
  "sentence-transformers~=5.6.0",
36
36
  "networkx>=3.2.1,<3.7",
37
37
  "python-louvain>=0.16,<0.17",
38
+ # openCypher over the materialised entity graph, owner-only
39
+ # (topos.features.entities.cypher; PLAN_GRAPH_QUERY_AND_LATENT_EDGES §4).
40
+ # Pure-Python parser (lark) + matcher over networkx — no graph database.
41
+ "grand-cypher>=0.12,<0.13",
38
42
  # Complexity readings (topos.features.complexity): entropy/MI + graph math.
39
43
  "numpy>=1.26,<3",
40
44
  "scipy>=1.11,<2",
@@ -58,7 +62,7 @@ database = [
58
62
  # ML + enrichment runtime (hosted topos-engine Cloud Run image).
59
63
  engine = [
60
64
  "duckdb~=1.5.2",
61
- "torch>=2.8.0,<3",
65
+ "torch>=2.8.0,<2.13",
62
66
  "transformers~=5.10.2",
63
67
  "huggingface-hub~=1.18.0",
64
68
  "tqdm~=4.67.3",
@@ -66,6 +70,7 @@ engine = [
66
70
  "sentence-transformers~=5.6.0",
67
71
  "networkx>=3.2.1,<3.7",
68
72
  "python-louvain>=0.16,<0.17",
73
+ "grand-cypher>=0.12,<0.13",
69
74
  "numpy>=1.26,<3",
70
75
  "scipy>=1.11,<2",
71
76
  "scikit-learn>=1.4,<2",
@@ -106,6 +111,8 @@ filterwarnings = [
106
111
  "ignore:on_event is deprecated.*:DeprecationWarning:fastapi.*",
107
112
  ]
108
113
  markers = [
114
+ "journey: binds this test to a J-* journey note in topos-ops-wiki (the id is the marker arg)",
115
+ "check: binds this test to a C-* check note in topos-ops-wiki (the id is the marker arg)",
109
116
  "gap: gap verification test (sprint pack); must pass after sprint lands",
110
117
  "qq_eval: live query quality/latency eval against owner database",
111
118
  "acceptance: Wiki MVP acceptance test (AT-1 through AT-8)",
@@ -0,0 +1,293 @@
1
+ """Guards for the handled-message-types protocol snapshot.
2
+
3
+ The snapshot (topos/protocol/handled_message_types.json) is the machine-readable
4
+ list of control-plane message types this engine dispatches. Two invariants:
5
+
6
+ 1. Freshness — the committed snapshot equals the runtime HANDLERS registry.
7
+ Adding or removing an @handles registration requires regenerating it:
8
+ uv run python scripts/dump_handled_types.py > topos/protocol/handled_message_types.json
9
+
10
+ 2. Static parity — the set of string literals in @handles(...) decorators equals
11
+ the runtime registry, so no handler is registered dynamically in a way that
12
+ static consumers of the snapshot (or this repo's source) would miss.
13
+
14
+ The snapshot's second key, ``owner_only_message_types``, carries the subset
15
+ registered with ``@handles(..., owner_only=True)``. Those are types the engine
16
+ answers for the node's owner but which must never be reachable from an agent or
17
+ cross-user surface; the tests below are the leak gates that enforce it.
18
+
19
+ What "not reachable" is measured against
20
+ ----------------------------------------
21
+ The control plane's ``/mcp`` gateway (``control_plane/mcp_gateway.py``) is the
22
+ only place the CP forwards an engine message on behalf of an agent or a UMA
23
+ grantee, so it is the forwarding set these gates assert against: both the tool
24
+ names it publishes and the message types those tools forward.
25
+
26
+ ``control_plane/engine_protocol.py::SENT_MESSAGE_TYPES`` is deliberately *not*
27
+ the gate. It declares what the owner's own authenticated dashboard routes send
28
+ to the owner's own node — ``delete_database_table`` is in it precisely because
29
+ the owner's data explorer exists. Owner-only means owner-only, not unreachable.
30
+ """
31
+ from __future__ import annotations
32
+
33
+ import ast
34
+ import json
35
+ import os
36
+ from pathlib import Path
37
+
38
+ import pytest
39
+
40
+ REPO_ROOT = Path(__file__).resolve().parents[1]
41
+ SNAPSHOT = REPO_ROOT / "topos" / "protocol" / "handled_message_types.json"
42
+
43
+ MCP_GATEWAY_RELPATH = Path("control_plane") / "mcp_gateway.py"
44
+
45
+
46
+ def _runtime_handled() -> set[str]:
47
+ from topos.core.handlers import HANDLERS
48
+
49
+ return set(HANDLERS)
50
+
51
+
52
+ def _runtime_owner_only() -> set[str]:
53
+ from topos.core.handlers import OWNER_ONLY_MESSAGE_TYPES
54
+
55
+ return set(OWNER_ONLY_MESSAGE_TYPES)
56
+
57
+
58
+ def _handles_calls() -> list[ast.Call]:
59
+ calls: list[ast.Call] = []
60
+ for py in sorted((REPO_ROOT / "topos").rglob("*.py")):
61
+ if "__pycache__" in py.parts:
62
+ continue
63
+ try:
64
+ tree = ast.parse(py.read_text(encoding="utf-8"))
65
+ except SyntaxError:
66
+ continue
67
+ for node in ast.walk(tree):
68
+ if isinstance(node, ast.Call) and getattr(node.func, "id", "") == "handles":
69
+ calls.append(node)
70
+ return calls
71
+
72
+
73
+ def _literal_str_args(call: ast.Call) -> set[str]:
74
+ return {
75
+ arg.value
76
+ for arg in call.args
77
+ if isinstance(arg, ast.Constant) and isinstance(arg.value, str)
78
+ }
79
+
80
+
81
+ def _static_handled() -> set[str]:
82
+ found: set[str] = set()
83
+ for call in _handles_calls():
84
+ found |= _literal_str_args(call)
85
+ return found
86
+
87
+
88
+ def _static_owner_only() -> set[str]:
89
+ found: set[str] = set()
90
+ for call in _handles_calls():
91
+ marked = any(
92
+ kw.arg == "owner_only"
93
+ and isinstance(kw.value, ast.Constant)
94
+ and kw.value.value is True
95
+ for kw in call.keywords
96
+ )
97
+ if marked:
98
+ found |= _literal_str_args(call)
99
+ return found
100
+
101
+
102
+ def _snapshot() -> dict:
103
+ return json.loads(SNAPSHOT.read_text(encoding="utf-8"))
104
+
105
+
106
+ def _mcp_gateway_tree() -> ast.AST:
107
+ """The CP's /mcp gateway module, or skip if the CP repo isn't checked out.
108
+
109
+ Mirrors the CP's own engine lookup in its tests/contract/test_engine_protocol.py.
110
+ """
111
+ env_path = os.environ.get("CONTROL_PLANE_REPO_PATH", "").strip()
112
+ roots = [Path(env_path)] if env_path else [REPO_ROOT.parent / "topos-control-plane"]
113
+ for root in roots:
114
+ gateway = root / MCP_GATEWAY_RELPATH
115
+ if gateway.is_file():
116
+ return ast.parse(gateway.read_text(encoding="utf-8"))
117
+ pytest.skip(
118
+ "control-plane repo not found; set CONTROL_PLANE_REPO_PATH to run the "
119
+ "owner-only /mcp leak gates (CI must provide it)"
120
+ )
121
+
122
+
123
+ def _mcp_tool_names(tree: ast.AST) -> set[str]:
124
+ """Names published as /mcp tools: functions decorated with @fastmcp.tool()."""
125
+ names: set[str] = set()
126
+ for node in ast.walk(tree):
127
+ if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
128
+ continue
129
+ for dec in node.decorator_list:
130
+ func = dec.func if isinstance(dec, ast.Call) else dec
131
+ if isinstance(func, ast.Attribute) and func.attr == "tool":
132
+ names.add(node.name)
133
+ return names
134
+
135
+
136
+ def _mcp_forwarded_message_types(tree: ast.AST) -> set[str]:
137
+ """Engine message types the /mcp gateway forwards (_forward/_forward_owner_scoped)."""
138
+ found: set[str] = set()
139
+ for node in ast.walk(tree):
140
+ if not isinstance(node, ast.Call) or not node.args:
141
+ continue
142
+ name = getattr(node.func, "id", "") or getattr(node.func, "attr", "")
143
+ if not name.startswith("_forward"):
144
+ continue
145
+ first = node.args[0]
146
+ if isinstance(first, ast.Constant) and isinstance(first.value, str):
147
+ found.add(first.value)
148
+ return found
149
+
150
+
151
+ def _mcp_string_literals(tree: ast.AST) -> set[str]:
152
+ return {
153
+ node.value
154
+ for node in ast.walk(tree)
155
+ if isinstance(node, ast.Constant) and isinstance(node.value, str)
156
+ }
157
+
158
+
159
+ def test_snapshot_matches_runtime_registry():
160
+ snapshot = set(_snapshot()["handled_message_types"])
161
+ runtime = _runtime_handled()
162
+ missing = sorted(runtime - snapshot)
163
+ stale = sorted(snapshot - runtime)
164
+ assert not missing and not stale, (
165
+ "topos/protocol/handled_message_types.json is stale "
166
+ f"(missing={missing}, stale={stale}). Regenerate with: "
167
+ "uv run python scripts/dump_handled_types.py > topos/protocol/handled_message_types.json"
168
+ )
169
+
170
+
171
+ def test_static_handles_literals_match_runtime_registry():
172
+ runtime = _runtime_handled()
173
+ static = _static_handled()
174
+ dynamic_only = sorted(runtime - static)
175
+ unregistered = sorted(static - runtime)
176
+ assert not dynamic_only, (
177
+ "Handlers registered without a literal @handles(...) decorator; static "
178
+ f"consumers of the registry cannot see them: {dynamic_only}"
179
+ )
180
+ assert not unregistered, (
181
+ f"@handles(...) literals that never reach the runtime registry: {unregistered}"
182
+ )
183
+
184
+
185
+ def test_owner_only_snapshot_matches_runtime_registry():
186
+ snapshot = set(_snapshot()["owner_only_message_types"])
187
+ runtime = _runtime_owner_only()
188
+ missing = sorted(runtime - snapshot)
189
+ stale = sorted(snapshot - runtime)
190
+ assert not missing and not stale, (
191
+ "owner_only_message_types in topos/protocol/handled_message_types.json is "
192
+ f"stale (missing={missing}, stale={stale}). Regenerate with: "
193
+ "uv run python scripts/dump_handled_types.py > topos/protocol/handled_message_types.json"
194
+ )
195
+
196
+
197
+ def test_owner_only_is_a_subset_of_handled():
198
+ snapshot = _snapshot()
199
+ orphans = sorted(
200
+ set(snapshot["owner_only_message_types"]) - set(snapshot["handled_message_types"])
201
+ )
202
+ assert not orphans, f"owner_only types with no registered handler: {orphans}"
203
+
204
+
205
+ def test_static_owner_only_markers_match_runtime_registry():
206
+ runtime = _runtime_owner_only()
207
+ static = _static_owner_only()
208
+ dynamic_only = sorted(runtime - static)
209
+ unregistered = sorted(static - runtime)
210
+ assert not dynamic_only, (
211
+ "Types marked owner-only at runtime with no literal "
212
+ f"@handles(..., owner_only=True) decorator: {dynamic_only}"
213
+ )
214
+ assert not unregistered, (
215
+ "@handles(..., owner_only=True) literals that never reach the runtime "
216
+ f"registry: {unregistered}"
217
+ )
218
+
219
+
220
+ def test_destructive_database_explorer_types_are_owner_only():
221
+ """These predate the marker and are why it exists; they may not be unmarked."""
222
+ runtime = _runtime_owner_only()
223
+ expected = {
224
+ "get_database_explorer_summary",
225
+ "delete_database_rows",
226
+ "delete_database_table",
227
+ }
228
+ assert expected <= runtime, f"no longer marked owner-only: {sorted(expected - runtime)}"
229
+
230
+
231
+ def test_graph_cypher_query_is_owner_only_and_off_every_agent_surface():
232
+ """The §4.1 gate, hard 0.
233
+
234
+ An arbitrary traversal punches straight through row-level redaction:
235
+ ``MATCH (a)-[*1..3]->(b)`` does not respect a scope unless the subgraph was
236
+ scoped BEFORE the query ran, and nothing scopes it today. Until a
237
+ scoped-subgraph materialisation story exists, openCypher is owner-only.
238
+ """
239
+ assert "graph_cypher_query" in _runtime_owner_only(), (
240
+ "graph_cypher_query must be registered @handles(..., owner_only=True)"
241
+ )
242
+ assert "graph_cypher_query" in set(_snapshot()["owner_only_message_types"])
243
+
244
+ tree = _mcp_gateway_tree()
245
+ assert "graph_cypher_query" not in _mcp_forwarded_message_types(tree), (
246
+ "graph_cypher_query is forwarded by the control plane's /mcp gateway"
247
+ )
248
+ assert "graph_cypher_query" not in _mcp_tool_names(tree), (
249
+ "graph_cypher_query is published as a /mcp tool"
250
+ )
251
+ assert "graph_cypher_query" not in _mcp_string_literals(tree), (
252
+ "graph_cypher_query is named in control_plane/mcp_gateway.py"
253
+ )
254
+
255
+
256
+ def test_owner_only_types_are_absent_from_the_local_mcp_tool_list():
257
+ """The engine's own stdio MCP proxy is an agent surface too.
258
+
259
+ ``_mcp_gateway_tree`` skips when the control-plane repo is not checked out;
260
+ this list ships in this repo, so this half of the gate can never be skipped.
261
+ """
262
+ owner_only = _runtime_owner_only()
263
+ assert owner_only, "owner-only marker registry is empty; the gate would be vacuous"
264
+
265
+ proxy = REPO_ROOT / "topos" / "mcp_stdio_proxy.py"
266
+ tree = ast.parse(proxy.read_text(encoding="utf-8"))
267
+
268
+ published = sorted(owner_only & _mcp_tool_names(tree))
269
+ assert not published, f"owner-only types published as local /mcp tools: {published}"
270
+
271
+ mentioned = sorted(owner_only & _mcp_string_literals(tree))
272
+ assert not mentioned, f"owner-only types named in {proxy.name}: {mentioned}"
273
+
274
+
275
+ def test_owner_only_types_are_absent_from_the_mcp_surface():
276
+ """Hard 0: no owner-only type may be reachable through the /mcp gateway."""
277
+ owner_only = _runtime_owner_only()
278
+ assert owner_only, "owner-only marker registry is empty; the gate would be vacuous"
279
+
280
+ tree = _mcp_gateway_tree()
281
+
282
+ forwarded = sorted(owner_only & _mcp_forwarded_message_types(tree))
283
+ assert not forwarded, f"owner-only message types forwarded by the /mcp gateway: {forwarded}"
284
+
285
+ published = sorted(owner_only & _mcp_tool_names(tree))
286
+ assert not published, f"owner-only message types published as /mcp tool names: {published}"
287
+
288
+ # Belt and braces: the forward helpers can be renamed or wrapped, so also fail
289
+ # on an owner-only type name appearing anywhere in the gateway module at all.
290
+ mentioned = sorted(owner_only & _mcp_string_literals(tree))
291
+ assert not mentioned, (
292
+ f"owner-only message types named in control_plane/mcp_gateway.py: {mentioned}"
293
+ )
@@ -1,6 +1,6 @@
1
1
  """Topos Control Plane Version Information."""
2
2
 
3
- __version__ = "1.3.4"
4
- __version_info__ = (1, 3, 4)
3
+ __version__ = "1.3.5"
4
+ __version_info__ = (1, 3, 5)
5
5
 
6
6
  __all__ = ["__version__", "__version_info__"]
@@ -415,9 +415,9 @@ def _delete_enrichment_data_core(source_id: str, job_name: str) -> Dict[str, Any
415
415
  ]
416
416
  cur = conn.execute(f"DELETE FROM signal_embeddings WHERE {where}", params)
417
417
  try:
418
- from ..storage.adapters.sqlite.vector_search import delete_vec_rows
418
+ from ..storage.adapters.sqlite.stores import SQLiteVectorIndex
419
419
 
420
- delete_vec_rows(conn, ids)
420
+ SQLiteVectorIndex(conn).delete_embeddings(ids)
421
421
  except Exception as exc:
422
422
  logger.warning("Vector companion cleanup failed: %s", exc)
423
423
  else:
@@ -21,13 +21,27 @@ async def report_progress() -> dict:
21
21
 
22
22
  @router.post("/ingestion/reprocess", dependencies=[Depends(require_api_key)])
23
23
  async def ingestion_reprocess(payload: dict = Body(default_factory=dict)) -> dict:
24
+ """Re-run raw→canonical for a source (optional newest-N via ``limit``).
25
+
26
+ Body:
27
+ - source_id (required)
28
+ - dataset_id (required)
29
+ - from_stage: ``raw`` (default) | ``canonical``
30
+ - limit: optional int — newest N raw rows only
31
+ - run_enrichment: optional bool (default true)
32
+ - force / sync_batch_id: optional
33
+ """
24
34
  try:
35
+ limit_raw = payload.get("limit")
36
+ limit = int(limit_raw) if limit_raw is not None and str(limit_raw).strip() != "" else None
25
37
  return await reprocess_source(
26
38
  source_id=str(payload["source_id"]),
27
39
  dataset_id=str(payload["dataset_id"]),
28
40
  from_stage=payload.get("from_stage") or "raw",
29
41
  sync_batch_id=payload.get("sync_batch_id"),
30
42
  force=bool(payload.get("force", False)),
43
+ limit=limit,
44
+ run_enrichment=bool(payload.get("run_enrichment", True)),
31
45
  )
32
46
  except KeyError as exc:
33
47
  raise HTTPException(status_code=400, detail=f"Missing field: {exc}") from exc
@@ -147,7 +147,48 @@ async def list_signal_dimensions(_api_key: str = Depends(require_api_key)):
147
147
  @router.get("/data-health")
148
148
  async def get_signal_data_health(_api_key: str = Depends(require_api_key)):
149
149
  service = get_signal_service()
150
- return service.get_data_health()
150
+ health = service.get_data_health()
151
+ # Derived data that a failed job still owes. Surfaced on the health route
152
+ # because "a batch silently lost its facts" is exactly the condition this
153
+ # endpoint exists to catch, and it was invisible until now.
154
+ try:
155
+ from ..core.state import get_db_connection
156
+ from ..enrichment.derivation_recovery import pending_derivation_summary
157
+
158
+ if isinstance(health, dict):
159
+ health["derivation_debt"] = pending_derivation_summary(get_db_connection())
160
+ except Exception as exc: # noqa: BLE001 — health must never 500
161
+ logger.debug("derivation debt summary skipped: %s", exc)
162
+ return health
163
+
164
+
165
+ @router.get("/derivation-debt")
166
+ async def get_derivation_debt(_api_key: str = Depends(require_api_key)):
167
+ """Derivation jobs that failed and still owe their output."""
168
+ from ..core.state import get_db_connection
169
+ from ..enrichment.derivation_recovery import (
170
+ list_pending_derivation_retries,
171
+ pending_derivation_summary,
172
+ )
173
+
174
+ conn = get_db_connection()
175
+ return {
176
+ "summary": pending_derivation_summary(conn),
177
+ "pending": list_pending_derivation_retries(conn, limit=200),
178
+ }
179
+
180
+
181
+ @router.post("/derivation-debt/retry")
182
+ async def retry_derivation_debt(
183
+ dry_run: bool = Query(default=False),
184
+ source_id: Optional[str] = Query(default=None),
185
+ limit: int = Query(default=20, ge=1, le=200),
186
+ _api_key: str = Depends(require_api_key),
187
+ ):
188
+ """Re-run failed derivations. ``dry_run`` reports without writing."""
189
+ from ..enrichment.derivation_recovery import retry_pending_derivations
190
+
191
+ return await retry_pending_derivations(source_id=source_id, limit=limit, dry_run=dry_run)
151
192
 
152
193
 
153
194
  @router.get("/topic-clusters")
@@ -406,6 +447,90 @@ async def dismiss_entity_review(review_id: str, _api_key: str = Depends(require_
406
447
  raise HTTPException(status_code=400, detail=str(exc))
407
448
 
408
449
 
450
+ # ---------------------------------------------------------------- affinity
451
+
452
+
453
+ class AffinityConfigBody(BaseModel):
454
+ percentile: Optional[float] = Field(default=None, ge=90.0, le=99.9)
455
+ nudge: Optional[str] = Field(default=None, pattern="^(fewer|more|ok)$")
456
+
457
+
458
+ class AffinityLabelBody(BaseModel):
459
+ a: str = Field(..., min_length=1, max_length=80)
460
+ b: str = Field(..., min_length=1, max_length=80)
461
+ label: str = Field(..., pattern="^(useful|obvious|wrong|same_person)$")
462
+ note: Optional[str] = Field(default=None, max_length=500)
463
+ cosine: Optional[float] = Field(default=None, ge=0.0, le=1.0)
464
+
465
+
466
+ @router.get("/affinity/status")
467
+ async def get_affinity_status_api(_api_key: str = Depends(require_api_key)):
468
+ """Last rebuild + current percentile + plain-language verdict."""
469
+ from ..features.entities.affinity_owner import get_affinity_status
470
+
471
+ return get_affinity_status(_entities_conn())
472
+
473
+
474
+ @router.put("/affinity/config")
475
+ async def put_affinity_config(
476
+ body: AffinityConfigBody,
477
+ _api_key: str = Depends(require_api_key),
478
+ ):
479
+ """Set P directly or nudge via too-few / looks-good / too-many."""
480
+ from ..features.entities.affinity_owner import apply_affinity_config
481
+
482
+ if body.percentile is None and body.nudge is None:
483
+ raise HTTPException(
484
+ status_code=400, detail="provide percentile or nudge (fewer|more|ok)"
485
+ )
486
+ return apply_affinity_config(
487
+ _entities_conn(),
488
+ percentile=body.percentile,
489
+ nudge=body.nudge, # type: ignore[arg-type]
490
+ )
491
+
492
+
493
+ @router.post("/affinity/recompute")
494
+ async def post_affinity_recompute(_api_key: str = Depends(require_api_key)):
495
+ """Rebuild context centroids then affinity edges now."""
496
+ import asyncio
497
+
498
+ from ..features.entities.affinity_owner import recompute_affinity_now
499
+
500
+ return await asyncio.to_thread(recompute_affinity_now, _entities_conn())
501
+
502
+
503
+ @router.get("/affinity/pairs")
504
+ async def list_affinity_pairs(
505
+ limit: int = Query(default=50, ge=1, le=200),
506
+ _api_key: str = Depends(require_api_key),
507
+ ):
508
+ """Active unlabeled affinity edges + suppressed near-misses for review."""
509
+ from ..features.entities.affinity_owner import list_affinity_pairs_for_review
510
+
511
+ return list_affinity_pairs_for_review(_entities_conn(), limit=limit)
512
+
513
+
514
+ @router.post("/affinity/pairs/label")
515
+ async def post_affinity_pair_label(
516
+ body: AffinityLabelBody,
517
+ _api_key: str = Depends(require_api_key),
518
+ ):
519
+ from ..features.entities.affinity_owner import label_affinity_pair
520
+
521
+ try:
522
+ return label_affinity_pair(
523
+ _entities_conn(),
524
+ entity_a=body.a,
525
+ entity_b=body.b,
526
+ label=body.label,
527
+ note=body.note,
528
+ cosine=body.cosine,
529
+ )
530
+ except ValueError as exc:
531
+ raise HTTPException(status_code=400, detail=str(exc))
532
+
533
+
409
534
  class EntitySplitBody(BaseModel):
410
535
  surface: str = Field(..., min_length=1, max_length=200)
411
536
 
@@ -183,7 +183,7 @@ def _maybe_offer_self_update(
183
183
  return True
184
184
 
185
185
 
186
- @click.command()
186
+ @click.group(invoke_without_command=True)
187
187
  @click.option(
188
188
  "--db-path",
189
189
  help="Database file path (SQLite). If not specified, uses auto-discovery.",
@@ -229,8 +229,27 @@ def _maybe_offer_self_update(
229
229
  is_flag=True,
230
230
  help="App mode: tray icon only, logs to ~/.topos/logs/node.log instead of the terminal.",
231
231
  )
232
- def main(db_path, topos_key, set_topos_key, discover, port, host, skip_update_check, tray, app_mode) -> None:
233
- """Topos Control Plane API entry point."""
232
+ @click.pass_context
233
+ def main(
234
+ ctx,
235
+ db_path,
236
+ topos_key,
237
+ set_topos_key,
238
+ discover,
239
+ port,
240
+ host,
241
+ skip_update_check,
242
+ tray,
243
+ app_mode,
244
+ ) -> None:
245
+ """Topos Control Plane API entry point.
246
+
247
+ Subcommands:
248
+ reprocess Re-run raw→canonical for a source (recovery utility).
249
+ """
250
+ if ctx.invoked_subcommand is not None:
251
+ return
252
+
234
253
  if set_topos_key:
235
254
  env_path = _save_topos_key(set_topos_key)
236
255
  click.echo(f"Saved TOPOS_KEY to {env_path}")
@@ -348,5 +367,10 @@ def main(db_path, topos_key, set_topos_key, discover, port, host, skip_update_ch
348
367
  uvicorn.run(app, host=host, port=port, log_config=get_uvicorn_log_config())
349
368
 
350
369
 
370
+ from topos.cli.reprocess_cmd import reprocess_command # noqa: E402
371
+
372
+ main.add_command(reprocess_command)
373
+
374
+
351
375
  if __name__ == "__main__":
352
376
  main()