topos-node 1.3.26__tar.gz → 1.3.28__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 (714) hide show
  1. {topos_node-1.3.26/topos_node.egg-info → topos_node-1.3.28}/PKG-INFO +1 -1
  2. {topos_node-1.3.26 → topos_node-1.3.28}/pyproject.toml +1 -1
  3. {topos_node-1.3.26 → topos_node-1.3.28}/topos/__version__.py +2 -2
  4. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/signal.py +18 -0
  5. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/derivation.py +20 -0
  6. topos_node-1.3.28/topos/enrichment/jobs/canonical/derivation_job.py +367 -0
  7. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/aspirations.goals.yaml +21 -3
  8. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/health.mental.yaml +21 -3
  9. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/registry.py +5 -2
  10. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/surfaces.py +40 -0
  11. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/writer.py +11 -2
  12. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/fact_materializer.py +35 -1
  13. {topos_node-1.3.26 → topos_node-1.3.28}/topos/protocol/handled_message_types.json +1 -0
  14. topos_node-1.3.28/topos/storage/db/migrations/derivation_factory_v1.py +106 -0
  15. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/registry.py +5 -0
  16. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/registry_checksums.json +1 -0
  17. {topos_node-1.3.26 → topos_node-1.3.28}/topos/upgrades/manifests.json +12 -0
  18. {topos_node-1.3.26 → topos_node-1.3.28/topos_node.egg-info}/PKG-INFO +1 -1
  19. {topos_node-1.3.26 → topos_node-1.3.28}/topos_node.egg-info/SOURCES.txt +1 -0
  20. topos_node-1.3.26/topos/enrichment/jobs/canonical/derivation_job.py +0 -208
  21. {topos_node-1.3.26 → topos_node-1.3.28}/LICENSE +0 -0
  22. {topos_node-1.3.26 → topos_node-1.3.28}/MANIFEST.in +0 -0
  23. {topos_node-1.3.26 → topos_node-1.3.28}/README.md +0 -0
  24. {topos_node-1.3.26 → topos_node-1.3.28}/setup.cfg +0 -0
  25. {topos_node-1.3.26 → topos_node-1.3.28}/shared/__init__.py +0 -0
  26. {topos_node-1.3.26 → topos_node-1.3.28}/shared/filtering.py +0 -0
  27. {topos_node-1.3.26 → topos_node-1.3.28}/shared/schema_registry.py +0 -0
  28. {topos_node-1.3.26 → topos_node-1.3.28}/tests/test_active_database_binding.py +0 -0
  29. {topos_node-1.3.26 → topos_node-1.3.28}/tests/test_active_ingestion_binding.py +0 -0
  30. {topos_node-1.3.26 → topos_node-1.3.28}/tests/test_extensions.py +0 -0
  31. {topos_node-1.3.26 → topos_node-1.3.28}/tests/test_gate_leg_hermeticity.py +0 -0
  32. {topos_node-1.3.26 → topos_node-1.3.28}/tests/test_llm_integrations_storage.py +0 -0
  33. {topos_node-1.3.26 → topos_node-1.3.28}/tests/test_local_gate_composition.py +0 -0
  34. {topos_node-1.3.26 → topos_node-1.3.28}/tests/test_owner_database_hermeticity.py +0 -0
  35. {topos_node-1.3.26 → topos_node-1.3.28}/tests/test_prewarm_first_run.py +0 -0
  36. {topos_node-1.3.26 → topos_node-1.3.28}/tests/test_profile_hygiene.py +0 -0
  37. {topos_node-1.3.26 → topos_node-1.3.28}/tests/test_profiles.py +0 -0
  38. {topos_node-1.3.26 → topos_node-1.3.28}/tests/test_protocol_handled_types.py +0 -0
  39. {topos_node-1.3.26 → topos_node-1.3.28}/tests/test_query_field_contract.py +0 -0
  40. {topos_node-1.3.26 → topos_node-1.3.28}/tests/test_system_computer_name.py +0 -0
  41. {topos_node-1.3.26 → topos_node-1.3.28}/topos/__init__.py +0 -0
  42. {topos_node-1.3.26 → topos_node-1.3.28}/topos/analytics/__init__.py +0 -0
  43. {topos_node-1.3.26 → topos_node-1.3.28}/topos/analytics/duckdb_adapter.py +0 -0
  44. {topos_node-1.3.26 → topos_node-1.3.28}/topos/analytics/messenger_communities.py +0 -0
  45. {topos_node-1.3.26 → topos_node-1.3.28}/topos/analytics/messenger_graph.py +0 -0
  46. {topos_node-1.3.26 → topos_node-1.3.28}/topos/analytics/messenger_labels.py +0 -0
  47. {topos_node-1.3.26 → topos_node-1.3.28}/topos/analytics/profiles.py +0 -0
  48. {topos_node-1.3.26 → topos_node-1.3.28}/topos/analytics/query_engine.py +0 -0
  49. {topos_node-1.3.26 → topos_node-1.3.28}/topos/analytics/raw_queries.py +0 -0
  50. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/__init__.py +0 -0
  51. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/analytics.py +0 -0
  52. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/app_registry.py +0 -0
  53. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/backup.py +0 -0
  54. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/compute_remote.py +0 -0
  55. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/conversation_context.py +0 -0
  56. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/data_commit.py +0 -0
  57. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/data_explorer_table_prefs.py +0 -0
  58. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/database_explorer.py +0 -0
  59. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/db.py +0 -0
  60. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/device.py +0 -0
  61. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/engine_run.py +0 -0
  62. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/enrichment.py +0 -0
  63. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/enrichment_lab.py +0 -0
  64. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/facts_llm_config.py +0 -0
  65. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/filter_lab.py +0 -0
  66. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/health.py +0 -0
  67. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/home_chat.py +0 -0
  68. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/ingestion_api.py +0 -0
  69. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/ingestion_compat.py +0 -0
  70. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/ingestion_sources.py +0 -0
  71. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/intelligence_lifecycle.py +0 -0
  72. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/llm.py +0 -0
  73. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/local_mcp.py +0 -0
  74. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/messenger_analytics.py +0 -0
  75. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/privacy_disclose.py +0 -0
  76. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/query_api.py +0 -0
  77. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/runtime_bootstrap.py +0 -0
  78. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/sanitization_ollama_config.py +0 -0
  79. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/shell.py +0 -0
  80. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/signal_extraction_config.py +0 -0
  81. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/source_install.py +0 -0
  82. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/source_scrub.py +0 -0
  83. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/sources.py +0 -0
  84. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/sources_overview.py +0 -0
  85. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/sync.py +0 -0
  86. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/tool_index.py +0 -0
  87. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/ui_config.py +0 -0
  88. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/uma_data.py +0 -0
  89. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/upgrades.py +0 -0
  90. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/usage.py +0 -0
  91. {topos_node-1.3.26 → topos_node-1.3.28}/topos/api/user_identity.py +0 -0
  92. {topos_node-1.3.26 → topos_node-1.3.28}/topos/app.py +0 -0
  93. {topos_node-1.3.26 → topos_node-1.3.28}/topos/auth.py +0 -0
  94. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/__init__.py +0 -0
  95. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/declared_field_map.py +0 -0
  96. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/mappers/__init__.py +0 -0
  97. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/mappers/base.py +0 -0
  98. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
  99. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
  100. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/mappers/demo_mappers.py +0 -0
  101. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/mappers/documents_mapper.py +0 -0
  102. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
  103. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
  104. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/mappers/grok_mapper.py +0 -0
  105. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
  106. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/models.py +0 -0
  107. {topos_node-1.3.26 → topos_node-1.3.28}/topos/canonicalization/resolver.py +0 -0
  108. {topos_node-1.3.26 → topos_node-1.3.28}/topos/cli/__init__.py +0 -0
  109. {topos_node-1.3.26 → topos_node-1.3.28}/topos/cli/__main__.py +0 -0
  110. {topos_node-1.3.26 → topos_node-1.3.28}/topos/cli/assets/topos_blk_rounded.png +0 -0
  111. {topos_node-1.3.26 → topos_node-1.3.28}/topos/cli/assets/topos_white.png +0 -0
  112. {topos_node-1.3.26 → topos_node-1.3.28}/topos/cli/commands.py +0 -0
  113. {topos_node-1.3.26 → topos_node-1.3.28}/topos/cli/profile_cmd.py +0 -0
  114. {topos_node-1.3.26 → topos_node-1.3.28}/topos/cli/reprocess_cmd.py +0 -0
  115. {topos_node-1.3.26 → topos_node-1.3.28}/topos/cli/setup_models_cmd.py +0 -0
  116. {topos_node-1.3.26 → topos_node-1.3.28}/topos/cli/tray.py +0 -0
  117. {topos_node-1.3.26 → topos_node-1.3.28}/topos/config/__init__.py +0 -0
  118. {topos_node-1.3.26 → topos_node-1.3.28}/topos/config/conversation_context_llm.py +0 -0
  119. {topos_node-1.3.26 → topos_node-1.3.28}/topos/config/facts_llm.py +0 -0
  120. {topos_node-1.3.26 → topos_node-1.3.28}/topos/config/local_model_builds.py +0 -0
  121. {topos_node-1.3.26 → topos_node-1.3.28}/topos/config/model_packs.py +0 -0
  122. {topos_node-1.3.26 → topos_node-1.3.28}/topos/config/node_function_providers.py +0 -0
  123. {topos_node-1.3.26 → topos_node-1.3.28}/topos/config/sanitization_ollama.py +0 -0
  124. {topos_node-1.3.26 → topos_node-1.3.28}/topos/config/settings.py +0 -0
  125. {topos_node-1.3.26 → topos_node-1.3.28}/topos/config/signal_extraction.py +0 -0
  126. {topos_node-1.3.26 → topos_node-1.3.28}/topos/config/uvicorn_logging.json +0 -0
  127. {topos_node-1.3.26 → topos_node-1.3.28}/topos/contacts/__init__.py +0 -0
  128. {topos_node-1.3.26 → topos_node-1.3.28}/topos/contacts/identity.py +0 -0
  129. {topos_node-1.3.26 → topos_node-1.3.28}/topos/control_plane_client.py +0 -0
  130. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/__init__.py +0 -0
  131. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/api_models.py +0 -0
  132. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/connection_resilience.py +0 -0
  133. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/db_health.py +0 -0
  134. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/device_helpers.py +0 -0
  135. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/errors.py +0 -0
  136. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/events.py +0 -0
  137. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/__init__.py +0 -0
  138. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/common.py +0 -0
  139. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/complexity.py +0 -0
  140. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/config.py +0 -0
  141. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/contacts_import.py +0 -0
  142. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/database_explorer.py +0 -0
  143. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/device.py +0 -0
  144. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/enrichment.py +0 -0
  145. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/enrichment_lab.py +0 -0
  146. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/filter_lab.py +0 -0
  147. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/graph_query.py +0 -0
  148. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/home_chat.py +0 -0
  149. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/ingest.py +0 -0
  150. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/messages.py +0 -0
  151. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/messenger_analytics.py +0 -0
  152. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/query.py +0 -0
  153. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/registry.py +0 -0
  154. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/routines.py +0 -0
  155. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/signal_features.py +0 -0
  156. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/sources.py +0 -0
  157. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/timeline_daily.py +0 -0
  158. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/tool_index.py +0 -0
  159. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/handlers/uma.py +0 -0
  160. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/logging.py +0 -0
  161. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/metrics.py +0 -0
  162. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/routine_access.py +0 -0
  163. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/startup_banner.py +0 -0
  164. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/state.py +0 -0
  165. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/table_layers.py +0 -0
  166. {topos_node-1.3.26 → topos_node-1.3.28}/topos/core/types.py +0 -0
  167. {topos_node-1.3.26 → topos_node-1.3.28}/topos/data_explorer_row_delete.py +0 -0
  168. {topos_node-1.3.26 → topos_node-1.3.28}/topos/data_explorer_table_prefs.py +0 -0
  169. {topos_node-1.3.26 → topos_node-1.3.28}/topos/data_explorer_tables.py +0 -0
  170. {topos_node-1.3.26 → topos_node-1.3.28}/topos/disclosure/__init__.py +0 -0
  171. {topos_node-1.3.26 → topos_node-1.3.28}/topos/disclosure/canonical_writer.py +0 -0
  172. {topos_node-1.3.26 → topos_node-1.3.28}/topos/disclosure/content_policy.py +0 -0
  173. {topos_node-1.3.26 → topos_node-1.3.28}/topos/disclosure/field_registry.py +0 -0
  174. {topos_node-1.3.26 → topos_node-1.3.28}/topos/disclosure/privacy_layer.py +0 -0
  175. {topos_node-1.3.26 → topos_node-1.3.28}/topos/disclosure/tier.py +0 -0
  176. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/__init__.py +0 -0
  177. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/backends/__init__.py +0 -0
  178. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/backends/base.py +0 -0
  179. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/backends/generative_prompts.py +0 -0
  180. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/backends/generative_response.py +0 -0
  181. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/backends/huggingface.py +0 -0
  182. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/backends/ollama.py +0 -0
  183. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/backends/openai.py +0 -0
  184. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/backends/openai_compatible.py +0 -0
  185. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/backends/redpill.py +0 -0
  186. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/backends/stub.py +0 -0
  187. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/client.py +0 -0
  188. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/disk_space.py +0 -0
  189. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/engine.py +0 -0
  190. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/intake.py +0 -0
  191. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/memory_utils.py +0 -0
  192. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/model_cache.py +0 -0
  193. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/ollama_install.py +0 -0
  194. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/ollama_pull.py +0 -0
  195. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/ollama_setup_guidance.py +0 -0
  196. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/pipeline_memory.py +0 -0
  197. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/queue_manager.py +0 -0
  198. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/registration.py +0 -0
  199. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/result_formatter.py +0 -0
  200. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/router.py +0 -0
  201. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/scoped_token.py +0 -0
  202. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/tasks.py +0 -0
  203. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/torch_runtime.py +0 -0
  204. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/transport.py +0 -0
  205. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/usage_guard.py +0 -0
  206. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/usage_observation.py +0 -0
  207. {topos_node-1.3.26 → topos_node-1.3.28}/topos/engine/validator.py +0 -0
  208. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/__init__.py +0 -0
  209. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/catalog.py +0 -0
  210. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/derivation_recovery.py +0 -0
  211. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/derived_tables.py +0 -0
  212. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/job_readiness.py +0 -0
  213. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/job_writer.py +0 -0
  214. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/__init__.py +0 -0
  215. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/base.py +0 -0
  216. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/__init__.py +0 -0
  217. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
  218. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
  219. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/attention_triage_job.py +0 -0
  220. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
  221. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
  222. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +0 -0
  223. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/dimension_summary_job.py +0 -0
  224. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
  225. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
  226. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/entities_job.py +0 -0
  227. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
  228. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
  229. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
  230. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
  231. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
  232. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
  233. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
  234. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
  235. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
  236. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/raw/__init__.py +0 -0
  237. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
  238. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/raw/language_job.py +0 -0
  239. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
  240. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
  241. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/model_overrides.py +0 -0
  242. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/models/__init__.py +0 -0
  243. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/models/manager.py +0 -0
  244. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/models/mvp_defaults.py +0 -0
  245. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/models/registry.py +0 -0
  246. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/models/versioning.py +0 -0
  247. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/orchestrator.py +0 -0
  248. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/pipeline_activity.py +0 -0
  249. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/processor.py +0 -0
  250. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/progress_bar.py +0 -0
  251. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/registry_contract.py +0 -0
  252. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/signal_derivation_config.json +0 -0
  253. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment/source_overrides.py +0 -0
  254. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment_lab/__init__.py +0 -0
  255. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment_lab/bundles.py +0 -0
  256. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment_lab/model_resolve.py +0 -0
  257. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment_lab/schema.py +0 -0
  258. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment_lab/service.py +0 -0
  259. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment_lab/store.py +0 -0
  260. {topos_node-1.3.26 → topos_node-1.3.28}/topos/enrichment_lab/worker.py +0 -0
  261. {topos_node-1.3.26 → topos_node-1.3.28}/topos/evals/__init__.py +0 -0
  262. {topos_node-1.3.26 → topos_node-1.3.28}/topos/evals/enrichment_eval.py +0 -0
  263. {topos_node-1.3.26 → topos_node-1.3.28}/topos/extensions.py +0 -0
  264. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/__init__.py +0 -0
  265. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/canonical.py +0 -0
  266. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/engine.py +0 -0
  267. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/entropy.py +0 -0
  268. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/focus.py +0 -0
  269. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/graph_metrics.py +0 -0
  270. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/influence.py +0 -0
  271. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/projection.py +0 -0
  272. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/snapshots.py +0 -0
  273. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/store.py +0 -0
  274. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/topic_merge.py +0 -0
  275. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/topics.py +0 -0
  276. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/topics_daily.py +0 -0
  277. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/complexity/volatility.py +0 -0
  278. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/__init__.py +0 -0
  279. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/_scales.yaml +0 -0
  280. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/admin.legal.yaml +0 -0
  281. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/behavior.habits.yaml +0 -0
  282. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/behavior.preferences.yaml +0 -0
  283. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/beliefs.civic.yaml +0 -0
  284. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/beliefs.spiritual.yaml +0 -0
  285. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/communication.style.yaml +0 -0
  286. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/community.membership.yaml +0 -0
  287. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/craft.tooling.yaml +0 -0
  288. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/expertise.knowledge.yaml +0 -0
  289. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/finances.economics.yaml +0 -0
  290. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/health.lifestyle.yaml +0 -0
  291. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/health.physical.yaml +0 -0
  292. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/household.pets.yaml +0 -0
  293. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/identity.core.yaml +0 -0
  294. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/interests.taste.yaml +0 -0
  295. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/life.events.yaml +0 -0
  296. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/narrative.self.yaml +0 -0
  297. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/personality.traits.yaml +0 -0
  298. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/places.mobility.yaml +0 -0
  299. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/possessions.assets.yaml +0 -0
  300. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/relationships.social.yaml +0 -0
  301. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/values.motivation.yaml +0 -0
  302. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/vocab/dispositions.yaml +0 -0
  303. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/vocab/expertise.yaml +0 -0
  304. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/vocab/habits.yaml +0 -0
  305. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/vocab/interests.yaml +0 -0
  306. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/vocab/preferences.yaml +0 -0
  307. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/vocab/stances.yaml +0 -0
  308. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/vocab/tools.yaml +0 -0
  309. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/vocab/values.yaml +0 -0
  310. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/bundled_packs/work.career.yaml +0 -0
  311. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/candidates.py +0 -0
  312. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/guard.py +0 -0
  313. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/packs.py +0 -0
  314. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/prefilter.py +0 -0
  315. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/synthesize.py +0 -0
  316. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/template.py +0 -0
  317. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/derivation/verify.py +0 -0
  318. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/__init__.py +0 -0
  319. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/affinity.py +0 -0
  320. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/affinity_owner.py +0 -0
  321. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/affinity_quality.py +0 -0
  322. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/consolidation.py +0 -0
  323. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/context_vectors.py +0 -0
  324. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/cypher.py +0 -0
  325. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/declared_mappings.py +0 -0
  326. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/dossier.py +0 -0
  327. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/edges.py +0 -0
  328. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/graph_enrichers.py +0 -0
  329. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/graph_refresh.py +0 -0
  330. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/graph_search.py +0 -0
  331. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/linking.py +0 -0
  332. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/maintenance.py +0 -0
  333. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/reads.py +0 -0
  334. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/rebuild_subprocess.py +0 -0
  335. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/entities/resolver.py +0 -0
  336. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/facts/__init__.py +0 -0
  337. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/facts/extract.py +0 -0
  338. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/facts/llm_extract.py +0 -0
  339. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/facts/reads.py +0 -0
  340. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/facts/store.py +0 -0
  341. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/facts/verdicts.py +0 -0
  342. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/fit/evaluator.py +0 -0
  343. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/fit/opportunity_types.json +0 -0
  344. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/lifecycle/__init__.py +0 -0
  345. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/lifecycle/blackhole.py +0 -0
  346. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/lifecycle/blackhole_guard.py +0 -0
  347. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/lifecycle/blackhole_llm.py +0 -0
  348. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/lifecycle/blackhole_rebuild.py +0 -0
  349. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/lifecycle/derived_scrub.py +0 -0
  350. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/lifecycle/exclusions.py +0 -0
  351. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/lifecycle/gc.py +0 -0
  352. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/provenance/__init__.py +0 -0
  353. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/provenance/posture.py +0 -0
  354. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/provenance/roles.py +0 -0
  355. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/__init__.py +0 -0
  356. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/brief_canonical_loader.py +0 -0
  357. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/brief_ontology.py +0 -0
  358. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/brief_renderer.py +0 -0
  359. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/brief_schemas.py +0 -0
  360. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/chunking.py +0 -0
  361. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/cluster_labels.py +0 -0
  362. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/conversation_context.py +0 -0
  363. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/data_health.py +0 -0
  364. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/definitions/brief_ontologies.json +0 -0
  365. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/definitions/intentions.json +0 -0
  366. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/definitions/interests.json +0 -0
  367. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/definitions/memory.json +0 -0
  368. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/definitions/places.json +0 -0
  369. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/definitions/profile.json +0 -0
  370. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/definitions/relationships.json +0 -0
  371. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/definitions/resources.json +0 -0
  372. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
  373. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/definitions/time.json +0 -0
  374. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/definitions/wellbeing.json +0 -0
  375. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/definitions/work.json +0 -0
  376. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/derived_spec.py +0 -0
  377. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/dimension_briefs.py +0 -0
  378. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/dimension_definition_loader.py +0 -0
  379. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/dimension_profiles.py +0 -0
  380. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/dimension_registry.py +0 -0
  381. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/embed_context.py +0 -0
  382. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/extraction/artifact_router.py +0 -0
  383. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/extraction/artifact_store.py +0 -0
  384. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/extraction/rule_extractors.py +0 -0
  385. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/graph_sanitize.py +0 -0
  386. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/hybrid_search.py +0 -0
  387. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/incremental_clustering.py +0 -0
  388. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/model_recommendations.py +0 -0
  389. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/query_embed_cache.py +0 -0
  390. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/schemas.py +0 -0
  391. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/service.py +0 -0
  392. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/signal_object_store.py +0 -0
  393. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/source_hydration.py +0 -0
  394. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/structured_signal.py +0 -0
  395. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/tool_index.py +0 -0
  396. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/topic_clustering.py +0 -0
  397. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/typed_stores/aggregates.py +0 -0
  398. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/typed_stores/commitments.py +0 -0
  399. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/typed_stores/rhythm.py +0 -0
  400. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
  401. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/vector_codec.py +0 -0
  402. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/vector_math.py +0 -0
  403. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/signal/vector_settings.py +0 -0
  404. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/stats/__init__.py +0 -0
  405. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/stats/definitions.py +0 -0
  406. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/stats/engine.py +0 -0
  407. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/stats/fold.py +0 -0
  408. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/stats/insights.py +0 -0
  409. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/timeline_projection.py +0 -0
  410. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/timeline_rollup.py +0 -0
  411. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/triage/__init__.py +0 -0
  412. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/triage/badges.py +0 -0
  413. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/triage/daily.py +0 -0
  414. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/triage/dashboard.py +0 -0
  415. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/triage/instruments.py +0 -0
  416. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/triage/intents.py +0 -0
  417. {topos_node-1.3.26 → topos_node-1.3.28}/topos/features/triage/readiness.py +0 -0
  418. {topos_node-1.3.26 → topos_node-1.3.28}/topos/filter_lab/__init__.py +0 -0
  419. {topos_node-1.3.26 → topos_node-1.3.28}/topos/filter_lab/bundles.py +0 -0
  420. {topos_node-1.3.26 → topos_node-1.3.28}/topos/filter_lab/schema.py +0 -0
  421. {topos_node-1.3.26 → topos_node-1.3.28}/topos/filter_lab/service.py +0 -0
  422. {topos_node-1.3.26 → topos_node-1.3.28}/topos/filter_lab/store.py +0 -0
  423. {topos_node-1.3.26 → topos_node-1.3.28}/topos/filter_lab/worker.py +0 -0
  424. {topos_node-1.3.26 → topos_node-1.3.28}/topos/home_chat/__init__.py +0 -0
  425. {topos_node-1.3.26 → topos_node-1.3.28}/topos/home_chat/schema.py +0 -0
  426. {topos_node-1.3.26 → topos_node-1.3.28}/topos/home_chat/store.py +0 -0
  427. {topos_node-1.3.26 → topos_node-1.3.28}/topos/hosted_pool_lease.py +0 -0
  428. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/__init__.py +0 -0
  429. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/canonical_pipeline.py +0 -0
  430. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/checkpoints/__init__.py +0 -0
  431. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
  432. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
  433. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/inbox_crypto.py +0 -0
  434. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/inbox_drain.py +0 -0
  435. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/ingest_helpers.py +0 -0
  436. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/jobs.py +0 -0
  437. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/journal_location_fanout.py +0 -0
  438. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/journal_time_log_normalize.py +0 -0
  439. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/local_sync.py +0 -0
  440. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/log_preview.py +0 -0
  441. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/manager.py +0 -0
  442. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parser.py +0 -0
  443. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parsers/__init__.py +0 -0
  444. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parsers/base.py +0 -0
  445. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parsers/browser_parser.py +0 -0
  446. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parsers/calendar_parser.py +0 -0
  447. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
  448. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
  449. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
  450. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parsers/documents_parser.py +0 -0
  451. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parsers/github_activity_parser.py +0 -0
  452. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
  453. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parsers/grok_parser.py +0 -0
  454. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parsers/messenger_parser.py +0 -0
  455. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/parsers/voxterm_parser.py +0 -0
  456. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/progress.py +0 -0
  457. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/reprocess.py +0 -0
  458. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/sources/__init__.py +0 -0
  459. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/sources/base.py +0 -0
  460. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/sources/calendar.py +0 -0
  461. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/sources/chatgpt.py +0 -0
  462. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/sources/contact_importers.py +0 -0
  463. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/sources/grok.py +0 -0
  464. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/sources/imessage_reader.py +0 -0
  465. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/sources/signal_export_parser.py +0 -0
  466. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/sources/signal_reader.py +0 -0
  467. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/state_machine.py +0 -0
  468. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/triggers/__init__.py +0 -0
  469. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/triggers/file_trigger.py +0 -0
  470. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
  471. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/usage_inbox_dedupe.py +0 -0
  472. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/validation/__init__.py +0 -0
  473. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/validation/base.py +0 -0
  474. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/validation/schema_registry.py +0 -0
  475. {topos_node-1.3.26 → topos_node-1.3.28}/topos/ingestion/validation/schema_validator.py +0 -0
  476. {topos_node-1.3.26 → topos_node-1.3.28}/topos/lineage/__init__.py +0 -0
  477. {topos_node-1.3.26 → topos_node-1.3.28}/topos/lineage/provenance.py +0 -0
  478. {topos_node-1.3.26 → topos_node-1.3.28}/topos/lineage/tracker.py +0 -0
  479. {topos_node-1.3.26 → topos_node-1.3.28}/topos/llm_integrations_storage.py +0 -0
  480. {topos_node-1.3.26 → topos_node-1.3.28}/topos/mcp_stdio_proxy.py +0 -0
  481. {topos_node-1.3.26 → topos_node-1.3.28}/topos/observability/__init__.py +0 -0
  482. {topos_node-1.3.26 → topos_node-1.3.28}/topos/observability/alerts.py +0 -0
  483. {topos_node-1.3.26 → topos_node-1.3.28}/topos/observability/metrics.py +0 -0
  484. {topos_node-1.3.26 → topos_node-1.3.28}/topos/observability/tracing.py +0 -0
  485. {topos_node-1.3.26 → topos_node-1.3.28}/topos/openai_client.py +0 -0
  486. {topos_node-1.3.26 → topos_node-1.3.28}/topos/pipeline/__init__.py +0 -0
  487. {topos_node-1.3.26 → topos_node-1.3.28}/topos/pipeline/audit.py +0 -0
  488. {topos_node-1.3.26 → topos_node-1.3.28}/topos/pipeline/envelope.py +0 -0
  489. {topos_node-1.3.26 → topos_node-1.3.28}/topos/pipeline/job_runner.py +0 -0
  490. {topos_node-1.3.26 → topos_node-1.3.28}/topos/pipeline/job_store.py +0 -0
  491. {topos_node-1.3.26 → topos_node-1.3.28}/topos/pipeline/stages.py +0 -0
  492. {topos_node-1.3.26 → topos_node-1.3.28}/topos/pipeline/stub_enqueue.py +0 -0
  493. {topos_node-1.3.26 → topos_node-1.3.28}/topos/profiles.py +0 -0
  494. {topos_node-1.3.26 → topos_node-1.3.28}/topos/projections/__init__.py +0 -0
  495. {topos_node-1.3.26 → topos_node-1.3.28}/topos/projections/vector_index/__init__.py +0 -0
  496. {topos_node-1.3.26 → topos_node-1.3.28}/topos/projections/vector_index/base.py +0 -0
  497. {topos_node-1.3.26 → topos_node-1.3.28}/topos/projections/vector_index/builders.py +0 -0
  498. {topos_node-1.3.26 → topos_node-1.3.28}/topos/projections/vector_index/health_checks.py +0 -0
  499. {topos_node-1.3.26 → topos_node-1.3.28}/topos/protocol/__init__.py +0 -0
  500. {topos_node-1.3.26 → topos_node-1.3.28}/topos/protocol/narrowing_vocabulary.json +0 -0
  501. {topos_node-1.3.26 → topos_node-1.3.28}/topos/protocol/query_field_contract.json +0 -0
  502. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/__init__.py +0 -0
  503. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/audit.py +0 -0
  504. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/cohort_resolvers.py +0 -0
  505. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/ddr.py +0 -0
  506. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/disclosure.py +0 -0
  507. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/entity_window.py +0 -0
  508. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/exclusion.py +0 -0
  509. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/facts_direct.py +0 -0
  510. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/fingerprint.py +0 -0
  511. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/game_layer.py +0 -0
  512. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/grant_cache.py +0 -0
  513. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/inference.py +0 -0
  514. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/intent.py +0 -0
  515. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/manifest.py +0 -0
  516. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/manifest_validation.py +0 -0
  517. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/minimizer.py +0 -0
  518. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/narrowing.py +0 -0
  519. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/negotiation.py +0 -0
  520. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/packet_resolution.py +0 -0
  521. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/pipeline.py +0 -0
  522. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/planner.py +0 -0
  523. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/retrieval.py +0 -0
  524. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/runtime.py +0 -0
  525. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/scope_arbiter.py +0 -0
  526. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/scope_classifier.py +0 -0
  527. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/scope_head.py +0 -0
  528. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/scope_registry.json +0 -0
  529. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/scope_registry_loader.py +0 -0
  530. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/scope_shadow.py +0 -0
  531. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/session.py +0 -0
  532. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/session_utils.py +0 -0
  533. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/source_generation.py +0 -0
  534. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/truth_facts.py +0 -0
  535. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/truth_prompts.py +0 -0
  536. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/turn_classifier.py +0 -0
  537. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/types.py +0 -0
  538. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/verify.py +0 -0
  539. {topos_node-1.3.26 → topos_node-1.3.28}/topos/query/verify_modes.py +0 -0
  540. {topos_node-1.3.26 → topos_node-1.3.28}/topos/rate_limit.py +0 -0
  541. {topos_node-1.3.26 → topos_node-1.3.28}/topos/routines/__init__.py +0 -0
  542. {topos_node-1.3.26 → topos_node-1.3.28}/topos/routines/schema.py +0 -0
  543. {topos_node-1.3.26 → topos_node-1.3.28}/topos/routines/store.py +0 -0
  544. {topos_node-1.3.26 → topos_node-1.3.28}/topos/runtime_housekeeping.py +0 -0
  545. {topos_node-1.3.26 → topos_node-1.3.28}/topos/runtime_shutdown.py +0 -0
  546. {topos_node-1.3.26 → topos_node-1.3.28}/topos/runtime_update.py +0 -0
  547. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sanitization/__init__.py +0 -0
  548. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sanitization/nsfw_classifier.py +0 -0
  549. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sanitization/ollama_transforms.py +0 -0
  550. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sanitization/prewarm.py +0 -0
  551. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sanitization/privacy_filter.py +0 -0
  552. {topos_node-1.3.26 → topos_node-1.3.28}/topos/scope_resolution.py +0 -0
  553. {topos_node-1.3.26 → topos_node-1.3.28}/topos/services/__init__.py +0 -0
  554. {topos_node-1.3.26 → topos_node-1.3.28}/topos/services/container.py +0 -0
  555. {topos_node-1.3.26 → topos_node-1.3.28}/topos/services/embeddings/__init__.py +0 -0
  556. {topos_node-1.3.26 → topos_node-1.3.28}/topos/services/embeddings/base.py +0 -0
  557. {topos_node-1.3.26 → topos_node-1.3.28}/topos/services/embeddings/local.py +0 -0
  558. {topos_node-1.3.26 → topos_node-1.3.28}/topos/services/embeddings/remote.py +0 -0
  559. {topos_node-1.3.26 → topos_node-1.3.28}/topos/services/interfaces.py +0 -0
  560. {topos_node-1.3.26 → topos_node-1.3.28}/topos/services/llm/__init__.py +0 -0
  561. {topos_node-1.3.26 → topos_node-1.3.28}/topos/services/llm/base.py +0 -0
  562. {topos_node-1.3.26 → topos_node-1.3.28}/topos/services/llm/openai.py +0 -0
  563. {topos_node-1.3.26 → topos_node-1.3.28}/topos/services/local.py +0 -0
  564. {topos_node-1.3.26 → topos_node-1.3.28}/topos/services/postgres.py +0 -0
  565. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sources/__init__.py +0 -0
  566. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sources/bundled_canonical_triples.py +0 -0
  567. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sources/canonical_signal_defaults.py +0 -0
  568. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sources/declared_field_map_spec.py +0 -0
  569. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sources/definitions.py +0 -0
  570. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sources/install_service.py +0 -0
  571. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sources/registry.py +0 -0
  572. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sources/runtime_install.py +0 -0
  573. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sources/scrub_attribution.py +0 -0
  574. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sources/scrub_service.py +0 -0
  575. {topos_node-1.3.26 → topos_node-1.3.28}/topos/startup_banner.py +0 -0
  576. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/__init__.py +0 -0
  577. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/adapters/__init__.py +0 -0
  578. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/adapters/factory.py +0 -0
  579. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/adapters/fakes.py +0 -0
  580. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/adapters/postgres/stores.py +0 -0
  581. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/adapters/protocols.py +0 -0
  582. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/adapters/sqlite/__init__.py +0 -0
  583. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/adapters/sqlite/stores.py +0 -0
  584. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/adapters/sqlite/vector_search.py +0 -0
  585. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/canonical/__init__.py +0 -0
  586. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/canonical/activity_tables.py +0 -0
  587. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/canonical/ai_chat/__init__.py +0 -0
  588. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
  589. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/canonical/ai_chat/mapper.py +0 -0
  590. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/canonical/ai_chat/model.py +0 -0
  591. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/canonical/ai_chat/tables.py +0 -0
  592. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
  593. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/canonical/canonical_store.py +0 -0
  594. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/canonical/conversations_tables.py +0 -0
  595. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/canonical/journal_repair.py +0 -0
  596. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/canonical/mapping_store.py +0 -0
  597. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/canonical/postgres.py +0 -0
  598. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/__init__.py +0 -0
  599. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/client.py +0 -0
  600. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/connection_tuning.py +0 -0
  601. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/__init__.py +0 -0
  602. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
  603. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/actor_role_v1.py +0 -0
  604. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/affinity_pair_labels_v1.py +0 -0
  605. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
  606. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
  607. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/backup.py +0 -0
  608. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
  609. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
  610. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
  611. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
  612. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/complexity_v1.py +0 -0
  613. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
  614. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
  615. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/derivation_provenance_v1.py +0 -0
  616. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/documents_v1.py +0 -0
  617. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/enrichment_record_progress_v1.py +0 -0
  618. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/enrichment_spec_version_v1.py +0 -0
  619. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/entity_affinity_v1.py +0 -0
  620. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/entity_blackhole_v1.py +0 -0
  621. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/entity_context_vectors_v1.py +0 -0
  622. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/entity_context_vectors_v2.py +0 -0
  623. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
  624. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/entity_mentions_authored_v1.py +0 -0
  625. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/entity_review_candidate_bar_v1.py +0 -0
  626. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/entity_review_dedup_v1.py +0 -0
  627. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/entity_review_provenance_v1.py +0 -0
  628. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/episodes_v1.py +0 -0
  629. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
  630. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
  631. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
  632. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
  633. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
  634. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
  635. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/journal_origin_dimension_v1.py +0 -0
  636. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/message_emotions_role_backfill_v1.py +0 -0
  637. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/message_emotions_role_v1.py +0 -0
  638. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/pack_registry_v1.py +0 -0
  639. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
  640. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/query_artifacts_duration_ms_v1.py +0 -0
  641. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/remediation_person_model.py +0 -0
  642. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/retire_url_classification_v1.py +0 -0
  643. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/scope_source_generation.py +0 -0
  644. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
  645. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
  646. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/signal_objects.py +0 -0
  647. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
  648. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
  649. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/signal_summaries_drop_v1.py +0 -0
  650. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
  651. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
  652. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
  653. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
  654. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
  655. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
  656. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
  657. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
  658. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
  659. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
  660. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
  661. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
  662. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
  663. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
  664. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
  665. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
  666. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
  667. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
  668. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
  669. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/paths.py +0 -0
  670. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/postgres.py +0 -0
  671. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/schema.py +0 -0
  672. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/schema_probe.py +0 -0
  673. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/storage_breakdown.py +0 -0
  674. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/db/write_gate.py +0 -0
  675. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/enrichment/__init__.py +0 -0
  676. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
  677. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
  678. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/normalized/__init__.py +0 -0
  679. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/normalized/normalized_store.py +0 -0
  680. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/oplog/__init__.py +0 -0
  681. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/oplog/decision.py +0 -0
  682. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/oplog/oplog_store.py +0 -0
  683. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/oplog/postgres.py +0 -0
  684. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/person/identity_resolver.py +0 -0
  685. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/projections/__init__.py +0 -0
  686. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/projections/index_ops_store.py +0 -0
  687. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/projections/vector_index_store.py +0 -0
  688. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/raw/__init__.py +0 -0
  689. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/raw/browser_flat_tables.py +0 -0
  690. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/raw/file_store.py +0 -0
  691. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/raw/raw_store.py +0 -0
  692. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/raw/raw_tables_manager.py +0 -0
  693. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/raw/sqlite_raw_store.py +0 -0
  694. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/security/encryption.py +0 -0
  695. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/signal_identity.py +0 -0
  696. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/source_settings.py +0 -0
  697. {topos_node-1.3.26 → topos_node-1.3.28}/topos/storage/user_identity.py +0 -0
  698. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sync/__init__.py +0 -0
  699. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sync/client.py +0 -0
  700. {topos_node-1.3.26 → topos_node-1.3.28}/topos/sync_handlers.py +0 -0
  701. {topos_node-1.3.26 → topos_node-1.3.28}/topos/testing/__init__.py +0 -0
  702. {topos_node-1.3.26 → topos_node-1.3.28}/topos/testing/lifespan.py +0 -0
  703. {topos_node-1.3.26 → topos_node-1.3.28}/topos/uma_contact_enrichment.py +0 -0
  704. {topos_node-1.3.26 → topos_node-1.3.28}/topos/uma_filters.py +0 -0
  705. {topos_node-1.3.26 → topos_node-1.3.28}/topos/uma_resource_id.py +0 -0
  706. {topos_node-1.3.26 → topos_node-1.3.28}/topos/uma_rpt.py +0 -0
  707. {topos_node-1.3.26 → topos_node-1.3.28}/topos/upgrades/__init__.py +0 -0
  708. {topos_node-1.3.26 → topos_node-1.3.28}/topos/upgrades/runner.py +0 -0
  709. {topos_node-1.3.26 → topos_node-1.3.28}/topos/utils/base_object.py +0 -0
  710. {topos_node-1.3.26 → topos_node-1.3.28}/topos/websocket_client.py +0 -0
  711. {topos_node-1.3.26 → topos_node-1.3.28}/topos_node.egg-info/dependency_links.txt +0 -0
  712. {topos_node-1.3.26 → topos_node-1.3.28}/topos_node.egg-info/entry_points.txt +0 -0
  713. {topos_node-1.3.26 → topos_node-1.3.28}/topos_node.egg-info/requires.txt +0 -0
  714. {topos_node-1.3.26 → topos_node-1.3.28}/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.26
