topos-node 1.3.51__tar.gz → 1.3.53__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.
- {topos_node-1.3.51/topos_node.egg-info → topos_node-1.3.53}/PKG-INFO +1 -9
- {topos_node-1.3.51 → topos_node-1.3.53}/README.md +0 -8
- {topos_node-1.3.51 → topos_node-1.3.53}/pyproject.toml +3 -3
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/__version__.py +2 -2
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/messenger_communities.py +10 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/person_graph.py +161 -1
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/relationship_reads.py +55 -6
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/messenger_analytics.py +98 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/signal.py +13 -3
- topos_node-1.3.53/topos/cli/assets/topos_blk_rounded.png +0 -0
- topos_node-1.3.53/topos/cli/assets/topos_white.png +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/derivation.py +11 -2
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/messenger_analytics.py +13 -2
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/derivation_job.py +26 -5
- topos_node-1.3.53/topos/features/derivation/bundled_packs/net.character.yaml +119 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/obligations.commitments.yaml +5 -3
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/personality.traits.yaml +1 -0
- topos_node-1.3.53/topos/features/derivation/commitments.py +294 -0
- topos_node-1.3.53/topos/features/derivation/person_reading.py +617 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/registry.py +6 -0
- topos_node-1.3.53/topos/features/derivation/social_kernels.py +590 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/surfaces.py +178 -16
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/template.py +59 -4
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/verify.py +47 -4
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/writer.py +16 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/definitions/relationships.json +2 -1
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/signal_object_store.py +1 -1
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/protocol/handled_message_types.json +1 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/protocol/narrowing_vocabulary.json +5 -0
- topos_node-1.3.53/topos/protocol/retrieval_text_contract.json +1013 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/narrowing.py +14 -3
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/retrieval.py +118 -2
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/upgrades/manifests.json +12 -0
- {topos_node-1.3.51 → topos_node-1.3.53/topos_node.egg-info}/PKG-INFO +1 -9
- {topos_node-1.3.51 → topos_node-1.3.53}/topos_node.egg-info/SOURCES.txt +4 -0
- topos_node-1.3.51/topos/cli/assets/topos_blk_rounded.png +0 -0
- topos_node-1.3.51/topos/cli/assets/topos_white.png +0 -0
- topos_node-1.3.51/topos/features/derivation/social_kernels.py +0 -221
- {topos_node-1.3.51 → topos_node-1.3.53}/LICENSE +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/MANIFEST.in +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/setup.cfg +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/shared/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/shared/filtering.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/shared/schema_registry.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/tests/test_active_database_binding.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/tests/test_active_ingestion_binding.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/tests/test_extensions.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/tests/test_gate_leg_hermeticity.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/tests/test_llm_integrations_storage.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/tests/test_local_gate_composition.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/tests/test_owner_database_hermeticity.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/tests/test_prewarm_first_run.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/tests/test_profile_hygiene.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/tests/test_profiles.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/tests/test_protocol_handled_types.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/tests/test_query_field_contract.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/tests/test_system_computer_name.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/dataset_resolution.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/duckdb_adapter.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/luck_surface.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/messenger_directed.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/messenger_graph.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/messenger_labels.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/person_overlay.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/profiles.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/query_engine.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/analytics/raw_queries.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/analytics.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/app_registry.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/backup.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/community_naming_config.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/compute_remote.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/connected_apps.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/conversation_context.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/data_commit.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/database_explorer.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/db.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/device.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/disk_space_config.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/engine_run.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/enrichment.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/enrichment_lab.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/facts_llm_config.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/filter_lab.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/health.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/home_chat.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/ingestion_api.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/ingestion_compat.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/ingestion_sources.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/intelligence_lifecycle.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/llm.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/local_mcp.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/privacy_disclose.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/query_api.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/runtime_bootstrap.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/sanitization_ollama_config.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/shell.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/signal_extraction_config.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/source_install.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/source_scrub.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/sources.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/sources_overview.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/sync.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/tool_index.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/ui_config.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/uma_data.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/upgrades.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/usage.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/api/user_identity.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/app.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/auth.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/declared_field_map.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/mappers/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/mappers/base.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/mappers/demo_mappers.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/mappers/documents_mapper.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/mappers/grok_mapper.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/mappers/transcript_mapper.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/models.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/canonicalization/resolver.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/cli/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/cli/__main__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/cli/commands.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/cli/profile_cmd.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/cli/reprocess_cmd.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/cli/setup_models_cmd.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/cli/tray.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/config/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/config/conversation_context_llm.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/config/facts_llm.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/config/local_model_builds.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/config/model_packs.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/config/node_function_providers.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/config/sanitization_ollama.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/config/settings.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/config/signal_extraction.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/config/uvicorn_logging.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/contacts/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/contacts/identity.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/control_plane_client.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/api_models.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/connection_resilience.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/db_health.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/device_helpers.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/errors.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/events.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/aggregate.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/common.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/complexity.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/config.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/contacts_import.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/database_explorer.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/device.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/enrichment.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/enrichment_lab.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/filter_lab.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/graph_query.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/graph_summary.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/home_chat.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/ingest.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/mcp_client_elevations.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/mcp_clients.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/messages.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/query.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/registry.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/routines.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/signal_features.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/sources.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/timeline_daily.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/tool_index.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/handlers/uma.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/logging.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/metrics.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/routine_access.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/startup_banner.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/state.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/table_layers.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/core/types.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/data_explorer_row_delete.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/data_explorer_tables.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/defaults.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/disclosure/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/disclosure/canonical_writer.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/disclosure/content_policy.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/disclosure/field_registry.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/disclosure/privacy_layer.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/disclosure/tier.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/backends/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/backends/base.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/backends/generative_prompts.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/backends/generative_response.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/backends/huggingface.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/backends/ollama.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/backends/openai.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/backends/openai_compatible.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/backends/redpill.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/backends/stub.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/client.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/disk_space.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/engine.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/hosted_llm_wallet.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/intake.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/memory_utils.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/model_cache.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/model_manager.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/ollama_install.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/ollama_pull.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/ollama_runtime.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/ollama_setup_guidance.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/pipeline_memory.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/queue_manager.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/registration.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/result_formatter.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/router.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/scoped_token.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/tasks.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/torch_runtime.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/transport.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/usage_guard.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/usage_observation.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/engine/validator.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/catalog.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/derivation_recovery.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/derived_tables.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/job_readiness.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/job_writer.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/base.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/attention_triage_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/derived_object_embeddings_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/dimension_summary_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/entities_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/raw/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/raw/language_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/model_overrides.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/models/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/models/manager.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/models/mvp_defaults.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/models/registry.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/models/versioning.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/orchestrator.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/pipeline_activity.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/processor.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/progress_bar.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/record_progress.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/registry_contract.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/signal_derivation_config.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment/source_overrides.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment_lab/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment_lab/bundles.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment_lab/model_resolve.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment_lab/schema.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment_lab/service.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment_lab/store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/enrichment_lab/worker.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/evals/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/evals/enrichment_eval.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/extensions.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/canonical.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/engine.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/entropy.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/focus.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/graph_metrics.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/influence.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/projection.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/snapshots.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/topic_merge.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/topics.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/topics_daily.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/complexity/volatility.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/_scales.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/admin.legal.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/aspirations.goals.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/behavior.habits.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/behavior.preferences.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/beliefs.civic.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/beliefs.spiritual.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/communication.style.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/community.membership.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/craft.tooling.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/expertise.knowledge.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/finances.economics.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/health.lifestyle.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/health.mental.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/health.physical.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/household.pets.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/identity.core.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/interests.taste.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/life.events.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/narrative.self.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/net.capability.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/places.mobility.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/possessions.assets.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/relationships.social.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/values.motivation.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/vocab/dispositions.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/vocab/expertise.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/vocab/habits.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/vocab/interests.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/vocab/preferences.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/vocab/stances.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/vocab/tools.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/vocab/values.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/bundled_packs/work.career.yaml +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/candidates.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/guard.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/kernels.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/net_subject_policy.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/packs.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/person_bridge.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/prefilter.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/report_card.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/router.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/social_bench.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/derivation/synthesize.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/affinity.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/affinity_owner.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/affinity_quality.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/chatgpt_declared.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/community_names.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/community_naming.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/consolidation.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/context_vectors.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/cypher.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/declared_mappings.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/discourse_graph.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/dossier.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/edges.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/fact_materializer.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/graph_enrichers.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/graph_refresh.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/graph_search.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/linking.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/maintenance.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/owner.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/reads.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/rebuild_subprocess.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/resolver.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/entities/structured_fields.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/facts/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/facts/extract.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/facts/llm_extract.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/facts/reads.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/facts/store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/facts/verdicts.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/fit/evaluator.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/fit/opportunity_types.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/lifecycle/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/lifecycle/blackhole.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/lifecycle/blackhole_guard.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/lifecycle/blackhole_llm.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/lifecycle/blackhole_rebuild.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/lifecycle/derived_scrub.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/lifecycle/exclusions.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/lifecycle/gc.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/provenance/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/provenance/posture.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/provenance/roles.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/brief_canonical_loader.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/brief_ontology.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/brief_renderer.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/brief_schemas.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/chunking.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/cluster_labels.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/conversation_context.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/conversation_windows.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/data_health.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/definitions/brief_ontologies.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/definitions/intentions.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/definitions/interests.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/definitions/memory.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/definitions/places.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/definitions/profile.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/definitions/resources.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/definitions/time.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/definitions/wellbeing.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/definitions/work.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/derived_index.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/derived_spec.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/dimension_briefs.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/dimension_definition_loader.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/dimension_profiles.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/dimension_registry.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/embed_context.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/extraction/artifact_router.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/extraction/artifact_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/extraction/rule_extractors.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/graph_sanitize.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/hybrid_search.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/incremental_clustering.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/model_recommendations.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/query_embed_cache.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/schemas.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/service.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/source_hydration.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/structured_signal.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/tool_index.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/topic_clustering.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/typed_stores/aggregates.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/typed_stores/commitments.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/typed_stores/rhythm.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/vector_codec.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/vector_math.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/signal/vector_settings.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/stats/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/stats/definitions.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/stats/engine.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/stats/fold.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/stats/insights.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/timeline_projection.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/timeline_rollup.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/triage/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/triage/badges.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/triage/daily.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/triage/dashboard.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/triage/instruments.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/triage/intents.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/features/triage/readiness.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/filter_lab/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/filter_lab/bundles.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/filter_lab/schema.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/filter_lab/service.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/filter_lab/store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/filter_lab/worker.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/home_chat/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/home_chat/schema.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/home_chat/store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/hosted_pool_lease.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/canonical_pipeline.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/checkpoints/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/inbox_crypto.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/inbox_drain.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/ingest_helpers.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/jobs.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/journal_location_fanout.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/journal_time_log_normalize.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/local_exports.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/local_sync.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/log_preview.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/manager.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parser.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/base.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/browser_parser.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/calendar_parser.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/chatgpt_export.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/documents_parser.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/github_activity_parser.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/grok_parser.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/messenger_parser.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/transcript_parser.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/parsers/voxterm_parser.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/progress.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/reprocess.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/sources/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/sources/base.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/sources/calendar.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/sources/chatgpt.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/sources/contact_importers.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/sources/grok.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/sources/imessage_reader.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/sources/signal_export_parser.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/sources/signal_reader.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/state_machine.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/triggers/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/triggers/file_trigger.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/usage_inbox_dedupe.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/validation/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/validation/base.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/validation/schema_registry.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/ingestion/validation/schema_validator.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/lineage/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/lineage/provenance.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/lineage/tracker.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/llm_integrations_storage.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/mcp_clients.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/mcp_stdio_proxy.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/observability/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/observability/alerts.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/observability/metrics.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/observability/tracing.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/openai_client.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/owner_key.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/pipeline/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/pipeline/audit.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/pipeline/envelope.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/pipeline/job_runner.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/pipeline/job_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/pipeline/stages.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/pipeline/stub_enqueue.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/principal.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/profiles.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/projections/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/projections/vector_index/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/projections/vector_index/base.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/projections/vector_index/builders.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/projections/vector_index/health_checks.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/protocol/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/protocol/query_field_contract.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/aggregate.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/audit.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/closeness.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/cohort_resolvers.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/collaborators.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/ddr.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/disclosure.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/entity_window.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/exclusion.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/facts_direct.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/fingerprint.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/game_layer.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/grant_cache.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/graph_lane.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/inference.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/intent.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/manifest.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/manifest_validation.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/minimizer.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/negotiation.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/overheard.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/packet_resolution.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/pipeline.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/planner.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/runtime.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/scope_arbiter.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/scope_classifier.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/scope_head.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/scope_registry.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/scope_registry_loader.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/scope_shadow.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/session.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/session_utils.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/source_generation.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/truth_facts.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/truth_prompts.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/turn_classifier.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/types.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/verify.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/query/verify_modes.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/rate_limit.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/relay_stamp.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/routines/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/routines/schema.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/routines/store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/runtime_housekeeping.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/runtime_shutdown.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/runtime_update.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sanitization/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sanitization/nsfw_classifier.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sanitization/ollama_transforms.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sanitization/prewarm.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sanitization/privacy_filter.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/scope_resolution.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/services/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/services/container.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/services/embeddings/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/services/embeddings/base.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/services/embeddings/local.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/services/embeddings/remote.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/services/interfaces.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/services/llm/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/services/llm/base.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/services/llm/openai.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/services/local.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/services/postgres.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sources/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sources/bundled_canonical_triples.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sources/canonical_signal_defaults.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sources/declared_field_map_spec.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sources/definitions.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sources/install_service.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sources/registry.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sources/runtime_install.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sources/scrub_attribution.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sources/scrub_service.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/startup_banner.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/adapters/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/adapters/factory.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/adapters/fakes.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/adapters/postgres/stores.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/adapters/protocols.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/adapters/sqlite/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/adapters/sqlite/stores.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/adapters/sqlite/vector_search.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/canonical/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/canonical/activity_tables.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/canonical/ai_chat/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/canonical/ai_chat/mapper.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/canonical/ai_chat/model.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/canonical/ai_chat/tables.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/canonical/canonical_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/canonical/conversations_tables.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/canonical/journal_repair.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/canonical/mapping_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/canonical/postgres.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/client.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/connection_tuning.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/actor_role_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/affinity_pair_labels_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/backup.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/backup_custody.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/community_names_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/complexity_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/conflict_provenance_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/derivation_factory_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/derivation_provenance_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/derived_row_identity_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/documents_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/enrichment_record_progress_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/enrichment_spec_version_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/entity_affinity_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/entity_blackhole_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/entity_context_vectors_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/entity_context_vectors_v2.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/entity_mentions_authored_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/entity_review_candidate_bar_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/entity_review_dedup_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/entity_review_provenance_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/episodes_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/fact_dimension_by_entity_type_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/journal_origin_dimension_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/mention_table_stamp_backfill_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/message_emotions_role_backfill_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/message_emotions_role_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/net_subject_policy_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/pack_registry_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/query_artifacts_duration_ms_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/registry.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/registry_checksums.json +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/remediation_person_model.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/retire_url_classification_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/scope_source_generation.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/signal_objects.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/signal_summaries_drop_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/transcripts_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/paths.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/postgres.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/schema.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/schema_probe.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/storage_breakdown.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/db/write_gate.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/derived_row_identity.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/enrichment/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/normalized/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/normalized/normalized_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/oplog/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/oplog/decision.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/oplog/oplog_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/oplog/postgres.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/person/identity_resolver.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/projections/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/projections/index_ops_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/projections/vector_index_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/raw/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/raw/browser_flat_tables.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/raw/file_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/raw/raw_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/raw/raw_tables_manager.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/raw/sqlite_raw_store.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/security/encryption.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/signal_identity.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/source_settings.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/storage/user_identity.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sync/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sync/client.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/sync_handlers.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/testing/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/testing/lifespan.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/uds.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/uma_contact_enrichment.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/uma_filters.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/uma_resource_id.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/uma_rpt.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/upgrades/__init__.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/upgrades/runner.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/utils/base_object.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos/websocket_client.py +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos_node.egg-info/dependency_links.txt +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos_node.egg-info/entry_points.txt +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/topos_node.egg-info/requires.txt +0 -0
- {topos_node-1.3.51 → topos_node-1.3.53}/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.
|
|
3
|
+
Version: 1.3.53
|
|
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
|
|
@@ -128,14 +128,6 @@ Topos Engine uses both local and model-hub paths so users can choose flexibility
|
|
|
128
128
|
|
|
129
129
|
The `shared/` package in this repo is part of the node runtime contract. It contains common schema and filtering definitions used by both API and engine paths.
|
|
130
130
|
|
|
131
|
-
### Architecture notes (where truth lives)
|
|
132
|
-
|
|
133
|
-
This README is orientation, not the architecture ledger. Prefer:
|
|
134
|
-
|
|
135
|
-
- **As-built / why:** sibling `topos-research-wiki` → `20_ARCHITECTURE/` (`As_Built_Node`, firewall, query, MCP, graph, …)
|
|
136
|
-
- **As-is invariants / checks:** sibling `topos-ops-wiki` → `25_SYSTEMS/` (`SYS-node`, `SYS-cognitive-firewall`, …)
|
|
137
|
-
- **Target design:** `topos-data-wiki` (`status: target`) — do not implement from it without checking as-built
|
|
138
|
-
|
|
139
131
|
## Quick Start
|
|
140
132
|
|
|
141
133
|
### 1) Install
|
|
@@ -61,14 +61,6 @@ Topos Engine uses both local and model-hub paths so users can choose flexibility
|
|
|
61
61
|
|
|
62
62
|
The `shared/` package in this repo is part of the node runtime contract. It contains common schema and filtering definitions used by both API and engine paths.
|
|
63
63
|
|
|
64
|
-
### Architecture notes (where truth lives)
|
|
65
|
-
|
|
66
|
-
This README is orientation, not the architecture ledger. Prefer:
|
|
67
|
-
|
|
68
|
-
- **As-built / why:** sibling `topos-research-wiki` → `20_ARCHITECTURE/` (`As_Built_Node`, firewall, query, MCP, graph, …)
|
|
69
|
-
- **As-is invariants / checks:** sibling `topos-ops-wiki` → `25_SYSTEMS/` (`SYS-node`, `SYS-cognitive-firewall`, …)
|
|
70
|
-
- **Target design:** `topos-data-wiki` (`status: target`) — do not implement from it without checking as-built
|
|
71
|
-
|
|
72
64
|
## Quick Start
|
|
73
65
|
|
|
74
66
|
### 1) Install
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "topos-node"
|
|
7
|
-
version = "1.3.
|
|
7
|
+
version = "1.3.53"
|
|
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"
|
|
@@ -128,8 +128,8 @@ filterwarnings = [
|
|
|
128
128
|
"ignore:on_event is deprecated.*:DeprecationWarning:fastapi.*",
|
|
129
129
|
]
|
|
130
130
|
markers = [
|
|
131
|
-
"journey: binds this test to a J-* journey note
|
|
132
|
-
"check: binds this test to a C-* check note
|
|
131
|
+
"journey: binds this test to a J-* journey note (the id is the marker arg)",
|
|
132
|
+
"check: binds this test to a C-* check note (the id is the marker arg)",
|
|
133
133
|
"gap: gap verification test (sprint pack); must pass after sprint lands",
|
|
134
134
|
"qq_eval: live query quality/latency eval against owner database",
|
|
135
135
|
"acceptance: Wiki MVP acceptance test (AT-1 through AT-8)",
|
|
@@ -448,6 +448,16 @@ def compute_and_persist_messenger_analytics(
|
|
|
448
448
|
directed_totals["error"] = str(exc)[:200]
|
|
449
449
|
totals.update(directed_totals)
|
|
450
450
|
|
|
451
|
+
# The readings lane hangs off this pass rather than off a request: a recompute means
|
|
452
|
+
# the dyads moved, so the evidence behind every reading may have. Debounced and
|
|
453
|
+
# single-flight inside; a failure to schedule never fails the analytics.
|
|
454
|
+
try:
|
|
455
|
+
from ..features.derivation.person_reading import mark_readings_due
|
|
456
|
+
|
|
457
|
+
mark_readings_due(dataset_id)
|
|
458
|
+
except Exception as exc: # noqa: BLE001
|
|
459
|
+
logger.debug("readings not scheduled: %s", exc)
|
|
460
|
+
|
|
451
461
|
return {
|
|
452
462
|
"dataset_id": dataset_id,
|
|
453
463
|
"period_granularity": period_granularity,
|
|
@@ -1183,6 +1183,7 @@ def _merge_appearances(
|
|
|
1183
1183
|
participation_total: int,
|
|
1184
1184
|
*,
|
|
1185
1185
|
show: int,
|
|
1186
|
+
keep_record_ids: bool = False,
|
|
1186
1187
|
) -> Tuple[List[Dict[str, Any]], int]:
|
|
1187
1188
|
merged: List[Dict[str, Any]] = []
|
|
1188
1189
|
seen: Set[Tuple[str, str, str]] = set()
|
|
@@ -1218,7 +1219,12 @@ def _merge_appearances(
|
|
|
1218
1219
|
chosen = merged[:show]
|
|
1219
1220
|
for row in chosen:
|
|
1220
1221
|
row.pop("_rich", None)
|
|
1221
|
-
|
|
1222
|
+
# The card's provenance list never wanted the raw id. The reading does: it is the
|
|
1223
|
+
# record its evidence row cites, and without it the reading's provenance ref
|
|
1224
|
+
# collapsed to the subject's spine ref alone (measured 2026-09-05 — every
|
|
1225
|
+
# message-backed evidence row carried a source and no record).
|
|
1226
|
+
if not keep_record_ids:
|
|
1227
|
+
row.pop("record_id", None)
|
|
1222
1228
|
return chosen, max(total, len(merged))
|
|
1223
1229
|
|
|
1224
1230
|
|
|
@@ -1228,6 +1234,7 @@ def batch_person_appearances(
|
|
|
1228
1234
|
*,
|
|
1229
1235
|
show: int = APPEARANCE_SHOW,
|
|
1230
1236
|
fetch: int = APPEARANCE_FETCH,
|
|
1237
|
+
keep_record_ids: bool = False,
|
|
1231
1238
|
) -> Dict[str, Dict[str, Any]]:
|
|
1232
1239
|
"""Connector-agnostic appearances for many people. Batched IN queries, never N+1.
|
|
1233
1240
|
|
|
@@ -1247,6 +1254,7 @@ def batch_person_appearances(
|
|
|
1247
1254
|
participated.get(nid, []),
|
|
1248
1255
|
part_totals.get(nid, 0),
|
|
1249
1256
|
show=show,
|
|
1257
|
+
keep_record_ids=keep_record_ids,
|
|
1250
1258
|
)
|
|
1251
1259
|
out[nid] = {
|
|
1252
1260
|
"mentions": mentions,
|
|
@@ -1504,6 +1512,34 @@ def structural_metrics(conn: Any, dataset_id: str, nodes: List[Dict[str, Any]],
|
|
|
1504
1512
|
for member in component:
|
|
1505
1513
|
brokerage_ok[str(member)] = big_enough
|
|
1506
1514
|
|
|
1515
|
+
# EXCLUSIVE REACH — what this person is the only way to. Two facts per node, both read
|
|
1516
|
+
# from the tie graph alone (who you know, never shared subjects): the people whose ONLY
|
|
1517
|
+
# connection into your network is this person (their leaf neighbours), and how many
|
|
1518
|
+
# people would lose their path to the rest of their corner if this person were absent
|
|
1519
|
+
# (articulation). Measured on the live node: 74 of 224 structural people are the only
|
|
1520
|
+
# link to at least one other, 48 are articulation points, the largest cut-off is 14.
|
|
1521
|
+
# Orgs and places a person alone carries measured ZERO on the same node — entity_edges
|
|
1522
|
+
# attach them to nobody in the structural set — so that half is not computed, rather
|
|
1523
|
+
# than reported as a confident zero.
|
|
1524
|
+
reach: Dict[str, Dict[str, int]] = {}
|
|
1525
|
+
for component in nx.connected_components(ties):
|
|
1526
|
+
sub = ties.subgraph(component)
|
|
1527
|
+
size = len(component)
|
|
1528
|
+
cut_by: Dict[str, int] = {}
|
|
1529
|
+
if size >= 3:
|
|
1530
|
+
for p in nx.articulation_points(sub):
|
|
1531
|
+
rest = sub.copy()
|
|
1532
|
+
rest.remove_node(p)
|
|
1533
|
+
pieces = sorted((len(c) for c in nx.connected_components(rest)), reverse=True)
|
|
1534
|
+
# everyone outside the largest remaining piece has lost their way to it
|
|
1535
|
+
cut_by[str(p)] = sum(pieces[1:])
|
|
1536
|
+
for p in component:
|
|
1537
|
+
leaves = sum(1 for q in sub.neighbors(p) if sub.degree(q) == 1)
|
|
1538
|
+
cut = cut_by.get(str(p), 0)
|
|
1539
|
+
if leaves or cut:
|
|
1540
|
+
reach[str(p)] = {"exclusive_people": leaves, "cut_off_if_absent": cut,
|
|
1541
|
+
"component_size": size}
|
|
1542
|
+
|
|
1507
1543
|
# Communities from greedy modularity, falling back to connected components — the point
|
|
1508
1544
|
# is a stable grouping to lay out by, not a claim about social clubs.
|
|
1509
1545
|
try:
|
|
@@ -1561,6 +1597,9 @@ def structural_metrics(conn: Any, dataset_id: str, nodes: List[Dict[str, Any]],
|
|
|
1561
1597
|
# A score from a four-person component is arithmetic; the flag says which ones are
|
|
1562
1598
|
# worth showing as a finding rather than as a number.
|
|
1563
1599
|
"brokerage_meaningful": brokerage_ok,
|
|
1600
|
+
# Only the nodes with something to say; a missing key means "no exclusive reach",
|
|
1601
|
+
# not "not computed" — every node in `ties` was looked at.
|
|
1602
|
+
"reach": reach,
|
|
1564
1603
|
"coverage": {
|
|
1565
1604
|
"basis": ("connections BETWEEN your people, with you removed — you are connected "
|
|
1566
1605
|
"to everyone here, so leaving you in makes you the only broker and "
|
|
@@ -1570,6 +1609,9 @@ def structural_metrics(conn: Any, dataset_id: str, nodes: List[Dict[str, Any]],
|
|
|
1570
1609
|
"communities_from": ("who you know, plus what people have in common — the second "
|
|
1571
1610
|
"is never drawn and never counted as a connection"),
|
|
1572
1611
|
"centrality_from": "who you know only",
|
|
1612
|
+
"reach_from": ("who you know only — leaf neighbours are people whose sole tie into "
|
|
1613
|
+
"your network is this person; cut-off counts who would lose their "
|
|
1614
|
+
"path to the rest of their corner without them"),
|
|
1573
1615
|
"context_pairs_joined": context_added,
|
|
1574
1616
|
"excluded": ("semantic similarity between two people is not evidence they know "
|
|
1575
1617
|
"each other"),
|
|
@@ -2120,6 +2162,124 @@ def attach_coactivity(conn: Any, nodes: List[Dict[str, Any]]) -> Dict[str, int]:
|
|
|
2120
2162
|
return {"attached": attached}
|
|
2121
2163
|
|
|
2122
2164
|
|
|
2165
|
+
def person_disposition_facts(conn: Any, nodes: List[Dict[str, Any]]) -> Dict[str, int]:
|
|
2166
|
+
"""The owner's informant ratings of a person's Big Five domains, onto their node.
|
|
2167
|
+
|
|
2168
|
+
Only `trait.bfi2_domain` facts whose SUBJECT is this person, and the card labels every
|
|
2169
|
+
one "your read": on this node they are all owner-stated, because the model's estimate
|
|
2170
|
+
is gated behind a validation it has not passed (plan §2.2). Negative Emotionality is
|
|
2171
|
+
named as withheld rather than left blank — a missing slider reads as "not rated yet",
|
|
2172
|
+
a withheld one reads as the decision it is.
|
|
2173
|
+
"""
|
|
2174
|
+
by_entity = {str(n["entity_id"]): n for n in nodes if n.get("entity_id") and not n.get("is_owner")}
|
|
2175
|
+
if not by_entity:
|
|
2176
|
+
return {"attached": 0}
|
|
2177
|
+
try:
|
|
2178
|
+
rows = conn.execute(
|
|
2179
|
+
"SELECT payload_json, valid_from FROM signal_objects"
|
|
2180
|
+
" WHERE object_type='fact' AND valid_to IS NULL"
|
|
2181
|
+
" AND payload_json LIKE '%trait.bfi2_domain%'").fetchall()
|
|
2182
|
+
except sqlite3.Error:
|
|
2183
|
+
return {"attached": 0}
|
|
2184
|
+
attached = 0
|
|
2185
|
+
for payload, valid_from in rows:
|
|
2186
|
+
try:
|
|
2187
|
+
fact = json.loads(payload or "{}")
|
|
2188
|
+
except (TypeError, ValueError):
|
|
2189
|
+
continue
|
|
2190
|
+
if str(fact.get("predicate") or "") != "trait.bfi2_domain":
|
|
2191
|
+
continue
|
|
2192
|
+
node = by_entity.get(str(fact.get("subject_entity_id") or ""))
|
|
2193
|
+
if node is None:
|
|
2194
|
+
continue
|
|
2195
|
+
struct = fact.get("value_struct") or fact.get("value") or {}
|
|
2196
|
+
domain, level = str(struct.get("domain") or ""), str(struct.get("level") or "")
|
|
2197
|
+
if not domain or not level:
|
|
2198
|
+
continue
|
|
2199
|
+
disp = node.setdefault("disposition", {
|
|
2200
|
+
"domains": {},
|
|
2201
|
+
"excluded": ["negative_emotionality"],
|
|
2202
|
+
"basis": ("your read — an informant rating you gave on this card; the model's "
|
|
2203
|
+
"estimate is not shown until it passes validation"),
|
|
2204
|
+
})
|
|
2205
|
+
if domain not in disp["domains"]:
|
|
2206
|
+
attached += 1
|
|
2207
|
+
disp["domains"][domain] = {
|
|
2208
|
+
"level": level,
|
|
2209
|
+
"at": str(valid_from or "")[:10] or None,
|
|
2210
|
+
"stated_by_owner": str(fact.get("asserted_by") or "") == "owner",
|
|
2211
|
+
}
|
|
2212
|
+
return {"attached": attached}
|
|
2213
|
+
|
|
2214
|
+
|
|
2215
|
+
def attach_heard_about(conn: Any, dataset_id: str, nodes: List[Dict[str, Any]]) -> Dict[str, int]:
|
|
2216
|
+
"""What of the OWNER'S OWN WORK this person has heard about, from the owner's DMs to them.
|
|
2217
|
+
|
|
2218
|
+
The Luck screen already computes this per body of work — "told two people" — and never
|
|
2219
|
+
per person, so a card could not answer the question an ask begins with: can I bring
|
|
2220
|
+
this up without cold-starting? Measured on the live node before this existed: 99
|
|
2221
|
+
owner-authored messages named a work item to 19 people, and none of those 19 cards said
|
|
2222
|
+
so. Reuses the luck rail's resolver end to end rather than a second surface matcher,
|
|
2223
|
+
so the two screens cannot disagree about who has heard what.
|
|
2224
|
+
|
|
2225
|
+
First-party by construction — the events are messages the OWNER wrote (`is_from_self`)
|
|
2226
|
+
in a DM, so this is the owner's record of what they said, never a claim about what the
|
|
2227
|
+
other person knows or repeated. One message is one telling; the chip carries the count
|
|
2228
|
+
and the date so a single mention a year ago reads as exactly that.
|
|
2229
|
+
"""
|
|
2230
|
+
from . import luck_surface as L
|
|
2231
|
+
|
|
2232
|
+
for table in ("entity_mentions", "conversation_messages"):
|
|
2233
|
+
if not _appearance_table_exists(conn, table):
|
|
2234
|
+
return {"attached": 0, "events": 0}
|
|
2235
|
+
try:
|
|
2236
|
+
items = L.compile_surfaces(conn, dataset_id, L.build_work_items(conn))
|
|
2237
|
+
except sqlite3.Error:
|
|
2238
|
+
return {"attached": 0, "events": 0}
|
|
2239
|
+
if not items:
|
|
2240
|
+
return {"attached": 0, "events": 0}
|
|
2241
|
+
try:
|
|
2242
|
+
tells = L.build_telling_events(conn, dataset_id, items)
|
|
2243
|
+
except sqlite3.Error:
|
|
2244
|
+
return {"attached": 0, "events": 0}
|
|
2245
|
+
if not tells:
|
|
2246
|
+
return {"attached": 0, "events": 0}
|
|
2247
|
+
|
|
2248
|
+
labels = {i["work_item_id"]: i["label"] for i in items}
|
|
2249
|
+
by_key: Dict[str, Dict[str, Any]] = {}
|
|
2250
|
+
for n in nodes:
|
|
2251
|
+
if n.get("is_owner"):
|
|
2252
|
+
continue
|
|
2253
|
+
for k in n.get("messenger_keys") or []:
|
|
2254
|
+
by_key[str(k)] = n
|
|
2255
|
+
# node_id -> work_item_id -> event times; merged across a person's handles so a person
|
|
2256
|
+
# with two numbers is told once, not twice.
|
|
2257
|
+
merged: Dict[str, Dict[str, List[str]]] = {}
|
|
2258
|
+
for work_item_id, _mid, recipient, _comm, event_at, _period, _n in tells:
|
|
2259
|
+
node = by_key.get(str(recipient))
|
|
2260
|
+
if node is None:
|
|
2261
|
+
continue
|
|
2262
|
+
merged.setdefault(str(node["node_id"]), {}).setdefault(
|
|
2263
|
+
str(work_item_id), []).append(str(event_at or ""))
|
|
2264
|
+
by_node = {str(n["node_id"]): n for n in nodes}
|
|
2265
|
+
attached = 0
|
|
2266
|
+
for node_id, per_item in merged.items():
|
|
2267
|
+
node = by_node.get(node_id)
|
|
2268
|
+
if node is None:
|
|
2269
|
+
continue
|
|
2270
|
+
entries = sorted(((len(times), labels.get(wid, wid), max(times)) for wid, times in per_item.items()),
|
|
2271
|
+
key=lambda e: (-e[0], e[1]))
|
|
2272
|
+
node["heard_about"] = {
|
|
2273
|
+
"items": [{"label": label, "events": count, "last_at": (last[:10] if last else None)}
|
|
2274
|
+
for count, label, last in entries[:4]],
|
|
2275
|
+
"events": sum(e[0] for e in entries),
|
|
2276
|
+
"basis": ("your own direct messages to them that name the work — "
|
|
2277
|
+
"never what they said"),
|
|
2278
|
+
}
|
|
2279
|
+
attached += 1
|
|
2280
|
+
return {"attached": attached, "events": len(tells)}
|
|
2281
|
+
|
|
2282
|
+
|
|
2123
2283
|
def attach_shared_with_owner(conn: Any, nodes: List[Dict[str, Any]]) -> Dict[str, int]:
|
|
2124
2284
|
"""What the owner and this person BOTH engage with, and what KIND of thing it is.
|
|
2125
2285
|
|
|
@@ -197,9 +197,13 @@ def read_directed_edges(
|
|
|
197
197
|
|
|
198
198
|
|
|
199
199
|
def read_relationship_signals(conn: Any, *, dataset_id: str, signal: str = "all") -> Dict[str, Any]:
|
|
200
|
-
"""The derived read: warmth / drift / reciprocity, calibrated against the
|
|
201
|
-
distribution, with what was NOT judged reported rather than hidden.
|
|
202
|
-
|
|
200
|
+
"""The derived read: warmth / drift / reciprocity / archetype, calibrated against the
|
|
201
|
+
owner's own distribution, with what was NOT judged reported rather than hidden.
|
|
202
|
+
|
|
203
|
+
The archetype reads the directed edges as well as the dyads (766 rows on the live node,
|
|
204
|
+
one pass, no DDL); it is the one signal that names its unmeasured axes per row."""
|
|
205
|
+
from ..features.derivation.social_kernels import (_dyad_rows, _edge_rows,
|
|
206
|
+
apply_evidence_floor, compute_archetype,
|
|
203
207
|
compute_drift, compute_reciprocity,
|
|
204
208
|
compute_warmth)
|
|
205
209
|
from .messenger_directed import MESSENGER_DYAD_STATS_TABLE
|
|
@@ -221,11 +225,13 @@ def read_relationship_signals(conn: Any, *, dataset_id: str, signal: str = "all"
|
|
|
221
225
|
out["drift_alarms"] = compute_drift(rows)
|
|
222
226
|
if signal in ("all", "reciprocity"):
|
|
223
227
|
out["reciprocity"] = compute_reciprocity(rows)
|
|
228
|
+
if signal in ("all", "archetype"):
|
|
229
|
+
out["archetypes"] = compute_archetype(rows, _edge_rows(conn, dataset_id))
|
|
224
230
|
|
|
225
|
-
labels_for = {r["peer_key"] for k in ("warmth", "drift_alarms", "reciprocity")
|
|
231
|
+
labels_for = {r["peer_key"] for k in ("warmth", "drift_alarms", "reciprocity", "archetypes")
|
|
226
232
|
for r in out.get(k, [])}
|
|
227
233
|
labels = peer_labels(conn, dataset_id, sorted(labels_for))
|
|
228
|
-
for k in ("warmth", "drift_alarms", "reciprocity"):
|
|
234
|
+
for k in ("warmth", "drift_alarms", "reciprocity", "archetypes"):
|
|
229
235
|
for r in out.get(k, []):
|
|
230
236
|
r["label"] = labels.get(r["peer_key"]) or r["peer_key"]
|
|
231
237
|
return out
|
|
@@ -280,7 +286,8 @@ def read_person_graph(conn: Any, *, dataset_id: str,
|
|
|
280
286
|
"""
|
|
281
287
|
from .dataset_resolution import resolve_messaging_dataset
|
|
282
288
|
from .person_graph import (attach_closeness, attach_coactivity, attach_fact_closeness,
|
|
283
|
-
attach_shared_with_owner,
|
|
289
|
+
attach_heard_about, attach_shared_with_owner,
|
|
290
|
+
person_disposition_facts,
|
|
284
291
|
auto_link_duplicates,
|
|
285
292
|
build_person_edges, build_person_nodes, group_ambient_people,
|
|
286
293
|
merge_suggestions, resolve_owner_identity,
|
|
@@ -328,6 +335,29 @@ def read_person_graph(conn: Any, *, dataset_id: str,
|
|
|
328
335
|
# different question of what the two of them WORK ON. Run after the duplicate fold, for
|
|
329
336
|
# the same reason the facts are: the edge must land on the surviving node.
|
|
330
337
|
attach_coactivity(conn, nodes)
|
|
338
|
+
# What of the owner's OWN work this person has heard about — the owner's DMs to them
|
|
339
|
+
# that name a body of work, through the luck rail's resolver. Per person here, per
|
|
340
|
+
# work item there; same events, so the two screens agree.
|
|
341
|
+
heard_stats = attach_heard_about(conn, dataset_id, nodes)
|
|
342
|
+
# The owner's informant ratings — stated facts about this person, labelled as such.
|
|
343
|
+
disposition_stats = person_disposition_facts(conn, nodes)
|
|
344
|
+
# The commitment ledger, owner's half: what the owner promised this person, in the
|
|
345
|
+
# owner's own words, and what the record says became of it.
|
|
346
|
+
from ..features.derivation.commitments import attach_commitments, attach_status_signals
|
|
347
|
+
|
|
348
|
+
commitment_stats = attach_commitments(conn, nodes)
|
|
349
|
+
# What they told you their situation is, in their words, expiring at 90 days.
|
|
350
|
+
status_stats = attach_status_signals(conn, nodes)
|
|
351
|
+
# The stored reading, when one exists: computed on the deferred lane, never here.
|
|
352
|
+
from ..features.derivation.person_reading import load_person_readings
|
|
353
|
+
|
|
354
|
+
readings = load_person_readings(conn)
|
|
355
|
+
for n in nodes:
|
|
356
|
+
r = readings.get(str(n.get("node_id") or ""))
|
|
357
|
+
if r:
|
|
358
|
+
n["reading"] = {k: r.get(k) for k in ("sentences", "strengths", "evidence", "coverage",
|
|
359
|
+
"computed_at", "model", "reason",
|
|
360
|
+
"dropped_uncited", "version")}
|
|
331
361
|
# Ambient is 173 of 437 and reads as an undifferentiated fringe, but it holds classical
|
|
332
362
|
# poets, GitHub collaborators, LinkedIn contacts and several pieces of software mistaken
|
|
333
363
|
# for people. Grouping by what each name was seen ALONGSIDE separates them.
|
|
@@ -353,6 +383,11 @@ def read_person_graph(conn: Any, *, dataset_id: str,
|
|
|
353
383
|
n["centrality_degree"] = structure["degree"].get(nid, 0.0)
|
|
354
384
|
n["centrality_betweenness"] = structure["betweenness"].get(nid, 0.0)
|
|
355
385
|
n["brokerage_meaningful"] = bool(structure.get("brokerage_meaningful", {}).get(nid))
|
|
386
|
+
reach = (structure.get("reach") or {}).get(nid)
|
|
387
|
+
if reach:
|
|
388
|
+
# `meaningful` carries the same component-size rule as brokerage: a cut-off
|
|
389
|
+
# claim inside a four-person corner is arithmetic, a leaf count is a fact.
|
|
390
|
+
n["reach"] = {**reach, "meaningful": bool(n["brokerage_meaningful"])}
|
|
356
391
|
# People who turn up in the same subjects. A pull on the LAYOUT only: not an edge, not a
|
|
357
392
|
# community, nothing that changes a colour or a count. The graph places people by their
|
|
358
393
|
# relationship to the owner and to each other through messages, and neither of those
|
|
@@ -389,6 +424,11 @@ def read_person_graph(conn: Any, *, dataset_id: str,
|
|
|
389
424
|
"behaviour understates it, and can only pull someone closer, "
|
|
390
425
|
"never push them away: silence is not evidence of distance"),
|
|
391
426
|
"fact_closeness_applied": fact_stats.get("applied", 0),
|
|
427
|
+
"heard_about": heard_stats,
|
|
428
|
+
"readings": {"attached": sum(1 for n in nodes if n.get("reading"))},
|
|
429
|
+
"disposition": disposition_stats,
|
|
430
|
+
"commitments": commitment_stats,
|
|
431
|
+
"status_signals": status_stats,
|
|
392
432
|
"ambient_groups": {k: ambient_stats.get(k) for k in ("grouped", "ungrouped", "groups")},
|
|
393
433
|
"context_affinity": context["pairs"],
|
|
394
434
|
"context_coverage": context["coverage"],
|
|
@@ -423,6 +463,15 @@ def read_person_graph(conn: Any, *, dataset_id: str,
|
|
|
423
463
|
}
|
|
424
464
|
|
|
425
465
|
|
|
466
|
+
def rate_person(conn: Any, *, subject_entity_id: str, domain: str, level: str,
|
|
467
|
+
note: str = "") -> Dict[str, Any]:
|
|
468
|
+
"""The owner's informant rating of a person's Big Five domain (plan §2.2)."""
|
|
469
|
+
from ..features.derivation.surfaces import rate_person_disposition
|
|
470
|
+
|
|
471
|
+
return rate_person_disposition(conn, subject_entity_id=subject_entity_id,
|
|
472
|
+
domain=domain, level=level, note=note)
|
|
473
|
+
|
|
474
|
+
|
|
426
475
|
def read_naming_queue(conn: Any, *, dataset_id: str, limit: int = 25) -> Dict[str, Any]:
|
|
427
476
|
"""Unnamed human peers, busiest first."""
|
|
428
477
|
from .dataset_resolution import resolve_messaging_dataset
|
|
@@ -436,6 +436,84 @@ def get_relationship_signals(
|
|
|
436
436
|
return read_relationship_signals(conn, dataset_id=dataset_id, signal=signal)
|
|
437
437
|
|
|
438
438
|
|
|
439
|
+
@router.post("/messenger-analytics/readings/refresh", dependencies=[Depends(require_api_key)])
|
|
440
|
+
def post_readings_refresh(
|
|
441
|
+
dataset_id: str = Query(...),
|
|
442
|
+
force: bool = Query(False),
|
|
443
|
+
limit: int = Query(60, ge=1, le=500),
|
|
444
|
+
) -> Dict[str, Any]:
|
|
445
|
+
"""Run the readings pass now, on a background thread (single-flight). Engine-only."""
|
|
446
|
+
import threading
|
|
447
|
+
|
|
448
|
+
from ..features.derivation import person_reading as PR
|
|
449
|
+
|
|
450
|
+
def _go() -> None:
|
|
451
|
+
from ..core.state import close_thread_db_connection
|
|
452
|
+
|
|
453
|
+
with PR._LOCK:
|
|
454
|
+
if PR._RUNNING:
|
|
455
|
+
return
|
|
456
|
+
PR._RUNNING = True
|
|
457
|
+
try:
|
|
458
|
+
conn = get_db_connection()
|
|
459
|
+
if conn is None:
|
|
460
|
+
return
|
|
461
|
+
PR._LAST.update(PR.refresh_person_readings(conn, dataset_id, limit=limit, force=force))
|
|
462
|
+
except Exception as exc: # noqa: BLE001
|
|
463
|
+
PR._LAST["error"] = str(exc)[:200]
|
|
464
|
+
finally:
|
|
465
|
+
with PR._LOCK:
|
|
466
|
+
PR._RUNNING = False
|
|
467
|
+
close_thread_db_connection()
|
|
468
|
+
|
|
469
|
+
if PR._RUNNING:
|
|
470
|
+
return {"status": "running", **PR.readings_status()}
|
|
471
|
+
t = threading.Thread(target=_go, name="topos-person-readings-manual", daemon=True)
|
|
472
|
+
t.start()
|
|
473
|
+
return {"status": "started", "dataset_id": dataset_id, "force": force, "limit": limit}
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
@router.post("/messenger-analytics/commitments/refresh", dependencies=[Depends(require_api_key)])
|
|
477
|
+
def post_commitments_refresh(limit: int = Query(40, ge=1, le=400)) -> Dict[str, Any]:
|
|
478
|
+
"""The commitment ledger's owner half: run `obligations.commitments` over the owner's
|
|
479
|
+
promise-shaped records only (engine-only; the pack must be enabled by the owner)."""
|
|
480
|
+
import threading
|
|
481
|
+
|
|
482
|
+
from ..features.derivation import commitments as C
|
|
483
|
+
from ..features.derivation import person_reading as PR
|
|
484
|
+
|
|
485
|
+
def _go() -> None:
|
|
486
|
+
from ..core.state import close_thread_db_connection
|
|
487
|
+
|
|
488
|
+
with PR._LOCK:
|
|
489
|
+
if PR._RUNNING:
|
|
490
|
+
return
|
|
491
|
+
PR._RUNNING = True
|
|
492
|
+
try:
|
|
493
|
+
conn = get_db_connection()
|
|
494
|
+
if conn is None:
|
|
495
|
+
return
|
|
496
|
+
PR._LAST.update({"commitments": C.refresh_commitments(conn, limit=limit)})
|
|
497
|
+
except Exception as exc: # noqa: BLE001
|
|
498
|
+
PR._LAST["commitments_error"] = str(exc)[:200]
|
|
499
|
+
finally:
|
|
500
|
+
with PR._LOCK:
|
|
501
|
+
PR._RUNNING = False
|
|
502
|
+
close_thread_db_connection()
|
|
503
|
+
|
|
504
|
+
if PR._RUNNING:
|
|
505
|
+
return {"status": "running", **PR.readings_status()}
|
|
506
|
+
threading.Thread(target=_go, name="topos-commitments-manual", daemon=True).start()
|
|
507
|
+
return {"status": "started", "limit": limit}
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
@router.get("/messenger-analytics/readings/status", dependencies=[Depends(require_api_key)])
|
|
511
|
+
def get_readings_status() -> Dict[str, Any]:
|
|
512
|
+
from ..features.derivation.person_reading import readings_status
|
|
513
|
+
|
|
514
|
+
return readings_status()
|
|
515
|
+
|
|
516
|
+
|
|
439
517
|
@router.get("/messenger-analytics/bench", dependencies=[Depends(require_api_key)])
|
|
440
518
|
def get_bench() -> Dict[str, Any]:
|
|
441
519
|
conn = get_db_connection()
|
|
@@ -517,6 +595,26 @@ def post_person_curate(payload: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
517
595
|
action=str(payload.get("action") or ""), value=payload.get("value"))
|
|
518
596
|
|
|
519
597
|
|
|
598
|
+
@router.post("/messenger-analytics/person-rate", dependencies=[Depends(require_api_key)])
|
|
599
|
+
def post_person_rate(payload: Dict[str, Any]) -> Dict[str, Any]:
|
|
600
|
+
"""The owner's informant rating of a person's Big Five domain — a stated fact through
|
|
601
|
+
the consent path. 400 with the reason when the rating is refused."""
|
|
602
|
+
from fastapi import HTTPException
|
|
603
|
+
|
|
604
|
+
conn = get_db_connection()
|
|
605
|
+
if conn is None:
|
|
606
|
+
return {"error": "no database"}
|
|
607
|
+
from ..analytics.relationship_reads import rate_person
|
|
608
|
+
|
|
609
|
+
try:
|
|
610
|
+
return rate_person(
|
|
611
|
+
conn, subject_entity_id=str(payload.get("subject_entity_id") or ""),
|
|
612
|
+
domain=str(payload.get("domain") or ""), level=str(payload.get("level") or ""),
|
|
613
|
+
note=str(payload.get("note") or ""))
|
|
614
|
+
except ValueError as bad:
|
|
615
|
+
raise HTTPException(status_code=400, detail={"reason": "rating_refused", "error": str(bad)}) from bad
|
|
616
|
+
|
|
617
|
+
|
|
520
618
|
@router.post("/messenger-analytics/person-undo", dependencies=[Depends(require_api_key)])
|
|
521
619
|
def post_person_undo(payload: Dict[str, Any]) -> Dict[str, Any]:
|
|
522
620
|
conn = get_db_connection()
|
|
@@ -1100,13 +1100,23 @@ async def get_derivation_packs(_api_key: str = Depends(require_api_key)):
|
|
|
1100
1100
|
async def put_derivation_pack(
|
|
1101
1101
|
pack_id: str,
|
|
1102
1102
|
enabled: bool = Body(..., embed=True),
|
|
1103
|
+
consent: bool = Body(False, embed=True),
|
|
1104
|
+
consent_note: str = Body("", embed=True),
|
|
1103
1105
|
_api_key: str = Depends(require_api_key),
|
|
1104
1106
|
):
|
|
1105
|
-
|
|
1107
|
+
"""Enabling an outward pack (`net_subject: allow`) needs `consent: true`; without it
|
|
1108
|
+
the route answers 409 with the terms the owner must be shown."""
|
|
1109
|
+
from ..features.derivation.surfaces import ConsentRequired, set_pack_enabled
|
|
1106
1110
|
|
|
1107
|
-
|
|
1111
|
+
try:
|
|
1112
|
+
ok = set_pack_enabled(_entities_conn(), pack_id, enabled,
|
|
1113
|
+
consent=consent, consent_note=consent_note)
|
|
1114
|
+
except ConsentRequired as need:
|
|
1115
|
+
raise HTTPException(status_code=409, detail={"reason": "consent_required",
|
|
1116
|
+
"terms": need.terms}) from need
|
|
1117
|
+
if not ok:
|
|
1108
1118
|
raise HTTPException(status_code=404, detail=f"unknown pack {pack_id}")
|
|
1109
|
-
return {"pack_id": pack_id, "enabled": enabled}
|
|
1119
|
+
return {"pack_id": pack_id, "enabled": enabled, "consented": bool(consent and enabled)}
|
|
1110
1120
|
|
|
1111
1121
|
|
|
1112
1122
|
@router.get("/facts/conflicts")
|
|
Binary file
|
|
Binary file
|
|
@@ -34,8 +34,17 @@ async def handle_put_derivation_pack(message: Dict[str, Any]) -> Optional[Dict[s
|
|
|
34
34
|
if not pack_id or not isinstance(enabled, bool):
|
|
35
35
|
return {"id": req_id, "status": "error", "error": "pack_id and enabled (bool) required"}
|
|
36
36
|
try:
|
|
37
|
-
from ...features.derivation.surfaces import set_pack_enabled
|
|
38
|
-
|
|
37
|
+
from ...features.derivation.surfaces import ConsentRequired, set_pack_enabled
|
|
38
|
+
try:
|
|
39
|
+
ok = set_pack_enabled(conn, pack_id, enabled,
|
|
40
|
+
consent=bool(payload.get("consent")),
|
|
41
|
+
consent_note=str(payload.get("consent_note") or ""))
|
|
42
|
+
except ConsentRequired as need:
|
|
43
|
+
# Not an error in the transport sense: the answer is "show the owner this and
|
|
44
|
+
# ask". The terms ride back so the client can render them verbatim.
|
|
45
|
+
return {"id": req_id, "status": "error", "error": str(need),
|
|
46
|
+
"reason": "consent_required", "terms": need.terms}
|
|
47
|
+
if not ok:
|
|
39
48
|
return {"id": req_id, "status": "error", "error": f"unknown pack {pack_id}"}
|
|
40
49
|
return {"id": req_id, "status": "ok",
|
|
41
50
|
"payload": {"status": "ok", "pack_id": pack_id, "enabled": enabled}}
|
|
@@ -492,7 +492,8 @@ async def handle_messenger_analytics_periods(message: Dict[str, Any]) -> Optiona
|
|
|
492
492
|
"messenger_directed_edges", "messenger_bench", "messenger_luck_surface",
|
|
493
493
|
"messenger_person_graph", "messenger_naming_queue",
|
|
494
494
|
"messenger_person_provenance", "messenger_person_curate",
|
|
495
|
-
"messenger_person_undo", "messenger_curation_history"
|
|
495
|
+
"messenger_person_undo", "messenger_curation_history",
|
|
496
|
+
"messenger_person_rate")
|
|
496
497
|
async def handle_relationship_reads(message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
497
498
|
req_id = message.get("id")
|
|
498
499
|
if not req_id:
|
|
@@ -518,7 +519,7 @@ async def handle_relationship_reads(message: Dict[str, Any]) -> Optional[Dict[st
|
|
|
518
519
|
"messenger_luck_surface", "messenger_person_graph",
|
|
519
520
|
"messenger_naming_queue", "messenger_person_provenance",
|
|
520
521
|
"messenger_person_curate", "messenger_person_undo",
|
|
521
|
-
"messenger_curation_history"):
|
|
522
|
+
"messenger_curation_history", "messenger_person_rate"):
|
|
522
523
|
return {"id": req_id, "status": "error", "error": "dataset_id required"}
|
|
523
524
|
if msg_type == "messenger_relationships":
|
|
524
525
|
result = reads.read_relationships(
|
|
@@ -547,6 +548,16 @@ async def handle_relationship_reads(message: Dict[str, Any]) -> Optional[Dict[st
|
|
|
547
548
|
conn, dataset_id=dataset_id,
|
|
548
549
|
subject_ids=payload.get("subject_ids") or payload.get("subject_id") or [],
|
|
549
550
|
action=str(payload.get("action") or ""), value=payload.get("value"))
|
|
551
|
+
elif msg_type == "messenger_person_rate":
|
|
552
|
+
try:
|
|
553
|
+
result = reads.rate_person(
|
|
554
|
+
conn, subject_entity_id=str(payload.get("subject_entity_id") or ""),
|
|
555
|
+
domain=str(payload.get("domain") or ""),
|
|
556
|
+
level=str(payload.get("level") or ""),
|
|
557
|
+
note=str(payload.get("note") or ""))
|
|
558
|
+
except ValueError as bad:
|
|
559
|
+
return {"id": req_id, "status": "error", "error": str(bad)[:300],
|
|
560
|
+
"reason": "rating_refused"}
|
|
550
561
|
elif msg_type == "messenger_person_undo":
|
|
551
562
|
result = reads.undo_curation(
|
|
552
563
|
conn, overlay_ids=payload.get("overlay_ids")
|