3
+ Version: 1.3.28
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.26"
7
+ version = "1.3.28"
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.26"
4
- __version_info__ = (1, 3, 26)
3
+ __version__ = "1.3.28"
4
+ __version_info__ = (1, 3, 28)
5
5
 
6
6
  __all__ = ["__version__", "__version_info__"]
@@ -1085,3 +1085,21 @@ async def post_fact_conflict_resolution(
1085
1085
  if not ok:
1086
1086
  raise HTTPException(status_code=404, detail=f"unknown conflict {conflict_id}")
1087
1087
  return {"conflict_id": conflict_id, "status": status}
1088
+
1089
+
1090
+ @router.post("/derivation/offers/resolve")
1091
+ async def post_pack_offer_resolution(
1092
+ offer_id: str = Body(...),
1093
+ action: str = Body(..., description="accept | dismiss"),
1094
+ _api_key: str = Depends(require_api_key),
1095
+ ):
1096
+ """Self-gating offers: the node offered, the owner decides (W-B)."""
1097
+ from ..features.derivation.surfaces import resolve_pack_offer
1098
+
1099
+ try:
1100
+ out = resolve_pack_offer(_entities_conn(), offer_id, action)
1101
+ except ValueError as exc:
1102
+ raise HTTPException(status_code=400, detail=str(exc)) from exc
1103
+ if not out:
1104
+ raise HTTPException(status_code=404, detail=f"unknown offer {offer_id}")
1105
+ return out
@@ -77,3 +77,23 @@ async def handle_put_fact_conflict(message: Dict[str, Any]) -> Optional[Dict[str
77
77
  return {"id": req_id, "status": "error", "error": str(exc)}
78
78
  except Exception as exc: # noqa: BLE001
79
79
  return {"id": req_id, "status": "error", "error": str(exc)}
80
+
81
+
82
+ @handles("put_pack_offer")
83
+ async def handle_put_pack_offer(message):
84
+ req_id = message.get("id")
85
+ conn = hub.get_db_connection()
86
+ if not conn:
87
+ return {"id": req_id, "status": "error", "error": "Database not available"}
88
+ payload = message.get("payload") or {}
89
+ try:
90
+ from ...features.derivation.surfaces import resolve_pack_offer
91
+ out = resolve_pack_offer(conn, str(payload.get("offer_id") or ""),
92
+ str(payload.get("action") or ""))
93
+ if not out:
94
+ return {"id": req_id, "status": "error", "error": "unknown offer"}
95
+ return {"id": req_id, "status": "ok", "payload": {"status": "ok", **out}}
96
+ except ValueError as exc:
97
+ return {"id": req_id, "status": "error", "error": str(exc)}
98
+ except Exception as exc: # noqa: BLE001
99
+ return {"id": req_id, "status": "error", "error": str(exc)}
@@ -0,0 +1,367 @@
1
+ """DerivationJob (W2.3): ontology-pack fact derivation over canonical batches.
2
+
3
+ Per (record, enabled pack): lexical prefilter -> shadow-8 prompt -> extraction
4
+ model (qwen3.5-class; recall) -> parse with A1/A2 guards -> A4 verifier
5
+ (27B-class; precision, selection-shaped) -> DerivationWriter (A3 routing,
6
+ revision ladder, event-identity keying).
7
+
8
+ Model split is MEASURED, not aesthetic (2026-08-26 battery, 32 records):
9
+ extractor alone recurs 19/23 junk classes; verifier-as-extractor loses half the
10
+ gold; extract+verify hits ~1/23 junk while keeping recall. See
11
+ derivation-packs/pilot/w1_report.md.
12
+
13
+ Verification policy: TOPOS_DERIVATION_VERIFY=required (default) — if the
14
+ verifier model is unavailable the batch DEFERS rather than writing unverified
15
+ owner-facts; the junk gate was earned WITH the verifier in the loop. "off"
16
+ exists for explicit opt-out (assertions then flagged verifier_status=skipped).
17
+
18
+ Occurrence dates: an episodic assertion with no stated date stays UNDATED —
19
+ defaulting to the record date is how one firing became six events (a July
20
+ retelling minted a phantom July firing). The writer's event-identity keying
21
+ merges undated retellings into the original.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import asyncio
27
+ import json as _json
28
+ import logging
29
+ import os
30
+ import threading
31
+ from typing import Any, Callable, Dict, List, Optional
32
+
33
+ from ..base import BaseEnrichmentJob
34
+ from ....core.state import get_db_connection
35
+
36
+ logger = logging.getLogger("topos.enrichment.jobs.derivation")
37
+
38
+
39
+ def derivation_enabled() -> bool:
40
+ return os.environ.get("TOPOS_DERIVATION", "on").strip().lower() not in (
41
+ "0", "false", "off", "no")
42
+
43
+
44
+ def _verify_mode() -> str:
45
+ return os.environ.get("TOPOS_DERIVATION_VERIFY", "required").strip().lower()
46
+
47
+
48
+ def _row_to_record(row: Dict[str, Any]) -> Optional[Dict[str, Any]]:
49
+ text = str(row.get("content") or row.get("text") or row.get("title") or "")
50
+ if len(text.strip()) <= 15:
51
+ return None
52
+ rid = str(row.get("record_id") or row.get("message_id") or row.get("entry_id")
53
+ or row.get("event_id") or row.get("id") or "")
54
+ if not rid:
55
+ return None
56
+ table = str(row.get("_table") or row.get("canonical_table") or "")
57
+ role = str(row.get("actor_role") or ("authored" if "journal" in table else "observed"))
58
+ date = str(row.get("event_at") or row.get("entry_at") or row.get("occurred_at") or "")[:10]
59
+ return {"record_id": rid, "table": table or "canonical", "text": text,
60
+ "role": role, "date": date,
61
+ "source_id": str(row.get("source_id") or "")}
62
+
63
+
64
+ def _ledger_write(conn, *, stage, pack, rec, a, model, vmodel, written_id=None):
65
+ """Training-data factory: EVERY judged assertion lands here, accepted or not
66
+ (rejects are the hard negatives; quotes+record refs recover spans)."""
67
+ import uuid as _uuid
68
+ from ....features.derivation import template as _T
69
+ conn.execute(
70
+ """INSERT INTO derivation_training_ledger
71
+ (ledger_id, stage, pack_id, pack_version, template_version, extract_model,
72
+ verifier_model, source_table, record_id, actor_role, predicate, value_json,
73
+ about, occurrence, quote, confidence, vstatus, vreason, written_object_id)
74
+ VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
75
+ (f"dtl_{_uuid.uuid4().hex[:16]}", stage, pack.pack, pack.version,
76
+ _T.TEMPLATE_VERSION, model, vmodel, rec["table"], rec["record_id"],
77
+ rec["role"], a.get("predicate"), _json.dumps(a.get("value"), default=str),
78
+ a.get("about"), a.get("occurrence"), a.get("quote"), a.get("confidence"),
79
+ a.get("verifier_status"), a.get("verifier_reason"), written_id))
80
+
81
+
82
+ def _bump_yield(conn, pack_id, **cols):
83
+ import datetime as _dt
84
+ day = _dt.datetime.now(_dt.timezone.utc).strftime("%Y-%m-%d")
85
+ conn.execute("INSERT OR IGNORE INTO pack_yield (pack_id, day) VALUES (?, ?)", (pack_id, day))
86
+ for col, inc in cols.items():
87
+ if inc:
88
+ conn.execute(f"UPDATE pack_yield SET {col} = {col} + ? WHERE pack_id=? AND day=?",
89
+ (int(inc), pack_id, day))
90
+
91
+
92
+ def _yield_window(conn, pack_id, days, col):
93
+ row = conn.execute(
94
+ f"SELECT COALESCE(SUM({col}),0) FROM pack_yield WHERE pack_id=? AND day >= date('now', ?)",
95
+ (pack_id, f"-{int(days)} day")).fetchone()
96
+ return int(row[0] or 0)
97
+
98
+
99
+ def _has_recent_offer(conn, pack_id, kind, days=30) -> bool:
100
+ row = conn.execute(
101
+ "SELECT 1 FROM pack_offers WHERE pack_id=? AND kind=? AND"
102
+ " (status='pending' OR updated_at >= datetime('now', ?)) LIMIT 1",
103
+ (pack_id, kind, f"-{int(days)} day")).fetchone()
104
+ return row is not None
105
+
106
+
107
+ def _mint_offer(conn, pack_id, kind, stats):
108
+ import uuid as _uuid
109
+ conn.execute(
110
+ "INSERT INTO pack_offers (offer_id, pack_id, kind, stats_json) VALUES (?,?,?,?)",
111
+ (f"ofr_{_uuid.uuid4().hex[:12]}", pack_id, kind, _json.dumps(stats, default=str)))
112
+ logger.info("pack offer minted: %s %s %s", kind, pack_id, stats)
113
+
114
+
115
+ #: self-gating knobs — deliberately conservative; the node OFFERS, the owner decides
116
+ TRIAL_MIN_HITS_14D = 25
117
+ TRIAL_SAMPLE_CAP = 30
118
+ TRIAL_MIN_ACCEPTED = 3
119
+ TRIAL_MIN_ACCEPT_RATE = 0.4
120
+ DRYWELL_MIN_CALLS_30D = 50
121
+
122
+
123
+ def run_derivation_batch(
124
+ conn,
125
+ rows: List[Dict[str, Any]],
126
+ *,
127
+ cancel: Optional[threading.Event] = None,
128
+ stats: Optional[Dict[str, Any]] = None,
129
+ ) -> int:
130
+ """Sync worker (runs in a thread). Returns facts written+routed."""
131
+ from ....features.derivation import template as _T
132
+ from ....features.derivation.prefilter import PackPrefilter
133
+ from ....features.derivation.registry import (bundled_pack_dir, enabled_packs,
134
+ mark_pack_run, seed_pack_registry)
135
+ from ....features.derivation.packs import load_packs
136
+ from ....features.derivation.template import build_prompt, parse_output
137
+ from ....features.derivation.verify import (build_verify_prompt, parse_verdict,
138
+ apply_verdict, verifier_model)
139
+ from ....features.derivation.writer import DerivationWriter
140
+ from ....features.facts.llm_extract import _resolved_extraction_model
141
+ from ....config.settings import settings as _settings
142
+ from ....engine.backends.ollama import OllamaAdapter
143
+
144
+ st = stats if stats is not None else {}
145
+ pack_dir = bundled_pack_dir()
146
+ _T.set_pack_dir(pack_dir)
147
+ seed_pack_registry(conn, pack_dir)
148
+ all_packs = load_packs(pack_dir)
149
+ packs = enabled_packs(conn, pack_dir)
150
+ owner_row = conn.execute("SELECT entity_id FROM entities WHERE is_self=1").fetchone()
151
+ if not owner_row:
152
+ st["skipped"] = "no_owner_entity"
153
+ return 0
154
+ owner = owner_row[0]
155
+ model = _resolved_extraction_model(_settings, conn)
156
+ vmodel = verifier_model()
157
+ adapter = OllamaAdapter()
158
+
159
+ def llm(m: str, prompt: str, n: int = 900) -> str:
160
+ out = adapter._generate(m, prompt, num_predict=n, think=False,
161
+ temperature=0.0, num_ctx=8192, timeout=180)
162
+ return str(out.get("text") or "") if isinstance(out, dict) else str(out or "")
163
+
164
+ verify_mode = _verify_mode()
165
+ if verify_mode == "required" and packs:
166
+ try:
167
+ probe = llm(vmodel, "Respond with exactly: ok", n=8)
168
+ if not probe.strip():
169
+ raise RuntimeError("empty verifier probe")
170
+ except Exception as exc: # noqa: BLE001
171
+ st["deferred"] = f"verifier_unavailable: {exc}"[:120]
172
+ logger.warning("derivation deferred: verifier %s unavailable (%s)", vmodel, exc)
173
+ return 0
174
+
175
+ filters = {pid: PackPrefilter(pk) for pid, pk in all_packs.items()}
176
+ writer = DerivationWriter(conn, model=model)
177
+ done = {r[0] for r in conn.execute("SELECT key FROM derivation_progress")}
178
+
179
+ def judge(pack, rec, a, stage):
180
+ """Verify one assertion; ledger it; return the annotated assertion."""
181
+ if verify_mode == "off":
182
+ a = dict(a); a["verifier_status"] = "skipped"
183
+ else:
184
+ try:
185
+ verdict = parse_verdict(llm(vmodel, build_verify_prompt(
186
+ rec["text"], rec["role"], rec["date"],
187
+ a["predicate"], a["value"], a.get("about", "owner")), n=250))
188
+ except Exception: # noqa: BLE001
189
+ verdict = None
190
+ a = apply_verdict(a, verdict)
191
+ return a
192
+
193
+ written = 0
194
+ for row in rows:
195
+ if cancel is not None and cancel.is_set():
196
+ st["cancelled"] = True
197
+ break
198
+ rec = _row_to_record(row)
199
+ if rec is None:
200
+ continue
201
+ for pid, pack in all_packs.items():
202
+ hit = rec["role"] in pack.allowed_roles() and filters[pid].passes(rec["text"])
203
+ if hit:
204
+ _bump_yield(conn, pid, prefilter_hits=1)
205
+ if pid not in packs:
206
+ continue # disabled: counted for self-gating, never run
207
+ key = f"{pid}@{pack.version}:{rec['table']}:{rec['record_id']}"
208
+ if key in done or not hit:
209
+ if hit:
210
+ conn.execute("INSERT OR REPLACE INTO derivation_progress (key) VALUES (?)", (key,))
211
+ continue
212
+ try:
213
+ raw = llm(model, build_prompt(pack, rec["text"], rec["date"], rec["role"]))
214
+ _bump_yield(conn, pid, llm_calls=1)
215
+ except Exception as exc: # noqa: BLE001
216
+ st["llm_errors"] = st.get("llm_errors", 0) + 1
217
+ logger.debug("derivation llm error on %s: %s", key, exc)
218
+ continue
219
+ valid, rejects = parse_output(raw, pack, record_text=rec["text"])
220
+ st["parse_rejects"] = st.get("parse_rejects", 0) + rejects
221
+ _bump_yield(conn, pid, assertions=len(valid))
222
+ for a in valid:
223
+ a = judge(pack, rec, a, "ingest")
224
+ st[f"v_{a.get('verifier_status')}"] = st.get(f"v_{a.get('verifier_status')}", 0) + 1
225
+ if a.get("verifier_status") == "rejected":
226
+ _ledger_write(conn, stage="ingest", pack=pack, rec=rec, a=a,
227
+ model=model, vmodel=vmodel)
228
+ continue
229
+ _bump_yield(conn, pid, accepted=1)
230
+ out = writer.assert_pack_fact(
231
+ pack=pack, predicate=a["predicate"], subject_entity_id=owner,
232
+ value=a["value"], actor_role=rec["role"],
233
+ source_refs=[{"table": rec["table"], "record_id": rec["record_id"],
234
+ "source_id": rec["source_id"]}],
235
+ confidence=a["confidence"],
236
+ occurrence=a["occurrence"], # NEVER defaulted to record date
237
+ quote=a.get("quote", ""), about=a.get("about", "owner"),
238
+ event_date=rec["date"] or None)
239
+ stored = out.get("outcome") in ("written", "corroborated", "retelling_merged",
240
+ "field_update", "corrected", "superseded")
241
+ if stored:
242
+ written += 1
243
+ _bump_yield(conn, pid, written=1)
244
+ _ledger_write(conn, stage="ingest", pack=pack, rec=rec, a=a,
245
+ model=model, vmodel=vmodel,
246
+ written_id=out.get("object_id") if stored else None)
247
+ conn.execute("INSERT OR REPLACE INTO derivation_progress (key) VALUES (?)", (key,))
248
+ conn.commit()
249
+
250
+ _self_gate(conn, all_packs=all_packs, enabled=set(packs), filters=filters,
251
+ llm=llm, judge=judge, model=model, vmodel=vmodel, st=st,
252
+ cancel=cancel)
253
+
254
+ for pid, pack in packs.items():
255
+ mark_pack_run(conn, pid, pack.version)
256
+ conn.commit()
257
+ st["written"] = written
258
+ st.update({f"w_{k}": v for k, v in writer.stats.items() if v})
259
+ return written
260
+
261
+
262
+ def _self_gate(conn, *, all_packs, enabled, filters, llm, judge, model, vmodel, st, cancel):
263
+ """Per-node self-gating (owner design, 2026-08-26): the node OFFERS, never
264
+ switches. Enable offers come from a capped shadow trial on a disabled pack
265
+ whose prefilter keeps hitting; disable nudges come from an enabled pack
266
+ burning calls with zero yield. Special-class packs (health, beliefs) are
267
+ NEVER auto-trialed — extracting their content requires the owner's opt-in
268
+ first (consent precedes computation)."""
269
+ from ....features.derivation.template import build_prompt, parse_output
270
+
271
+ for pid, pack in all_packs.items():
272
+ if cancel is not None and cancel.is_set():
273
+ return
274
+ if pid in enabled:
275
+ calls = _yield_window(conn, pid, 30, "llm_calls")
276
+ wrote = _yield_window(conn, pid, 30, "written")
277
+ if calls >= DRYWELL_MIN_CALLS_30D and wrote == 0 and not _has_recent_offer(conn, pid, "disable_nudge"):
278
+ _mint_offer(conn, pid, "disable_nudge",
279
+ {"calls_30d": calls, "written_30d": 0})
280
+ continue
281
+ if getattr(pack, "sensitivity_class", "personal") == "special":
282
+ continue
283
+ hits = _yield_window(conn, pid, 14, "prefilter_hits")
284
+ if hits < TRIAL_MIN_HITS_14D or _has_recent_offer(conn, pid, "enable_offer"):
285
+ continue
286
+ # sample recent prefilter-hit records for the trial
287
+ sample = []
288
+ import sqlite3 as _sqlite3
289
+ def _rows(sql):
290
+ try:
291
+ return conn.execute(sql).fetchall()
292
+ except _sqlite3.OperationalError:
293
+ return [] # canonical table absent on this node — fine
294
+ recent = _rows(
295
+ """SELECT 'conversation_messages', message_id, content, event_at, actor_role
296
+ FROM conversation_messages WHERE content IS NOT NULL AND LENGTH(content)>15
297
+ AND event_at >= datetime('now','-14 day') ORDER BY event_at DESC LIMIT 400""")
298
+ recent += _rows(
299
+ """SELECT 'journal_entries', entry_id, content, entry_at, 'authored'
300
+ FROM journal_entries WHERE content IS NOT NULL AND LENGTH(content)>15
301
+ AND entry_at >= datetime('now','-14 day') ORDER BY entry_at DESC LIMIT 100""")
302
+ for tbl, rid, text, at, role in recent:
303
+ role = role or "observed"
304
+ if role in pack.allowed_roles() and filters[pid].passes(text):
305
+ sample.append({"table": tbl, "record_id": rid, "text": (text or "")[:6000],
306
+ "date": str(at or "")[:10], "role": role, "source_id": ""})
307
+ if len(sample) >= TRIAL_SAMPLE_CAP:
308
+ break
309
+ if len(sample) < 5:
310
+ continue
311
+ n_assert = n_acc = 0
312
+ examples = []
313
+ for rec in sample:
314
+ if cancel is not None and cancel.is_set():
315
+ return
316
+ try:
317
+ raw = llm(model, build_prompt(pack, rec["text"], rec["date"], rec["role"]))
318
+ except Exception: # noqa: BLE001
319
+ continue
320
+ valid, _rej = parse_output(raw, pack, record_text=rec["text"])
321
+ for a in valid:
322
+ a = judge(pack, rec, a, "trial")
323
+ n_assert += 1
324
+ _ledger_write(conn, stage="trial", pack=pack, rec=rec, a=a,
325
+ model=model, vmodel=vmodel)
326
+ if a.get("verifier_status") in ("accepted", "rerouted"):
327
+ n_acc += 1
328
+ if len(examples) < 3:
329
+ examples.append({"predicate": a["predicate"],
330
+ "value": a["value"], "quote": a.get("quote", "")})
331
+ conn.commit()
332
+ st[f"trial_{pid}"] = {"sampled": len(sample), "assertions": n_assert, "accepted": n_acc}
333
+ if n_acc >= TRIAL_MIN_ACCEPTED and n_assert and (n_acc / n_assert) >= TRIAL_MIN_ACCEPT_RATE:
334
+ _mint_offer(conn, pid, "enable_offer",
335
+ {"sampled": len(sample), "assertions": n_assert,
336
+ "accepted": n_acc, "examples": examples})
337
+
338
+
339
+ class DerivationJob(BaseEnrichmentJob):
340
+ def get_derived_table(self) -> str:
341
+ return "" # writes signal_objects via DerivationWriter
342
+
343
+ def get_job_name(self) -> str:
344
+ return "derivation"
345
+
346
+ def should_run(self, canonical_messages: List[Dict[str, Any]]) -> bool:
347
+ return bool(canonical_messages) and derivation_enabled()
348
+
349
+ async def enrich(
350
+ self,
351
+ canonical_messages: List[Dict[str, Any]],
352
+ progress_callback: Optional[Callable[[int, int], None]] = None,
353
+ ) -> List[Dict[str, Any]]:
354
+ conn = get_db_connection()
355
+ if conn is None:
356
+ return [{"_deferred": True, "error": "database_unavailable"}]
357
+ cancel = threading.Event()
358
+ stats: Dict[str, Any] = {}
359
+ try:
360
+ written = await asyncio.to_thread(
361
+ run_derivation_batch, conn, canonical_messages,
362
+ cancel=cancel, stats=stats)
363
+ except asyncio.CancelledError:
364
+ cancel.set()
365
+ raise
366
+ logger.info("derivation batch: %s written, stats=%s", written, stats)
367
+ return [{"derivation_written": written, **stats}]
@@ -3,7 +3,7 @@
3
3
  # STRATEGIC ROLE: bridges the EXISTING goal system (user_goals table + goal extraction
4
4
  # job + goal graph nodes) into the pack registry — same move as the `core` pack in the plan.
5
5
  pack: aspirations.goals
6
- version: 0.2.0
6
+ version: 0.2.4
7
7
  status: draft
8
8
  title: "Goals & aspirations"
9
9
  author: topos
@@ -36,8 +36,20 @@ predicates:
36
36
  - {name: asp.commitment, value_type: structured, cardinality: multi, temporal: interval, altitude: stated,
37
37
  value_schema: {commitment: string, to_whom: entity_ref_or_self, due: date_or_approx},
38
38
  note: "promises with a counterparty/date — feeds the EXISTING Commitment time-signal lane"}
39
- - {name: asp.milestone, value_type: structured, cardinality: multi, temporal: episodic, altitude: stated,
40
- value_schema: {goal_ref: string, milestone: string, kind: [progress, setback, completion]}}
39
+ - name: asp.milestone
40
+ value_type: structured
41
+ cardinality: multi
42
+ temporal: episodic
43
+ altitude: stated
44
+ value_schema:
45
+ goal_ref: string
46
+ milestone: string
47
+ kind: {enum: [progress, setback, completion]}
48
+ note: >
49
+ v0.2.4 — a milestone belongs to a NAMED, ENDURING goal (one the owner pursues
50
+ across days), and goal_ref is that goal's short name, never a copied sentence.
51
+ Finishing a morning's task is a day's work, not a milestone: if the goal it
52
+ advances wouldn't be recognizable next week, extract nothing.
41
53
  - {name: asp.focus_period, value_type: structured, cardinality: multi, temporal: interval, altitude: inferred,
42
54
  value_schema: {focus: string, evidence_kind: [stated_priority, activity_concentration]},
43
55
  note: "what the owner is ACTUALLY prioritizing right now — reconciles stated goals with observed activity; the lens-lab goal-attachment work is the direct precedent"}
@@ -60,6 +72,12 @@ guidance:
60
72
  abstention:
61
73
  - "Authored-only: an assigned OKR is work context, not a personal goal, unless the owner adopts it in their own words."
62
74
  - "Idle wishes ('would love to someday') are aspirations, never goals — the horizon field is load-bearing."
75
+ - "v0.2.4 A goal is STATED INTENT in the owner's own words ('Goal:', 'I want to', 'I will').
76
+ Wry observations, jokes and family lore ('this is the closest I can keep that pattern
77
+ going') are never goals — if the owner would be surprised to see it on their goal list,
78
+ extract nothing."
79
+ - "v0.2.4 goal_ref is a NAME (a few words), not a sentence — a goal_ref longer than ~8 words
80
+ means the goal was never really named; prefer the Goal: header's own phrasing."
63
81
  - "Never mark a goal abandoned from silence; stalled requires the owner's words or a passed deadline plus zero activity (then still status=stalled, not abandoned)."
64
82
  - "asp.focus_period must cite both the stated goal AND the activity evidence; if they disagree, record the divergence honestly (that divergence IS the insight)."
65
83
 
@@ -3,7 +3,7 @@
3
3
  # health_neurodivergence, health_attention_condition, health_cognitive_load_capacity)
4
4
  # + Personality: MBTI (neurotype). Split from health.physical: stricter rules, different consumers.
5
5
  pack: health.mental
6
- version: 0.2.0
6
+ version: 0.2.4
7
7
  status: draft
8
8
  title: "Mental wellbeing"
9
9
  author: topos
@@ -19,8 +19,22 @@ routing:
19
19
  exemplars: ["so burned out", "my therapist", "haven't been sleeping", "anxiety's been bad", "feeling great lately", "my ADHD"]
20
20
 
21
21
  predicates:
22
- - {name: mind.self_reported_state, value_type: structured, cardinality: multi, temporal: episodic, altitude: stated,
23
- value_schema: {dimension: {enum: [mood, stress, energy, sleep_quality, focus]}, report: string}}
22
+ - name: mind.self_reported_state
23
+ value_type: structured
24
+ cardinality: multi
25
+ temporal: episodic
26
+ altitude: stated
27
+ value_schema:
28
+ dimension: {enum: [mood, stress, energy, sleep_quality, focus]}
29
+ report: string
30
+ note: >
31
+ v0.2.4 — a state report is a FELT-STATE statement about how the owner is/was
32
+ ("I am exhausted", "slept 8 hours, wild dreams", "so nervous with the talk").
33
+ An intention, aspiration, reflection or observation is NOT a state, whatever
34
+ dimension it brushes: "I need to be talking to more intelligent people" is a
35
+ want, not an energy report; "the talk motivated me to write" is a reflection,
36
+ not a focus report. If the words don't describe how the owner FEELS or FELT,
37
+ extract nothing.
24
38
  - {name: mind.neurodivergence, value_type: string, cardinality: multi, temporal: interval, altitude: stated,
25
39
  note: "stated-only, verbatim self-identification; NEVER inferred"}
26
40
  - {name: mind.care_practice, value_type: structured, cardinality: multi, temporal: interval, altitude: stated,
@@ -56,6 +70,10 @@ eval:
56
70
  - {text: "Third week straight of terrible sleep, I'm running on fumes", role: authored,
57
71
  expect: [{predicate: mind.self_reported_state, value: {dimension: sleep_quality}}]}
58
72
  negative_controls:
73
+ - {text: "I need to be talking to more intelligent people. To go out of my way to speak with people.", role: authored,
74
+ expect_not: [{predicate: mind.self_reported_state}], note: "v0.2.4 measured junk: a want is not an energy state"}
75
+ - {text: "The talk at the end motivated me to write my own thought on coordination tools.", role: authored,
76
+ expect_not: [{predicate: mind.self_reported_state}], note: "v0.2.4 measured junk: a reflection is not a focus state"}
59
77
  - {text: "Podcast episode about burnout culture in tech", role: ambient, expect: []}
60
78
  - {text: "My brother finally started therapy, proud of him", role: authored, expect: [], note: "third party"}
61
79
  - {text: "ugh this parser is driving me insane", role: authored, expect: [], note: "idiom, not state report"}
@@ -15,8 +15,11 @@ from typing import Dict
15
15
 
16
16
  from .packs import Pack, load_packs
17
17
 
18
- #: Wave A (PLAN_DERIVATION_WAVE2 §W5) — the only packs seeded enabled.
18
+ #: Packs seeded enabled by default. Wave A earned its gate 2026-08-26 (full-corpus,
19
+ #: junk ≈4-5%, zero critical misattribution); health.mental joined the same day
20
+ #: (Wave B first admit: 0/7 junk under the 0.2.4 felt-state contract).
19
21
  WAVE_A = ("relationships.social", "work.career", "health.physical")
22
+ ENABLED_BY_DEFAULT = WAVE_A + ("health.mental",)
20
23
 
21
24
 
22
25
  def seed_pack_registry(conn: sqlite3.Connection, pack_dir: Path) -> None:
@@ -28,7 +31,7 @@ def seed_pack_registry(conn: sqlite3.Connection, pack_dir: Path) -> None:
28
31
  """INSERT OR IGNORE INTO pack_registry
29
32
  (pack_id, version, enabled, disclosure_default)
30
33
  VALUES (?, ?, ?, ?)""",
31
- (pid, pack.version, 1 if pid in WAVE_A else 0,
34
+ (pid, pack.version, 1 if pid in ENABLED_BY_DEFAULT else 0,
32
35
  getattr(pack, "disclosure_default", "owner_only") or "owner_only"),
33
36
  )
34
37
  # version follows the bundled catalog (upgrades are additive; the
@@ -22,6 +22,20 @@ def list_packs(conn: sqlite3.Connection) -> Dict[str, Any]:
22
22
  conflict_counts = dict(conn.execute(
23
23
  "SELECT predicate, COUNT(*) FROM fact_conflicts WHERE status='pending'"
24
24
  " GROUP BY predicate").fetchall())
25
+ def _q(sql, args=()):
26
+ try:
27
+ return conn.execute(sql, args).fetchall()
28
+ except sqlite3.OperationalError:
29
+ return [] # pre-migration-66 node
30
+ offers = {}
31
+ for oid, pid_, kind, stats_json, created in _q(
32
+ "SELECT offer_id, pack_id, kind, stats_json, created_at FROM pack_offers"
33
+ " WHERE status='pending' ORDER BY created_at DESC"):
34
+ offers.setdefault(pid_, {"offer_id": oid, "kind": kind, "created_at": created,
35
+ "stats": json.loads(stats_json or "{}")})
36
+ yield_30d = {r[0]: {"prefilter_hits": r[1], "llm_calls": r[2], "written": r[3]}
37
+ for r in _q("SELECT pack_id, SUM(prefilter_hits), SUM(llm_calls), SUM(written)"
38
+ " FROM pack_yield WHERE day >= date('now','-30 day') GROUP BY pack_id")}
25
39
  packs: List[Dict[str, Any]] = []
26
40
  for pid, ver, enabled, disclosure, last_run in conn.execute(
27
41
  "SELECT pack_id, version, enabled, disclosure_default, last_run_at"
@@ -38,6 +52,8 @@ def list_packs(conn: sqlite3.Connection) -> Dict[str, Any]:
38
52
  "pending_conflicts": pending,
39
53
  "last_run_at": last_run,
40
54
  "predicates": len(getattr(p, "predicates", {}) or {}) if p else 0,
55
+ "offer": offers.get(pid),
56
+ "yield_30d": yield_30d.get(pid),
41
57
  })
42
58
  return {"packs": packs, "total_conflicts": sum(conflict_counts.values())}
43
59
 
@@ -81,3 +97,27 @@ def resolve_conflict(conn: sqlite3.Connection, conflict_id: str, status: str) ->
81
97
  (status, conflict_id))
82
98
  commit_connection(conn)
83
99
  return bool(cur.rowcount)
100
+
101
+
102
+ def resolve_pack_offer(conn: sqlite3.Connection, offer_id: str, action: str) -> Dict[str, Any]:
103
+ """Owner decision on a self-gating offer. accept on an enable_offer enables
104
+ the pack; accept on a disable_nudge disables it; dismiss just records the
105
+ choice (with backoff — a dismissed offer is not re-minted for 30 days)."""
106
+ if action not in ("accept", "dismiss"):
107
+ raise ValueError("action must be accept|dismiss")
108
+ row = conn.execute("SELECT pack_id, kind, status FROM pack_offers WHERE offer_id=?",
109
+ (offer_id,)).fetchone()
110
+ if not row:
111
+ return {}
112
+ pack_id, kind, status = row
113
+ from ...storage.db.write_gate import commit_connection, with_db_write
114
+ with with_db_write():
115
+ conn.execute("UPDATE pack_offers SET status=?, updated_at=datetime('now')"
116
+ " WHERE offer_id=?",
117
+ ("accepted" if action == "accept" else "dismissed", offer_id))
118
+ if action == "accept":
119
+ enable = 1 if kind == "enable_offer" else 0
120
+ conn.execute("UPDATE pack_registry SET enabled=?, updated_at=datetime('now')"
121
+ " WHERE pack_id=?", (enable, pack_id))
122
+ commit_connection(conn)
123
+ return {"offer_id": offer_id, "pack_id": pack_id, "kind": kind, "action": action}
@@ -182,6 +182,8 @@ class DerivationWriter:
182
182
  occurrence: Optional[str] = None, # episodic anchor (event date)
183
183
  quote: str = "",
184
184
  about: str = "owner", # A2/A3 routing: owner | other:<name> | unclear
185
+ event_date: Optional[str] = None, # source-record date: a fact's time is its
186
+ # EVIDENCE time, never extraction time
185
187
  ) -> Dict[str, Any]:
186
188
  pred = pack.predicates.get(predicate)
187
189
  if pred is None:
@@ -236,6 +238,13 @@ class DerivationWriter:
236
238
  self.stats["retelling_merged"] = self.stats.get("retelling_merged", 0) + 1
237
239
  return {"outcome": "retelling_merged", "object_id": retold["object_id"]}
238
240
  now = _now_iso()
241
+ # THE FACT'S TIME IS ITS EVIDENCE TIME (owner rule, 2026-08-26): a stated
242
+ # fact anchors to its stated occurrence, else its source record's date;
243
+ # extraction time lives only in the extractor provenance stamp. A fact
244
+ # that emerges from accumulation anchors to the newest record that
245
+ # completed it (synthesis passes the newest evidence date as event_date).
246
+ anchor = (str(occurrence)[:10] if occurrence else None) or \
247
+ (str(event_date)[:10] if event_date else None) or now
239
248
 
240
249
  if incumbent is not None:
241
250
  inc_payload = incumbent["payload"]
@@ -279,12 +288,12 @@ class DerivationWriter:
279
288
  # SUPERSESSION: new evidence, the world changed
280
289
  self._close(incumbent, reason="superseded", at=now)
281
290
  row = self._insert(pack, pred, subject_entity_id, value, actor_role, source_refs,
282
- confidence, object_entity_id, occurrence, quote, valid_from=now, key=key)
291
+ confidence, object_entity_id, occurrence, quote, valid_from=anchor, key=key)
283
292
  self.stats["superseded"] += 1
284
293
  return {"outcome": "superseded", "object_id": row}
285
294
 
286
295
  row = self._insert(pack, pred, subject_entity_id, value, actor_role, source_refs,
287
- confidence, object_entity_id, occurrence, quote, valid_from=now, key=key)
296
+ confidence, object_entity_id, occurrence, quote, valid_from=anchor, key=key)
288
297
  self.stats["written"] += 1
289
298
  # Tier-2 `closes`: a value transition that closes OTHER active rows of this predicate
290
299
  self._apply_closes_rules(pack, pred, subject_entity_id, value)